@simplysf/simply-cicd-core 0.2.2 → 0.4.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 +32 -3
- package/lib/build/checkPermissionSets.d.ts +22 -0
- package/lib/build/checkPermissionSets.js +102 -0
- package/lib/build/checkPermissionSets.js.map +1 -0
- package/lib/build/cleanupScratchOrgs.d.ts +6 -0
- package/lib/build/cleanupScratchOrgs.js +91 -0
- package/lib/build/cleanupScratchOrgs.js.map +1 -0
- package/lib/build/createFallbackTag.d.ts +24 -0
- package/lib/build/createFallbackTag.js +147 -0
- package/lib/build/createFallbackTag.js.map +1 -0
- package/lib/build/createPackageVersion.d.ts +42 -0
- package/lib/build/createPackageVersion.js +191 -0
- package/lib/build/createPackageVersion.js.map +1 -0
- package/lib/build/createScratchOrg.d.ts +14 -0
- package/lib/build/createScratchOrg.js +182 -0
- package/lib/build/createScratchOrg.js.map +1 -0
- package/lib/build/deleteScratchOrg.d.ts +13 -0
- package/lib/build/deleteScratchOrg.js +62 -0
- package/lib/build/deleteScratchOrg.js.map +1 -0
- package/lib/build/deltaRunner.d.ts +73 -0
- package/lib/build/deltaRunner.js +109 -0
- package/lib/build/deltaRunner.js.map +1 -0
- package/lib/build/determinePackageChanges.d.ts +11 -0
- package/lib/build/determinePackageChanges.js +90 -0
- package/lib/build/determinePackageChanges.js.map +1 -0
- package/lib/build/devHubs.d.ts +12 -0
- package/lib/build/devHubs.js +42 -0
- package/lib/build/devHubs.js.map +1 -0
- package/lib/build/flexipageDelta.d.ts +18 -0
- package/lib/build/flexipageDelta.js +35 -0
- package/lib/build/flexipageDelta.js.map +1 -0
- package/lib/build/flowDelta.d.ts +17 -0
- package/lib/build/flowDelta.js +34 -0
- package/lib/build/flowDelta.js.map +1 -0
- package/lib/build/installDependencies.d.ts +10 -0
- package/lib/build/installDependencies.js +39 -0
- package/lib/build/installDependencies.js.map +1 -0
- package/lib/build/lwcJest.d.ts +25 -0
- package/lib/build/lwcJest.js +126 -0
- package/lib/build/lwcJest.js.map +1 -0
- package/lib/build/publishUtamPageObjects.d.ts +50 -0
- package/lib/build/publishUtamPageObjects.js +274 -0
- package/lib/build/publishUtamPageObjects.js.map +1 -0
- package/lib/build/pushScratch.d.ts +9 -0
- package/lib/build/pushScratch.js +60 -0
- package/lib/build/pushScratch.js.map +1 -0
- package/lib/build/scratchOrgAuth.d.ts +18 -0
- package/lib/build/scratchOrgAuth.js +52 -0
- package/lib/build/scratchOrgAuth.js.map +1 -0
- package/lib/build/scratchOrgInfo.d.ts +14 -0
- package/lib/build/scratchOrgInfo.js +21 -0
- package/lib/build/scratchOrgInfo.js.map +1 -0
- package/lib/build/skipGuard.d.ts +8 -0
- package/lib/build/skipGuard.js +42 -0
- package/lib/build/skipGuard.js.map +1 -0
- package/lib/build/testScratch.d.ts +15 -0
- package/lib/build/testScratch.js +42 -0
- package/lib/build/testScratch.js.map +1 -0
- package/lib/build/utamPageObjects.d.ts +143 -0
- package/lib/build/utamPageObjects.js +258 -0
- package/lib/build/utamPageObjects.js.map +1 -0
- package/lib/build/versionTagFormat.d.ts +57 -0
- package/lib/build/versionTagFormat.js +194 -0
- package/lib/build/versionTagFormat.js.map +1 -0
- package/lib/config/defaultDeploymentPlugins.d.ts +2 -0
- package/lib/config/defaultDeploymentPlugins.js +18 -0
- package/lib/config/defaultDeploymentPlugins.js.map +1 -0
- package/lib/config/trustedPlugins.d.ts +2 -0
- package/lib/config/trustedPlugins.js +18 -0
- package/lib/config/trustedPlugins.js.map +1 -0
- package/lib/deploy/deployCommon.d.ts +105 -0
- package/lib/deploy/deployCommon.js +358 -0
- package/lib/deploy/deployCommon.js.map +1 -0
- package/lib/deploy/deployHappySoup.d.ts +56 -0
- package/lib/deploy/deployHappySoup.js +159 -0
- package/lib/deploy/deployHappySoup.js.map +1 -0
- package/lib/deploy/deployProject.d.ts +27 -0
- package/lib/deploy/deployProject.js +114 -0
- package/lib/deploy/deployProject.js.map +1 -0
- package/lib/deploy/runDeployStage.d.ts +16 -0
- package/lib/deploy/runDeployStage.js +65 -0
- package/lib/deploy/runDeployStage.js.map +1 -0
- package/lib/deploy/stageOptions.d.ts +49 -0
- package/lib/deploy/stageOptions.js +70 -0
- package/lib/deploy/stageOptions.js.map +1 -0
- package/lib/deploy/validate.d.ts +11 -0
- package/lib/deploy/validate.js +54 -0
- package/lib/deploy/validate.js.map +1 -0
- package/lib/env.d.ts +9 -0
- package/lib/env.js +47 -0
- package/lib/env.js.map +1 -0
- package/lib/exec/sfCli.d.ts +27 -0
- package/lib/exec/sfCli.js +50 -0
- package/lib/exec/sfCli.js.map +1 -0
- package/lib/flags/env.d.ts +44 -0
- package/lib/flags/env.js +81 -0
- package/lib/flags/env.js.map +1 -0
- package/lib/git.d.ts +32 -0
- package/lib/git.js +106 -0
- package/lib/git.js.map +1 -0
- package/lib/happySoup/resolveOriginProject.d.ts +22 -0
- package/lib/happySoup/resolveOriginProject.js +61 -0
- package/lib/happySoup/resolveOriginProject.js.map +1 -0
- package/lib/index.d.ts +52 -0
- package/lib/index.js +64 -2
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +10 -0
- package/lib/logger.js +33 -0
- package/lib/logger.js.map +1 -0
- package/lib/notify/buildNotification.d.ts +53 -0
- package/lib/notify/buildNotification.js +176 -0
- package/lib/notify/buildNotification.js.map +1 -0
- package/lib/notify/getCommitStories.d.ts +30 -0
- package/lib/notify/getCommitStories.js +70 -0
- package/lib/notify/getCommitStories.js.map +1 -0
- package/lib/notify/getRemoteCommitStories.d.ts +10 -0
- package/lib/notify/getRemoteCommitStories.js +45 -0
- package/lib/notify/getRemoteCommitStories.js.map +1 -0
- package/lib/notify/happySoupNotification.d.ts +26 -0
- package/lib/notify/happySoupNotification.js +140 -0
- package/lib/notify/happySoupNotification.js.map +1 -0
- package/lib/notify/projectNotification.d.ts +46 -0
- package/lib/notify/projectNotification.js +167 -0
- package/lib/notify/projectNotification.js.map +1 -0
- package/lib/notify/renderTemplate.d.ts +3 -0
- package/lib/notify/renderTemplate.js +24 -0
- package/lib/notify/renderTemplate.js.map +1 -0
- package/lib/notify/sendNotification.d.ts +2 -0
- package/lib/notify/sendNotification.js +50 -0
- package/lib/notify/sendNotification.js.map +1 -0
- package/lib/notify/templates.d.ts +13 -0
- package/lib/notify/templates.js +118 -0
- package/lib/notify/templates.js.map +1 -0
- package/lib/schemas/deployConfig.d.ts +25 -0
- package/lib/schemas/deployConfig.js +55 -0
- package/lib/schemas/deployConfig.js.map +1 -0
- package/lib/schemas/deployProgress.d.ts +33 -0
- package/lib/schemas/deployProgress.js +46 -0
- package/lib/schemas/deployProgress.js.map +1 -0
- package/lib/schemas/deployRules.d.ts +34 -0
- package/lib/schemas/deployRules.js +40 -0
- package/lib/schemas/deployRules.js.map +1 -0
- package/lib/sfApex.d.ts +22 -0
- package/lib/sfApex.js +169 -0
- package/lib/sfApex.js.map +1 -0
- package/lib/sfAuth.d.ts +19 -0
- package/lib/sfAuth.js +78 -0
- package/lib/sfAuth.js.map +1 -0
- package/lib/sfConfig.d.ts +23 -0
- package/lib/sfConfig.js +82 -0
- package/lib/sfConfig.js.map +1 -0
- package/lib/sfOrg.d.ts +13 -0
- package/lib/sfOrg.js +39 -0
- package/lib/sfOrg.js.map +1 -0
- package/lib/sfPackages.d.ts +63 -0
- package/lib/sfPackages.js +185 -0
- package/lib/sfPackages.js.map +1 -0
- package/lib/sfPlugins.d.ts +11 -0
- package/lib/sfPlugins.js +134 -0
- package/lib/sfPlugins.js.map +1 -0
- package/lib/sfdxDependabot/dependabotRun.d.ts +95 -0
- package/lib/sfdxDependabot/dependabotRun.js +287 -0
- package/lib/sfdxDependabot/dependabotRun.js.map +1 -0
- package/lib/sfdxDependabot/updater.d.ts +14 -0
- package/lib/sfdxDependabot/updater.js +94 -0
- package/lib/sfdxDependabot/updater.js.map +1 -0
- package/package.json +16 -4
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://npmjs.com/@simplysf/simply-cicd-core) [](https://npmjs.com/@simplysf/simply-cicd-core) [](https://raw.githubusercontent.com/SimplySF/simply-plugins-core/main/LICENSE.txt)
|
|
4
4
|
|
|
5
|
-
ALM issue linking (Jira, GitLab Issues) and VCS API clients (GitHub, GitLab). This is not a Salesforce CLI plugin — it's the library layer behind [`@simplysf/simply-cicd`](https://github.com/SimplySF/simply-plugins/tree/main/packages/simply-cicd)
|
|
5
|
+
Salesforce CI/CD pipeline stages (build, deploy, notify, sfdx-dependabot), ALM issue linking (Jira, GitLab Issues) and VCS API clients (GitHub, GitLab). This is not a Salesforce CLI plugin — it's the library layer behind [`@simplysf/simply-cicd`](https://github.com/SimplySF/simply-plugins/tree/main/packages/simply-cicd), published separately so it can be imported directly by anything that wants the same logic (a bot, a script, a CI job) without pulling in the CLI framework.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`@simplysf/simply-cicd` is a thin command layer over this package: its commands parse flags and call the functions below. Only its oclif flag declarations stay in the plugin. See [docs/design/0037-simply-cicd-core.md](https://github.com/SimplySF/simply-plugins-core/blob/main/docs/design/0037-simply-cicd-core.md) for the original `alm/`/`vcs/` split and [docs/design/0053-simply-cicd-core-common.md](https://github.com/SimplySF/simply-plugins-core/blob/main/docs/design/0053-simply-cicd-core-common.md) for the move of everything else.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -12,10 +12,12 @@ Only `alm/` and `vcs/` moved here — `@simplysf/simply-cicd` itself still owns
|
|
|
12
12
|
npm install @simplysf/simply-cicd-core
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Requires Node.js `>=22` and either `"type": "module"` or a dynamic `import()` — this package ships ESM only.
|
|
15
|
+
Requires Node.js `>=22` and either `"type": "module"` or a dynamic `import()` — this package ships ESM only. `vcs/`'s GitHub/GitLab clients use the platform `fetch`. The pipeline stages shell out to the `sf` and `git` binaries (via `execa`), so those must be on `PATH` wherever a stage runs, and they write `[SIMPLY-CICD]`-prefixed progress output to the console.
|
|
16
16
|
|
|
17
17
|
## API
|
|
18
18
|
|
|
19
|
+
### ALM and VCS
|
|
20
|
+
|
|
19
21
|
Everything below is exported from the package root. Removing or renaming an export is a breaking change; see [`src/index.ts`](src/index.ts).
|
|
20
22
|
|
|
21
23
|
| Export | Description |
|
|
@@ -51,6 +53,33 @@ const gitlab = createVcsProvider('gitlab', { token: process.env.GITLAB_TOKEN });
|
|
|
51
53
|
const mr = await gitlab.findMergeRequest({ sourceBranch: 'feature/x' });
|
|
52
54
|
```
|
|
53
55
|
|
|
56
|
+
### Pipeline stages
|
|
57
|
+
|
|
58
|
+
The modules `@simplysf/simply-cicd`'s commands run, also exported from the package root. Each stage function takes a plain options object (the camelCase equivalent of the command's flags) and throws on failure. Full signatures are in the [API reference](https://simplysf.github.io/simply-plugins-core/api/simply-cicd-core/readme/).
|
|
59
|
+
|
|
60
|
+
| Area | Main exports |
|
|
61
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
62
|
+
| Build | `createScratchOrg`, `deleteScratchOrg`, `cleanupScratchOrgs`, `pushToScratch`, `runScratchApexTests`, `installDependencies`, `createPackageVersion`, `createFallbackTag`, `determinePackageChanges`, `runLwcJest`, `runCheckPermissionSets`, `runFlowDelta`, `runFlexipageDelta`, `publishUtamPageObjects`, `VersionTagFormat` |
|
|
63
|
+
| Deploy | `deployProject`, `deployHappySoup`, `runDeployStage`, `validateDeployFiles`, `toProjectStageOptions`, `toHappySoupStageOptions`, plus the `deployCommon` helpers (`runDeploymentSteps`, `loadProgress`, `updateProgress`, `installDeployPackageDependencies`, `runDeployApexTests`, …) |
|
|
64
|
+
| Notify | `sendBuildNotification`, `projectNotifyBeforeScript`/`projectNotifyAfterScript`, `happySoupNotifyBeforeScript`/`happySoupNotifyAfterScript`, `getCommitStories`, `getRemoteCommitStories`, `sendNotification`, `renderNotifyTemplate`, `NOTIFY_TEMPLATES` |
|
|
65
|
+
| sfdx-dependabot | `discoverEligibleProjects`, `processProject`, `applyProjectUpdate`, `updateSfdxProject` |
|
|
66
|
+
| Schemas (zod) | `deployConfigSchema`, `deployProgressSchema`, `deployRulesSchema`, `deployStageSchema` |
|
|
67
|
+
| Salesforce org and package lookups | `getPackageVersionReport`, `listInstalledPackages`, `getOrgInstanceUrl`, `getRemainingDailyScratchOrgs` (in-process via `@salesforce/core` / `@salesforce/packaging`, no `sf` needed) |
|
|
68
|
+
| `sf`/`git`/env utilities | `runSf`, `runSfJson`, `authenticateOrg`, `installPackageDependencies`, `runApexTests`, `installPlugin`, `cloneRepo`, `appendToEnvFile`, `resolveString`/`resolveBoolean`, `logger` |
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { deployProject } from '@simplysf/simply-cicd-core';
|
|
72
|
+
|
|
73
|
+
// The same work `sf simply cicd deploy project install-packaged` does, without the CLI.
|
|
74
|
+
await deployProject({
|
|
75
|
+
stage: 'install-packaged',
|
|
76
|
+
alias: 'uat',
|
|
77
|
+
ciJobToken: process.env.CI_JOB_TOKEN!,
|
|
78
|
+
vcsProvider: 'gitlab',
|
|
79
|
+
deployConfigFile: 'config/deploy.json',
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
54
83
|
## Issues
|
|
55
84
|
|
|
56
85
|
Please report any issues at https://github.com/SimplySF/simply-plugins-core/issues
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type PermissionSetCheckResult } from '@simplysf/simply-permissions-core';
|
|
2
|
+
export type RunCheckPermissionSetsOptions = {
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export type PermissionSetBuildFileCheck = {
|
|
6
|
+
file: string;
|
|
7
|
+
permissionSet: PermissionSetCheckResult;
|
|
8
|
+
};
|
|
9
|
+
export type RunCheckPermissionSetsResult = {
|
|
10
|
+
skipped: boolean;
|
|
11
|
+
files: PermissionSetBuildFileCheck[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Finds every permission set build file in the repo and checks the permission set each defines
|
|
15
|
+
* against the generated file on disk, writing nothing. A repo with no permission set build files is
|
|
16
|
+
* a skip. Every file is loaded and validated, and names are checked for duplicates across files,
|
|
17
|
+
* before anything is checked; then every permission set is checked before failing, so one run
|
|
18
|
+
* reports every stale permission set.
|
|
19
|
+
*
|
|
20
|
+
* @throws When any permission set has drifted or is missing, or a permission set build file is invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare function runCheckPermissionSets(options: RunCheckPermissionSetsOptions): Promise<RunCheckPermissionSetsResult>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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 { assertUniquePermissionSetNames, checkPermissionSets, findPermissionSetBuildFiles, loadPermissionSetBuildFile, PermissionSetBuildError, } from '@simplysf/simply-permissions-core';
|
|
17
|
+
import { logger } from '../logger.js';
|
|
18
|
+
/** The same text `simply permissions build` reports for each `PermissionSetBuildError` code. */
|
|
19
|
+
function describeBuildError(error) {
|
|
20
|
+
switch (error.code) {
|
|
21
|
+
case 'scan-failed':
|
|
22
|
+
return `Failed to scan the Salesforce project directory: ${error.args[0]}`;
|
|
23
|
+
case 'invalid-config':
|
|
24
|
+
return `The configuration file ${error.args[0]} is invalid: ${error.args[1]}`;
|
|
25
|
+
case 'config-not-found':
|
|
26
|
+
return `The configuration file ${error.args[0]} does not exist.`;
|
|
27
|
+
case 'directory-not-found':
|
|
28
|
+
return `The source directory ${error.args[0]} for permission set ${error.args[1]} does not exist.`;
|
|
29
|
+
case 'legacy-format':
|
|
30
|
+
return `${error.args[0]} uses the old format, a "permissionSets" list, which is no longer supported. Split it into one .psbuild.json file per permission set, with each permission set's settings at the top level.`;
|
|
31
|
+
case 'duplicate-name':
|
|
32
|
+
return `Permission set ${error.args[0]} is defined by both ${error.args[1]} and ${error.args[2]}. Each permission set must be defined by exactly one .psbuild.json file.`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Logs `message` and throws it, keeping the build error as the cause. */
|
|
36
|
+
function fail(message, cause) {
|
|
37
|
+
logger.error(message);
|
|
38
|
+
throw new Error(message, { cause });
|
|
39
|
+
}
|
|
40
|
+
/** Loads every file in order, naming the file in any validation error, then checks names are unique across files. */
|
|
41
|
+
async function loadFiles(files) {
|
|
42
|
+
const entries = [];
|
|
43
|
+
for (const file of files) {
|
|
44
|
+
logger.info(`Loading permission set build file ${file}...`);
|
|
45
|
+
try {
|
|
46
|
+
// eslint-disable-next-line no-await-in-loop -- files are loaded in order so the first invalid one is the one reported
|
|
47
|
+
entries.push({ file, spec: await loadPermissionSetBuildFile(file) });
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error instanceof PermissionSetBuildError) {
|
|
51
|
+
fail(`Permission set build file ${file}: ${describeBuildError(error)}`, error);
|
|
52
|
+
}
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
assertUniquePermissionSetNames(entries);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error instanceof PermissionSetBuildError) {
|
|
61
|
+
fail(describeBuildError(error), error);
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
return entries;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Finds every permission set build file in the repo and checks the permission set each defines
|
|
69
|
+
* against the generated file on disk, writing nothing. A repo with no permission set build files is
|
|
70
|
+
* a skip. Every file is loaded and validated, and names are checked for duplicates across files,
|
|
71
|
+
* before anything is checked; then every permission set is checked before failing, so one run
|
|
72
|
+
* reports every stale permission set.
|
|
73
|
+
*
|
|
74
|
+
* @throws When any permission set has drifted or is missing, or a permission set build file is invalid.
|
|
75
|
+
*/
|
|
76
|
+
export async function runCheckPermissionSets(options) {
|
|
77
|
+
if (options.disabled) {
|
|
78
|
+
logger.warn('check-permission-sets is disabled. Skipping.');
|
|
79
|
+
return { skipped: true, files: [] };
|
|
80
|
+
}
|
|
81
|
+
const files = await findPermissionSetBuildFiles();
|
|
82
|
+
if (files.length === 0) {
|
|
83
|
+
logger.warn('No permission set build files found. Skipping.');
|
|
84
|
+
return { skipped: true, files: [] };
|
|
85
|
+
}
|
|
86
|
+
const entries = await loadFiles(files);
|
|
87
|
+
const results = await checkPermissionSets(entries.map(({ spec }) => spec));
|
|
88
|
+
const checks = entries.map(({ file }, i) => ({ file, permissionSet: results[i] }));
|
|
89
|
+
const stale = checks.filter(({ permissionSet }) => permissionSet.status !== 'up-to-date');
|
|
90
|
+
for (const { file, permissionSet } of stale) {
|
|
91
|
+
logger.error(`${permissionSet.name} ${permissionSet.status} ${permissionSet.path} (${file})`);
|
|
92
|
+
}
|
|
93
|
+
if (stale.length > 0) {
|
|
94
|
+
logger.log('Regenerate with: sf simply permissions build');
|
|
95
|
+
const message = `${stale.length} of ${checks.length} permission set(s) have drifted from their source metadata or are missing.`;
|
|
96
|
+
logger.error(message);
|
|
97
|
+
throw new Error(message);
|
|
98
|
+
}
|
|
99
|
+
logger.success(`All ${checks.length} permission set(s) are up to date.`);
|
|
100
|
+
return { skipped: false, files: checks };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=checkPermissionSets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkPermissionSets.js","sourceRoot":"","sources":["../../src/build/checkPermissionSets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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 path from 'node:path';
|
|
17
|
+
import { promises as fs } from 'node:fs';
|
|
18
|
+
import { runSf } from '../exec/sfCli.js';
|
|
19
|
+
import { logger } from '../logger.js';
|
|
20
|
+
import { resolveDevHubs } from './devHubs.js';
|
|
21
|
+
async function cleanupScratchOrgsForHub(hubUsername) {
|
|
22
|
+
logger.info(`Querying for scratch orgs in ${hubUsername}...`);
|
|
23
|
+
const csvFile = path.join(process.cwd(), `${hubUsername}_orgs.csv`);
|
|
24
|
+
try {
|
|
25
|
+
const threeHoursAgo = new Date(Date.now() - 3 * 60 * 60 * 1000).toISOString();
|
|
26
|
+
const query = `SELECT Id FROM ActiveScratchOrg WHERE CreatedDate < ${threeHoursAgo}`;
|
|
27
|
+
const { stdout } = await runSf([
|
|
28
|
+
'data',
|
|
29
|
+
'query',
|
|
30
|
+
'--query',
|
|
31
|
+
query,
|
|
32
|
+
'--result-format',
|
|
33
|
+
'csv',
|
|
34
|
+
'--target-org',
|
|
35
|
+
hubUsername,
|
|
36
|
+
]);
|
|
37
|
+
await fs.writeFile(csvFile, stdout);
|
|
38
|
+
const fileContent = await fs.readFile(csvFile, 'utf-8');
|
|
39
|
+
// Fixed: the original split on '' (individual characters), so this line count was
|
|
40
|
+
// effectively always > 1 for any non-empty CSV and the "no old scratch orgs" branch below
|
|
41
|
+
// was unreachable. Splitting on newlines actually counts CSV rows.
|
|
42
|
+
const lines = fileContent.trim().split('\n');
|
|
43
|
+
if (lines.length > 1) {
|
|
44
|
+
logger.info(`Found ${lines.length - 1} old scratch orgs in ${hubUsername}. Deleting...`);
|
|
45
|
+
await runSf([
|
|
46
|
+
'data',
|
|
47
|
+
'bulk',
|
|
48
|
+
'delete',
|
|
49
|
+
'--sobject',
|
|
50
|
+
'ActiveScratchOrg',
|
|
51
|
+
'--file',
|
|
52
|
+
csvFile,
|
|
53
|
+
'--target-org',
|
|
54
|
+
hubUsername,
|
|
55
|
+
'--wait',
|
|
56
|
+
'30',
|
|
57
|
+
], {
|
|
58
|
+
stdio: 'inherit',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
logger.info(`No old scratch orgs found in ${hubUsername}.`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.error(`Failed to cleanup scratch orgs for ${hubUsername}:`, error.shortMessage);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
try {
|
|
70
|
+
await fs.unlink(csvFile);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
/* ignore */
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Cleans up scratch orgs older than 3 hours from every given Dev Hub.
|
|
79
|
+
*
|
|
80
|
+
* Every Dev Hub alias passed in must already be authenticated by the calling pipeline.
|
|
81
|
+
*/
|
|
82
|
+
export async function cleanupScratchOrgs(devHubAliases) {
|
|
83
|
+
logger.info('Starting cleanup of old scratch orgs...');
|
|
84
|
+
const devHubs = await resolveDevHubs(devHubAliases);
|
|
85
|
+
for (const hub of devHubs) {
|
|
86
|
+
// eslint-disable-next-line no-await-in-loop -- cleanup runs per hub sequentially, matching the original
|
|
87
|
+
await cleanupScratchOrgsForHub(hub.username);
|
|
88
|
+
}
|
|
89
|
+
logger.success('Scratch org cleanup complete.');
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=cleanupScratchOrgs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanupScratchOrgs.js","sourceRoot":"","sources":["../../src/build/cleanupScratchOrgs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,KAAK,UAAU,wBAAwB,CAAC,WAAmB;IACzD,MAAM,CAAC,IAAI,CAAC,gCAAgC,WAAW,KAAK,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,WAAW,WAAW,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9E,MAAM,KAAK,GAAG,uDAAuD,aAAa,EAAE,CAAC;QACrF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC;YAC7B,MAAM;YACN,OAAO;YACP,SAAS;YACT,KAAK;YACL,iBAAiB;YACjB,KAAK;YACL,cAAc;YACd,WAAW;SACZ,CAAC,CAAC;QACH,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,kFAAkF;QAClF,0FAA0F;QAC1F,mEAAmE;QACnE,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,GAAG,CAAC,wBAAwB,WAAW,eAAe,CAAC,CAAC;YACzF,MAAM,KAAK,CACT;gBACE,MAAM;gBACN,MAAM;gBACN,QAAQ;gBACR,WAAW;gBACX,kBAAkB;gBAClB,QAAQ;gBACR,OAAO;gBACP,cAAc;gBACd,WAAW;gBACX,QAAQ;gBACR,IAAI;aACL,EACD;gBACE,KAAK,EAAE,SAAS;aACjB,CACF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,gCAAgC,WAAW,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,sCAAsC,WAAW,GAAG,EACnD,KAAmC,CAAC,YAAY,CAClD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,aAAuB;IAC9D,MAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,aAAa,CAAC,CAAC;IAEpD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,wGAAwG;QACxG,MAAM,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type VcsProviderKind } from '../vcs/index.js';
|
|
2
|
+
export type CreateFallbackTagOptions = {
|
|
3
|
+
ciCommitRefName: string;
|
|
4
|
+
ciProjectPath: string;
|
|
5
|
+
projectAccessToken: string;
|
|
6
|
+
ciPipelineId: string;
|
|
7
|
+
lastTag?: string;
|
|
8
|
+
out?: string;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
vcsHost?: string;
|
|
11
|
+
vcsProvider: VcsProviderKind;
|
|
12
|
+
};
|
|
13
|
+
export type CreateFallbackTagResult = {
|
|
14
|
+
created: boolean;
|
|
15
|
+
tag?: string;
|
|
16
|
+
packageId?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Creates and pushes a fallback git tag that increments the suffix of the last release tag and
|
|
20
|
+
* annotates it with the previous package version's `04t` ID, for builds that didn't produce a new
|
|
21
|
+
* package version. Soft no-ops (does not throw) when HEAD already carries a version tag, or when no
|
|
22
|
+
* last tag, or no valid package ID within it, can be found — a build with nothing to fall back to just has nothing to do here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createFallbackTag(options: CreateFallbackTagOptions): Promise<CreateFallbackTagResult>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026, SimplySF.
|
|
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 { promises as fs } from 'node:fs';
|
|
17
|
+
import { execa } from 'execa';
|
|
18
|
+
import { getDefaultPackageDirectory, isSubscriberPackageVersionId, readSfdxProject, } from '@simplysf/simply-core';
|
|
19
|
+
import { createVcsProvider } from '../vcs/index.js';
|
|
20
|
+
import { addGitRemote } from '../git.js';
|
|
21
|
+
import { logger } from '../logger.js';
|
|
22
|
+
import { VersionTagFormat } from './versionTagFormat.js';
|
|
23
|
+
/**
|
|
24
|
+
* The project's version tag format and the glob for its current `major.minor.patch`. An unreadable
|
|
25
|
+
* `sfdx-project.json` falls back to `SIMPLY_CICD_VERSION_TAG_FORMAT` or the default format; an
|
|
26
|
+
* invalid format still throws.
|
|
27
|
+
*/
|
|
28
|
+
async function resolveTagContext() {
|
|
29
|
+
let project;
|
|
30
|
+
try {
|
|
31
|
+
project = await readSfdxProject();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
const versionTagFormat = VersionTagFormat.fromProject(undefined);
|
|
35
|
+
const tagMatchPattern = versionTagFormat.matchPattern();
|
|
36
|
+
logger.info(`Could not read version prefix from sfdx-project.json. Defaulting to match pattern ${tagMatchPattern}`);
|
|
37
|
+
return { versionTagFormat, tagMatchPattern };
|
|
38
|
+
}
|
|
39
|
+
const versionTagFormat = VersionTagFormat.fromProject(project);
|
|
40
|
+
return {
|
|
41
|
+
versionTagFormat,
|
|
42
|
+
tagMatchPattern: versionTagFormat.matchPattern(getDefaultPackageDirectory(project)?.versionNumber),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolves the last tag to increment: the explicit `--last-tag`, if given, otherwise the closest
|
|
47
|
+
* reachable tag matching the project's version prefix. Returns `''` (not a thrown error) when no
|
|
48
|
+
* tag can be found, either because none exists yet or because `git describe` fails outright — a
|
|
49
|
+
* fix from the original, where an unguarded `git describe` call meant "no tags yet" crashed the
|
|
50
|
+
* whole job instead of soft-exiting the way "no valid package ID in the tag" already did.
|
|
51
|
+
*/
|
|
52
|
+
async function resolveLastTag(explicitLastTag, tagMatchPattern) {
|
|
53
|
+
if (explicitLastTag) {
|
|
54
|
+
return explicitLastTag;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const { stdout } = await execa('git', ['describe', '--tags', '--abbrev=0', '--match', tagMatchPattern]);
|
|
58
|
+
return stdout.trim();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Version tags already pointing at HEAD. `create-package-version` tags the commit it just built, and
|
|
66
|
+
* the documented pipeline runs `create-fallback-tag` right after it in the same job, so a non-empty
|
|
67
|
+
* result means this commit already has a real package version and needs no fallback. It also keeps a
|
|
68
|
+
* retried job from stacking a second fallback tag on a commit that already got one.
|
|
69
|
+
*/
|
|
70
|
+
async function findVersionTagsAtHead(tagMatchPattern) {
|
|
71
|
+
try {
|
|
72
|
+
const { stdout } = await execa('git', ['tag', '--points-at', 'HEAD', '--list', tagMatchPattern]);
|
|
73
|
+
return stdout.split(/\r?\n/).filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function extractPackageId(tagAnnotation) {
|
|
80
|
+
const parts = tagAnnotation.trim().split(/\s+/);
|
|
81
|
+
return parts.find((part) => isSubscriberPackageVersionId(part) && (part.length === 15 || part.length === 18)) ?? '';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The last tag with its trailing `-<n>` fallback counter incremented, or `-1` appended. For a tag in
|
|
85
|
+
* the project's format, only a counter **after** the rendered version counts, so the build number of
|
|
86
|
+
* a format like `v{MAJOR}.{MINOR}.{PATCH}-{BUILD}` is never mistaken for one: `v1.2.3-4` becomes
|
|
87
|
+
* `v1.2.3-4-1`, not `v1.2.3-5`. Tags that don't match the format (older three-part tags, an explicit
|
|
88
|
+
* `--last-tag`) keep the original rule.
|
|
89
|
+
*/
|
|
90
|
+
function computeNextTag(lastTag, versionTagFormat) {
|
|
91
|
+
const parsed = versionTagFormat.parseTag(lastTag);
|
|
92
|
+
if (parsed) {
|
|
93
|
+
const counter = /^(?:(?<base>.*)-)?(?<n>\d+)$/.exec(parsed.rest)?.groups;
|
|
94
|
+
if (!counter) {
|
|
95
|
+
return `${lastTag}-1`;
|
|
96
|
+
}
|
|
97
|
+
const base = counter.base ? `${parsed.versionTag}-${counter.base}` : parsed.versionTag;
|
|
98
|
+
return `${base}-${parseInt(counter.n, 10) + 1}`;
|
|
99
|
+
}
|
|
100
|
+
const match = /^(?<baseVersion>v.*)-(?<suffix>\d+)$/.exec(lastTag);
|
|
101
|
+
const baseVersion = match?.groups?.baseVersion ?? lastTag;
|
|
102
|
+
const currentN = match?.groups?.suffix ? parseInt(match.groups.suffix, 10) : 0;
|
|
103
|
+
return `${baseVersion}-${currentN + 1}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates and pushes a fallback git tag that increments the suffix of the last release tag and
|
|
107
|
+
* annotates it with the previous package version's `04t` ID, for builds that didn't produce a new
|
|
108
|
+
* package version. Soft no-ops (does not throw) when HEAD already carries a version tag, or when no
|
|
109
|
+
* last tag, or no valid package ID within it, can be found — a build with nothing to fall back to just has nothing to do here.
|
|
110
|
+
*/
|
|
111
|
+
export async function createFallbackTag(options) {
|
|
112
|
+
logger.info('Starting fallback tagging process...');
|
|
113
|
+
const outFile = options.out ?? 'subscriberPackageVersionId.env';
|
|
114
|
+
const { versionTagFormat, tagMatchPattern } = await resolveTagContext();
|
|
115
|
+
const tagsAtHead = await findVersionTagsAtHead(tagMatchPattern);
|
|
116
|
+
if (tagsAtHead.length > 0) {
|
|
117
|
+
logger.info(`HEAD is already tagged (${tagsAtHead.join(', ')}). No fallback tag needed.`);
|
|
118
|
+
return { created: false };
|
|
119
|
+
}
|
|
120
|
+
const lastTag = await resolveLastTag(options.lastTag, tagMatchPattern);
|
|
121
|
+
if (!lastTag) {
|
|
122
|
+
logger.warn('No previous tag found to increment.');
|
|
123
|
+
return { created: false };
|
|
124
|
+
}
|
|
125
|
+
const { stdout: tagAnnotation } = await execa('git', ['tag', '-l', '-n1', lastTag]);
|
|
126
|
+
const packageId = extractPackageId(tagAnnotation);
|
|
127
|
+
if (!packageId) {
|
|
128
|
+
logger.warn(`Could not find a valid 04t package ID in the annotation of last tag: ${lastTag}`);
|
|
129
|
+
return { created: false };
|
|
130
|
+
}
|
|
131
|
+
logger.info(`Found last tag: ${lastTag} with package ID: ${packageId}`);
|
|
132
|
+
const nextTag = computeNextTag(lastTag, versionTagFormat);
|
|
133
|
+
logger.info(`Next fallback tag determined: ${nextTag}`);
|
|
134
|
+
const vcsProvider = createVcsProvider(options.vcsProvider, {
|
|
135
|
+
host: options.vcsHost,
|
|
136
|
+
token: options.projectAccessToken,
|
|
137
|
+
});
|
|
138
|
+
const remoteAlias = await addGitRemote(options.ciPipelineId, options.projectAccessToken, options.ciProjectPath, vcsProvider);
|
|
139
|
+
logger.info(`Tagging commit with tag: ${nextTag}`);
|
|
140
|
+
await execa('git', ['tag', '-a', nextTag, '-m', packageId]);
|
|
141
|
+
await execa('git', ['push', remoteAlias, nextTag]);
|
|
142
|
+
logger.success(`Successfully created and pushed tag: ${nextTag}`);
|
|
143
|
+
await fs.writeFile(outFile, `SUBSCRIBER_PACKAGE_VERSION_ID=${packageId}\n`, 'utf-8');
|
|
144
|
+
logger.success(`Wrote package version ID to ${outFile}`);
|
|
145
|
+
return { created: true, tag: nextTag, packageId };
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=createFallbackTag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createFallbackTag.js","sourceRoot":"","sources":["../../src/build/createFallbackTag.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type VcsProviderKind } from '../vcs/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether this build's ref is a release-branch build.
|
|
4
|
+
*
|
|
5
|
+
* Exported for `publishUtamPageObjects`, which derives its npm version from the same
|
|
6
|
+
* release-vs-feature-branch decision this module makes for the git tag.
|
|
7
|
+
*/
|
|
8
|
+
export declare function refIncludesPrefix(ciCommitRefName: string, packageReleaseBranchPrefix?: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The suffix appended to this build's version tag: the package's `branch` attribute, else the CI ref
|
|
11
|
+
* unless this is a release-branch build, which gets none. A build with neither a `branch` attribute
|
|
12
|
+
* nor a ref is treated like a release build, the only reading that doesn't produce a tag ending in
|
|
13
|
+
* `-undefined`.
|
|
14
|
+
*
|
|
15
|
+
* Exported because `publishUtamPageObjects` derives its npm version from the same suffix, so that
|
|
16
|
+
* the published page-object version reads like the tag rather than being a second, parallel rule.
|
|
17
|
+
*/
|
|
18
|
+
export declare function determineTagSuffix(branchAttribute: string | undefined, ciCommitRefName: string | undefined, packageReleaseBranchPrefix?: string): string | undefined;
|
|
19
|
+
export type CreatePackageVersionOptions = {
|
|
20
|
+
ciCommitRefName: string;
|
|
21
|
+
ciCommitSha: string;
|
|
22
|
+
ciPipelineId: string;
|
|
23
|
+
ciPipelineSource?: string;
|
|
24
|
+
ciPipelineUrl: string;
|
|
25
|
+
ciProjectPath: string;
|
|
26
|
+
projectAccessToken: string;
|
|
27
|
+
/** The packaging DevHub's alias. Must already be authenticated. */
|
|
28
|
+
packagingDevhub: string;
|
|
29
|
+
debug?: boolean;
|
|
30
|
+
alwaysCreatePackage?: boolean;
|
|
31
|
+
packageReleaseBranchPrefix?: string;
|
|
32
|
+
codeCoverageMinimum?: string;
|
|
33
|
+
vcsHost?: string;
|
|
34
|
+
vcsProvider: VcsProviderKind;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new package version for the default package directory, verifies it meets minimum code
|
|
38
|
+
* coverage, and creates/pushes a version-tracking git tag. No-ops (without error) when the pipeline
|
|
39
|
+
* was triggered by a merge request, or when this isn't a release-branch build and
|
|
40
|
+
* `alwaysCreatePackage` wasn't requested.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createPackageVersion(options: CreatePackageVersionOptions): Promise<void>;
|