@teambit/ci 0.0.0-01196c5baebfaeabe37f33253bb4c38b8b774ea8
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 +258 -0
- package/commands/merge.cmd.ts +78 -0
- package/commands/pr.cmd.ts +76 -0
- package/commands/verify.cmd.ts +25 -0
- package/dist/ci.aspect.d.ts +3 -0
- package/dist/ci.aspect.js +19 -0
- package/dist/ci.aspect.js.map +1 -0
- package/dist/ci.cmd.d.ts +17 -0
- package/dist/ci.cmd.js +29 -0
- package/dist/ci.cmd.js.map +1 -0
- package/dist/ci.docs.mdx +258 -0
- package/dist/ci.main.runtime.d.ts +132 -0
- package/dist/ci.main.runtime.js +605 -0
- package/dist/ci.main.runtime.js.map +1 -0
- package/dist/commands/merge.cmd.d.ts +33 -0
- package/dist/commands/merge.cmd.js +59 -0
- package/dist/commands/merge.cmd.js.map +1 -0
- package/dist/commands/pr.cmd.d.ts +22 -0
- package/dist/commands/pr.cmd.js +69 -0
- package/dist/commands/pr.cmd.js.map +1 -0
- package/dist/commands/verify.cmd.d.ts +18 -0
- package/dist/commands/verify.cmd.js +35 -0
- package/dist/commands/verify.cmd.js.map +1 -0
- package/dist/git.d.ts +1 -0
- package/dist/git.js +16 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/preview-1753780788128.js +7 -0
- package/package.json +64 -0
- package/types/asset.d.ts +41 -0
- package/types/style.d.ts +42 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.CiMain = void 0;
|
|
7
|
+
function _cli() {
|
|
8
|
+
const data = require("@teambit/cli");
|
|
9
|
+
_cli = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _logger() {
|
|
15
|
+
const data = require("@teambit/logger");
|
|
16
|
+
_logger = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
function _workspace() {
|
|
22
|
+
const data = require("@teambit/workspace");
|
|
23
|
+
_workspace = function () {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
function _builder() {
|
|
29
|
+
const data = require("@teambit/builder");
|
|
30
|
+
_builder = function () {
|
|
31
|
+
return data;
|
|
32
|
+
};
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
function _status() {
|
|
36
|
+
const data = require("@teambit/status");
|
|
37
|
+
_status = function () {
|
|
38
|
+
return data;
|
|
39
|
+
};
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
42
|
+
function _lanes() {
|
|
43
|
+
const data = require("@teambit/lanes");
|
|
44
|
+
_lanes = function () {
|
|
45
|
+
return data;
|
|
46
|
+
};
|
|
47
|
+
return data;
|
|
48
|
+
}
|
|
49
|
+
function _snapping() {
|
|
50
|
+
const data = require("@teambit/snapping");
|
|
51
|
+
_snapping = function () {
|
|
52
|
+
return data;
|
|
53
|
+
};
|
|
54
|
+
return data;
|
|
55
|
+
}
|
|
56
|
+
function _export() {
|
|
57
|
+
const data = require("@teambit/export");
|
|
58
|
+
_export = function () {
|
|
59
|
+
return data;
|
|
60
|
+
};
|
|
61
|
+
return data;
|
|
62
|
+
}
|
|
63
|
+
function _importer() {
|
|
64
|
+
const data = require("@teambit/importer");
|
|
65
|
+
_importer = function () {
|
|
66
|
+
return data;
|
|
67
|
+
};
|
|
68
|
+
return data;
|
|
69
|
+
}
|
|
70
|
+
function _checkout() {
|
|
71
|
+
const data = require("@teambit/checkout");
|
|
72
|
+
_checkout = function () {
|
|
73
|
+
return data;
|
|
74
|
+
};
|
|
75
|
+
return data;
|
|
76
|
+
}
|
|
77
|
+
function _execa() {
|
|
78
|
+
const data = _interopRequireDefault(require("execa"));
|
|
79
|
+
_execa = function () {
|
|
80
|
+
return data;
|
|
81
|
+
};
|
|
82
|
+
return data;
|
|
83
|
+
}
|
|
84
|
+
function _chalk() {
|
|
85
|
+
const data = _interopRequireDefault(require("chalk"));
|
|
86
|
+
_chalk = function () {
|
|
87
|
+
return data;
|
|
88
|
+
};
|
|
89
|
+
return data;
|
|
90
|
+
}
|
|
91
|
+
function _ci() {
|
|
92
|
+
const data = require("./ci.aspect");
|
|
93
|
+
_ci = function () {
|
|
94
|
+
return data;
|
|
95
|
+
};
|
|
96
|
+
return data;
|
|
97
|
+
}
|
|
98
|
+
function _ci2() {
|
|
99
|
+
const data = require("./ci.cmd");
|
|
100
|
+
_ci2 = function () {
|
|
101
|
+
return data;
|
|
102
|
+
};
|
|
103
|
+
return data;
|
|
104
|
+
}
|
|
105
|
+
function _verify() {
|
|
106
|
+
const data = require("./commands/verify.cmd");
|
|
107
|
+
_verify = function () {
|
|
108
|
+
return data;
|
|
109
|
+
};
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
function _pr() {
|
|
113
|
+
const data = require("./commands/pr.cmd");
|
|
114
|
+
_pr = function () {
|
|
115
|
+
return data;
|
|
116
|
+
};
|
|
117
|
+
return data;
|
|
118
|
+
}
|
|
119
|
+
function _merge() {
|
|
120
|
+
const data = require("./commands/merge.cmd");
|
|
121
|
+
_merge = function () {
|
|
122
|
+
return data;
|
|
123
|
+
};
|
|
124
|
+
return data;
|
|
125
|
+
}
|
|
126
|
+
function _git() {
|
|
127
|
+
const data = require("./git");
|
|
128
|
+
_git = function () {
|
|
129
|
+
return data;
|
|
130
|
+
};
|
|
131
|
+
return data;
|
|
132
|
+
}
|
|
133
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
134
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
135
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
136
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
137
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
138
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
139
|
+
class CiMain {
|
|
140
|
+
constructor(workspace, builder, status, lanes, snapping, exporter, importer, checkout, logger, config) {
|
|
141
|
+
this.workspace = workspace;
|
|
142
|
+
this.builder = builder;
|
|
143
|
+
this.status = status;
|
|
144
|
+
this.lanes = lanes;
|
|
145
|
+
this.snapping = snapping;
|
|
146
|
+
this.exporter = exporter;
|
|
147
|
+
this.importer = importer;
|
|
148
|
+
this.checkout = checkout;
|
|
149
|
+
this.logger = logger;
|
|
150
|
+
this.config = config;
|
|
151
|
+
}
|
|
152
|
+
static async provider([cli, workspace, loggerAspect, builder, status, lanes, snapping, exporter, importer, checkout], config) {
|
|
153
|
+
const logger = loggerAspect.createLogger(_ci().CiAspect.id);
|
|
154
|
+
const ci = new CiMain(workspace, builder, status, lanes, snapping, exporter, importer, checkout, logger, config);
|
|
155
|
+
const ciCmd = new (_ci2().CiCmd)(workspace, logger);
|
|
156
|
+
ciCmd.commands = [new (_verify().CiVerifyCmd)(workspace, logger, ci), new (_pr().CiPrCmd)(workspace, logger, ci), new (_merge().CiMergeCmd)(workspace, logger, ci)];
|
|
157
|
+
cli.register(ciCmd);
|
|
158
|
+
return ci;
|
|
159
|
+
}
|
|
160
|
+
async getBranchName() {
|
|
161
|
+
try {
|
|
162
|
+
// if we are running on github, use the GITHUB_HEAD_REF env var
|
|
163
|
+
if (process.env.GITHUB_HEAD_REF) return process.env.GITHUB_HEAD_REF;
|
|
164
|
+
const branch = await _git().git.branch();
|
|
165
|
+
return branch.current;
|
|
166
|
+
} catch (e) {
|
|
167
|
+
throw new Error(`Unable to read branch: ${e.toString()}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async getDefaultBranchName() {
|
|
171
|
+
try {
|
|
172
|
+
// Try to get the default branch from git symbolic-ref
|
|
173
|
+
const result = await _git().git.raw(['symbolic-ref', 'refs/remotes/origin/HEAD']);
|
|
174
|
+
const defaultBranch = result.trim().split('/').pop();
|
|
175
|
+
return defaultBranch || 'master';
|
|
176
|
+
} catch (e) {
|
|
177
|
+
// Fallback to common default branch names
|
|
178
|
+
try {
|
|
179
|
+
const branches = await _git().git.branch(['-r']);
|
|
180
|
+
if (branches.all.includes('origin/main')) return 'main';
|
|
181
|
+
if (branches.all.includes('origin/master')) return 'master';
|
|
182
|
+
return 'master'; // Final fallback
|
|
183
|
+
} catch {
|
|
184
|
+
this.logger.console(_chalk().default.yellow(`Unable to detect default branch, using 'master': ${e.toString()}`));
|
|
185
|
+
return 'master';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async getGitCommitMessage() {
|
|
190
|
+
try {
|
|
191
|
+
const commit = await _git().git.log({
|
|
192
|
+
maxCount: 1
|
|
193
|
+
});
|
|
194
|
+
if (!commit.latest) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const {
|
|
198
|
+
message,
|
|
199
|
+
body
|
|
200
|
+
} = commit.latest;
|
|
201
|
+
return body ? `${message}\n\n${body}` : message;
|
|
202
|
+
} catch (e) {
|
|
203
|
+
throw new Error(`Unable to read commit message: ${e.toString()}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
parseVersionBumpFromCommit(commitMessage) {
|
|
207
|
+
// Check explicit bump keywords (highest priority after env vars)
|
|
208
|
+
if (this.config.useExplicitBumpKeywords !== false) {
|
|
209
|
+
// default to true
|
|
210
|
+
if (commitMessage.includes('BIT-BUMP-MAJOR')) {
|
|
211
|
+
this.logger.console(_chalk().default.blue('Found BIT-BUMP-MAJOR keyword in commit message'));
|
|
212
|
+
return 'major';
|
|
213
|
+
}
|
|
214
|
+
if (commitMessage.includes('BIT-BUMP-MINOR')) {
|
|
215
|
+
this.logger.console(_chalk().default.blue('Found BIT-BUMP-MINOR keyword in commit message'));
|
|
216
|
+
return 'minor';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check conventional commits if enabled
|
|
221
|
+
if (this.config.useConventionalCommitsForVersionBump) {
|
|
222
|
+
// Check for breaking changes (major version bump)
|
|
223
|
+
if (/^feat!(\(.+\))?:|^fix!(\(.+\))?:|BREAKING CHANGE/m.test(commitMessage)) {
|
|
224
|
+
this.logger.console(_chalk().default.blue('Found breaking changes in commit message (conventional commits)'));
|
|
225
|
+
return 'major';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Check for features (minor version bump)
|
|
229
|
+
if (/^feat(\(.+\))?:/m.test(commitMessage)) {
|
|
230
|
+
this.logger.console(_chalk().default.blue('Found feature commits (conventional commits)'));
|
|
231
|
+
return 'minor';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Check for fixes (patch version bump) - explicit patch not needed as it's default
|
|
235
|
+
if (/^fix(\(.+\))?:/m.test(commitMessage)) {
|
|
236
|
+
this.logger.console(_chalk().default.blue('Found fix commits (conventional commits) - using default patch'));
|
|
237
|
+
return 'patch';
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return null; // No specific version bump detected
|
|
241
|
+
}
|
|
242
|
+
async getCustomCommitMessage() {
|
|
243
|
+
try {
|
|
244
|
+
const commitMessageScript = this.config.commitMessageScript;
|
|
245
|
+
if (commitMessageScript) {
|
|
246
|
+
this.logger.console(_chalk().default.blue(`Running custom commit message script: ${commitMessageScript}`));
|
|
247
|
+
|
|
248
|
+
// Parse the command to avoid shell injection
|
|
249
|
+
const parts = commitMessageScript.split(' ');
|
|
250
|
+
const command = parts[0];
|
|
251
|
+
const args = parts.slice(1);
|
|
252
|
+
const result = await (0, _execa().default)(command, args, {
|
|
253
|
+
cwd: this.workspace.path,
|
|
254
|
+
encoding: 'utf8'
|
|
255
|
+
});
|
|
256
|
+
const customMessage = result.stdout.trim();
|
|
257
|
+
if (customMessage) {
|
|
258
|
+
this.logger.console(_chalk().default.green(`Using custom commit message: ${customMessage}`));
|
|
259
|
+
return customMessage;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} catch (e) {
|
|
263
|
+
this.logger.console(_chalk().default.yellow(`Failed to run custom commit message script: ${e.toString()}`));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Fallback to default message
|
|
267
|
+
return 'chore: update .bitmap and lockfiles as needed [skip ci]';
|
|
268
|
+
}
|
|
269
|
+
async verifyWorkspaceStatusInternal(strict = false) {
|
|
270
|
+
this.logger.console('📊 Workspace Status');
|
|
271
|
+
this.logger.console(_chalk().default.blue('Verifying status of workspace'));
|
|
272
|
+
const status = await this.status.status({
|
|
273
|
+
lanes: true
|
|
274
|
+
});
|
|
275
|
+
const {
|
|
276
|
+
data: statusOutput,
|
|
277
|
+
code
|
|
278
|
+
} = await this.status.formatStatusOutput(status, strict ? {
|
|
279
|
+
strict: true,
|
|
280
|
+
warnings: true
|
|
281
|
+
} // When strict=true, fail on both errors and warnings
|
|
282
|
+
: {
|
|
283
|
+
failOnError: true,
|
|
284
|
+
warnings: false
|
|
285
|
+
} // By default, fail only on errors (tag blockers)
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
// Log the formatted status output
|
|
289
|
+
this.logger.console(statusOutput);
|
|
290
|
+
if (code !== 0) {
|
|
291
|
+
throw new Error('Workspace status verification failed');
|
|
292
|
+
}
|
|
293
|
+
this.logger.consoleSuccess(_chalk().default.green('Workspace status is correct'));
|
|
294
|
+
return {
|
|
295
|
+
status
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
async switchToLane(laneName, options = {}) {
|
|
299
|
+
this.logger.console(_chalk().default.blue(`Switching to ${laneName}`));
|
|
300
|
+
await this.lanes.switchLanes(laneName, _objectSpread({
|
|
301
|
+
forceOurs: true,
|
|
302
|
+
head: true,
|
|
303
|
+
workspaceOnly: true,
|
|
304
|
+
skipDependencyInstallation: true
|
|
305
|
+
}, options)).catch(e => {
|
|
306
|
+
if (e.toString().includes('already checked out')) {
|
|
307
|
+
this.logger.console(_chalk().default.yellow(`Lane ${laneName} already checked out, skipping checkout`));
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
this.logger.console(_chalk().default.red(`Failed to checkout lane ${laneName}: ${e.toString()}`));
|
|
311
|
+
return null;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
async verifyWorkspaceStatus() {
|
|
315
|
+
await this.verifyWorkspaceStatusInternal();
|
|
316
|
+
this.logger.console('🔨 Build Process');
|
|
317
|
+
const components = await this.workspace.list();
|
|
318
|
+
this.logger.console(_chalk().default.blue(`Building ${components.length} components`));
|
|
319
|
+
const build = await this.builder.build(components);
|
|
320
|
+
build.throwErrorsIfExist();
|
|
321
|
+
this.logger.console(_chalk().default.green('Components built'));
|
|
322
|
+
return {
|
|
323
|
+
code: 0,
|
|
324
|
+
data: ''
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
async snapPrCommit({
|
|
328
|
+
laneIdStr,
|
|
329
|
+
message,
|
|
330
|
+
build,
|
|
331
|
+
strict
|
|
332
|
+
}) {
|
|
333
|
+
this.logger.console(_chalk().default.blue(`Lane name: ${laneIdStr}`));
|
|
334
|
+
const originalLane = await this.lanes.getCurrentLane();
|
|
335
|
+
const laneId = await this.lanes.parseLaneId(laneIdStr);
|
|
336
|
+
await this.verifyWorkspaceStatusInternal(strict);
|
|
337
|
+
await this.importer.import({
|
|
338
|
+
ids: [],
|
|
339
|
+
installNpmPackages: false,
|
|
340
|
+
writeConfigFiles: false
|
|
341
|
+
}).catch(e => {
|
|
342
|
+
throw new Error(`Failed to import components: ${e.toString()}`);
|
|
343
|
+
});
|
|
344
|
+
this.logger.console('🔄 Lane Management');
|
|
345
|
+
const availableLanesInScope = await this.lanes.getLanes({
|
|
346
|
+
remote: laneId.scope
|
|
347
|
+
}).catch(e => {
|
|
348
|
+
throw new Error(`Failed to get lanes in scope ${laneId.scope}: ${e.toString()}`);
|
|
349
|
+
});
|
|
350
|
+
const laneExists = availableLanesInScope.find(lane => lane.id.name === laneId.name);
|
|
351
|
+
let foundErr;
|
|
352
|
+
try {
|
|
353
|
+
if (laneExists) {
|
|
354
|
+
const lane = await this.lanes.importLaneObject(laneId, true);
|
|
355
|
+
this.workspace.consumer.setCurrentLane(laneId, true);
|
|
356
|
+
const laneIds = lane.toComponentIds();
|
|
357
|
+
laneIds.forEach(compId => this.workspace.consumer.bitMap.updateComponentId(compId));
|
|
358
|
+
await this.workspace.bitMap.write();
|
|
359
|
+
await this.importer.importCurrentObjects();
|
|
360
|
+
this.logger.console(_chalk().default.green(`Imported lane ${laneId.toString()}`));
|
|
361
|
+
} else {
|
|
362
|
+
this.logger.console(_chalk().default.blue(`Creating lane ${laneId.toString()}`));
|
|
363
|
+
try {
|
|
364
|
+
await this.lanes.createLane(laneId.name, {
|
|
365
|
+
scope: laneId.scope,
|
|
366
|
+
forkLaneNewScope: true
|
|
367
|
+
});
|
|
368
|
+
} catch (e) {
|
|
369
|
+
if (e.message.includes('already exists')) {
|
|
370
|
+
this.logger.console(_chalk().default.yellow(`Lane ${laneId.toString()} already exists, skipping creation`));
|
|
371
|
+
} else {
|
|
372
|
+
throw new Error(`Failed to create lane ${laneId.toString()}: ${e.toString()}`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const currentLane = await this.lanes.getCurrentLane();
|
|
377
|
+
this.logger.console(_chalk().default.blue(`Current lane: ${currentLane?.name ?? 'main'}`));
|
|
378
|
+
if (currentLane?.name === laneId.name) {
|
|
379
|
+
this.logger.console(_chalk().default.yellow(`Current lane is already ${laneId.name}, skipping switch`));
|
|
380
|
+
} else {
|
|
381
|
+
await this.switchToLane(laneId.toString());
|
|
382
|
+
}
|
|
383
|
+
this.logger.console('📦 Snapping Components');
|
|
384
|
+
const results = await this.snapping.snap({
|
|
385
|
+
message,
|
|
386
|
+
build,
|
|
387
|
+
exitOnFirstFailedTask: true
|
|
388
|
+
});
|
|
389
|
+
if (!results) {
|
|
390
|
+
return 'No changes detected, nothing to snap';
|
|
391
|
+
}
|
|
392
|
+
const {
|
|
393
|
+
snappedComponents
|
|
394
|
+
} = results;
|
|
395
|
+
const snapOutput = (0, _snapping().snapResultOutput)(results);
|
|
396
|
+
this.logger.console(snapOutput);
|
|
397
|
+
this.logger.console(_chalk().default.blue(`Exporting ${snappedComponents.length} components`));
|
|
398
|
+
const exportResults = await this.exporter.export();
|
|
399
|
+
this.logger.console(_chalk().default.green(`Exported ${exportResults.componentsIds.length} components`));
|
|
400
|
+
} catch (e) {
|
|
401
|
+
foundErr = e;
|
|
402
|
+
throw e;
|
|
403
|
+
} finally {
|
|
404
|
+
if (foundErr) {
|
|
405
|
+
this.logger.console(_chalk().default.red(`Found error: ${foundErr.message}`));
|
|
406
|
+
}
|
|
407
|
+
// Whatever happens, switch back to the original lane
|
|
408
|
+
this.logger.console('🔄 Cleanup');
|
|
409
|
+
this.logger.console(_chalk().default.blue(`Switching back to ${originalLane?.name ?? 'main'}`));
|
|
410
|
+
const lane = await this.lanes.getCurrentLane();
|
|
411
|
+
if (!lane) {
|
|
412
|
+
this.logger.console(_chalk().default.yellow('Already on main, no need to switch. Checking out to head'));
|
|
413
|
+
await this.lanes.checkout.checkout({
|
|
414
|
+
head: true,
|
|
415
|
+
skipNpmInstall: true
|
|
416
|
+
});
|
|
417
|
+
} else {
|
|
418
|
+
await this.switchToLane(originalLane?.name ?? 'main');
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async mergePr({
|
|
423
|
+
message: argMessage,
|
|
424
|
+
build,
|
|
425
|
+
strict,
|
|
426
|
+
releaseType,
|
|
427
|
+
preReleaseId,
|
|
428
|
+
incrementBy,
|
|
429
|
+
explicitVersionBump,
|
|
430
|
+
verbose
|
|
431
|
+
}) {
|
|
432
|
+
const message = argMessage || (await this.getGitCommitMessage());
|
|
433
|
+
if (!message) {
|
|
434
|
+
throw new Error('Failed to get commit message from git. Please provide a message using --message option.');
|
|
435
|
+
}
|
|
436
|
+
const currentLane = await this.lanes.getCurrentLane();
|
|
437
|
+
if (currentLane) {
|
|
438
|
+
// this doesn't normally happen. we expect this mergePr to be called from the default branch, which normally checks
|
|
439
|
+
// out to main lane.
|
|
440
|
+
this.logger.console(_chalk().default.blue(`Currently on lane ${currentLane.name}, switching to main`));
|
|
441
|
+
await this.switchToLane('main');
|
|
442
|
+
this.logger.console(_chalk().default.green('Switched to main lane'));
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Pull latest changes from remote to ensure we have the most up-to-date .bitmap
|
|
446
|
+
// This prevents issues when multiple PRs are merged in sequence
|
|
447
|
+
const defaultBranch = await this.getDefaultBranchName();
|
|
448
|
+
this.logger.console(_chalk().default.blue(`Pulling latest git changes from ${defaultBranch} branch`));
|
|
449
|
+
|
|
450
|
+
// Check if there are any changes to stash before rebasing
|
|
451
|
+
const gitStatus = await _git().git.status();
|
|
452
|
+
const hasChanges = gitStatus.files.length > 0;
|
|
453
|
+
if (hasChanges) {
|
|
454
|
+
this.logger.console(_chalk().default.yellow('Stashing uncommitted changes before rebase'));
|
|
455
|
+
await _git().git.stash(['push', '-u', '-m', 'CI merge temporary stash']);
|
|
456
|
+
}
|
|
457
|
+
await _git().git.pull('origin', defaultBranch, {
|
|
458
|
+
'--rebase': 'true'
|
|
459
|
+
});
|
|
460
|
+
if (hasChanges) {
|
|
461
|
+
this.logger.console(_chalk().default.yellow('Restoring stashed changes after rebase'));
|
|
462
|
+
await _git().git.stash(['pop']);
|
|
463
|
+
}
|
|
464
|
+
this.logger.console(_chalk().default.green('Pulled latest git changes'));
|
|
465
|
+
this.logger.console('🔄 Checking out to main head');
|
|
466
|
+
await this.importer.importCurrentObjects();
|
|
467
|
+
const checkoutProps = {
|
|
468
|
+
forceOurs: true,
|
|
469
|
+
head: true,
|
|
470
|
+
skipNpmInstall: true
|
|
471
|
+
};
|
|
472
|
+
const checkoutResults = await this.checkout.checkout(checkoutProps);
|
|
473
|
+
await this.workspace.bitMap.write('checkout head');
|
|
474
|
+
this.logger.console((0, _checkout().checkoutOutput)(checkoutResults, checkoutProps));
|
|
475
|
+
const {
|
|
476
|
+
status
|
|
477
|
+
} = await this.verifyWorkspaceStatusInternal(strict);
|
|
478
|
+
const hasSoftTaggedComponents = status.softTaggedComponents.length > 0;
|
|
479
|
+
this.logger.console('📦 Component Operations');
|
|
480
|
+
this.logger.console(_chalk().default.blue('Tagging components'));
|
|
481
|
+
const finalReleaseType = await this.determineReleaseType(releaseType, explicitVersionBump);
|
|
482
|
+
const tagResults = await this.snapping.tag({
|
|
483
|
+
all: true,
|
|
484
|
+
message,
|
|
485
|
+
build,
|
|
486
|
+
failFast: true,
|
|
487
|
+
persist: hasSoftTaggedComponents,
|
|
488
|
+
releaseType: finalReleaseType,
|
|
489
|
+
preReleaseId,
|
|
490
|
+
incrementBy
|
|
491
|
+
});
|
|
492
|
+
if (tagResults) {
|
|
493
|
+
const tagOutput = (0, _snapping().tagResultOutput)(tagResults);
|
|
494
|
+
this.logger.console(tagOutput);
|
|
495
|
+
} else {
|
|
496
|
+
this.logger.console(_chalk().default.yellow('No components to tag'));
|
|
497
|
+
}
|
|
498
|
+
const hasTaggedComponents = tagResults?.taggedComponents && tagResults.taggedComponents.length > 0;
|
|
499
|
+
if (hasTaggedComponents) {
|
|
500
|
+
this.logger.console(_chalk().default.blue('Exporting components'));
|
|
501
|
+
const exportResult = await this.exporter.export();
|
|
502
|
+
if (exportResult.componentsIds.length > 0) {
|
|
503
|
+
this.logger.console(_chalk().default.green(`Exported ${exportResult.componentsIds.length} component(s)`));
|
|
504
|
+
} else {
|
|
505
|
+
this.logger.console(_chalk().default.yellow('Nothing to export'));
|
|
506
|
+
}
|
|
507
|
+
this.logger.console('🔄 Git Operations');
|
|
508
|
+
// Set user.email and user.name
|
|
509
|
+
await _git().git.addConfig('user.email', 'bit-ci[bot]@bit.cloud');
|
|
510
|
+
await _git().git.addConfig('user.name', 'Bit CI');
|
|
511
|
+
|
|
512
|
+
// Check git status before commit
|
|
513
|
+
const statusBeforeCommit = await _git().git.status();
|
|
514
|
+
this.logger.console(_chalk().default.blue(`Git status before commit: ${statusBeforeCommit.files.length} files`));
|
|
515
|
+
statusBeforeCommit.files.forEach(file => {
|
|
516
|
+
this.logger.console(_chalk().default.gray(` ${file.working_dir}${file.index} ${file.path}`));
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
// Show git diff if there are uncommitted changes
|
|
520
|
+
if (verbose && statusBeforeCommit.files.length > 0) {
|
|
521
|
+
try {
|
|
522
|
+
const diff = await _git().git.diff();
|
|
523
|
+
if (diff) {
|
|
524
|
+
this.logger.console(_chalk().default.blue('Git diff before commit:'));
|
|
525
|
+
this.logger.console(diff);
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
this.logger.console(_chalk().default.yellow(`Failed to show git diff: ${error}`));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Previously we committed only .bitmap and pnpm-lock.yaml files.
|
|
533
|
+
// However, it's possible that "bit checkout head" we did above, modified other files as well.
|
|
534
|
+
// So now we commit all files that were changed.
|
|
535
|
+
await _git().git.add(['.']);
|
|
536
|
+
const commitMessage = await this.getCustomCommitMessage();
|
|
537
|
+
await _git().git.commit(commitMessage);
|
|
538
|
+
|
|
539
|
+
// Check git status after commit
|
|
540
|
+
const statusAfterCommit = await _git().git.status();
|
|
541
|
+
this.logger.console(_chalk().default.blue(`Git status after commit: ${statusAfterCommit.files.length} files`));
|
|
542
|
+
statusAfterCommit.files.forEach(file => {
|
|
543
|
+
this.logger.console(_chalk().default.gray(` ${file.working_dir}${file.index} ${file.path}`));
|
|
544
|
+
});
|
|
545
|
+
await _git().git.pull('origin', defaultBranch, {
|
|
546
|
+
'--rebase': 'true'
|
|
547
|
+
});
|
|
548
|
+
await _git().git.push('origin', defaultBranch);
|
|
549
|
+
} else {
|
|
550
|
+
this.logger.console(_chalk().default.yellow('No components were tagged, skipping export and git operations'));
|
|
551
|
+
}
|
|
552
|
+
this.logger.console(_chalk().default.green('Merged PR'));
|
|
553
|
+
if (currentLane) {
|
|
554
|
+
this.logger.console('🗑️ Lane Cleanup');
|
|
555
|
+
const laneId = currentLane.id();
|
|
556
|
+
this.logger.console(_chalk().default.blue(`Archiving lane ${laneId}`));
|
|
557
|
+
// force means to remove the lane even if it was not merged. in this case, we don't care much because main already has the changes.
|
|
558
|
+
const archiveLane = await this.lanes.removeLanes([laneId], {
|
|
559
|
+
remote: true,
|
|
560
|
+
force: true
|
|
561
|
+
});
|
|
562
|
+
if (archiveLane.length) {
|
|
563
|
+
this.logger.console(_chalk().default.green('Lane archived'));
|
|
564
|
+
} else {
|
|
565
|
+
this.logger.console(_chalk().default.yellow('Failed to archive lane'));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
code: 0,
|
|
570
|
+
data: ''
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Auto-detect version bump from commit messages if no explicit version bump was provided
|
|
576
|
+
*/
|
|
577
|
+
async determineReleaseType(releaseType, explicitVersionBump) {
|
|
578
|
+
if (explicitVersionBump) {
|
|
579
|
+
this.logger.console(_chalk().default.blue(`Using explicit version bump: ${releaseType}`));
|
|
580
|
+
return releaseType;
|
|
581
|
+
}
|
|
582
|
+
// Only auto-detect if user didn't specify any version flags
|
|
583
|
+
const lastCommit = await this.getGitCommitMessage();
|
|
584
|
+
if (!lastCommit) {
|
|
585
|
+
this.logger.console(_chalk().default.blue('No commit message found, using default patch'));
|
|
586
|
+
return releaseType;
|
|
587
|
+
}
|
|
588
|
+
const detectedReleaseType = this.parseVersionBumpFromCommit(lastCommit);
|
|
589
|
+
if (detectedReleaseType) {
|
|
590
|
+
this.logger.console(_chalk().default.green(`Auto-detected version bump: ${detectedReleaseType}`));
|
|
591
|
+
return detectedReleaseType;
|
|
592
|
+
}
|
|
593
|
+
this.logger.console(_chalk().default.blue('No specific version bump detected, using default patch'));
|
|
594
|
+
return releaseType;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// @ts-ignore
|
|
599
|
+
exports.CiMain = CiMain;
|
|
600
|
+
_defineProperty(CiMain, "runtime", _cli().MainRuntime);
|
|
601
|
+
_defineProperty(CiMain, "dependencies", [_cli().CLIAspect, _workspace().WorkspaceAspect, _logger().LoggerAspect, _builder().BuilderAspect, _status().StatusAspect, _lanes().LanesAspect, _snapping().SnappingAspect, _export().ExportAspect, _importer().ImporterAspect, _checkout().CheckoutAspect]);
|
|
602
|
+
_defineProperty(CiMain, "slots", []);
|
|
603
|
+
_ci().CiAspect.addRuntime(CiMain);
|
|
604
|
+
|
|
605
|
+
//# sourceMappingURL=ci.main.runtime.js.map
|