@teambit/ci 1.0.485 → 1.0.486

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 (97) hide show
  1. package/ci.docs.mdx +344 -83
  2. package/commands/sync.cmd.ts +77 -0
  3. package/dist/ci.docs.mdx +344 -83
  4. package/dist/ci.main.runtime.d.ts +67 -6
  5. package/dist/ci.main.runtime.js +152 -25
  6. package/dist/ci.main.runtime.js.map +1 -1
  7. package/dist/commands/sync.cmd.d.ts +34 -0
  8. package/dist/commands/sync.cmd.js +57 -0
  9. package/dist/commands/sync.cmd.js.map +1 -0
  10. package/dist/git.d.ts +11 -1
  11. package/dist/git.js +11 -1
  12. package/dist/git.js.map +1 -1
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +26 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/{preview-1785858957533.js → preview-1785864931304.js} +1 -1
  17. package/dist/sync/git-host-provider.d.ts +47 -0
  18. package/dist/sync/git-host-provider.js +54 -0
  19. package/dist/sync/git-host-provider.js.map +1 -0
  20. package/dist/sync/git-host-provider.spec.d.ts +1 -0
  21. package/dist/sync/git-host-provider.spec.js +171 -0
  22. package/dist/sync/git-host-provider.spec.js.map +1 -0
  23. package/dist/sync/git-ops.d.ts +171 -0
  24. package/dist/sync/git-ops.js +354 -0
  25. package/dist/sync/git-ops.js.map +1 -0
  26. package/dist/sync/git-ops.spec.d.ts +1 -0
  27. package/dist/sync/git-ops.spec.js +476 -0
  28. package/dist/sync/git-ops.spec.js.map +1 -0
  29. package/dist/sync/github-client.d.ts +79 -0
  30. package/dist/sync/github-client.js +198 -0
  31. package/dist/sync/github-client.js.map +1 -0
  32. package/dist/sync/github-client.spec.d.ts +1 -0
  33. package/dist/sync/github-client.spec.js +205 -0
  34. package/dist/sync/github-client.spec.js.map +1 -0
  35. package/dist/sync/init-scaffold.d.ts +40 -0
  36. package/dist/sync/init-scaffold.js +326 -0
  37. package/dist/sync/init-scaffold.js.map +1 -0
  38. package/dist/sync/init-scaffold.spec.d.ts +1 -0
  39. package/dist/sync/init-scaffold.spec.js +169 -0
  40. package/dist/sync/init-scaffold.spec.js.map +1 -0
  41. package/dist/sync/lane-sync-executor.d.ts +256 -0
  42. package/dist/sync/lane-sync-executor.js +1249 -0
  43. package/dist/sync/lane-sync-executor.js.map +1 -0
  44. package/dist/sync/lane-sync-executor.spec.d.ts +1 -0
  45. package/dist/sync/lane-sync-executor.spec.js +416 -0
  46. package/dist/sync/lane-sync-executor.spec.js.map +1 -0
  47. package/dist/sync/main-sync-executor.d.ts +62 -0
  48. package/dist/sync/main-sync-executor.js +305 -0
  49. package/dist/sync/main-sync-executor.js.map +1 -0
  50. package/dist/sync/sync-config.d.ts +83 -0
  51. package/dist/sync/sync-config.js +187 -0
  52. package/dist/sync/sync-config.js.map +1 -0
  53. package/dist/sync/sync-config.spec.d.ts +1 -0
  54. package/dist/sync/sync-config.spec.js +254 -0
  55. package/dist/sync/sync-config.spec.js.map +1 -0
  56. package/dist/sync/sync-orchestrator.d.ts +76 -0
  57. package/dist/sync/sync-orchestrator.js +396 -0
  58. package/dist/sync/sync-orchestrator.js.map +1 -0
  59. package/dist/sync/sync-orchestrator.spec.d.ts +1 -0
  60. package/dist/sync/sync-orchestrator.spec.js +155 -0
  61. package/dist/sync/sync-orchestrator.spec.js.map +1 -0
  62. package/dist/sync/sync-planner.d.ts +60 -0
  63. package/dist/sync/sync-planner.js +114 -0
  64. package/dist/sync/sync-planner.js.map +1 -0
  65. package/dist/sync/sync-planner.spec.d.ts +1 -0
  66. package/dist/sync/sync-planner.spec.js +210 -0
  67. package/dist/sync/sync-planner.spec.js.map +1 -0
  68. package/dist/sync/sync-state.d.ts +94 -0
  69. package/dist/sync/sync-state.js +178 -0
  70. package/dist/sync/sync-state.js.map +1 -0
  71. package/dist/sync/sync-state.spec.d.ts +1 -0
  72. package/dist/sync/sync-state.spec.js +271 -0
  73. package/dist/sync/sync-state.spec.js.map +1 -0
  74. package/dist/sync/workspace-lane.d.ts +13 -0
  75. package/dist/sync/workspace-lane.js +27 -0
  76. package/dist/sync/workspace-lane.js.map +1 -0
  77. package/package.json +17 -12
  78. package/sync/git-host-provider.spec.ts +197 -0
  79. package/sync/git-host-provider.ts +89 -0
  80. package/sync/git-ops.spec.ts +506 -0
  81. package/sync/git-ops.ts +334 -0
  82. package/sync/github-client.spec.ts +174 -0
  83. package/sync/github-client.ts +209 -0
  84. package/sync/init-scaffold.spec.ts +142 -0
  85. package/sync/init-scaffold.ts +340 -0
  86. package/sync/lane-sync-executor.spec.ts +389 -0
  87. package/sync/lane-sync-executor.ts +1363 -0
  88. package/sync/main-sync-executor.ts +321 -0
  89. package/sync/sync-config.spec.ts +283 -0
  90. package/sync/sync-config.ts +214 -0
  91. package/sync/sync-orchestrator.spec.ts +120 -0
  92. package/sync/sync-orchestrator.ts +386 -0
  93. package/sync/sync-planner.spec.ts +126 -0
  94. package/sync/sync-planner.ts +99 -0
  95. package/sync/sync-state.spec.ts +263 -0
  96. package/sync/sync-state.ts +176 -0
  97. package/sync/workspace-lane.ts +20 -0
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,92 +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). |
98
- | `--auto-tag-increment` | | Version bump level for auto-tagged dependents. See below. |
99
-
100
- ### Bumping Dependents
101
-
102
- The version flags above apply only to the components that actually changed. Dependents that are
103
- picked up by auto-tag are bumped by a `patch`, regardless of `--major`/`--minor`:
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:
104
107
 
