@salesforce/plugin-devops-center 2.0.0 → 2.1.0
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/README.md +170 -44
- package/lib/commands/devops/pipeline/create.d.ts +1 -1
- package/lib/commands/devops/pipeline/create.js +5 -4
- package/lib/commands/devops/pipeline/create.js.map +1 -1
- package/lib/commands/devops/pipeline/stage/update.d.ts +19 -0
- package/lib/commands/devops/pipeline/stage/update.js +66 -0
- package/lib/commands/devops/pipeline/stage/update.js.map +1 -0
- package/lib/commands/devops/pipeline/update.d.ts +2 -1
- package/lib/commands/devops/pipeline/update.js +10 -4
- package/lib/commands/devops/pipeline/update.js.map +1 -1
- package/lib/commands/devops/promote.d.ts +5 -0
- package/lib/commands/devops/promote.js +49 -3
- package/lib/commands/devops/promote.js.map +1 -1
- package/lib/commands/devops/promotion/complete.d.ts +1 -1
- package/lib/commands/devops/promotion/complete.js +1 -1
- package/lib/commands/devops/promotion/complete.js.map +1 -1
- package/lib/commands/devops/promotion/validate.d.ts +21 -0
- package/lib/commands/devops/promotion/validate.js +137 -0
- package/lib/commands/devops/promotion/validate.js.map +1 -0
- package/lib/commands/devops/stage/branch/delete.d.ts +15 -0
- package/lib/commands/devops/stage/branch/delete.js +107 -0
- package/lib/commands/devops/stage/branch/delete.js.map +1 -0
- package/lib/commands/devops/work-item/prepare.js +0 -3
- package/lib/commands/devops/work-item/prepare.js.map +1 -1
- package/lib/utils/addPipelineStage.js +1 -0
- package/lib/utils/addPipelineStage.js.map +1 -1
- package/lib/utils/createPipeline.d.ts +1 -2
- package/lib/utils/createPipeline.js +28 -19
- package/lib/utils/createPipeline.js.map +1 -1
- package/lib/utils/deleteStageBranch.d.ts +22 -0
- package/lib/utils/deleteStageBranch.js +44 -0
- package/lib/utils/deleteStageBranch.js.map +1 -0
- package/lib/utils/pipelineUtils.d.ts +9 -0
- package/lib/utils/pipelineUtils.js +32 -0
- package/lib/utils/pipelineUtils.js.map +1 -1
- package/lib/utils/prepareWorkItem.d.ts +1 -1
- package/lib/utils/prepareWorkItem.js +4 -5
- package/lib/utils/prepareWorkItem.js.map +1 -1
- package/lib/utils/{deployStage.d.ts → promotionUtils.d.ts} +24 -0
- package/lib/utils/{deployStage.js → promotionUtils.js} +65 -1
- package/lib/utils/promotionUtils.js.map +1 -0
- package/lib/utils/soqlUtils.d.ts +5 -0
- package/lib/utils/soqlUtils.js +7 -0
- package/lib/utils/soqlUtils.js.map +1 -1
- package/messages/devops.pipeline.create.md +11 -7
- package/messages/devops.pipeline.stage.update.md +25 -0
- package/messages/devops.pipeline.update.md +10 -6
- package/messages/devops.promote.md +16 -0
- package/messages/devops.promotion.complete.md +3 -3
- package/messages/devops.promotion.validate.md +64 -0
- package/messages/devops.stage.branch.delete.md +37 -0
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +324 -72
- package/package.json +3 -3
- package/schemas/devops-pipeline-create.json +0 -3
- package/schemas/devops-pipeline-stage-update.json +22 -0
- package/schemas/devops-promote.json +38 -0
- package/schemas/devops-promotion-validate.json +66 -0
- package/schemas/devops-stage-branch-delete.json +47 -0
- package/lib/utils/deployStage.js.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { Messages } from '@salesforce/core';
|
|
17
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
18
|
+
import { deleteStageBranch } from '../../../../utils/deleteStageBranch.js';
|
|
19
|
+
import { computeUpstreamStageIds, fetchPipelineStages } from '../../../../utils/pipelineUtils.js';
|
|
20
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
21
|
+
const messages = Messages.loadMessages('@salesforce/plugin-devops-center', 'devops.stage.branch.delete');
|
|
22
|
+
const commonErrorMessages = Messages.loadMessages('@salesforce/plugin-devops-center', 'commonErrors');
|
|
23
|
+
export default class DevopsStageBranchDelete extends SfCommand {
|
|
24
|
+
static summary = messages.getMessage('summary');
|
|
25
|
+
static description = messages.getMessage('description');
|
|
26
|
+
static examples = messages.getMessages('examples');
|
|
27
|
+
static flags = {
|
|
28
|
+
'target-org': Flags.requiredOrg(),
|
|
29
|
+
'api-version': Flags.orgApiVersion(),
|
|
30
|
+
'pipeline-id': Flags.salesforceId({
|
|
31
|
+
summary: messages.getMessage('flags.pipeline-id.summary'),
|
|
32
|
+
required: true,
|
|
33
|
+
char: undefined,
|
|
34
|
+
}),
|
|
35
|
+
'stage-id': Flags.salesforceId({
|
|
36
|
+
summary: messages.getMessage('flags.stage-id.summary'),
|
|
37
|
+
required: true,
|
|
38
|
+
char: undefined,
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
async run() {
|
|
42
|
+
const { flags } = await this.parse(DevopsStageBranchDelete);
|
|
43
|
+
const org = flags['target-org'];
|
|
44
|
+
const connection = org.getConnection(flags['api-version']);
|
|
45
|
+
const pipelineId = flags['pipeline-id'];
|
|
46
|
+
const stageId = flags['stage-id'];
|
|
47
|
+
// The branch can only be removed while the pipeline is inactive.
|
|
48
|
+
const pipelineQueryResult = await connection.query(`SELECT IsActive FROM DevopsPipeline WHERE Id = '${pipelineId}' LIMIT 1`);
|
|
49
|
+
const pipelineRecord = (pipelineQueryResult.records ?? [])[0];
|
|
50
|
+
if (pipelineRecord?.IsActive) {
|
|
51
|
+
this.error(messages.getMessage('error.PipelineAlreadyActive', [pipelineId]));
|
|
52
|
+
}
|
|
53
|
+
let stages;
|
|
54
|
+
try {
|
|
55
|
+
stages = await fetchPipelineStages(connection, pipelineId);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
59
|
+
if (errMsg.includes('sObject type') && errMsg.includes('is not supported')) {
|
|
60
|
+
this.error(commonErrorMessages.getMessage('error.DevopsCenterNotEnabled'));
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
const targetStage = stages.find((s) => s.Id === stageId);
|
|
65
|
+
if (!targetStage) {
|
|
66
|
+
this.error(messages.getMessage('error.StageNotFound', [stageId, pipelineId]));
|
|
67
|
+
}
|
|
68
|
+
const branchName = targetStage.SourceCodeRepositoryBranch?.Name;
|
|
69
|
+
if (!branchName) {
|
|
70
|
+
this.error(messages.getMessage('error.NoBranch', [targetStage.Name ?? stageId]));
|
|
71
|
+
}
|
|
72
|
+
// Branches are configured right-to-left, so removing this stage's branch must also remove the
|
|
73
|
+
// branch from every upstream (left) stage to keep the pipeline in a valid state.
|
|
74
|
+
const upstreamStageIds = computeUpstreamStageIds(stages, stageId);
|
|
75
|
+
const stagesById = new Map(stages.map((s) => [s.Id, s]));
|
|
76
|
+
const stagesToClear = [targetStage, ...upstreamStageIds.map((id) => stagesById.get(id))]
|
|
77
|
+
.filter((s) => Boolean(s?.SourceCodeRepositoryBranch?.Name))
|
|
78
|
+
.map((s) => ({ stageId: s.Id, stageName: s.Name, branchName: s.SourceCodeRepositoryBranch?.Name }));
|
|
79
|
+
let result;
|
|
80
|
+
try {
|
|
81
|
+
result = await deleteStageBranch(connection, stageId, stagesToClear);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
85
|
+
if (errMsg.includes('sObject type') && errMsg.includes('is not supported')) {
|
|
86
|
+
this.error(commonErrorMessages.getMessage('error.DevopsCenterNotEnabled'));
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
if (result.success) {
|
|
91
|
+
this.log(`Successfully deleted branch "${result.branchName ?? ''}" from the stage.`);
|
|
92
|
+
this.log(` Stage ID: ${stageId}`);
|
|
93
|
+
this.log(` Pipeline ID: ${pipelineId}`);
|
|
94
|
+
const cascaded = (result.clearedStages ?? []).filter((s) => s.stageId !== stageId);
|
|
95
|
+
if (cascaded.length > 0) {
|
|
96
|
+
this.log('');
|
|
97
|
+
this.log('Also removed branches from upstream stages:');
|
|
98
|
+
cascaded.forEach((s) => this.log(` - ${s.stageName ?? s.stageId}: "${s.branchName ?? ''}"`));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
this.error(messages.getMessage('error.BranchDeleteFailed', [result.error ?? '']));
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../../../src/commands/devops/stage/branch/delete.ts"],"names":[],"mappings":"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"}
|
|
@@ -59,9 +59,6 @@ export default class DevopsWorkItemPrepare extends SfCommand {
|
|
|
59
59
|
}
|
|
60
60
|
throw error;
|
|
61
61
|
}
|
|
62
|
-
if (!sourceStageId) {
|
|
63
|
-
this.error(`Work item '${workItemId}' is not currently assigned to a pipeline stage.`);
|
|
64
|
-
}
|
|
65
62
|
const pipelineId = await getPipelineIdForProject(connection, projectId);
|
|
66
63
|
if (!pipelineId) {
|
|
67
64
|
this.error(`No pipeline found for work item ${workItemId}. Ensure the project has an associated pipeline.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../../../src/commands/devops/work-item/prepare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EACL,eAAe,EAEf,4BAA4B,GAC7B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,kCAAkC,EAAE,0BAA0B,CAAC,CAAC;AACvG,MAAM,mBAAmB,GAAG,QAAQ,CAAC,YAAY,CAAC,kCAAkC,EAAE,cAAc,CAAC,CAAC;AAEtG,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,SAAgC;IAC1E,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC7B,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE;QACjC,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE;QACpC,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC;YACjC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,4BAA4B,CAAC;YAC1D,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;SAClB,CAAC;QACF,iBAAiB,EAAE,KAAK,CAAC,YAAY,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,+BAA+B,CAAC;YAC7D,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;SAClB,CAAC;KACH,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;QAEzC,IAAI,SAAiB,CAAC;QACtB,IAAI,aAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,4BAA4B,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAC5E,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;YAC/B,aAAa,GAAG,QAAQ,CAAC,eAAe,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC3E,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC,CAAC;YAC7E,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../../../src/commands/devops/work-item/prepare.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addPipelineStage.js","sourceRoot":"","sources":["../../src/utils/addPipelineStage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA0BH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAA8B;IACnE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAE7D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC;QACpE,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,UAAU;QAC5B,WAAW,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"addPipelineStage.js","sourceRoot":"","sources":["../../src/utils/addPipelineStage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA0BH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAA8B;IACnE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAE7D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC;QACpE,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,UAAU;QAC5B,WAAW,EAAE,WAAW;QACxB,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAwC,CAAC;IAE9D,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC;QAC1F,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,QAAQ;SAChB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,YAAY,CAAC,EAAE;QACxB,IAAI;QACJ,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -7,19 +7,18 @@ export type RepoInfo = {
|
|
|
7
7
|
export type CreatePipelineParams = {
|
|
8
8
|
connection: Connection;
|
|
9
9
|
name: string;
|
|
10
|
-
description?: string;
|
|
11
10
|
repo: string;
|
|
12
11
|
repoType: string;
|
|
13
12
|
createRepo?: boolean;
|
|
14
13
|
repoOwner?: string;
|
|
15
14
|
bitbucketWorkspace?: string;
|
|
16
15
|
bitbucketProjectKey?: string;
|
|
16
|
+
stages?: string[];
|
|
17
17
|
};
|
|
18
18
|
export type CreatePipelineResult = {
|
|
19
19
|
success: boolean;
|
|
20
20
|
pipelineId?: string;
|
|
21
21
|
name?: string;
|
|
22
|
-
description?: string;
|
|
23
22
|
status?: string;
|
|
24
23
|
repository?: RepoInfo;
|
|
25
24
|
error?: string;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { execSync } from 'node:child_process';
|
|
17
|
-
const
|
|
17
|
+
const DEFAULT_STAGE_NAMES = ['Integration', 'UAT', 'Staging', 'Production'];
|
|
18
18
|
/**
|
|
19
19
|
* Detects repo type from a URL. Returns 'github' or 'bitbucket', or undefined.
|
|
20
20
|
*/
|
|
@@ -34,11 +34,21 @@ export function detectRepoType(repoUrl) {
|
|
|
34
34
|
* don't block the command when the check itself is unavailable.
|
|
35
35
|
*/
|
|
36
36
|
export async function validateGitHubOwner(owner, token, fetchFn = fetch) {
|
|
37
|
+
const encoded = encodeURIComponent(owner);
|
|
37
38
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
41
|
-
|
|
39
|
+
// Try user first, then org — owner may be either a personal account or an organization
|
|
40
|
+
try {
|
|
41
|
+
execSync(`gh api users/${encoded}`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
const stderr = String(e.stderr ?? '');
|
|
46
|
+
const stdout = String(e.stdout ?? '');
|
|
47
|
+
if (!stderr.includes('404') && !stdout.includes('"Not Found"'))
|
|
48
|
+
throw e;
|
|
49
|
+
// 404 on users/ — try orgs/
|
|
50
|
+
}
|
|
51
|
+
execSync(`gh api orgs/${encoded}`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
42
52
|
return;
|
|
43
53
|
}
|
|
44
54
|
catch (e) {
|
|
@@ -51,14 +61,16 @@ export async function validateGitHubOwner(owner, token, fetchFn = fetch) {
|
|
|
51
61
|
}
|
|
52
62
|
if (!token)
|
|
53
63
|
return;
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
const headers = {
|
|
65
|
+
Accept: 'application/vnd.github+json',
|
|
66
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
67
|
+
Authorization: `Bearer ${token}`,
|
|
68
|
+
};
|
|
69
|
+
const userRes = await fetchFn(`https://api.github.com/users/${encoded}`, { headers });
|
|
70
|
+
if (userRes.status !== 404)
|
|
71
|
+
return;
|
|
72
|
+
const orgRes = await fetchFn(`https://api.github.com/orgs/${encoded}`, { headers });
|
|
73
|
+
if (orgRes.status === 404)
|
|
62
74
|
throw new GitHubOwnerNotFoundError(owner);
|
|
63
75
|
// 403 or other non-404: skip validation
|
|
64
76
|
}
|
|
@@ -74,12 +86,13 @@ export class GitHubOwnerNotFoundError extends Error {
|
|
|
74
86
|
* POST /services/data/v{version}/connect/devops/pipelines
|
|
75
87
|
*/
|
|
76
88
|
export async function createPipeline(params) {
|
|
77
|
-
const { connection, name,
|
|
89
|
+
const { connection, name, repo, repoType, createRepo, repoOwner, bitbucketWorkspace, bitbucketProjectKey, stages } = params;
|
|
78
90
|
const path = `/services/data/v${connection.getApiVersion()}/connect/devops/pipelines`;
|
|
91
|
+
const stageNames = stages && stages.length > 0 ? stages : DEFAULT_STAGE_NAMES;
|
|
79
92
|
const payload = {
|
|
80
93
|
name,
|
|
81
94
|
vcsType: repoType,
|
|
82
|
-
stages:
|
|
95
|
+
stages: stageNames.map((stageName) => ({ name: stageName })),
|
|
83
96
|
};
|
|
84
97
|
if (createRepo) {
|
|
85
98
|
payload.createVcsRepo = true;
|
|
@@ -98,9 +111,6 @@ export async function createPipeline(params) {
|
|
|
98
111
|
else {
|
|
99
112
|
payload.vcsRepoUrl = repo;
|
|
100
113
|
}
|
|
101
|
-
if (description) {
|
|
102
|
-
payload.description = description;
|
|
103
|
-
}
|
|
104
114
|
const data = await connection.request({
|
|
105
115
|
method: 'POST',
|
|
106
116
|
url: path,
|
|
@@ -111,7 +121,6 @@ export async function createPipeline(params) {
|
|
|
111
121
|
success: true,
|
|
112
122
|
pipelineId: data.id,
|
|
113
123
|
name,
|
|
114
|
-
description,
|
|
115
124
|
status: data.status ?? 'Inactive',
|
|
116
125
|
repository: {
|
|
117
126
|
repoUrl: repo,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPipeline.js","sourceRoot":"","sources":["../../src/utils/createPipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"createPipeline.js","sourceRoot":"","sources":["../../src/utils/createPipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAoC9C,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAE5E;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,QAAQ,CAAC;IAClD,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC;QAAE,OAAO,WAAW,CAAC;IACxD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAAa,EAAE,KAAc,EAAE,UAAwB,KAAK;IACpG,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,uFAAuF;QACvF,IAAI,CAAC;YACH,QAAQ,CAAC,gBAAgB,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YAC5F,OAAO;QACT,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,MAAM,CAAE,CAAyB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC/D,MAAM,MAAM,GAAG,MAAM,CAAE,CAAyB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC/D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAAE,MAAM,CAAC,CAAC;YACxE,4BAA4B;QAC9B,CAAC;QACD,QAAQ,CAAC,eAAe,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3F,OAAO;IACT,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAE,CAAyB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAE,CAAyB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QACD,4EAA4E;IAC9E,CAAC;IAED,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,6BAA6B;QACrC,sBAAsB,EAAE,YAAY;QACpC,aAAa,EAAE,UAAU,KAAK,EAAE;KACjC,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,gCAAgC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACtF,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO;IACnC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,+BAA+B,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACpF,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG;QAAE,MAAM,IAAI,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACrE,wCAAwC;AAC1C,CAAC;AAED,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjC,KAAK,CAAS;IAC9B,YAAmB,KAAa;QAC9B,KAAK,CAAC,iBAAiB,KAAK,kBAAkB,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAA4B;IAC/D,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAChH,MAAM,CAAC;IAET,MAAM,IAAI,GAAG,mBAAmB,UAAU,CAAC,aAAa,EAAE,2BAA2B,CAAC;IAEtF,MAAM,UAAU,GAAG,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAE9E,MAAM,OAAO,GAA4B;QACvC,IAAI;QACJ,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;KAC7D,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;QAC7B,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;QAE3B,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC7B,MAAM,YAAY,GAA2B,EAAE,kBAAkB,EAAE,kBAAmB,EAAE,CAAC;YACzF,IAAI,mBAAmB,EAAE,CAAC;gBACxB,YAAY,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;YACzD,CAAC;YACD,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;QACnC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAA0B;QAC7D,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,IAAI;QACT,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QAC7B,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,IAAI,CAAC,EAAE;QACnB,IAAI;QACJ,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,UAAU;QACjC,UAAU,EAAE;YACV,OAAO,EAAE,IAAI;YACb,QAAQ;YACR,OAAO,EAAE,UAAU,IAAI,KAAK;SAC7B;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
export type ClearedStage = {
|
|
3
|
+
stageId: string;
|
|
4
|
+
stageName?: string;
|
|
5
|
+
branchName?: string;
|
|
6
|
+
};
|
|
7
|
+
export type DeleteStageBranchResult = {
|
|
8
|
+
success: boolean;
|
|
9
|
+
stageId: string;
|
|
10
|
+
branchName?: string;
|
|
11
|
+
clearedStages?: ClearedStage[];
|
|
12
|
+
error?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Removes the branch associated with a pipeline stage, cascading to every upstream (left) stage.
|
|
16
|
+
*
|
|
17
|
+
* Branches are configured right-to-left, so a stage can only have a branch once the stage to its
|
|
18
|
+
* right does. Clearing a branch therefore also clears the branch on every upstream stage to keep
|
|
19
|
+
* the pipeline in a valid state. Each stage's SourceCodeRepositoryBranchId lookup is cleared; the
|
|
20
|
+
* branch records themselves are left untouched.
|
|
21
|
+
*/
|
|
22
|
+
export declare function deleteStageBranch(connection: Connection, targetStageId: string, stagesToClear: ClearedStage[]): Promise<DeleteStageBranchResult>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { validateSalesforceId } from './soqlUtils.js';
|
|
17
|
+
/**
|
|
18
|
+
* Removes the branch associated with a pipeline stage, cascading to every upstream (left) stage.
|
|
19
|
+
*
|
|
20
|
+
* Branches are configured right-to-left, so a stage can only have a branch once the stage to its
|
|
21
|
+
* right does. Clearing a branch therefore also clears the branch on every upstream stage to keep
|
|
22
|
+
* the pipeline in a valid state. Each stage's SourceCodeRepositoryBranchId lookup is cleared; the
|
|
23
|
+
* branch records themselves are left untouched.
|
|
24
|
+
*/
|
|
25
|
+
export async function deleteStageBranch(connection, targetStageId, stagesToClear) {
|
|
26
|
+
validateSalesforceId(targetStageId, 'stage');
|
|
27
|
+
stagesToClear.forEach((s) => validateSalesforceId(s.stageId, 'stage'));
|
|
28
|
+
const updates = stagesToClear.map((s) => ({ Id: s.stageId, SourceCodeRepositoryBranchId: null }));
|
|
29
|
+
const rawResults = await connection.sobject('DevopsPipelineStage').update(updates);
|
|
30
|
+
const results = (Array.isArray(rawResults) ? rawResults : [rawResults]);
|
|
31
|
+
const failures = results.filter((r) => !r.success);
|
|
32
|
+
if (failures.length > 0) {
|
|
33
|
+
const errorMsg = failures.flatMap((r) => r.errors?.map((e) => e.message) ?? ['Unknown error']).join('; ');
|
|
34
|
+
return { success: false, stageId: targetStageId, error: errorMsg };
|
|
35
|
+
}
|
|
36
|
+
const target = stagesToClear.find((s) => s.stageId === targetStageId);
|
|
37
|
+
return {
|
|
38
|
+
success: true,
|
|
39
|
+
stageId: targetStageId,
|
|
40
|
+
branchName: target?.branchName,
|
|
41
|
+
clearedStages: stagesToClear,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=deleteStageBranch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deleteStageBranch.js","sourceRoot":"","sources":["../../src/utils/deleteStageBranch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAgBtD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAsB,EACtB,aAAqB,EACrB,aAA6B;IAE7B,oBAAoB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC7C,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClG,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnF,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAGpE,CAAC;IAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1G,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,aAAa,CAAC,CAAC;IACtE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,aAAa;QACtB,UAAU,EAAE,MAAM,EAAE,UAAU;QAC9B,aAAa,EAAE,aAAa;KAC7B,CAAC;AACJ,CAAC"}
|
|
@@ -6,3 +6,12 @@ export declare function computeFirstStageId(stages: PipelineStageRecord[]): stri
|
|
|
6
6
|
export declare function resolveTargetStageId(currentStageId: string | undefined, stages: PipelineStageRecord[]): string | undefined;
|
|
7
7
|
export declare function findStageById(stages: PipelineStageRecord[], stageId: string | undefined): PipelineStageRecord | undefined;
|
|
8
8
|
export declare function getBranchNameFromStage(stage: PipelineStageRecord | undefined): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the IDs of all stages upstream (to the left) of the given stage, i.e. every stage
|
|
11
|
+
* whose promotion path eventually reaches it by following NextStageId. The target stage itself
|
|
12
|
+
* is not included. Order is nearest-to-farthest from the target.
|
|
13
|
+
*
|
|
14
|
+
* Branches are configured right-to-left (a stage can only have a branch once the stage to its
|
|
15
|
+
* right does), so removing a branch must cascade to every upstream stage to keep the pipeline valid.
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeUpstreamStageIds(stages: PipelineStageRecord[], stageId: string): string[];
|
|
@@ -51,4 +51,36 @@ export function findStageById(stages, stageId) {
|
|
|
51
51
|
export function getBranchNameFromStage(stage) {
|
|
52
52
|
return stage?.SourceCodeRepositoryBranch?.Name ?? undefined;
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns the IDs of all stages upstream (to the left) of the given stage, i.e. every stage
|
|
56
|
+
* whose promotion path eventually reaches it by following NextStageId. The target stage itself
|
|
57
|
+
* is not included. Order is nearest-to-farthest from the target.
|
|
58
|
+
*
|
|
59
|
+
* Branches are configured right-to-left (a stage can only have a branch once the stage to its
|
|
60
|
+
* right does), so removing a branch must cascade to every upstream stage to keep the pipeline valid.
|
|
61
|
+
*/
|
|
62
|
+
export function computeUpstreamStageIds(stages, stageId) {
|
|
63
|
+
const predecessorsByStageId = new Map();
|
|
64
|
+
for (const stage of stages) {
|
|
65
|
+
if (stage.NextStageId) {
|
|
66
|
+
const predecessors = predecessorsByStageId.get(stage.NextStageId) ?? [];
|
|
67
|
+
predecessors.push(stage.Id);
|
|
68
|
+
predecessorsByStageId.set(stage.NextStageId, predecessors);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const upstream = [];
|
|
72
|
+
const seen = new Set([stageId]);
|
|
73
|
+
const queue = [stageId];
|
|
74
|
+
while (queue.length > 0) {
|
|
75
|
+
const current = queue.shift();
|
|
76
|
+
for (const predecessorId of predecessorsByStageId.get(current) ?? []) {
|
|
77
|
+
if (!seen.has(predecessorId)) {
|
|
78
|
+
seen.add(predecessorId);
|
|
79
|
+
upstream.push(predecessorId);
|
|
80
|
+
queue.push(predecessorId);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return upstream;
|
|
85
|
+
}
|
|
54
86
|
//# sourceMappingURL=pipelineUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipelineUtils.js","sourceRoot":"","sources":["../../src/utils/pipelineUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,UAAsB,EAAE,SAAiB;IACrF,oBAAoB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,+EAA+E,SAAS,WAAW,CAAC;IAClH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAmC,KAAK,CAAC,CAAC;IAC/E,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAsB,EAAE,UAAkB;IAClF,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,oHAAoH,UAAU,GAAG,CAAC;IACrJ,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,KAAK,CAAsB,UAAU,CAAC,CAAC;IAC5E,OAAO,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAA6B;IAC/D,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC,CAAC;IACnG,MAAM,aAAa,GAAa,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACjD,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,cAAkC,EAClC,MAA6B;IAE7B,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACrC,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,CAAC;QAC5D,OAAO,OAAO,EAAE,WAAW,IAAI,SAAS,CAAC;IAC3C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAA6B,EAC7B,OAA2B;IAE3B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAsC;IAC3E,OAAO,KAAK,EAAE,0BAA0B,EAAE,IAAI,IAAI,SAAS,CAAC;AAC9D,CAAC"}
|
|
1
|
+
{"version":3,"file":"pipelineUtils.js","sourceRoot":"","sources":["../../src/utils/pipelineUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,11 +22,10 @@ import { validateSalesforceId } from './soqlUtils.js';
|
|
|
22
22
|
export async function prepareWorkItem(params) {
|
|
23
23
|
const { connection, pipelineId, workItemId, sourceStageId, targetStageId } = params;
|
|
24
24
|
const path = `/services/data/v${connection.getApiVersion()}/connect/devops/pipelines/${pipelineId}/promote/oneoff/prepare`;
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
sourceStageId
|
|
28
|
-
|
|
29
|
-
});
|
|
25
|
+
const payload = { selectedWorkItemId: workItemId, targetStageId };
|
|
26
|
+
if (sourceStageId)
|
|
27
|
+
payload.sourceStageId = sourceStageId;
|
|
28
|
+
const body = JSON.stringify(payload);
|
|
30
29
|
const data = await connection.request({
|
|
31
30
|
method: 'POST',
|
|
32
31
|
url: path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepareWorkItem.js","sourceRoot":"","sources":["../../src/utils/prepareWorkItem.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAwBtD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAA6B;IACjE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAEpF,MAAM,IAAI,GAAG,mBAAmB,UAAU,CAAC,aAAa,EAAE,6BAA6B,UAAU,yBAAyB,CAAC;IAC3H,MAAM,
|
|
1
|
+
{"version":3,"file":"prepareWorkItem.js","sourceRoot":"","sources":["../../src/utils/prepareWorkItem.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAwBtD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAA6B;IACjE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAEpF,MAAM,IAAI,GAAG,mBAAmB,UAAU,CAAC,aAAa,EAAE,6BAA6B,UAAU,yBAAyB,CAAC;IAC3H,MAAM,OAAO,GAA2B,EAAE,kBAAkB,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;IAC1F,IAAI,aAAa;QAAE,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAErC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAiC;QACpE,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,IAAI;QACT,IAAI;QACJ,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;QAC7B,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;QACvC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;KACxC,CAAC;AACJ,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,UAAsB,EACtB,UAAkB;IAElB,oBAAoB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CACnC,2EAA2E,UAAU,WAAW,CACjG,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,cAAc,UAAU,qDAAqD,CAAC,CAAC;IACjG,CAAC;IACD,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,eAAe;QACrC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,qBAAqB,IAAI,EAAE;KACxD,CAAC;AACJ,CAAC"}
|
|
@@ -13,6 +13,24 @@ export type DeployStageResult = {
|
|
|
13
13
|
message: string;
|
|
14
14
|
promotedWorkitemIds: string[];
|
|
15
15
|
};
|
|
16
|
+
/** Maps a comma-separated list of work item names to the components they share. */
|
|
17
|
+
export type SharedComponentsList = Record<string, string[]>;
|
|
18
|
+
export type CombineDetails = {
|
|
19
|
+
childWorkitemsId?: string[];
|
|
20
|
+
parentWorkitemId?: string;
|
|
21
|
+
sharedComponentsList?: SharedComponentsList;
|
|
22
|
+
} & Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns true when the combine details describe work items that share one or more components.
|
|
25
|
+
* Shared components mean the work items can optionally be combined before promotion.
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasSharedComponents(combineDetails: CombineDetails | null): boolean;
|
|
28
|
+
export type ValidatePromotionResult = {
|
|
29
|
+
success: boolean;
|
|
30
|
+
errorType: string | null;
|
|
31
|
+
errorDetails: string | null;
|
|
32
|
+
combineDetails: CombineDetails | null;
|
|
33
|
+
};
|
|
16
34
|
/**
|
|
17
35
|
* GET /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/stages/{stageId}/undeployedWorkitems
|
|
18
36
|
*/
|
|
@@ -21,6 +39,12 @@ export declare function getUndeployedWorkItems(connection: Connection, pipelineI
|
|
|
21
39
|
* POST /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/validatePromote
|
|
22
40
|
*/
|
|
23
41
|
export declare function validateDeploy(connection: Connection, pipelineId: string, workItemIds: string[], targetStageId: string): Promise<ValidateDeployResult>;
|
|
42
|
+
export declare function formatValidationDetails(raw: string | null): string;
|
|
43
|
+
/**
|
|
44
|
+
* POST /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/validatePromote
|
|
45
|
+
* Full variant that accepts checkCombineDetails and returns combineDetails.
|
|
46
|
+
*/
|
|
47
|
+
export declare function validatePromotion(connection: Connection, pipelineId: string, workItemIds: string[], targetStageId: string, checkCombineDetails?: boolean, allWorkItemsInStage?: boolean): Promise<ValidatePromotionResult>;
|
|
24
48
|
/**
|
|
25
49
|
* POST /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/promote
|
|
26
50
|
* When workItemIds are provided, targets those specific items (allWorkItemsInStage: false).
|
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { normalizeSalesforceId } from './soqlUtils.js';
|
|
17
|
+
/**
|
|
18
|
+
* Returns true when the combine details describe work items that share one or more components.
|
|
19
|
+
* Shared components mean the work items can optionally be combined before promotion.
|
|
20
|
+
*/
|
|
21
|
+
export function hasSharedComponents(combineDetails) {
|
|
22
|
+
const shared = combineDetails?.sharedComponentsList;
|
|
23
|
+
return Boolean(shared && Object.keys(shared).length > 0);
|
|
24
|
+
}
|
|
16
25
|
/**
|
|
17
26
|
* GET /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/stages/{stageId}/undeployedWorkitems
|
|
18
27
|
*/
|
|
@@ -38,6 +47,61 @@ export async function validateDeploy(connection, pipelineId, workItemIds, target
|
|
|
38
47
|
errorDetails: response.errorDetails ?? null,
|
|
39
48
|
};
|
|
40
49
|
}
|
|
50
|
+
const VALIDATION_REASON_LABELS = {
|
|
51
|
+
PR_DOES_NOT_EXIST: 'no pull request exists',
|
|
52
|
+
PR_NOT_MERGED: 'pull request has not been merged',
|
|
53
|
+
BRANCH_NOT_FOUND: 'source branch not found',
|
|
54
|
+
};
|
|
55
|
+
export function formatValidationDetails(raw) {
|
|
56
|
+
if (!raw)
|
|
57
|
+
return '';
|
|
58
|
+
const decoded = raw
|
|
59
|
+
.replace(/"/g, '"')
|
|
60
|
+
.replace(/&/g, '&')
|
|
61
|
+
.replace(/</g, '<')
|
|
62
|
+
.replace(/>/g, '>');
|
|
63
|
+
try {
|
|
64
|
+
const parsed = JSON.parse(decoded);
|
|
65
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
66
|
+
return parsed
|
|
67
|
+
.map((entry) => {
|
|
68
|
+
const label = entry.reason ? VALIDATION_REASON_LABELS[entry.reason] ?? entry.reason : '';
|
|
69
|
+
return entry.workItem ? `${entry.workItem}: ${label}` : label;
|
|
70
|
+
})
|
|
71
|
+
.join(', ');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// not JSON — fall through
|
|
76
|
+
}
|
|
77
|
+
return decoded;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* POST /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/validatePromote
|
|
81
|
+
* Full variant that accepts checkCombineDetails and returns combineDetails.
|
|
82
|
+
*/
|
|
83
|
+
export async function validatePromotion(connection, pipelineId, workItemIds, targetStageId, checkCombineDetails = false, allWorkItemsInStage = false) {
|
|
84
|
+
const path = `/services/data/v${connection.getApiVersion()}/connect/devops/pipelines/${pipelineId}/validatePromote`;
|
|
85
|
+
const payload = {
|
|
86
|
+
selectedWorkItemIds: workItemIds.map(normalizeSalesforceId),
|
|
87
|
+
targetStageId: normalizeSalesforceId(targetStageId),
|
|
88
|
+
allWorkItemsInStage,
|
|
89
|
+
};
|
|
90
|
+
if (checkCombineDetails)
|
|
91
|
+
payload.checkCombineDetails = true;
|
|
92
|
+
const response = await connection.request({
|
|
93
|
+
method: 'POST',
|
|
94
|
+
url: path,
|
|
95
|
+
body: JSON.stringify(payload),
|
|
96
|
+
headers: { 'Content-Type': 'application/json' },
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
success: response.success ?? true,
|
|
100
|
+
errorType: response.errorType ?? null,
|
|
101
|
+
errorDetails: response.errorDetails ?? null,
|
|
102
|
+
combineDetails: response.combineDetails ?? null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
41
105
|
/**
|
|
42
106
|
* POST /services/data/vXX.X/connect/devops/pipelines/{pipelineId}/promote
|
|
43
107
|
* When workItemIds are provided, targets those specific items (allWorkItemsInStage: false).
|
|
@@ -65,4 +129,4 @@ export async function executeDeploy(connection, pipelineId, targetStageId, fullD
|
|
|
65
129
|
promotedWorkitemIds: response.promotedWorkitemIds ?? [],
|
|
66
130
|
};
|
|
67
131
|
}
|
|
68
|
-
//# sourceMappingURL=
|
|
132
|
+
//# sourceMappingURL=promotionUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promotionUtils.js","sourceRoot":"","sources":["../../src/utils/promotionUtils.ts"],"names":[],"mappings":"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"}
|
package/lib/utils/soqlUtils.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export declare function escapeSOQL(value: string): string;
|
|
|
11
11
|
* Use this before interpolating IDs into SOQL queries.
|
|
12
12
|
*/
|
|
13
13
|
export declare function validateSalesforceId(id: string, context?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Trims an 18-character Salesforce ID to its 15-character form.
|
|
16
|
+
* 15-char IDs are returned unchanged. Accepts IDs that have already passed validateSalesforceId.
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeSalesforceId(id: string): string;
|
|
14
19
|
/**
|
|
15
20
|
* Validates that a string starts with the expected Salesforce object prefix.
|
|
16
21
|
* Throws an error if validation fails.
|
package/lib/utils/soqlUtils.js
CHANGED
|
@@ -39,6 +39,13 @@ export function validateSalesforceId(id, context) {
|
|
|
39
39
|
}
|
|
40
40
|
return id;
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Trims an 18-character Salesforce ID to its 15-character form.
|
|
44
|
+
* 15-char IDs are returned unchanged. Accepts IDs that have already passed validateSalesforceId.
|
|
45
|
+
*/
|
|
46
|
+
export function normalizeSalesforceId(id) {
|
|
47
|
+
return id.length === 18 ? id.slice(0, 15) : id;
|
|
48
|
+
}
|
|
42
49
|
/**
|
|
43
50
|
* Validates that a string starts with the expected Salesforce object prefix.
|
|
44
51
|
* Throws an error if validation fails.
|