@teambit/ci 0.0.0-e308aa46791bdab3538e682864e5a61a001dfd3d → 0.0.0-e30f7cc0f89342e52b1917ccd4a0ddd5dd679bc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/.npmignore +18 -0
  2. package/ci.docs.mdx +393 -69
  3. package/commands/merge.cmd.ts +50 -3
  4. package/commands/pr.cmd.ts +27 -4
  5. package/commands/sync.cmd.ts +77 -0
  6. package/commands/verify.cmd.ts +2 -1
  7. package/dist/ci.cmd.d.ts +1 -0
  8. package/dist/ci.cmd.js +2 -1
  9. package/dist/ci.cmd.js.map +1 -1
  10. package/dist/ci.docs.mdx +393 -69
  11. package/dist/ci.main.runtime.d.ts +239 -8
  12. package/dist/ci.main.runtime.js +1403 -120
  13. package/dist/ci.main.runtime.js.map +1 -1
  14. package/dist/commands/merge.cmd.d.ts +8 -0
  15. package/dist/commands/merge.cmd.js +28 -4
  16. package/dist/commands/merge.cmd.js.map +1 -1
  17. package/dist/commands/pr.cmd.d.ts +6 -1
  18. package/dist/commands/pr.cmd.js +9 -6
  19. package/dist/commands/pr.cmd.js.map +1 -1
  20. package/dist/commands/sync.cmd.d.ts +34 -0
  21. package/dist/commands/sync.cmd.js +57 -0
  22. package/dist/commands/sync.cmd.js.map +1 -0
  23. package/dist/commands/verify.cmd.d.ts +1 -0
  24. package/dist/commands/verify.cmd.js +2 -1
  25. package/dist/commands/verify.cmd.js.map +1 -1
  26. package/dist/git.d.ts +11 -1
  27. package/dist/git.js +11 -1
  28. package/dist/git.js.map +1 -1
  29. package/dist/index.d.ts +4 -0
  30. package/dist/index.js +26 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/{preview-1754339160316.js → preview-1786544691221.js} +1 -1
  33. package/dist/pull-request-ref.d.ts +1 -0
  34. package/dist/pull-request-ref.js +11 -0
  35. package/dist/pull-request-ref.js.map +1 -0
  36. package/dist/pull-request-ref.spec.d.ts +1 -0
  37. package/dist/pull-request-ref.spec.js +30 -0
  38. package/dist/pull-request-ref.spec.js.map +1 -0
  39. package/dist/skip-tasks-from-message.d.ts +4 -0
  40. package/dist/skip-tasks-from-message.js +30 -0
  41. package/dist/skip-tasks-from-message.js.map +1 -0
  42. package/dist/skip-tasks-from-message.spec.d.ts +1 -0
  43. package/dist/skip-tasks-from-message.spec.js +43 -0
  44. package/dist/skip-tasks-from-message.spec.js.map +1 -0
  45. package/dist/source-branch-detector.d.ts +55 -0
  46. package/dist/source-branch-detector.js +255 -0
  47. package/dist/source-branch-detector.js.map +1 -0
  48. package/dist/sync/adopt-lane-new-components.d.ts +36 -0
  49. package/dist/sync/adopt-lane-new-components.js +146 -0
  50. package/dist/sync/adopt-lane-new-components.js.map +1 -0
  51. package/dist/sync/git-host-provider.d.ts +47 -0
  52. package/dist/sync/git-host-provider.js +54 -0
  53. package/dist/sync/git-host-provider.js.map +1 -0
  54. package/dist/sync/git-host-provider.spec.d.ts +1 -0
  55. package/dist/sync/git-host-provider.spec.js +171 -0
  56. package/dist/sync/git-host-provider.spec.js.map +1 -0
  57. package/dist/sync/git-ops.d.ts +212 -0
  58. package/dist/sync/git-ops.js +425 -0
  59. package/dist/sync/git-ops.js.map +1 -0
  60. package/dist/sync/git-ops.spec.d.ts +1 -0
  61. package/dist/sync/git-ops.spec.js +515 -0
  62. package/dist/sync/git-ops.spec.js.map +1 -0
  63. package/dist/sync/github-client.d.ts +79 -0
  64. package/dist/sync/github-client.js +198 -0
  65. package/dist/sync/github-client.js.map +1 -0
  66. package/dist/sync/github-client.spec.d.ts +1 -0
  67. package/dist/sync/github-client.spec.js +205 -0
  68. package/dist/sync/github-client.spec.js.map +1 -0
  69. package/dist/sync/init-scaffold.d.ts +40 -0
  70. package/dist/sync/init-scaffold.js +326 -0
  71. package/dist/sync/init-scaffold.js.map +1 -0
  72. package/dist/sync/init-scaffold.spec.d.ts +1 -0
  73. package/dist/sync/init-scaffold.spec.js +169 -0
  74. package/dist/sync/init-scaffold.spec.js.map +1 -0
  75. package/dist/sync/lane-sync-executor.d.ts +322 -0
  76. package/dist/sync/lane-sync-executor.js +1521 -0
  77. package/dist/sync/lane-sync-executor.js.map +1 -0
  78. package/dist/sync/lane-sync-executor.spec.d.ts +1 -0
  79. package/dist/sync/lane-sync-executor.spec.js +638 -0
  80. package/dist/sync/lane-sync-executor.spec.js.map +1 -0
  81. package/dist/sync/main-sync-executor.d.ts +68 -0
  82. package/dist/sync/main-sync-executor.js +363 -0
  83. package/dist/sync/main-sync-executor.js.map +1 -0
  84. package/dist/sync/sync-config.d.ts +83 -0
  85. package/dist/sync/sync-config.js +187 -0
  86. package/dist/sync/sync-config.js.map +1 -0
  87. package/dist/sync/sync-config.spec.d.ts +1 -0
  88. package/dist/sync/sync-config.spec.js +254 -0
  89. package/dist/sync/sync-config.spec.js.map +1 -0
  90. package/dist/sync/sync-orchestrator.d.ts +76 -0
  91. package/dist/sync/sync-orchestrator.js +396 -0
  92. package/dist/sync/sync-orchestrator.js.map +1 -0
  93. package/dist/sync/sync-orchestrator.spec.d.ts +1 -0
  94. package/dist/sync/sync-orchestrator.spec.js +155 -0
  95. package/dist/sync/sync-orchestrator.spec.js.map +1 -0
  96. package/dist/sync/sync-planner.d.ts +69 -0
  97. package/dist/sync/sync-planner.js +138 -0
  98. package/dist/sync/sync-planner.js.map +1 -0
  99. package/dist/sync/sync-planner.spec.d.ts +1 -0
  100. package/dist/sync/sync-planner.spec.js +252 -0
  101. package/dist/sync/sync-planner.spec.js.map +1 -0
  102. package/dist/sync/sync-state.d.ts +127 -0
  103. package/dist/sync/sync-state.js +236 -0
  104. package/dist/sync/sync-state.js.map +1 -0
  105. package/dist/sync/sync-state.spec.d.ts +1 -0
  106. package/dist/sync/sync-state.spec.js +299 -0
  107. package/dist/sync/sync-state.spec.js.map +1 -0
  108. package/dist/sync/workspace-lane.d.ts +13 -0
  109. package/dist/sync/workspace-lane.js +27 -0
  110. package/dist/sync/workspace-lane.js.map +1 -0
  111. package/package.json +38 -17
  112. package/sync/adopt-lane-new-components.ts +128 -0
  113. package/sync/git-host-provider.spec.ts +197 -0
  114. package/sync/git-host-provider.ts +89 -0
  115. package/sync/git-ops.spec.ts +566 -0
  116. package/sync/git-ops.ts +406 -0
  117. package/sync/github-client.spec.ts +174 -0
  118. package/sync/github-client.ts +209 -0
  119. package/sync/init-scaffold.spec.ts +142 -0
  120. package/sync/init-scaffold.ts +340 -0
  121. package/sync/lane-sync-executor.spec.ts +595 -0
  122. package/sync/lane-sync-executor.ts +1680 -0
  123. package/sync/main-sync-executor.ts +398 -0
  124. package/sync/sync-config.spec.ts +283 -0
  125. package/sync/sync-config.ts +214 -0
  126. package/sync/sync-orchestrator.spec.ts +120 -0
  127. package/sync/sync-orchestrator.ts +386 -0
  128. package/sync/sync-planner.spec.ts +161 -0
  129. package/sync/sync-planner.ts +119 -0
  130. package/sync/sync-state.spec.ts +296 -0
  131. package/sync/sync-state.ts +238 -0
  132. package/sync/workspace-lane.ts +20 -0
  133. package/types/style.d.ts +4 -0