105
108
  ```bash
106
109
  # button 1.0.0 -> 2.0.0, but its dependent lib 1.0.0 -> 1.0.1
107
110
  bit ci merge --major
108
111
  ```
109
112
 
110
- The one exception is a pre-release `--increment` (`prepatch`, `prerelease`, `preminor`,
111
- `premajor`), which the dependents do follow:
113
+ A pre-release `--increment` is the one exception. The dependents follow `prepatch`, `prerelease`,
114
+ `preminor` and `premajor`:
112
115
 
113
116
  ```bash
114
117
  # button 1.0.0 -> 1.0.1-0, and its dependent lib 1.0.0 -> 1.0.1-0 too
115
118
  bit ci merge --increment prerelease
116
119
  ```
117
120
 
118
- Use `--auto-tag-increment` to bump the dependents by an explicit level instead. It overrides both
119
- defaults above:
121
+ Use `--auto-tag-increment` for an explicit dependent level. The flag overrides both defaults above:
120
122
 
121
123
  ```bash
122
124
  # button 1.0.0 -> 2.0.0, and its dependent lib 1.0.0 -> 2.0.0 as well
123
125
  bit ci merge --major --auto-tag-increment major
124
126
  ```
125
127
 
126
- The two levels are independent, so `--major --auto-tag-increment minor` is also valid.
128
+ The two levels are independent. The pair `--major --auto-tag-increment minor` is valid.
127
129
 
