-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Drapeza Oleg <o.drapeza@tinkoff.ru> Co-authored-by: Andrey Rublev <box@anru.me> GitOrigin-RevId: 529e46620111f4e0cb11659b4502e54f415461ed
- Loading branch information
1 parent
aed44b8
commit dbcdd26
Showing
21 changed files
with
556 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Versioning | ||
|
||
Most of the libraries in the `tramvai` repository are bundled into a unified versioning. | ||
|
||
All current versions of libraries are stored in release tags, in `package.json` versions are used - stubs `0.0.0-stub`. | ||
|
||
The versioning of `tramvai` libraries follows [semver](https://semver.org/lang/ru/). For versions that start with zero (`0.x.x`), the major (` major`) is the second digit in the version, and the minor (`minor`) is the third digit - `0.major.minor`. Thus, on a `BREAKING CHANGE` commit, package version `1.0.0` will go up to `2.0.0`, and package version `0.1.0` will go up to `0.2.0`. | ||
|
||
Library versions are updated according to [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) | ||
|
||
## Unified versioning | ||
|
||
Most of the libraries in the `tramvai` repository are combined into end-to-end versioning - these are `core` packages, tram modules and tokens, everything that is included in the `@tramvai` and `@tramvai-tinkoff` scopes. The release and publication of these libraries occurs at the same time, even if the changes affect only one package from the list. | ||
You can see this approach in [Angular](https://angular.io/guide/releases), and with some restrictions, in monorepositories using [Lerna](https://github.com/lerna/lerna#fixedlocked-mode-default) | ||
|
||
The main advantage of unified versioning is that compatibility between packages of the same version is guaranteed. | ||
|
||
Previously, the user had only one way to raise the framework version without losing compatibility between packages - to install all packages to their latest version. | ||
Now, you can specify a common target version for each `tramvai` library, or use the `tramvai update` command. | ||
|
||
One of the drawbacks of this approach is that any update of a package from the unified list requires raising versions and publishing all these packages from the list, which significantly slows down CI. | ||
|
||
## Storing versions in release tags | ||
|
||
One of the reasons for storing a version in release tags is the protected `master` branch, which we cannot automatically make changes to after the release and update of package versions. | ||
|
||
Storing versions in release tags does not in itself provide any advantage, and we use it together with stub versions of packages in the source `package.json` files. | ||
|
||
Let's say we had a package with dependencies: | ||
|
||
```json | ||
{ | ||
"name": "@tramvai/foo", | ||
"version": "0.1.0", | ||
"dependencies": { | ||
"@tramvai/bar": "^1.1.0", | ||
"@tramvai/baz": "^2.0.0" | ||
} | ||
} | ||
``` | ||
|
||
Previously, every big Merge Request was accompanied by conflicts if package versions were updated in the master branch, and the affected libraries in MR contained changes in dependencies. | ||
|
||
Now, our package looks like this: | ||
|
||
```json | ||
{ | ||
"name": "@tramvai/foo", | ||
"version": "0.0.0-stub", | ||
"dependencies": { | ||
"@tramvai/bar": "0.0.0-stub", | ||
"@tramvai/baz": "0.0.0-stub" | ||
} | ||
} | ||
``` | ||
|
||
The version `0.0.0-stub` will never cause merge conflicts, and the calculation of real versions occurs only in CI - when creating a new release tag and publishing, inside the `pvm` library. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Версионирование | ||
|
||
Большинство библиотек в `tramvai` репозитории объединены в общее версионирование. | ||
|
||
Все актуальные версии библиотек хранятся в релизных тегах, в `package.json` используются версии - заглушки `0.0.0-stub`. | ||
|
||
Версионирование `tramvai` библиотек придерживается [semver](https://semver.org/lang/ru/). Для версий, которые начинаются с нуля (`0.x.x`), мажорной (`major`) считается вторая цифра в версии, а минорной (`minor`) считается третья цифра - `0.major.minor`. Таким образом, при `BREAKING CHANGE` коммите, пакет версии `1.0.0` поднимется до `2.0.0`, а пакет версии `0.1.0` поднимется до `0.2.0`. | ||
|
||
Версии библиотек обновляются согласно [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) | ||
|
||
## Сквозное версионирование | ||
|
||
Большинство библиотек в `tramvai` репозитории объединены в сквозное версионирование - это `core` пакеты, трамвай модули и токены, все что входит в скоупы `@tramvai` и `@tramvai-tinkoff`. Релиз и публикация этих библиотек происходит одновременно, даже если изменения затронули только один пакет из списка. | ||
Такой подход вы можете увидеть у [Angular](https://angular.io/guide/releases), и с некоторыми ограничениями, в монорепозиториях использующих [Lerna](https://github.com/lerna/lerna#fixedlocked-mode-default) | ||
|
||
Основной плюс unified версионирования - гарантируется совместимость между пакетами одной версии. | ||
|
||
Раньше у пользователя был только один способ поднять версию фреймворка, не потеряв совместимость между пакетами - устанавливать все пакеты до их latest версии. | ||
Сейчас, можно указать общую целевую версию для каждой `tramvai` библиотеки, либо использовать команду `tramvai update`. | ||
|
||
Один из минусов подхода - любое обновление пакета из списка unified, требует поднять версии и опубликовать все эти пакеты из списка, что значительно замедляет CI. | ||
|
||
## Хранение версий в релизных тегах | ||
|
||
Одна из причин для хранения версии в релизных тегах - protected ветка `master`, в которую мы не можем автоматически внести изменения после релиза и обновления версий пакетов. | ||
|
||
Хранение версий в релизных тегах само по себе не дает преимуществ, и у нас используется вместе со stub версиями пакетов в исходных `package.json` файлах. | ||
|
||
Допустим, у нас был пакет с зависимостями: | ||
|
||
```json | ||
{ | ||
"name": "@tramvai/foo", | ||
"version": "0.1.0", | ||
"dependencies": { | ||
"@tramvai/bar": "^1.1.0", | ||
"@tramvai/baz": "^2.0.0" | ||
} | ||
} | ||
``` | ||
|
||
Раньше, каждый крупный Merge Request сопровождался конфликтами, если в master ветке обновлялась версии пакетов, а затронутые библиотеки в MR содержали изменения в dependencies. | ||
|
||
Теперь, наш пакет выглядит так: | ||
```json | ||
{ | ||
"name": "@tramvai/foo", | ||
"version": "0.0.0-stub", | ||
"dependencies": { | ||
"@tramvai/bar": "0.0.0-stub", | ||
"@tramvai/baz": "0.0.0-stub" | ||
} | ||
} | ||
``` | ||
|
||
Версия `0.0.0-stub` никогда не вызовет конфликтов слияния, а вычисление реальных версий происходит только в CI - при создании нового релизного тега и публикации, внутри библиотеки `pvm`. |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
--- | ||
id: tramvai-library | ||
title: Creating a tramvai library | ||
--- | ||
|
||
Adding a new library or module to the `tramvai` repository is detailed in the [Contribute section](contribute/contribute.md) | ||
|
||
This guide contains a set of tips for developing individual `tramvai` packages in application repositories, | ||
also, many teams maintain separate monoreps with common packages for a number of applications, divided into different repositories. | ||
|
||
### Prerequisites | ||
|
||
Let's consider all important cases using the example of creating a new `tramvai` module. | ||
Let's say the module will provide a new HTTP client to work with the Github `API`. | ||
|
||
### Package name | ||
|
||
It is highly discouraged to use the `@tramvai` and `@tramvai-tinkoff` scopes outside the `tramvai` repository. | ||
If our application is called `tincoin`, you can, for example, select one of these scopes: | ||
|
||
- `@tincoin` | ||
- `@tramvai-tincoin` | ||
- `@tincoin-core` | ||
|
||
For modules, the prefix is usually `module-`, for example: `@tramvai-tincoin/module-github-api-client` | ||
|
||
### Versioning | ||
|
||
The choice of a versioning strategy is entirely yours. | ||
We definitely recommend following `semver`, and we can recommend using [unified versioning](concepts/versioning.md) if: | ||
|
||
- you support monorep with core libraries | ||
- these libraries can be linked | ||
- and these packages are used in applications all together (or most of them) | ||
|
||
### Dependencies | ||
|
||
Dealing with library dependencies is not an easy task, and there is no ideal solution, but there are a number of tips to make it easier to manage dependencies. | ||
The best place to start is by dividing dependencies into different types: | ||
|
||
#### Framework | ||
|
||
Examples of such dependencies are `react` and `react-dom`, `@tramvai/*` and `@tramvai-tinkoff/*`. | ||
If we write `babel` or `eslint` plugin, it can be `@babel/core` and `eslint`. | ||
|
||
Typically, an end user, such as a `tramvai` application, is required to install a dependency framework, | ||
without them it simply won't work. | ||
|
||
Therefore, our library should set them to `peerDependencies`, with the most free versions, for example, if the package is tied to the basic functionality of `tramvai`, and uses React hooks: | ||
|
||
```json | ||
{ | ||
"peerDependencies": { | ||
"@tramvai/core": "*", | ||
"react": ">=16.8", | ||
"react-dom": ">=16.8" | ||
} | ||
} | ||
``` | ||
|
||
#### Singleton | ||
|
||
A number of dependencies must be strictly one in the application. | ||
Any duplicates are a minus. increase the weight of the application bundle, but libraries such as `react` or `@tinkoff/logger` require a single copy in our application. | ||
|
||
For them, the rule applies as with the framework, you need to install them in `peerDependencies`, with the most free versions: | ||
|
||
```json | ||
{ | ||
"peerDependencies": { | ||
"@tinkoff/logger": "*" | ||
} | ||
} | ||
``` | ||
|
||
#### Popular | ||
|
||
Many packages are popular enough that chances are they are already being used in the final application. | ||
An example of such dependencies is - `date-fns`, `lru-cache`, `@tinkoff/dippy` | ||
|
||
For them, the rule applies as with the framework, you need to install them in `peerDependencies`, with the most free versions: | ||
|
||
```json | ||
{ | ||
"peerDependencies": { | ||
"@tinkoff/dippy": "*", | ||
"date-fns": ">=2", | ||
"lru-cache": "*" | ||
} | ||
} | ||
``` | ||
|
||
#### Specific | ||
|
||
Let's say our new tramvai module delivers unique functionality to the application that requires a third-party library (or even another package in your monorepo) | ||
|
||
If we are developing a service to work with the Github API, it might be the `@octokit/rest` package. | ||
|
||
In this case, you need to put the library in `dependencies`, and you can leave the standard range using `^`: | ||
|
||
```json | ||
{ | ||
"dependencies": { | ||
"@octokit/rest": "^18.0.0" | ||
} | ||
} | ||
``` | ||
|
||
#### Development | ||
|
||
A dependency may be involved in building your package - for example, `rollup` or `@tramvai/build`. | ||
The dependency is required to run library tests. | ||
The dependency contains the taipings required for the build. | ||
|
||
In all these cases, even if either is already in `peerDependencies`, it is worth adding a more specific version to `devDependencies`, for example: | ||
|
||
```json | ||
{ | ||
"devDependencies": { | ||
"@tramvai/build": "^2.5.0", | ||
"@types/react": "^17.0.0", | ||
"react": "^17.0.0" | ||
} | ||
} | ||
``` | ||
|
||
#### Exclusion | ||
|
||
Of course, there are exceptional cases. | ||
|
||
For example, tramvai provides many test utilities where all the main `@tramvai` dependencies were in `peerDependencies`. | ||
As soon as these utilities began to be used not in repositories with applications, but in monoreps with core packages, the problem of missing dependencies appeared, and we moved almost everything from `peerDependencies` to `dependencies` | ||
|
||
Proceed according to the situation and always think about the usability of your product :) | ||
|
||
### Build | ||
|
||
It is assumed that the final assembly of packages in the context of the application will be done by `@tramvai/cli`. | ||
Therefore, to publish packages written in `TypeScript`, it suffices to use` tsc`, and publish many compiled `.js` and` .d.ts` files. | ||
|
||
But building packages into bundles before publishing, for example via `rollup` or` @tramvai/build`, gives a number of possibilities: | ||
|
||
- preliminary tree-shaking will cut off all unnecessary, this will have a positive effect on the assembly of the application | ||
- you can make several bundles for different environments, in CJS or ES modules formats | ||
- you can make a separate bundle for the browser build, separate for the server one - top for libraries with SSR support | ||
|
||
Detailed documentation on using `@tramvai/build` is available in [documentation](references/tools/build.md) |
Oops, something went wrong.