@teambit/ci 0.0.0-e308aa46791bdab3538e682864e5a61a001dfd3d → 0.0.0-e30ef93ccee6b6078f8ab7ea6c002fca3263c9c3

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.
package/ci.docs.mdx CHANGED
@@ -83,18 +83,51 @@ Publishes new semantic versions after a PR merges to `main`.
83
83
  bit ci merge [--message <string>] [--build] [--increment <level>] [--patch|--minor|--major] [--increment-by <number>]
84
84
  ```
85
85
 
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). |
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`:
104
+
105
+ ```bash
106
+ # button 1.0.0 -> 2.0.0, but its dependent lib 1.0.0 -> 1.0.1
107
+ bit ci merge --major
108
+ ```
109
+
110
+ The one exception is a pre-release `--increment` (`prepatch`, `prerelease`, `preminor`,
111
+ `premajor`), which the dependents do follow:
112
+
113
+ ```bash
114
+ # button 1.0.0 -> 1.0.1-0, and its dependent lib 1.0.0 -> 1.0.1-0 too
115
+ bit ci merge --increment prerelease
116
+ ```
117
+
118
+ Use `--auto-tag-increment` to bump the dependents by an explicit level instead. It overrides both
119
+ defaults above:
120
+
121
+ ```bash
122
+ # button 1.0.0 -> 2.0.0, and its dependent lib 1.0.0 -> 2.0.0 as well
123
+ bit ci merge --major --auto-tag-increment major
124
+ ```
125
+
126
+ The two levels are independent, so `--major --auto-tag-increment minor` is also valid.
127
+
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`.
98
131
 
99
132
  ### Automatic Version Bump Detection
100
133
 
@@ -113,7 +146,7 @@ When **no explicit version flags** are provided, `bit ci merge` can automaticall
113
146
 
114
147
  3. **Default**: 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
+ **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.
117
150
 
118
151
  ### Internal flow
119
152
 
@@ -3,6 +3,8 @@ import type { Logger } from '@teambit/logger';
3
3
  import { OutsideWorkspaceError, type Workspace } from '@teambit/workspace';
4
4
  import type { ReleaseType } from 'semver';
5
5
  import { validateOptions } from '@teambit/snapping';
6
+ import { BitError } from '@teambit/bit-error';
7
+ import type { MergeStrategy } from '@teambit/component.modules.merge-helper';
6
8
  import type { CiMain } from '../ci.main.runtime';
7
9
 
8
10
  type Options = {
@@ -10,6 +12,7 @@ type Options = {
10
12
  build?: boolean;
11
13
  strict?: boolean;
12
14
  increment?: ReleaseType;
15
+ autoTagIncrement?: ReleaseType;
13
16
  patch?: boolean;
14
17
  minor?: boolean;
15
18
  major?: boolean;
@@ -18,11 +21,17 @@ type Options = {
18
21
  incrementBy?: number;
19
22
  verbose?: boolean;
20
23
  versionsFile?: string;
24
+ autoMergeResolve?: MergeStrategy;
25
+ forceTheirs?: boolean;
26
+ laneName?: string;
27
+ skipPush?: boolean;
28
+ noBitmapCommit?: boolean;
21
29
  };
22
30
 
23
31
  export class CiMergeCmd implements Command {
24
32
  name = 'merge';
25
- description = 'Merges a PR';
33
+ description = 'Tags and exports new semantic versions after merging a PR to main.';
34
+ extendedDescription = `By default, bumps patch versions when merging to main. If specific configuration variables are set, it can use commit messages or explicit flags to determine the version bump. Runs install, tag, build, and export, then archives the remote lane and syncs lockfiles. Use in merge-to-main CI pipelines to publish releases.`;
26
35
  group = 'collaborate';
27
36
 
28
37
  options: CommandOptions = [
@@ -39,6 +48,13 @@ export class CiMergeCmd implements Command {
39
48
  ['', 'minor', 'syntactic sugar for "--increment minor"'],
40
49
  ['', 'major', 'syntactic sugar for "--increment major"'],
41
50
  ['', 'pre-release [identifier]', 'syntactic sugar for "--increment prerelease" and `--prerelease-id <identifier>`'],
51
+ [
52
+ '',
53
+ 'auto-tag-increment <level>',
54
+ `the increment level to use for auto-tagged dependents. options are: [major, premajor, minor, preminor, patch, prepatch, prerelease].
55
+ by default, dependents are bumped by a patch, unless --increment is one of [prepatch, prerelease, preminor, premajor], which they follow.
56
+ note that dependents are auto-tagged transitively, so the entire dependents graph is bumped by this level`,
57
+ ],
42
58
  [
43
59
  '',
44
60
  'increment-by <number>',
@@ -46,6 +62,19 @@ export class CiMergeCmd implements Command {
46
62
  ],
47
63
  ['', 'versions-file <path>', 'path to a file containing component versions. format: "component-id: version"'],
48
64
  ['', 'verbose', 'show verbose output'],
65
+ [
66
+ 'r',
67
+ 'auto-merge-resolve <merge-strategy>',
68
+ 'in case of merge conflict during checkout, resolve according to the provided strategy: [ours, theirs, manual]',
69
+ ],
70
+ ['', 'force-theirs', 'do not merge during checkout, just overwrite with incoming files'],
71
+ ['', 'lane-name <name>', 'specify the lane name to delete after merge (auto-detected if not provided)'],
72
+ ['', 'skip-push', 'skip pushing the changes to the remote repository (useful when CI handles the push separately)'],
73
+ [
74
+ '',
75
+ 'no-bitmap-commit',
76
+ 'skip the post-tag git add/commit/push entirely. The new versions still land in the scope, but no .bitmap (or lockfile) commit is created on the default branch. Pair with `bitmapAutoSync: true` in workspace.jsonc so developers auto-sync their local .bitmap on the first bit command after `git pull`.',
77
+ ],
49
78
  ];
50
79
 
51
80
  constructor(
@@ -59,9 +88,21 @@ export class CiMergeCmd implements Command {
59
88
  this.logger.console('🚀 Initializing Merge command');
60
89
  if (!this.workspace) throw new OutsideWorkspaceError();
61
90
 
62
- const { releaseType, preReleaseId } = validateOptions(options);
91
+ // Validate autoMergeResolve option
92
+ if (
93
+ options.autoMergeResolve &&
94
+ options.autoMergeResolve !== 'ours' &&
95
+ options.autoMergeResolve !== 'theirs' &&
96
+ options.autoMergeResolve !== 'manual'
97
+ ) {
98
+ throw new BitError('--auto-merge-resolve must be one of the following: [ours, theirs, manual]');
99
+ }
100
+
101
+ const { releaseType, autoTagReleaseType, preReleaseId } = validateOptions(options);
63
102
 
64
- // Check if user explicitly provided any version bump flags
103
+ // Check if user explicitly provided any version bump flags.
104
+ // --auto-tag-increment is deliberately excluded: it only affects dependents, so it shouldn't
105
+ // disable the commit-message auto-detection that determines the modified components' bump.
65
106
  const explicitVersionBump = Boolean(
66
107
  options.increment || options.patch || options.minor || options.major || options.preRelease
67
108
  );
@@ -71,11 +112,17 @@ export class CiMergeCmd implements Command {
71
112
  build: options.build,
72
113
  strict: options.strict,
73
114
  releaseType,
115
+ autoTagReleaseType,
74
116
  preReleaseId,
75
117
  incrementBy: options.incrementBy,
76
118
  explicitVersionBump,
77
119
  verbose: options.verbose,
78
120
  versionsFile: options.versionsFile,
121
+ autoMergeResolve: options.autoMergeResolve,
122
+ forceTheirs: options.forceTheirs,
123
+ laneName: options.laneName,
124
+ skipPush: options.skipPush,
125
+ noBitmapCommit: options.noBitmapCommit,
79
126
  });
80
127
  }
81
128
  }
@@ -8,11 +8,16 @@ type Options = {
8
8
  build?: boolean;
9
9
  lane?: string;
10
10
  strict?: boolean;
11
+ dryRun?: boolean;
12
+ keepLane?: boolean;
13
+ skipCleanup?: boolean;
14
+ skipTasks?: string;
11
15
  };
12
16
 
13
17
  export class CiPrCmd implements Command {
14
18
  name = 'pr';
15
- description = 'This command is meant to run when a PR was open/updated and meant to export a lane to bit-cloud.';
19
+ description = 'Exports a feature lane to Bit Cloud when a Pull Request is opened or updated.';
20
+ extendedDescription = `Resolves the lane name from --lane or the current Git branch, validates it, and runs install, status, snap, and export. By default it then restores the workspace by switching back to main; pass --skip-cleanup to skip that restore when the workspace is about to be discarded (e.g. an ephemeral CI container). PR builds run the full pipeline by default; to trade specific tasks for speed on a given PR, add a [skip-tasks: ...] token to the commit message (e.g. [skip-tasks: GeneratePreview,ExtractSchema]), which merges with any --skip-tasks flag. Use in pull-request CI pipelines after tests and before deploy.`;
16
21
  group = 'collaborate';
17
22
 
18
23
  options: CommandOptions = [
@@ -20,6 +25,22 @@ export class CiPrCmd implements Command {
20
25
  ['l', 'lane <lane>', 'If set, use as the lane name, if not available, grab from git-branch name'],
21
26
  ['b', 'build', 'Set to true to build the app locally, false (default) will build on Ripple CI'],
22
27
  ['s', 'strict', 'Set to true to fail on warnings as well as errors, false (default) only fails on errors'],
28
+ ['d', 'dry-run', 'Run the full pipeline but skip exporting to remote (build runs only if --build is set)'],
29
+ [
30
+ '',
31
+ 'keep-lane',
32
+ 'Reuse the same remote lane across PR commits (preserves lane history and cloud UI edits) instead of recreating it on every run',
33
+ ],
34
+ [
35
+ '',
36
+ 'skip-cleanup',
37
+ 'Skip restoring the workspace (switching back to main) after export. Use when the workspace is discarded right after, e.g. an ephemeral CI container',
38
+ ],
39
+ [
40
+ '',
41
+ 'skip-tasks <tasks>',
42
+ `Comma-separated list of build/publish task names (or aspect-ids) to skip during snap, e.g. "ExtractSchema,GeneratePreview,GenerateEnvTemplate,PublishComponents". Speeds up PR builds by trading optional artifacts (schema/preview) and publishing for build time; they are produced on the final export to main`,
43
+ ],
23
44
  ];
24
45
 
25
46
  constructor(
@@ -45,9 +66,7 @@ export class CiPrCmd implements Command {
45
66
  if (!currentBranch) {
46
67
  throw new Error('Failed to get branch name');
47
68
  }
48
- // Sanitize branch name to make it valid for Bit lane IDs by replacing slashes with dashes
49
- const sanitizedBranch = currentBranch.replace(/\//g, '-');
50
- laneIdStr = `${this.workspace.defaultScope}/${sanitizedBranch}`;
69
+ laneIdStr = this.ci.convertBranchToLaneId(currentBranch);
51
70
  }
52
71
 
53
72
  if (options.message) {
@@ -65,6 +84,10 @@ export class CiPrCmd implements Command {
65
84
  message,
66
85
  build: options.build,
67
86
  strict: options.strict,
87
+ dryRun: options.dryRun,
88
+ keepLane: options.keepLane,
89
+ skipCleanup: options.skipCleanup,
90
+ skipTasks: options.skipTasks,
68
91
  });
69
92
 
70
93
  if (results) {
@@ -5,7 +5,8 @@ import type { CiMain } from '../ci.main.runtime';
5
5
 
6
6
  export class CiVerifyCmd implements Command {
7
7
  name = 'verify';
8
- description = 'CI commands';
8
+ description = 'Ensures the workspace passes CI checks on every commit.';
9
+ extendedDescription = `Runs lint, build, and status checks to catch dependency drift or broken builds early. Typically used as a pre-push hook or early CI job. Stops at the first failing step and returns a non-zero exit code.`;
9
10
  group = 'development';
10
11
 
11
12
  options: CommandOptions = [];
package/dist/ci.cmd.d.ts CHANGED
@@ -6,6 +6,7 @@ export declare class CiCmd implements Command {
6
6
  private logger;
7
7
  name: string;
8
8
  description: string;
9
+ extendedDescription: string;
9
10
  group: string;
10
11
  options: CommandOptions;
11
12
  commands: Command[];
package/dist/ci.cmd.js CHANGED
@@ -12,7 +12,8 @@ class CiCmd {
12
12
  this.workspace = workspace;
13
13
  this.logger = logger;
14
14
  _defineProperty(this, "name", 'ci <sub-command>');
15
- _defineProperty(this, "description", 'CI commands');
15
+ _defineProperty(this, "description", 'continuous integration commands for automated workflows');
16
+ _defineProperty(this, "extendedDescription", 'provides commands designed for use in CI/CD pipelines with Git workflows to automate component development tasks like verification, pull request handling, and deployment preparation.');
16
17
  _defineProperty(this, "group", 'collaborate');
17
18
  _defineProperty(this, "options", []);
18
19
  _defineProperty(this, "commands", []);
@@ -1 +1 @@
1
- {"version":3,"names":["CiCmd","constructor","workspace","logger","_defineProperty","report","code","data","exports"],"sources":["ci.cmd.ts"],"sourcesContent":["import type { Command, CommandOptions } from '@teambit/cli';\nimport type { Logger } from '@teambit/logger';\nimport type { Workspace } from '@teambit/workspace';\n\nexport class CiCmd implements Command {\n name = 'ci <sub-command>';\n description = 'CI commands';\n group = 'collaborate';\n\n options: CommandOptions = [];\n commands: Command[] = [];\n\n constructor(\n private workspace: Workspace,\n private logger: Logger\n ) {}\n\n async report() {\n return { code: 1, data: '[ci] not implemented' };\n }\n}\n"],"mappings":";;;;;;;;;AAIO,MAAMA,KAAK,CAAoB;EAQpCC,WAAWA,CACDC,SAAoB,EACpBC,MAAc,EACtB;IAAA,KAFQD,SAAoB,GAApBA,SAAoB;IAAA,KACpBC,MAAc,GAAdA,MAAc;IAAAC,eAAA,eATjB,kBAAkB;IAAAA,eAAA,sBACX,aAAa;IAAAA,eAAA,gBACnB,aAAa;IAAAA,eAAA,kBAEK,EAAE;IAAAA,eAAA,mBACN,EAAE;EAKrB;EAEH,MAAMC,MAAMA,CAAA,EAAG;IACb,OAAO;MAAEC,IAAI,EAAE,CAAC;MAAEC,IAAI,EAAE;IAAuB,CAAC;EAClD;AACF;AAACC,OAAA,CAAAR,KAAA,GAAAA,KAAA","ignoreList":[]}
1
+ {"version":3,"names":["CiCmd","constructor","workspace","logger","_defineProperty","report","code","data","exports"],"sources":["ci.cmd.ts"],"sourcesContent":["import type { Command, CommandOptions } from '@teambit/cli';\nimport type { Logger } from '@teambit/logger';\nimport type { Workspace } from '@teambit/workspace';\n\nexport class CiCmd implements Command {\n name = 'ci <sub-command>';\n description = 'continuous integration commands for automated workflows';\n extendedDescription =\n 'provides commands designed for use in CI/CD pipelines with Git workflows to automate component development tasks like verification, pull request handling, and deployment preparation.';\n group = 'collaborate';\n\n options: CommandOptions = [];\n commands: Command[] = [];\n\n constructor(\n private workspace: Workspace,\n private logger: Logger\n ) {}\n\n async report() {\n return { code: 1, data: '[ci] not implemented' };\n }\n}\n"],"mappings":";;;;;;;;;AAIO,MAAMA,KAAK,CAAoB;EAUpCC,WAAWA,CACDC,SAAoB,EACpBC,MAAc,EACtB;IAAA,KAFQD,SAAoB,GAApBA,SAAoB;IAAA,KACpBC,MAAc,GAAdA,MAAc;IAAAC,eAAA,eAXjB,kBAAkB;IAAAA,eAAA,sBACX,yDAAyD;IAAAA,eAAA,8BAErE,wLAAwL;IAAAA,eAAA,gBAClL,aAAa;IAAAA,eAAA,kBAEK,EAAE;IAAAA,eAAA,mBACN,EAAE;EAKrB;EAEH,MAAMC,MAAMA,CAAA,EAAG;IACb,OAAO;MAAEC,IAAI,EAAE,CAAC;MAAEC,IAAI,EAAE;IAAuB,CAAC;EAClD;AACF;AAACC,OAAA,CAAAR,KAAA,GAAAA,KAAA","ignoreList":[]}
package/dist/ci.docs.mdx CHANGED
@@ -83,18 +83,51 @@ Publishes new semantic versions after a PR merges to `main`.
83
83
  bit ci merge [--message <string>] [--build] [--increment <level>] [--patch|--minor|--major] [--increment-by <number>]
84
84
  ```