128
- **Note**: auto-tag is transitive — a dependent of a dependent is auto-tagged too. So
129
- `--auto-tag-increment major` bumps the _entire_ dependents graph by a major, not just the direct
130
- dependents. It cannot be combined with `--skip-auto-tag`.
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`.
131
133
 
132
- ### Automatic Version Bump Detection
134
+ ### How the command detects the version bump
133
135
 
134
- When **no explicit version flags** are provided, `bit ci merge` can automatically determine the version bump level from the commit message:
136
+ If no explicit version flag is present, `bit ci merge` reads the version bump level from the commit message.
135
137
 
136
- 1. **Explicit Keywords** (highest priority):
138
+ 1. **Explicit keywords** (the highest priority):
137
139
 
138
- - `BIT-BUMP-MAJOR` anywhere in commit message → major version bump
139
- - `BIT-BUMP-MINOR` anywhere in commit message → minor version bump
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.
140
142
 
141
- 2. **Conventional Commits** (when enabled):
143
+ 2. **Conventional commits** (when the config enables them):
142
144
 
143
- - `feat!:` or `BREAKING CHANGE` → major version bump
144
- - `feat:` → minor version bump
145
- - `fix:` → 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.
146
148
 
147
- 3. **Default**: patch version bump
149
+ 3. **Default**: a patch version bump.
148
150
 
149
- **Note**: Auto-detection only occurs when no version flags (`--patch`, `--minor`, `--major`, etc.) are provided. Explicit flags always take precedence. `--auto-tag-increment` is not considered a version flag for this purpose — it only affects dependents, so it can be combined with auto-detection.
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.
150
154
 
151
155
  ### Internal flow
152
156
 
153
- 1. **Ensure main lane**
157
+ 1. **Switch to the main lane**
154
158
 
155
159
  ```bash
156
160
  bit lane switch main # preserves working tree files
157
161
  ```
158
162
 
159
- 2. **Tag, build, export**
163
+ 2. **Tag, build and export**
160
164
 
161
165
  ```bash
162
166
  bit install
@@ -164,8 +168,8 @@ When **no explicit version flags** are provided, `bit ci merge` can automaticall
164
168
  bit export
165
169
  ```
166
170
 
167
- 3. **Archive remote lane** (house-keeping).
168
- 4. **Commit lock-file updates**
171
+ 3. **Archive the remote lane.** This step is house-keeping.
172
+ 4. **Commit the lock-file updates**
169
173
 
170
174
  ```bash
171
175
  git add .bitmap pnpm-lock.yaml
@@ -207,13 +211,213 @@ bit ci merge --pre-release dev --message "feat: experimental feature"
207
211
 
208
212
  ### CI hint
209
213
 
