@teambit/ci 1.0.533 → 1.0.534

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
@@ -168,7 +168,18 @@ flag changes only the dependents, so you can combine it with the detection.
168
168
  bit export
169
169
  ```
170
170
 
171
- 3. **Archive the remote lane.** This step is house-keeping.
171
+ 3. **Archive the remote lane.** This step is house-keeping, with one condition. A lane can carry
172
+ components of several scopes. Every component this run tagged and exported is released (while
173
+ the lane still sits at the head it was tagged from), so a
174
+ repository that holds components of several scopes archives as before. Any other component
175
+ of another scope is released only if its lane head is already
176
+ on its own main — in main's history, or released onto main's head: the same sources, package
177
+ and component dependencies and extension config (that is what a `bit ci merge` in that
178
+ scope's repository leaves behind); a component the lane deletes is released once its main is
179
+ removed. While such a component is pending, the lane is left open
180
+ and the command names it; the last scope to release archives the lane. An open lane whose
181
+ branch was merged stays converged; delete the branch only after the archive.
182
+ To archive by hand: `bit lane remove --remote <scope>/<lane>`.
172
183
  4. **Commit the lock-file updates**
173
184
 
174
185
  ```bash
package/dist/ci.docs.mdx CHANGED
@@ -168,7 +168,18 @@ flag changes only the dependents, so you can combine it with the detection.
168
168
  bit export
169
169
  ```
170
170
 
171
- 3. **Archive the remote lane.** This step is house-keeping.
171
+ 3. **Archive the remote lane.** This step is house-keeping, with one condition. A lane can carry
172
+ components of several scopes. Every component this run tagged and exported is released (while
173
+ the lane still sits at the head it was tagged from), so a
174
+ repository that holds components of several scopes archives as before. Any other component
175
+ of another scope is released only if its lane head is already
176
+ on its own main — in main's history, or released onto main's head: the same sources, package
177
+ and component dependencies and extension config (that is what a `bit ci merge` in that
178
+ scope's repository leaves behind); a component the lane deletes is released once its main is
179
+ removed. While such a component is pending, the lane is left open
180
+ and the command names it; the last scope to release archives the lane. An open lane whose
181
+ branch was merged stays converged; delete the branch only after the archive.
182
+ To archive by hand: `bit lane remove --remote <scope>/<lane>`.
172
183
  4. **Commit the lock-file updates**
173
184
 
174
185
  ```bash