85
85
 
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). |
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`:
104
+
105
+ ```bash
106
+ # button 1.0.0 -> 2.0.0, but its dependent lib 1.0.0 -> 1.0.1
107
+ bit ci merge --major
108
+ ```
109
+
110
+ The one exception is a pre-release `--increment` (`prepatch`, `prerelease`, `preminor`,
111
+ `premajor`), which the dependents do follow:
112
+
113
+ ```bash
114
+ # button 1.0.0 -> 1.0.1-0, and its dependent lib 1.0.0 -> 1.0.1-0 too
115
+ bit ci merge --increment prerelease
116
+ ```
117
+
118
+ Use `--auto-tag-increment` to bump the dependents by an explicit level instead. It overrides both
119
+ defaults above:
120
+
121
+ ```bash
122
+ # button 1.0.0 -> 2.0.0, and its dependent lib 1.0.0 -> 2.0.0 as well
123
+ bit ci merge --major --auto-tag-increment major
124
+ ```
125
+
126
+ The two levels are independent, so `--major --auto-tag-increment minor` is also valid.
127
+
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`.
98
131
 
99
132
  ### Automatic Version Bump Detection
100
133
 
@@ -113,7 +146,7 @@ When **no explicit version flags** are provided, `bit ci merge` can automaticall
113
146
 