210
- 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
+ | 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. |
306
+ | no lane, and the branch is not ours | `noop` | Nothing. Read [when the command deletes a branch](#when-the-command-deletes-a-branch). |
307
+ | nothing moved, or the pull request has the `bit-sync-conflict` label | `noop` | Nothing. |
308
+
309
+ An `--all` run visits two sets of targets: the lanes that match the `lanes` patterns, and the lane-mapped
310
+ branches on `origin`. The second set makes the cleanup possible. A lane that bit.cloud deleted is absent from
311
+ the first set, so a run that reads lanes only would leave an orphan branch and an open pull request.
312
+
313
+ ### Halts and conflicts
314
+
315
+ The command halts a lane that it cannot reconcile without a person. The command puts the
316
+ `bit-sync-conflict` label on the pull request of that lane, and adds a comment with the recovery steps. The
317
+ command still syncs the other lanes, and the command exits non-zero. A halt covers one lane only: an
318
+ unexpected failure never stops the lanes after it. A halt also suppresses itself. While the label is on the
319
+ pull request, the command does nothing for that lane. Remove the label to sync the lane again.
320
+
321
+ `onConflict` decides what the command does with one contested line during a `merge-diverged` action. Read
322
+ [the three sync keys](#the-three-sync-keys-control-different-things) for the values. The command resolves at
323
+ component granularity: every file of a conflicted component takes the winning side. The summary names what
324
+ the command rewrote.
325
+
326
+ ### When the command deletes a branch
327
+
328
+ With the default empty `branchPrefix`, every branch maps to a lane of the same name. The command therefore
329
+ enumerates a developer branch too. Such a branch reaches the reconciler in the same shape as a lane branch
330
+ whose lane is gone, and that action deletes the branch. Three tests gate the deletion, and the command
331
+ judges all three from the git history alone:
332
+
333
+ 1. **Attribution** — the committed `.bitmap` of the branch must hold the scope-qualified pointer of Bit to
334
+ _this_ lane. The pointer is structural, so it survives a squash-merge message rewrite. A pointer that Bit
335
+ marked **not exported** does not count, because that lane was never on a remote.
336
+ 2. **Reachability** — either the state commit is not in the default branch yet _and_ nothing sits on top of
337
+ it, or the branch **tip** is already in the default branch. In the second case the deletion loses nothing.
338
+ 3. **Authorship** — for a live branch, the tip must carry the `[bit-sync]` marker on its own line. A
339
+ developer commits `.bitmap` too, so this test is necessary and never sufficient. The test can withhold a
340
+ deletion, and it can never authorize one.
341
+
342
+ If the attribution test fails, the action is a plain `noop` and the command writes nothing. The command
343
+ reports a **kept** branch on every later run, until a person deletes the branch, or until its commits reach
344
+ the default branch. The report is idempotent, because the command closed the pull request on the first run.
345
+ Set a `branchPrefix`, or an explicit `lanes` list, to leave developer branches out.
346
+
347
+ ### Cross-scope lanes
348
+
349
+ The hosting scope of a lane holds the lane object. The scopes of the components of the lane show which
350
+ repositories the change touches. The two are different. This version supports one shape only: the content of
351
+ the lane must live in one scope, the `defaultScope` of this workspace. The hosting scope can be another
352
+ scope, and a scope-qualified id addresses such a lane.
353
+
354
+ ```bash
355
+ bit ci sync my-lane # hosted on this workspace's defaultScope
356
+ bit ci sync other-org.other-scope/my-lane # hosted elsewhere, content still in this repo's scope
357
+ ```
358
+
359
+ The branch mapping always uses the lane **name**, so a lane that another scope hosts maps to the same branch
360
+ as before. Every request to Bit uses the full `hostScope/name` id.
361
+
362
+ **The command never mirrors a lane that has components outside `defaultScope`.** Such a mirror writes the
363
+ components of another repository into this repository, and exports them from here. A lane like this is still
364
+ legitimate, so only the report depends on how the command reached the lane:
365
+
366
+ | How the command reached the lane | Outcome | Exit | Pull request touched |
367
+ | -------------------------------------------------------------------- | --------- | ---- | ---------------------------- |
368
+ | **Enumerated** — an `--all` run, or a push or webhook `--branch` run | `skipped` | 0 | no |
369
+ | **Named** — `bit ci sync my-lane` | refusal | ≠ 0 | no |
370
+ | **The lane became cross-scope during a live mirror** | `HALTED` | ≠ 0 | yes — labelled and commented |
371
+
372
+ The skip keeps the exit code at 0 on purpose: a permanent cross-scope lane must not fail every scheduled run.
373
+ A named lane exits non-zero, so the user learns why nothing happened. That exit is a plain refusal, because
374
+ the command writes nothing and labels no pull request. The command refuses two lanes that map to one branch
375
+ in the same way, and neither lane takes the branch. The command never lane-maps the default branch or
376
+ `mainSyncBranch`. No config key changes these rules.
377
+
378
+ ### Main-scope reconciliation
379
+
380
+ A `--main` run, and the last step of an `--all` run, reconciles the `main` lane of the scope with the
381
+ repository:
382
+
383
+ 1. The command runs `git checkout -B <mainSyncBranch>` from the existing sync branch, or from the default
384
+ branch. If a sync branch exists, the command merges the default branch into it, so the pull request stays
385
+ mergeable.
386
+ 2. The command runs `bit checkout head`, and includes the components that the scope holds but this workspace
387
+ does not. The command resolves a conflict **in favour of the scope**, with `--auto-merge-resolve theirs`.
388
+ 3. An empty `git status` **is** convergence. In every other case the command commits the drift with a
389
+ `[bit-sync]` marker, pushes the commit to `<mainSyncBranch>`, and proposes a pull request against the
390
+ default branch. The command never force-pushes.
391
+
392
+ The one-sided resolution is the point. The pull request shows the repository at the latest exported versions
393
+ of the scope, so the command **reverts** component source that nobody exported. The revert is visible in the
394
+ pull-request diff, and a person rejects it: close the pull request. With `mainSync: "direct-push"` the
395
+ command commits the same drift on the default branch, and uses no sync branch and no pull request. The push
396
+ is a plain push, so the run stops if the default branch moved during the run.
397
+
398
+ ### Git host providers and credentials
399
+
400
+ The command uses plain git for every git operation. The command uses a `GitHostProvider` for every
401
+ pull-request operation. GitHub is built in, and `ci.registerGitHostProvider(...)` registers it — the same
402
+ public slot that another provider uses. The command selects one provider per run at most, from the `origin`
403
+ remote:
404
+
405
+ - If a provider claims the remote, the command selects that provider exclusively. If no claimant holds
406
+ credentials, the command runs without pull-request operations, and acts on no other host.
407
+ - If no provider claims the remote, and the config holds one provider, the command selects that provider.
408
+
409
+ If the command selects no provider, the command reports the reason. The command still does every git
410
+ operation and every Bit operation, and skips only the pull-request operations.
411
+
412
+ For GitHub, the command reads **`BIT_GITHUB_TOKEN` before `GITHUB_TOKEN`**. GitHub Actions sets
413
+ `GITHUB_TOKEN` on every job, so an override needs the higher priority. The command reads the repository from
414
+ `GITHUB_REPOSITORY`. If that variable is absent, the command reads the `origin` remote.
211
415
 
212
416
  ---
213
417
 
214
418
  ## Configuration
215
419
 
216
- The CI aspect supports configuration in `workspace.jsonc`:
420
+ Configure the CI aspect in `workspace.jsonc`:
217
421
 
218
422
  ```json
219
423
  {
@@ -227,12 +431,12 @@ The CI aspect supports configuration in `workspace.jsonc`:
227
431
 
228
432
  ### `commitMessageScript`
229
433
 
230
- **Optional.** Path to a script that generates custom commit messages for the `bit ci merge` command.
434
+ **Optional.** The path to a script. The script writes the commit message for the `bit ci merge` command.
231
435
 
232
- - **Default**: Uses `"chore: update .bitmap and lockfiles as needed [skip ci]"`
233
- - **Usage**: The script should output the desired commit message to stdout
234
- - **Security**: Commands are parsed to avoid shell injection - no chaining allowed
235
- - **Working Directory**: Script runs in the workspace root directory
436
+ - **Default**: the command uses `"chore: update .bitmap and lockfiles as needed [skip ci]"`.
437
+ - **Usage**: the script writes the commit message to stdout.
438
+ - **Security**: the command parses the script command and permits no chaining. This blocks shell injection.
439
+ - **Working directory**: the script runs in the workspace root directory.
236
440
 
237
441
  **Example script:**
238
442
 
@@ -250,13 +454,14 @@ try {
250
454
 
251
455
  ### `useConventionalCommitsForVersionBump`
252
456
 
253
- **Optional.** Enable automatic version bump detection based on conventional commit patterns.
457
+ **Optional.** Set the key to `true`. The command then reads the version bump level from a conventional commit
458
+ message.
254
459
 
255
- - **Default**: `false` (disabled)
256
- - **When enabled**: Analyzes commit messages for conventional commit patterns:
257
- - `feat!:` or `BREAKING CHANGE` → major version bump
258
- - `feat:` → minor version bump
259
- - `fix:` → patch version bump
460
+ - **Default**: `false`.
461
+ - **With the key set to `true`**, the command reads these patterns:
462
+ - `feat!:` or `BREAKING CHANGE` gives a major version bump.
463
+ - `feat:` gives a minor version bump.
464
+ - `fix:` gives a patch version bump.
260
465
 
261
466
  ```json
262
467
  {
@@ -268,12 +473,13 @@ try {
268
473
 
269
474
  ### `useExplicitBumpKeywords`
270
475
 
271
- **Optional.** Enable automatic version bump detection using explicit keywords.
476
+ **Optional.** The command reads the version bump level from an explicit keyword. Set the key to `false` to
477
+ stop this behaviour.
272
478
 
273
- - **Default**: `true` (enabled)
479
+ - **Default**: `true`.
274
480
  - **Keywords**:
275
- - `BIT-BUMP-MAJOR` anywhere in commit message → major version bump
276
- - `BIT-BUMP-MINOR` anywhere in commit message → minor version bump
481
+ - `BIT-BUMP-MAJOR` anywhere in the commit message gives a major version bump.
482
+ - `BIT-BUMP-MINOR` anywhere in the commit message gives a minor version bump.
277
483
 
278
484
  ```json
279
485
  {
@@ -289,3 +495,58 @@ try {
289
495
  git commit -m "feat: add new feature BIT-BUMP-MINOR"
290
496
  bit ci merge --build # → automatically uses minor version bump
291
497
  ```
498
+
499
+ ### `sync`
500
+
501
+ **Optional.** The lane-to-branch mapping and the main-scope settings for [`bit ci sync`](#bit-ci-sync).
502
+
503
+ ```json
504
+ {
505
+ "teambit.git/ci": {
506
+ "sync": { "branchPrefix": "lane/", "lanes": ["*"], "onConflict": "halt" }
507
+ }
508
+ }
509
+ ```
510
+
511
+ | Field | Default | Description |
512
+ | --------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------- |
513
+ | `branchPrefix` | `""` | The prefix for a lane-mapped branch. The value `"lane/"` maps lane `my-lane` to branch `lane/my-lane`. |
514
+ | `branches` | `{}` | Explicit overrides that map a lane name to a branch name. An override wins over `branchPrefix`. |
515
+ | `lanes` | `["*"]` | The glob patterns of the lane names to sync. The command supports the `*` wildcard only. |
516
+ | `mainSyncBranch` | `"bit-sync/main"` | The branch that carries the main-scope drift. The command ignores the field with `mainSync: "direct-push"`. |
517
+ | `mainSync` | `"pr"` | How main-scope drift reaches the default branch. Read the tables below. |
518
+ | `onConflict` | `"halt"` | What the command does with one contested line. Read the tables below. |
519
+ | `autoMergeMainSyncPr` | `false` | **Reserved.** The command warns and enables no auto-merge on the sync pull request. Use a repository rule. |
520
+
521
+ The command validates every branch name at startup, and the error names the config field. The command never
522
+ treats the default branch or `mainSyncBranch` as lane-mapped, even with an empty `branchPrefix`.
523
+
524
+ #### The three sync keys control different things
525
+
526
+ | Key | The decision the key makes |
527
+ | ------------ | ---------------------------------------------------- |
528
+ | `onConflict` | What the command does with **one contested line**. |
529
+ | `mainSync` | **How** main-scope drift reaches the default branch. |
530
+ | `lanes` | **Which** lanes get a branch. |
531
+
532
+ No key changes which side wins a review. People merge pull requests.
533
+
534
+ `onConflict` applies to one contested line during a merge of a diverged pair.
535
+
536
+ | Value | What the command does |
537
+ | ---------------- | ---------------------------------------------------------------------------------------------- |
538
+ | `halt` (default) | The command stops. The command labels the pull request. The command writes the recovery steps. |
539
+ | `git-wins` | The command keeps the branch version of a contested line. |
540
+ | `lane-wins` | The command takes the lane version of a contested line. |
541
+
542
+ Non-conflicting changes always merge, with every value of `onConflict`.
543
+
544
+ `mainSync` decides how main-scope drift reaches the default branch.
545
+
546
+ | Value | What the command does |
547
+ | -------------- | ------------------------------------------------------------------------------------ |
548
+ | `pr` (default) | The command commits the drift to `mainSyncBranch`. The command opens a pull request. |
549
+ | `direct-push` | The command commits the drift on the default branch. The command pushes the commit. |
550
+
551
+ `lanes` decides which lanes get a branch. If the `lanes` list is empty, the command stops lane mirroring and
552
+ reconciles the main scope only.