@@ -339,11 +339,6 @@ export declare class CiMain {
339
339
  * the switch from lane to main and get included in the subsequent tag.
340
340
  */
341
341
  private restoreLaneConfigChanges;
342
- /**
343
- * Performs lane cleanup by attempting to detect and delete the source lane
344
- * after a successful merge, even when running on the main branch
345
- */
346
- private performLaneCleanup;
347
342
  /**
348
343
  * Export with retry on lane hash-mismatch, caused by a concurrent `bit ci pr` run pushing the
349
344
  * same lane id between our pre-export delete and the hub's merge (the export takes 1-2 minutes,
@@ -186,9 +186,16 @@ function _objects() {
186
186
  };
187
187
  return data;
188
188
  }
189
- function _sourceBranchDetector() {
190
- const data = require("./source-branch-detector");
191
- _sourceBranchDetector = function () {
189
+ function _laneCleanup() {
190
+ const data = require("./lane-cleanup");
191
+ _laneCleanup = function () {
192
+ return data;
193
+ };
194
+ return data;
195
+ }
196
+ function _legacy() {
197
+ const data = require("@teambit/legacy.scope-api");
198
+ _legacy = function () {
192
199
  return data;
193
200
  };
194
201
  return data;
@@ -1621,9 +1628,19 @@ class CiMain {
1621
1628
  this.logger.console(_chalk().default.yellow('No components to tag'));
1622
1629
  }
1623
1630
  const hasTaggedComponents = tagResults?.taggedComponents && tagResults.taggedComponents.length > 0;
1631
+ const releasedHeads = new Map();
1624
1632
  if (hasTaggedComponents) {
1625
1633
  this.logger.console(_chalk().default.blue('Exporting components'));
1626
1634
  const exportResult = await this.exporter.export();
1635
+ // released here = tagged by this run AND exported now, remembered with the lane head each was
1636
+ // tagged from (its pre-tag version); an export with no ids also carries components left
1637
+ // export-pending by an earlier run, which this run did not release.
1638
+ const exported = _componentId().ComponentIdList.fromArray(exportResult.componentsIds);
1639
+ [...tagResults.taggedComponents, ...tagResults.autoTaggedResults.map(res => res.component)].forEach(comp => {
1640
+ if (exported.hasWithoutVersion(comp.id)) {
1641
+ releasedHeads.set(comp.id.toStringWithoutVersion(), comp.previouslyUsedVersion);
1642
+ }
1643
+ });
1627
1644
  if (exportResult.componentsIds.length > 0) {
1628
1645
  this.logger.console(_chalk().default.green(`Exported ${exportResult.componentsIds.length} component(s)`));
1629
1646
  } else {
@@ -1644,8 +1661,42 @@ class CiMain {
1644
1661
  }
1645
1662
  this.logger.console(_chalk().default.green('Merged PR'));
1646
1663
 
1647
- // Enhanced lane cleanup logic
1648
- await this.performLaneCleanup(currentLane, laneName, initialCommitSha);
1664
+ // Archive the source lane, unless other scopes still have to release their slice of it.
1665
+ await new (_laneCleanup().LaneCleanup)({
1666
+ logger: this.logger,
1667
+ defaultScope: this.workspace.defaultScope,
1668
+ parseLaneId: idStr => this.lanes.parseLaneId(idStr),
1669
+ convertBranchToLaneId: branch => this.convertBranchToLaneId(branch),
1670
+ archiveLane: laneId => this.archiveLane(laneId),
1671
+ readLane: async laneId => {
1672
+ // the lane object itself: `getLanes` drops deleted entries, which are lane work too.
1673
+ // Only bit's own "no such lane" means the lane is gone; any other failure propagates.
1674
+ const lane = await this.lanes.importLaneObject(laneId, false).catch(err => {
1675
+ if (err instanceof _legacy().LaneNotFound) return undefined;
1676
+ throw err;
1677
+ });
1678
+ if (!lane) return undefined;
1679
+ return {
1680
+ components: lane.components.map(c => ({
1681
+ id: c.id,
1682
+ head: c.head.toString(),
1683
+ isDeleted: c.isDeleted
1684
+ })),
1685
+ updateDependents: (lane.updateDependents ?? []).map(id => ({
1686
+ id: id.changeVersion(undefined),
1687
+ head: id.version
1688
+ })),
1689
+ readme: lane.readmeComponent ? `${lane.readmeComponent.id.toStringWithoutVersion()}@${lane.readmeComponent.head?.toString() ?? ''}` : undefined
1690
+ };
1691
+ },
1692
+ // no cache: a model already present locally may predate another scope's release
1693
+ importMainObjects: ids => this.importer.importObjectsFromMainIfExist(ids),
1694
+ getModelComponent: id => this.workspace.scope.legacyScope.getModelComponentIfExist(id),
1695
+ importObjectsByHashes: (scope, hashes) => this.importer.importObjectsByHashes(hashes, scope),
1696
+ releasedHeadByThisRun: id => releasedHeads.get(id.toStringWithoutVersion()),
1697
+ objects: this.workspace.scope.legacyScope.objects,
1698
+ warn: text => this.logger.console((0, _cli().formatWarningSummary)(text))
1699
+ }).run(currentLane, laneName, initialCommitSha);
1649
1700
  return {
1650
1701
  code: 0,
1651
1702
  data: ''
@@ -1747,50 +1798,6 @@ class CiMain {
1747
1798
  }
1748
1799
  }
1749
1800
 
1750
- /**
1751
- * Performs lane cleanup by attempting to detect and delete the source lane
1752
- * after a successful merge, even when running on the main branch
1753
- */
1754
- async performLaneCleanup(currentLane, explicitLaneName, initialCommitSha) {
1755
- this.logger.console('🗑️ Lane Cleanup');
1756
-
1757
- // If we already have a current lane, use it
1758
- if (currentLane) {
1759
- this.logger.console(_chalk().default.blue(`Found current lane: ${currentLane.name}`));
1760
- const laneId = currentLane.id();
1761
- await this.archiveLane(laneId.toString());
1762
- return;
1763
- }
1764
-
1765
- // If no current lane but explicit lane name provided, try to delete it
1766
- if (explicitLaneName) {
1767
- this.logger.console(_chalk().default.blue(`Using explicitly provided lane name: ${explicitLaneName}`));
1768
- try {
1769
- const laneId = await this.lanes.parseLaneId(explicitLaneName);
1770
- await this.archiveLane(laneId.toString());
1771
- return;
1772
- } catch (e) {
1773
- this.logger.console(_chalk().default.yellow(`Failed to parse lane name '${explicitLaneName}': ${e.message}`));
1774
- }
1775
- }
1776
-
1777
- // Try to auto-detect source branch/lane name using the dedicated detector
1778
- const sourceBranchDetector = new (_sourceBranchDetector().SourceBranchDetector)(this.logger);
1779
- const sourceBranchName = await sourceBranchDetector.getSourceBranchName(initialCommitSha);
1780
- if (!sourceBranchName) {
1781
- this.logger.console(_chalk().default.yellow('No current lane and unable to detect source branch - skipping lane cleanup'));
1782
- return;
1783
- }
1784
- try {
1785
- const laneIdStr = this.convertBranchToLaneId(sourceBranchName);
1786
- this.logger.console(_chalk().default.blue(`Attempting to delete lane based on source branch: ${sourceBranchName} -> ${laneIdStr}`));
1787
- const laneId = await this.lanes.parseLaneId(laneIdStr);
1788
- await this.archiveLane(laneId.toString());
1789
- } catch (e) {
1790
- this.logger.console(_chalk().default.yellow(`Error during lane cleanup for source branch '${sourceBranchName}': ${e.message}`));
1791
- }
1792
- }
1793
-
1794
1801
  /**
1795
1802
  * Export with retry on lane hash-mismatch, caused by a concurrent `bit ci pr` run pushing the
1796
1803
  * same lane id between our pre-export delete and the hub's merge (the export takes 1-2 minutes,