package/.npmignore ADDED
@@ -0,0 +1,18 @@
1
+ dist/tsconfig.tsbuildinfo
2
+ dist/tsconfig.json
3
+ /tsconfig.json
4
+
5
+ package-tar/
6
+ .bit-capsule-ready
7
+ /*.ts
8
+ artifacts/*
9
+ !artifacts/env-template
10
+ !artifacts/ui-bundle
11
+ !artifacts/preview-bundle
12
+ package-tar/
13
+ .bit-capsule-ready
14
+ /*.ts
15
+ artifacts/*
16
+ !artifacts/env-template
17
+ !artifacts/ui-bundle
18
+ !artifacts/preview-bundle
package/ci.docs.mdx CHANGED
@@ -5,13 +5,14 @@ labels: ['aspect', 'ci']
5
5
 
6
6
  # Bit CI
7
7
 
8
- Bit's **`bit ci`** commands (plus one BVM enhancement) wrap several routine Bit tasks into single-purpose scripts so your CI pipelines stay short, readable and consistent.
8
+ The `bit ci` commands wrap routine Bit tasks in single-purpose scripts. Each command keeps a CI pipeline short and consistent.
9
9
 
10
- | Command | Purpose | Typical CI Stage |
11
- | --------------------------------- | ----------------------------------------------------- | ---------------------- |
12
- | [`bit ci verify`](#bit-ci-verify) | Lint + build gate on every commit | pre-push / commit hook |
13
- | [`bit ci pr`](#bit-ci-pr) | Snap + export a feature lane when a PR opens/updates | pull-request pipeline |
14
- | [`bit ci merge`](#bit-ci-merge) | Tag + export new semantic versions on merge to `main` | merge-to-main pipeline |
10
+ | Command | Purpose | Typical CI stage |
11
+ | --------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------- |
12
+ | [`bit ci verify`](#bit-ci-verify) | Checks the status and builds every commit | pre-push hook, commit hook |
13
+ | [`bit ci pr`](#bit-ci-pr) | Snaps and exports a lane when a pull request opens or updates | pull-request pipeline |
14
+ | [`bit ci merge`](#bit-ci-merge) | Tags and exports new semantic versions after a merge to `main` | merge-to-main pipeline |
15
+ | [`bit ci sync`](#bit-ci-sync) | Reconciles a lane with its branch and pull request, and the main scope with the default branch | webhook, push, cron |
15
16
 
16
17
  ---
17
18
 
@@ -20,40 +21,42 @@ Bit's **`bit ci`** commands (plus one BVM enhancement) wrap several routine Bit
20
21
  | | |
21
22
  | ---------------- | ------------------------------------------------- |
22
23
  | **Syntax** | `bit ci verify` |
23
- | **What it does** | Ensures the component passes CI on every commit |
24
+ | **What it does** | Confirms that the component passes CI |
24
25
  | **Runs** | `bit install && bit status --strict && bit build` |
25
26
 
26
- ### When to run
27
+ ### When to run the command
27
28
 
28
- - Every commit that **is not** part of an open Pull Request (e.g. a pre-push hook).
29
- - As an early CI job to fail fast on dependency drift or broken builds.
29
+ - Run the command on every commit that is not part of an open pull request. A pre-push hook is one place.
30
+ - Run the command early in CI. The command then fails on dependency drift or on a broken build immediately.
30
31
 
31
32
  ### Exit behaviour
32
33
 
33
- The command stops at the first failing step (`status`, then `build`) and returns a non-zero exit code.
34
+ The command stops at the first step that fails. The command runs `status` first, then `build`. The command returns a non-zero exit code.
34
35
 
35
36
  ---
36
37
 
37
38
  ## `bit ci pr`
38
39
 
39
- Export a lane to Bit Cloud whenever a Pull Request is opened or updated.
40
+ The command exports a lane to Bit Cloud. Run the command when a pull request opens or updates.
40
41
 
41
42
  ```bash
42
43
  bit ci pr [--message <string>] [--build] [--lane <string>]
43
44
  ```
44
45
 
45
- | Flag | Shorthand | Description |
46
- | ----------- | --------- | ----------------------------------------------------------------------------------------- |
47
- | `--message` | `-m` | Changelog entry. If omitted, tries the latest Git commit message (fails if unavailable). |
48
- | `--build` | `-b` | Build locally before export. If absent, Ripple-CI builds the components. |
49
- | `--lane` | `-l` | Explicit lane name. Falls back to the current Git branch name. Performs input validation. |
46
+ | Flag | Shorthand | Description |
47
+ | ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------- |
48
+ | `--message` | `-m` | The changelog entry. Without the flag, the command reads the latest git commit message. The command fails if no message is available. |
49
+ | `--build` | `-b` | The command builds locally before the export. Without the flag, Ripple CI builds the components. |
50
+ | `--lane` | `-l` | The lane name. Without the flag, the command uses the current git branch name. The command validates the name. |
50
51
 
51
- ### Internal flow (fail-fast on any step)
52
+ ### Internal flow
53
+
54
+ The command stops at the first step that fails.
52
55
 
53
- 1. **Resolve lane name**
54
- - From `--lane` or current Git branch.
55
- - If the lane doesn’t exist remotely, create it; otherwise, `bit lane checkout <lane>`.
56
- 2. **Run wrapped Bit commands**
56
+ 1. **Resolve the lane name**
57
+ - The command reads `--lane`, or the current git branch.
58
+ - If the lane is absent on the remote, the command creates the lane. If the lane is present, the command runs `bit lane checkout <lane>`.
59
+ 2. **Run the wrapped Bit commands**
57
60
 
58
61
  ```bash
59
62
  bit install
@@ -63,7 +66,7 @@ bit ci pr [--message <string>] [--build] [--lane <string>]
63
66
  bit export
64
67
  ```
65
68
 
66
- 3. **Clean-up**
69
+ 3. **Clean up**
67
70
 
68
71
  ```bash
69
72
  bit lane switch main # leaves .bitmap unchanged in the working tree
@@ -71,59 +74,93 @@ bit ci pr [--message <string>] [--build] [--lane <string>]
71
74
 
72
75
  ### Typical CI placement
73
76
 
74
- Run on the _pull-request_ event after tests but before any deploy step.
77
+ Run the command on the pull-request event. Put the command after the tests and before every deploy step.
75
78
 
76
79
  ---
77
80
 
78
81
  ## `bit ci merge`
79
82
 
80
- Publishes new semantic versions after a PR merges to `main`.
83
+ The command publishes new semantic versions. Run the command after a pull request merges to `main`.
81
84
 
82
85
  ```bash
83
86
  bit ci merge [--message <string>] [--build] [--increment <level>] [--patch|--minor|--major] [--increment-by <number>]
84
87
  ```
85
88
 
86
- | Flag | Shorthand | Description |
87
- | ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------- |
88
- | `--message` | `-m` | Changelog entry (defaults to last Git commit message). |
89
- | `--build` | `-b` | Build locally (otherwise Ripple-CI does it). Required if workspace contains _soft-tagged_ components. |
90
- | `--strict` | `-s` | Fail on warnings as well as errors (default: only fails on errors). |
91
- | `--increment` | `-l` | Version bump level: `major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, `prerelease` (default: `patch`). |
92
- | `--patch` | `-p` | Shortcut for `--increment patch`. |
93
- | `--minor` | | Shortcut for `--increment minor`. |
94
- | `--major` | | Shortcut for `--increment major`. |
95
- | `--pre-release` | | Shortcut for `--increment prerelease` with optional identifier. |
96
- | `--prerelease-id` | | Prerelease identifier (e.g. "dev" to get "1.0.0-dev.1"). |
97
- | `--increment-by` | | Increment by more than 1 (e.g. `--increment-by 2` with patch: 0.0.1 → 0.0.3). |
89
+ | Flag | Shorthand | Description |
90
+ | ---------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
91
+ | `--message` | `-m` | The changelog entry. Without the flag, the command uses the last git commit message. |
92
+ | `--build` | `-b` | The command builds locally. Without the flag, Ripple CI builds. The flag is necessary if the workspace holds soft-tagged components. |
93
+ | `--strict` | `-s` | The command fails on a warning and on an error. Without the flag, the command fails only on an error. |
94
+ | `--increment` | `-l` | The version bump level: `major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch` or `prerelease`. The default is `patch`. |
95
+ | `--patch` | `-p` | The same as `--increment patch`. |
96
+ | `--minor` | | The same as `--increment minor`. |
97
+ | `--major` | | The same as `--increment major`. |
98
+ | `--pre-release` | | The same as `--increment prerelease`, with an optional identifier. |
99
+ | `--prerelease-id` | | The prerelease identifier. The value `dev` gives `1.0.0-dev.1`. |
100
+ | `--increment-by` | | The command increments by more than 1. `--increment-by 2` with a patch gives 0.0.1 → 0.0.3. |
101
+ | `--auto-tag-increment` | | The version bump level for the auto-tagged dependents. Read the text below. |
102
+
103
+ ### How the command bumps dependents
104
+
105
+ The version flags above apply only to the components that changed. Auto-tag also bumps the dependents, and
106
+ it bumps them by a `patch`. The flags `--major` and `--minor` do not change that level:
107
+
108
+ ```bash
109
+ # button 1.0.0 -> 2.0.0, but its dependent lib 1.0.0 -> 1.0.1
110
+ bit ci merge --major
111
+ ```
112
+
113
+ A pre-release `--increment` is the one exception. The dependents follow `prepatch`, `prerelease`,
114
+ `preminor` and `premajor`:
115
+
116
+ ```bash
117
+ # button 1.0.0 -> 1.0.1-0, and its dependent lib 1.0.0 -> 1.0.1-0 too
118
+ bit ci merge --increment prerelease
119
+ ```
120
+
121
+ Use `--auto-tag-increment` for an explicit dependent level. The flag overrides both defaults above:
122
+
123
+ ```bash
124
+ # button 1.0.0 -> 2.0.0, and its dependent lib 1.0.0 -> 2.0.0 as well
125
+ bit ci merge --major --auto-tag-increment major
126
+ ```
127
+
128
+ The two levels are independent. The pair `--major --auto-tag-increment minor` is valid.
98
129
 
99
- ### Automatic Version Bump Detection
130
+ **Note:** auto-tag is transitive. Auto-tag includes a dependent of a dependent. `--auto-tag-increment major`
131
+ bumps the full dependents graph by a major, not only the direct dependents. The command refuses
132
+ `--auto-tag-increment` together with `--skip-auto-tag`.
100
133
 
101
- When **no explicit version flags** are provided, `bit ci merge` can automatically determine the version bump level from the commit message:
134
+ ### How the command detects the version bump
102
135
 
103
- 1. **Explicit Keywords** (highest priority):
136
+ If no explicit version flag is present, `bit ci merge` reads the version bump level from the commit message.
104
137
 
105
- - `BIT-BUMP-MAJOR` anywhere in commit message → major version bump
106
- - `BIT-BUMP-MINOR` anywhere in commit message → minor version bump
138
+ 1. **Explicit keywords** (the highest priority):
107
139
 
108
- 2. **Conventional Commits** (when enabled):
140
+ - `BIT-BUMP-MAJOR` anywhere in the commit message gives a major version bump.
141
+ - `BIT-BUMP-MINOR` anywhere in the commit message gives a minor version bump.
109
142
 
110
- - `feat!:` or `BREAKING CHANGE` → major version bump
111
- - `feat:` → minor version bump
112
- - `fix:` → patch version bump
143
+ 2. **Conventional commits** (when the config enables them):
113
144
 
114
- 3. **Default**: patch version bump
145
+ - `feat!:` or `BREAKING CHANGE` gives a major version bump.
146
+ - `feat:` gives a minor version bump.
147
+ - `fix:` gives a patch version bump.
115
148
 
116
- **Note**: Auto-detection only occurs when no version flags (`--patch`, `--minor`, `--major`, etc.) are provided. Explicit flags always take precedence.
149
+ 3. **Default**: a patch version bump.
150
+
151
+ **Note:** the command detects the level only when no version flag (`--patch`, `--minor`, `--major` or
152
+ another) is present. An explicit flag always wins. `--auto-tag-increment` is not a version flag here. That
153
+ flag changes only the dependents, so you can combine it with the detection.
117
154
 
118
155
  ### Internal flow
119
156
 
120
- 1. **Ensure main lane**
157
+ 1. **Switch to the main lane**
121
158
 
122
159
  ```bash
123
160
  bit lane switch main # preserves working tree files
124
161
  ```
125
162
 
126
- 2. **Tag, build, export**
163
+ 2. **Tag, build and export**
127
164
 
128
165
  ```bash
129
166
  bit install
@@ -131,8 +168,8 @@ When **no explicit version flags** are provided, `bit ci merge` can automaticall
131
168
  bit export
132
169
  ```
133
170
 
134
- 3. **Archive remote lane** (house-keeping).
135
- 4. **Commit lock-file updates**
171
+ 3. **Archive the remote lane.** This step is house-keeping.
172
+ 4. **Commit the lock-file updates**
136
173
 
137
174
  ```bash
138
175
  git add .bitmap pnpm-lock.yaml
@@ -174,13 +211,243 @@ bit ci merge --pre-release dev --message "feat: experimental feature"
174
211
 
175
212
  ### CI hint
176
213
 
177
- Gate this step behind a branch-protection rule so only fast-forward merges trigger a release.
214
+ Put a branch-protection rule in front of this step. Only a fast-forward merge then starts a release.
215
+
216
+ ---
217
+
218
+ ## `bit ci sync`
219
+
220
+ The command keeps a lane and its branch converged in both directions. The command opens a pull request when
221
+ the main scope moves ahead of the repository. Every pull-request operation goes through a git host provider.
222
+ GitHub is built in.
223
+
224
+ The command is a reconciler, not a pipeline. The command is stateless and idempotent. The command reads the
225
+ current state of the lane and of the branch, then picks the action. A second run on a converged pair changes
226
+ nothing. The trigger decides when the command runs. The trigger never decides what the command does.
227
+
228
+ ### First-time setup
229
+
230
+ ```bash
231
+ bit ci sync --init
232
+ ```
233
+
234
+ `--init` writes `.github/workflows/bit-sync.yml` and `bit-release.yml`, with the real default branch of this
235
+ repository in both files. `--init` adds `"teambit.git/ci": { "sync": {} }` to `workspace.jsonc` if the key is
236
+ absent. The edit keeps the comments in the file, and it changes no existing `sync` setting. `--init` then
237
+ prints the steps that need a person:
238
+
239
+ - the `BIT_CONFIG_ACCESS_TOKEN` secret
240
+ - the optional `BIT_SYNC_GH_TOKEN` token
241
+ - the bit.cloud webhook recipe
242
+ - a `fetch-depth: 0` reminder
243
+
244
+ `--init` reports an existing file as skipped, and overwrites no file, so a second run is safe. `--init`
245
+ writes the files, then exits. Do not combine `--init` with a lane argument or with another flag.
246
+
247
+ ### Usage
248
+
249
+ ```bash
250
+ bit ci sync [lane] [--branch <branch>] [--all] [--main] [--dry-run] [--init]
251
+ ```
252
+
253
+ | Flag | Description |
254
+ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
255
+ | _(no args)_ | The same as `--all`. |
256
+ | `[lane]` | One lane. Give the lane name, which the command resolves against `defaultScope`, or a scope-qualified id such as `other-org.other-scope/my-lane`. The `lanes` patterns still filter the lane, and those patterns match the lane **name**. |
257
+ | `--branch` | The command resolves the lane from a branch name through the mapping config. Use the flag for a push-triggered run. The flag carries a branch name only, so the command assumes `defaultScope`. |
258
+ | `--all` | Every mapped lane, plus the main scope. The run includes a lane that exists only as a branch. The command therefore retires the branch and the pull request of a lane that bit.cloud deleted. |
259
+ | `--main` | Only the main scope, against the default branch. |
260
+ | `--dry-run` | The command reports the action for each target. The command pushes nothing, and the command creates, closes, labels and comments no pull request. The run is not read-only on disk: the command writes the working tree, `.bitmap` and the local scope, then restores them. The command therefore refuses a dirty working tree. The command exits non-zero if the plan needs a person. |
261
+ | `--init` | First-time setup, above. Do not combine `--init` with another flag. |
262
+
263
+ ### Triggers
264
+
265
+ Every trigger works, because the command is a reconciler. The scaffolded workflow wires the three triggers
266
+ that matter:
267
+
268
+ - a bit.cloud webhook, for a lane that moved
269
+ - a `push`, for a branch that moved
270
+ - a cron schedule, as a safety net
271
+
272
+ ```yaml
273
+ name: bit-sync
274
+ on:
275
+ repository_dispatch: { types: [bit-lane-updated] }
276
+ push: { branches-ignore: ['bit-sync/**'] }
277
+ schedule: [{ cron: '0 * * * *' }]
278
+ permissions: { contents: write, pull-requests: write }
279
+ jobs:
280
+ sync:
281
+ runs-on: ubuntu-latest
282
+ steps:
283
+ - uses: actions/checkout@v4
284
+ with: { fetch-depth: 0 } # full history is required
285
+ - run: npx @teambit/bvm install && bit ci sync
286
+ env:
287
+ BIT_CONFIG_ACCESS_TOKEN: ${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}
288
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
289
+ ```
290
+
291
+ The clone needs the full history, so set `fetch-depth: 0`. The state of a branch is the `.bitmap` at the
292
+ newest commit that touched `.bitmap` on the first-parent line of that branch. A shallow clone does not hold
293
+ that commit. A narrow refspec is acceptable, and a cold local scope is acceptable.
294
+
295
+ ### Per-lane reconciliation
296
+
297
+ For each mapped lane, the command compares the remote head of the lane with the state that the committed
298
+ `.bitmap` of the branch records. The command then picks one action:
299
+
300
+ | Situation | Action | Effect |
301
+ | ----------------------------------------------------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
302
+ | the lane moved, the branch did not | `import-lane` | The command puts the lane on the branch, pushes, and opens the pull request if it is absent. |
303
+ | the branch got dev commits, the lane did not move | `export-branch` | The command snaps and exports the tree of the branch onto the lane. |
304
+ | both moved | `merge-diverged` | The command merges the lane into the tree of the branch, then snaps and exports. |
305
+ | the lane exists, the branch has dev commits, but the branch never recorded a lane pointer | `adopt-branch` | First contact. Read [Adopting a branch on first contact](#adopting-a-branch-on-first-contact). |
306
+ | bit.cloud removed the lane, and the branch is ours | `close-pr` | The command closes the pull request. The command deletes the branch, unless the branch holds unmerged commits. |
307
+ | no lane, and the branch is not ours | `noop` | Nothing. Read [when the command deletes a branch](#when-the-command-deletes-a-branch). |
308
+ | nothing moved, or the pull request has the `bit-sync-conflict` label | `noop` | Nothing. |
309
+
310
+ An `--all` run visits two sets of targets: the lanes that match the `lanes` patterns, and the lane-mapped
311
+ branches on `origin`. The second set makes the cleanup possible. A lane that bit.cloud deleted is absent from
312
+ the first set, so a run that reads lanes only would leave an orphan branch and an open pull request.
313
+
314
+ ### Halts and conflicts
315
+
316
+ The command halts a lane that it cannot reconcile without a person. The command puts the
317
+ `bit-sync-conflict` label on the pull request of that lane, and adds a comment with the recovery steps. The
318
+ command still syncs the other lanes, and the command exits non-zero. A halt covers one lane only: an
319
+ unexpected failure never stops the lanes after it. A halt also suppresses itself. While the label is on the
320
+ pull request, the command does nothing for that lane. Remove the label to sync the lane again.
321
+
322
+ `onConflict` decides what the command does with one contested line during a `merge-diverged` action. Read
323
+ [the three sync keys](#the-three-sync-keys-control-different-things) for the values. The command resolves at
324
+ component granularity: every file of a conflicted component takes the winning side. The summary names what
325
+ the command rewrote.
326
+
327
+ ### Adopting a branch on first contact
328
+
329
+ A lane can exist on bit.cloud before its branch ever records a pointer to it — for example, a pull request
330
+ that `bit ci pr --keep-lane` turned into a lane, on a branch a developer pushed with plain git. The branch
331
+ has dev commits, and the lane exists, but the committed `.bitmap` of the branch holds no state for it: a
332
+ first-contact pair, not a conflict. `adopt-branch` handles it, PROVIDED the branch would not change the lane.
333
+ The command switches onto the lane, keeping the files of the branch, and asks `bit status` whether anything
334
+ is new or modified relative to the lane — a read, never a snap. Two outcomes:
335
+
336
+ - **Nothing changed.** The content of the branch already matches the lane's — the common shape, since
337
+ `bit ci pr --keep-lane` exported that very content already. The command records the lane pointer on the
338
+ branch (the same commit every other action pushes) and moves on. The next run reads a converged pair.
339
+ - **Something changed.** The two sides genuinely disagree, with no known common history to merge from.
340
+ The command halts, the same way it halted before this action existed: it cannot tell which side is
341
+ newer. Nothing is snapped or exported; the lane is untouched, and the workspace is left clean.
342
+
343
+ Adoption never touches a branch whose `.bitmap` asserts a DIFFERENT lane's claim of its own.
344
+ A different-lane pointer the branch merely inherited — its `.bitmap` is unchanged since the branch forked
345
+ from the default branch, the ordinary shape of a branch cut after some other lane's sync pull request
346
+ landed — is history, not a claim, and does not block adoption.
347
+
348
+ A pointer Bit marked **not exported**, same as for [deletion attribution](#when-the-command-deletes-a-branch),
349
+ does not count as state either: it is intentional, not a gap. Nothing was ever proven about that lane, so
350
+ there is nothing to protect, and the branch is a first-contact candidate exactly as if no pointer existed.
351
+
352
+ ### When the command deletes a branch
353
+
354
+ With the default empty `branchPrefix`, every branch maps to a lane of the same name. The command therefore
355
+ enumerates a developer branch too. Such a branch reaches the reconciler in the same shape as a lane branch
356
+ whose lane is gone, and that action deletes the branch. Three tests gate the deletion, and the command
357
+ judges all three from the git history alone:
358
+
359
+ 1. **Attribution** — the committed `.bitmap` of the branch must hold the scope-qualified pointer of Bit to
360
+ _this_ lane. The pointer is structural, so it survives a squash-merge message rewrite. A pointer that Bit
361
+ marked **not exported** does not count, because that lane was never on a remote.
362
+ 2. **Reachability** — either the state commit is not in the default branch yet _and_ nothing sits on top of
363
+ it, or the branch **tip** is already in the default branch. In the second case the deletion loses nothing.
364
+ 3. **Authorship** — for a live branch, the tip must carry the `[bit-sync]` marker on its own line. A
365
+ developer commits `.bitmap` too, so this test is necessary and never sufficient. The test can withhold a
366
+ deletion, and it can never authorize one. A tip from [adopting a branch on first
367
+ contact](#adopting-a-branch-on-first-contact) carries the marker too, but never authorizes a deletion
368
+ either, while the state commit is not yet reachable from the default branch: adoption proved the content
369
+ of the branch matched the lane's, never that the pre-existing history of the branch is disposable. Once
370
+ the branch is genuinely merged, reachability alone is enough, exactly as for any other branch.
371
+
372
+ If the attribution test fails, the action is a plain `noop` and the command writes nothing. The command
373
+ reports a **kept** branch on every later run, until a person deletes the branch, or until its commits reach
374
+ the default branch. The report is idempotent, because the command closed the pull request on the first run.
375
+ Set a `branchPrefix`, or an explicit `lanes` list, to leave developer branches out.
376
+
377
+ ### Cross-scope lanes
378
+
379
+ The hosting scope of a lane holds the lane object. The scopes of the components of the lane show which
380
+ repositories the change touches. The two are different. This version supports one shape only: the content of
381
+ the lane must live in one scope, the `defaultScope` of this workspace. The hosting scope can be another
382
+ scope, and a scope-qualified id addresses such a lane.
383
+
384
+ ```bash
385
+ bit ci sync my-lane # hosted on this workspace's defaultScope
386
+ bit ci sync other-org.other-scope/my-lane # hosted elsewhere, content still in this repo's scope
387
+ ```
388
+
389
+ The branch mapping always uses the lane **name**, so a lane that another scope hosts maps to the same branch
390
+ as before. Every request to Bit uses the full `hostScope/name` id.
391
+
392
+ **The command never mirrors a lane that has components outside `defaultScope`.** Such a mirror writes the
393
+ components of another repository into this repository, and exports them from here. A lane like this is still
394
+ legitimate, so only the report depends on how the command reached the lane:
395
+
396
+ | How the command reached the lane | Outcome | Exit | Pull request touched |
397
+ | -------------------------------------------------------------------- | --------- | ---- | ---------------------------- |
398
+ | **Enumerated** — an `--all` run, or a push or webhook `--branch` run | `skipped` | 0 | no |
399
+ | **Named** — `bit ci sync my-lane` | refusal | ≠ 0 | no |
400
+ | **The lane became cross-scope during a live mirror** | `HALTED` | ≠ 0 | yes — labelled and commented |
401
+
402
+ The skip keeps the exit code at 0 on purpose: a permanent cross-scope lane must not fail every scheduled run.
403
+ A named lane exits non-zero, so the user learns why nothing happened. That exit is a plain refusal, because
404
+ the command writes nothing and labels no pull request. The command refuses two lanes that map to one branch
405
+ in the same way, and neither lane takes the branch. The command never lane-maps the default branch or
406
+ `mainSyncBranch`. No config key changes these rules.
407
+
408
+ ### Main-scope reconciliation
409
+
410
+ A `--main` run, and the last step of an `--all` run, reconciles the `main` lane of the scope with the
411
+ repository:
412
+
413
+ 1. The command runs `git checkout -B <mainSyncBranch>` from the existing sync branch, or from the default
414
+ branch. If a sync branch exists, the command merges the default branch into it, so the pull request stays
415
+ mergeable.
416
+ 2. The command runs `bit checkout head`, and includes the components that the scope holds but this workspace
417
+ does not. The command resolves a conflict **in favour of the scope**, with `--auto-merge-resolve theirs`.
418
+ 3. An empty `git status` **is** convergence. In every other case the command commits the drift with a
419
+ `[bit-sync]` marker, pushes the commit to `<mainSyncBranch>`, and proposes a pull request against the
420
+ default branch. The command never force-pushes.
421
+
422
+ The one-sided resolution is the point. The pull request shows the repository at the latest exported versions
423
+ of the scope, so the command **reverts** component source that nobody exported. The revert is visible in the
424
+ pull-request diff, and a person rejects it: close the pull request. With `mainSync: "direct-push"` the
425
+ command commits the same drift on the default branch, and uses no sync branch and no pull request. The push
426
+ is a plain push, so the run stops if the default branch moved during the run.
427
+
428
+ ### Git host providers and credentials
429
+
430
+ The command uses plain git for every git operation. The command uses a `GitHostProvider` for every
431
+ pull-request operation. GitHub is built in, and `ci.registerGitHostProvider(...)` registers it — the same
432
+ public slot that another provider uses. The command selects one provider per run at most, from the `origin`
433
+ remote:
434
+
435
+ - If a provider claims the remote, the command selects that provider exclusively. If no claimant holds
436
+ credentials, the command runs without pull-request operations, and acts on no other host.
437
+ - If no provider claims the remote, and the config holds one provider, the command selects that provider.
438
+
439
+ If the command selects no provider, the command reports the reason. The command still does every git
440
+ operation and every Bit operation, and skips only the pull-request operations.
441
+
442
+ For GitHub, the command reads **`BIT_GITHUB_TOKEN` before `GITHUB_TOKEN`**. GitHub Actions sets
443
+ `GITHUB_TOKEN` on every job, so an override needs the higher priority. The command reads the repository from
444
+ `GITHUB_REPOSITORY`. If that variable is absent, the command reads the `origin` remote.
178
445
 
179
446
  ---
180
447
 
181
448
  ## Configuration
182
449
 
183
- The CI aspect supports configuration in `workspace.jsonc`:
450
+ Configure the CI aspect in `workspace.jsonc`:
184
451
 
185
452
  ```json
186
453
  {
@@ -194,12 +461,12 @@ The CI aspect supports configuration in `workspace.jsonc`:
194
461
 
195
462
  ### `commitMessageScript`
196
463
 
197
- **Optional.** Path to a script that generates custom commit messages for the `bit ci merge` command.
464
+ **Optional.** The path to a script. The script writes the commit message for the `bit ci merge` command.
198
465
 
199
- - **Default**: Uses `"chore: update .bitmap and lockfiles as needed [skip ci]"`
200
- - **Usage**: The script should output the desired commit message to stdout
201
- - **Security**: Commands are parsed to avoid shell injection - no chaining allowed
202
- - **Working Directory**: Script runs in the workspace root directory
466
+ - **Default**: the command uses `"chore: update .bitmap and lockfiles as needed [skip ci]"`.
467
+ - **Usage**: the script writes the commit message to stdout.
468
+ - **Security**: the command parses the script command and permits no chaining. This blocks shell injection.
469
+ - **Working directory**: the script runs in the workspace root directory.
203
470
 
204
471
  **Example script:**
205
472
 
@@ -217,13 +484,14 @@ try {
217
484
 
218
485
  ### `useConventionalCommitsForVersionBump`
219
486
 
220
- **Optional.** Enable automatic version bump detection based on conventional commit patterns.
487
+ **Optional.** Set the key to `true`. The command then reads the version bump level from a conventional commit
488
+ message.
221
489
 
222
- - **Default**: `false` (disabled)
223
- - **When enabled**: Analyzes commit messages for conventional commit patterns:
224
- - `feat!:` or `BREAKING CHANGE` → major version bump
225
- - `feat:` → minor version bump
226
- - `fix:` → patch version bump
490
+ - **Default**: `false`.
491
+ - **With the key set to `true`**, the command reads these patterns:
492
+ - `feat!:` or `BREAKING CHANGE` gives a major version bump.
493
+ - `feat:` gives a minor version bump.
494
+ - `fix:` gives a patch version bump.
227
495
 
228
496
  ```json
229
497
  {
@@ -235,12 +503,13 @@ try {
235
503
 
236
504
  ### `useExplicitBumpKeywords`
237
505
 
238
- **Optional.** Enable automatic version bump detection using explicit keywords.
506
+ **Optional.** The command reads the version bump level from an explicit keyword. Set the key to `false` to
507
+ stop this behaviour.
239
508
 
240
- - **Default**: `true` (enabled)
509
+ - **Default**: `true`.
241
510
  - **Keywords**:
242
- - `BIT-BUMP-MAJOR` anywhere in commit message → major version bump
243
- - `BIT-BUMP-MINOR` anywhere in commit message → minor version bump
511
+ - `BIT-BUMP-MAJOR` anywhere in the commit message gives a major version bump.
512
+ - `BIT-BUMP-MINOR` anywhere in the commit message gives a minor version bump.
244
513
 
245
514
  ```json
246
515
  {
@@ -256,3 +525,58 @@ try {
256
525
  git commit -m "feat: add new feature BIT-BUMP-MINOR"
257
526
  bit ci merge --build # → automatically uses minor version bump
258
527
  ```
528
+
529
+ ### `sync`
530
+
531
+ **Optional.** The lane-to-branch mapping and the main-scope settings for [`bit ci sync`](#bit-ci-sync).
532
+
533
+ ```json
534
+ {
535
+ "teambit.git/ci": {
536
+ "sync": { "branchPrefix": "lane/", "lanes": ["*"], "onConflict": "halt" }
537
+ }
538
+ }
539
+ ```
540
+
541
+ | Field | Default | Description |
542
+ | --------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------- |
543
+ | `branchPrefix` | `""` | The prefix for a lane-mapped branch. The value `"lane/"` maps lane `my-lane` to branch `lane/my-lane`. |
544
+ | `branches` | `{}` | Explicit overrides that map a lane name to a branch name. An override wins over `branchPrefix`. |
545
+ | `lanes` | `["*"]` | The glob patterns of the lane names to sync. The command supports the `*` wildcard only. |
546
+ | `mainSyncBranch` | `"bit-sync/main"` | The branch that carries the main-scope drift. The command ignores the field with `mainSync: "direct-push"`. |
547
+ | `mainSync` | `"pr"` | How main-scope drift reaches the default branch. Read the tables below. |
548
+ | `onConflict` | `"halt"` | What the command does with one contested line. Read the tables below. |
549
+ | `autoMergeMainSyncPr` | `false` | **Reserved.** The command warns and enables no auto-merge on the sync pull request. Use a repository rule. |
550
+
551
+ The command validates every branch name at startup, and the error names the config field. The command never
552
+ treats the default branch or `mainSyncBranch` as lane-mapped, even with an empty `branchPrefix`.
553
+
554
+ #### The three sync keys control different things
555
+
556
+ | Key | The decision the key makes |
557
+ | ------------ | ---------------------------------------------------- |
558
+ | `onConflict` | What the command does with **one contested line**. |
559
+ | `mainSync` | **How** main-scope drift reaches the default branch. |
560
+ | `lanes` | **Which** lanes get a branch. |
561
+
562
+ No key changes which side wins a review. People merge pull requests.
563
+
564
+ `onConflict` applies to one contested line during a merge of a diverged pair.
565
+
566
+ | Value | What the command does |
567
+ | ---------------- | ---------------------------------------------------------------------------------------------- |
568
+ | `halt` (default) | The command stops. The command labels the pull request. The command writes the recovery steps. |
569
+ | `git-wins` | The command keeps the branch version of a contested line. |
570
+ | `lane-wins` | The command takes the lane version of a contested line. |
571
+
572
+ Non-conflicting changes always merge, with every value of `onConflict`.
573
+
574
+ `mainSync` decides how main-scope drift reaches the default branch.
575
+
576
+ | Value | What the command does |
577
+ | -------------- | ------------------------------------------------------------------------------------ |
578
+ | `pr` (default) | The command commits the drift to `mainSyncBranch`. The command opens a pull request. |
579
+ | `direct-push` | The command commits the drift on the default branch. The command pushes the commit. |
580
+
581
+ `lanes` decides which lanes get a branch. If the `lanes` list is empty, the command stops lane mirroring and
582
+ reconciles the main scope only.