114
147
  3. **Default**: 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
+ **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.
117
150
 
118
151
  ### Internal flow
119
152
 
@@ -9,6 +9,7 @@ import type { SnappingMain } from '@teambit/snapping';
9
9
  import { type ExportMain } from '@teambit/export';
10
10
  import { type ImporterMain } from '@teambit/importer';
11
11
  import { type CheckoutMain } from '@teambit/checkout';
12
+ import type { MergeStrategy } from '@teambit/component.modules.merge-helper';
12
13
  import type { ReleaseType } from 'semver';
13
14
  export interface CiWorkspaceConfig {
14
15
  /**
@@ -96,36 +97,191 @@ export declare class CiMain {
96
97
  CheckoutMain
97
98
  ], config: CiWorkspaceConfig): Promise<CiMain>;
98
99
  getBranchName(): Promise<string>;
100
+ /**
101
+ * Converts a branch name to a lane ID string using Bit's naming conventions.
102
+ * Sanitizes branch name by replacing slashes and dots with dashes, converting to lowercase, then
103
+ * prefixes with the workspace's default scope.
104
+ *
105
+ * @param branchName - The git branch name to convert
106
+ * @returns Lane ID in format: {defaultScope}/{sanitizedBranch}
107
+ * @example convertBranchToLaneId("feature/New-Component") => "my-scope/feature-new-component"
108
+ */
109
+ convertBranchToLaneId(branchName: string): string;
99
110
  getDefaultBranchName(): Promise<string>;
100
111
  getGitCommitMessage(): Promise<string | null>;
101
112
  private parseVersionBumpFromCommit;
102
113
  private getCustomCommitMessage;
103
114
  private verifyWorkspaceStatusInternal;
115
+ /**
116
+ * Returns the caught Error on failure, or undefined on success (including the "already checked
117
+ * out" no-op case). Callers that need to react to a specific failure mode (e.g. stale lane) can
118
+ * inspect the returned error; existing callers ignore it and rely on a follow-up
119
+ * `getCurrentLane()` check.
120
+ */
104
121
  private switchToLane;
122
+ /**
123
+ * Sync *config-only* changes from main onto the lane — without a full `bit lane merge`.
124
+ *
125
+ * In this workflow git is the source of truth for files: the PR author merges the default branch
126
+ * into their PR branch, so source changes arrive via git. The one thing git can't carry is
127
+ * config that's already been *tagged into objects* on main — e.g. another PR ran `bit env set` /
128
+ * `bit deps set`; those records lived in `.bitmap`, rode git into main, and `bit ci merge` baked
129
+ * them into the component's Version (clearing them from `.bitmap`). A long-running PR's lane
130
+ * would otherwise miss them.
131
+ *
132
+ * A full lane merge is the wrong tool here: it does a 3-way *file* merge and refuses to run while
133
+ * the workspace has modified components — but in `bit ci pr` the workspace is always dirty (the
134
+ * PR's changes, not yet snapped). So instead we do a per-component 3-way merge of the aspect
135
+ * *config only* (base = common ancestor, ours = lane, theirs = main), keeping the PR's config on
136
+ * conflict, and stash the result on an `unmergedComponents` entry's `mergedConfig`. The
137
+ * subsequent `snap` reads it (via the aspects-merger on component load) and bakes main's config
138
+ * into the new snap, while the snap's files still come from the workspace (git). No file
139
+ * checkout, so no clean-workspace requirement.
140
+ */
141
+ private syncConfigFromMain;
142
+ /**
143
+ * Batch-fetch main-side Version objects the config merge needs (heads, then common ancestors),
144
+ * mirroring the lane-merge flows (merge-status-provider / merge-lanes). Best-effort: a fetch
145
+ * hiccup shouldn't abort `bit ci pr` — the merge loop still runs and any component whose object is
146
+ * still missing just logs the existing per-component skip. `label` names which objects for the log.
147
+ */
148
+ private prefetchFromMainForConfigSync;
149
+ /**
150
+ * Copied from `merging.main.runtime` (`filterDeletedDependenciesFromConfig`): the config merge
151
+ * can emit deletion markers (`version: '-'`) for deps removed on main. The aspects-merger applies
152
+ * `mergedConfig` verbatim, so strip those here to avoid writing a policy entry with version '-'.
153
+ */
154
+ private filterDeletedDependenciesFromConfig;
155
+ /**
156
+ * Best-effort, fetch-free check for whether the current (PR) branch is *behind* the default
157
+ * branch — i.e. the default branch has commits the PR branch doesn't contain.
158
+ *
159
+ * We intentionally do NOT `git fetch` here (a fetch in CI can hang on an interactive SSH
160
+ * host-key prompt — that's why `isStaleCiRun` was removed in #10300). We compare against
161
+ * whatever `origin/<default>` ref the checkout already has, which reflects the state the default
162
+ * branch was in when this CI run started — exactly the reference point we care about.
163
+ *
164
+ * Returns true only when we can *confirm* the branch is behind. If the ref can't be resolved or
165
+ * anything else goes wrong, returns false (treat as "not behind" / proceed) so we never silently
166
+ * disable the main→lane config propagation.
167
+ */
168
+ private isBranchBehindDefaultBranch;
105
169
  verifyWorkspaceStatus(): Promise<{
106
170
  code: number;
107
171
  data: string;
108
172
  }>;
109
- snapPrCommit({ laneIdStr, message, build, strict, }: {
173
+ snapPrCommit({ laneIdStr, message, build, strict, dryRun, keepLane, skipCleanup, skipTasks, }: {
110
174
  laneIdStr: string;
111
175
  message: string;
112
176
  build: boolean | undefined;
113
177
  strict: boolean | undefined;
114
- }): Promise<"No changes detected, nothing to snap" | undefined>;
115
- mergePr({ message: argMessage, build, strict, releaseType, preReleaseId, incrementBy, explicitVersionBump, verbose, versionsFile, }: {
178
+ dryRun?: boolean;
179
+ keepLane?: boolean;
180
+ skipCleanup?: boolean;
181
+ skipTasks?: string;
182
+ }): Promise<string | undefined>;
183
+ /**
184
+ * Post-export cleanup: restore the workspace to the original lane / main so an interactive
185
+ * `bit ci pr` leaves you where you started. `switchToLane('main')` re-checks-out main's HEAD,
186
+ * which re-imports every workspace component — on a large monorepo that's minutes of work for a
187
+ * workspace that, in CI, is thrown away the moment the command exits. Hence `skipCleanup`.
188
+ * Wrapped so a restore failure only warns instead of throwing out of the caller's `finally` and
189
+ * masking the real error from snap/export. Returns whether the switch actually ran (callers use
190
+ * it to decide whether follow-up lane bookkeeping that assumes we left the lane is safe).
191
+ */
192
+ private restoreWorkspaceAfterPr;
193
+ /**
194
+ * `--keep-lane` flow: reuse the existing remote lane (or create it on the first run), merge main
195
+ * into it to pick up config changes that landed since the fork, snap, and export with
196
+ * adopt-on-conflict recovery for concurrent CI pushes. The lane object is preserved across PR
197
+ * commits, so its history and lane-based UI edits on Bit Cloud survive.
198
+ */
199
+ private snapAndExportReusingLane;
200
+ /**
201
+ * Default flow: snap onto a uniquely-named temporary lane, then at export time delete any
202
+ * existing remote lane and rename the temp lane to the final name. The temp name minimizes the
203
+ * race window when multiple CI jobs run concurrently on the same branch. Trade-off: the final
204
+ * lane is recreated on every PR commit, so its history and any lane-based UI edits on Bit Cloud
205
+ * don't survive across commits — use `--keep-lane` for that.
206
+ */
207
+ private snapAndExportWithTempLane;
208
+ /**
209
+ * Export with a recovery path for the two concurrent-CI conflicts that can surface from the
210
+ * remote (see the marker constants at the top of the file): lane-hash mismatch (both runners
211
+ * created fresh lane objects when the lane didn't yet exist on the remote) and per-component
212
+ * divergence (both reused the existing lane but snapped the same component with different
213
+ * content).
214
+ *
215
+ * Recovery: adopt-the-winner. The remote lane (whoever pushed first) becomes canonical. We
216
+ * drop our local lane object, fetch the remote, rebase our snapped Version objects so each
217
+ * one's parent points to the remote head for that component, then swap those rebased Versions
218
+ * in as the new lane heads and re-export. Build artifacts are preserved — only the parent
219
+ * pointers on the Version objects change. Result: both runners' snaps end up chained on a
220
+ * single lane object (last-writer-wins on content for any contested component, with the
221
+ * winner's snap preserved in history as the parent).
222
+ */
223
+ private exportWithAdoptOnConflict;
224
+ /**
225
+ * Wrap `exporter.export()` with retry on the "server is busy" error. The retried export's
226
+ * pending-dir lands behind whichever concurrent client is still in the remote's queue (we
227
+ * arrived second by definition — we're the loser of the original race). The 60s wait inside
228
+ * `export-validate.waitIfNeeded` covers the common case, but on slow CI hosts or large pushes
229
+ * we sometimes time out before the other client finishes its persist. A short sleep + retry
230
+ * here just gives the queue room to drain.
231
+ */
232
+ private exportWithBusyRetry;
233
+ private rebaseOntoRemoteLane;
234
+ mergePr({ message: argMessage, build, strict, releaseType, autoTagReleaseType, preReleaseId, incrementBy, explicitVersionBump, verbose, versionsFile, autoMergeResolve, forceTheirs, laneName, skipPush, noBitmapCommit, }: {
116
235
  message?: string;
117
236
  build?: boolean;
118
237
  strict?: boolean;
119
238
  releaseType: ReleaseType;
239
+ autoTagReleaseType?: ReleaseType;
120
240
  preReleaseId?: string;
121
241
  incrementBy?: number;
122
242
  explicitVersionBump?: boolean;
123
243
  verbose?: boolean;
124
244
  versionsFile?: string;
245
+ autoMergeResolve?: MergeStrategy;
246
+ forceTheirs?: boolean;
247
+ laneName?: string;
248
+ skipPush?: boolean;
249
+ noBitmapCommit?: boolean;
125
250
  }): Promise<{
126
251
  code: number;
127
252
  data: string;
128
253
  }>;
254
+ /**
255
+ * Stage every changed file (post-tag/export the bitmap, lockfiles, and any files
256
+ * touched by `bit checkout head` may differ), commit with the configured message,
257
+ * rebase against origin, and push — unless `skipPush` was passed.
258
+ */
259
+ private commitAndPushBitmapChanges;
260
+ /**
261
+ * Compare lane Version extensions with main Version extensions for each component.
262
+ * Any config differences (e.g. env-set, deps-set) are saved to .bitmap so they survive
263
+ * the switch from lane to main and get included in the subsequent tag.
264
+ */
265
+ private restoreLaneConfigChanges;
266
+ /**
267
+ * Performs lane cleanup by attempting to detect and delete the source lane
268
+ * after a successful merge, even when running on the main branch
269
+ */
270
+ private performLaneCleanup;
271
+ /**
272
+ * Export with retry on lane hash-mismatch, caused by a concurrent `bit ci pr` run pushing the
273
+ * same lane id between our pre-export delete and the hub's merge (the export takes 1-2 minutes,
274
+ * plenty of time to race). Used by the default (temp-lane) flow. On mismatch we delete the
275
+ * remote lane and retry — the temp-lane flow recreates the lane on every run anyway, so there's
276
+ * no lane history to preserve. (The `--keep-lane` flow instead adopts the remote lane and
277
+ * rebases onto it; see `exportWithAdoptOnConflict`.)
278
+ */
279
+ private exportWithRetryOnLaneHashMismatch;
280
+ /**
281
+ * Archives (deletes) a lane with proper error handling and logging.
282
+ * @param throwOnError - if true, throws on failure (use for critical operations like pre-export cleanup)
283
+ */
284
+ private archiveLane;
129
285
  /**
130
286
  * Auto-detect version bump from commit messages if no explicit version bump was provided
131
287
  */