@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.
Files changed (167) hide show
  1. package/README.md +32 -3
  2. package/lib/build/checkPermissionSets.d.ts +22 -0
  3. package/lib/build/checkPermissionSets.js +102 -0
  4. package/lib/build/checkPermissionSets.js.map +1 -0
  5. package/lib/build/cleanupScratchOrgs.d.ts +6 -0
  6. package/lib/build/cleanupScratchOrgs.js +91 -0
  7. package/lib/build/cleanupScratchOrgs.js.map +1 -0
  8. package/lib/build/createFallbackTag.d.ts +24 -0
  9. package/lib/build/createFallbackTag.js +147 -0
  10. package/lib/build/createFallbackTag.js.map +1 -0
  11. package/lib/build/createPackageVersion.d.ts +42 -0
  12. package/lib/build/createPackageVersion.js +191 -0
  13. package/lib/build/createPackageVersion.js.map +1 -0
  14. package/lib/build/createScratchOrg.d.ts +14 -0
  15. package/lib/build/createScratchOrg.js +182 -0
  16. package/lib/build/createScratchOrg.js.map +1 -0
  17. package/lib/build/deleteScratchOrg.d.ts +13 -0
  18. package/lib/build/deleteScratchOrg.js +62 -0
  19. package/lib/build/deleteScratchOrg.js.map +1 -0
  20. package/lib/build/deltaRunner.d.ts +73 -0
  21. package/lib/build/deltaRunner.js +109 -0
  22. package/lib/build/deltaRunner.js.map +1 -0
  23. package/lib/build/determinePackageChanges.d.ts +11 -0
  24. package/lib/build/determinePackageChanges.js +90 -0
  25. package/lib/build/determinePackageChanges.js.map +1 -0
  26. package/lib/build/devHubs.d.ts +12 -0
  27. package/lib/build/devHubs.js +42 -0
  28. package/lib/build/devHubs.js.map +1 -0
  29. package/lib/build/flexipageDelta.d.ts +18 -0
  30. package/lib/build/flexipageDelta.js +35 -0
  31. package/lib/build/flexipageDelta.js.map +1 -0
  32. package/lib/build/flowDelta.d.ts +17 -0
  33. package/lib/build/flowDelta.js +34 -0
  34. package/lib/build/flowDelta.js.map +1 -0
  35. package/lib/build/installDependencies.d.ts +10 -0
  36. package/lib/build/installDependencies.js +39 -0
  37. package/lib/build/installDependencies.js.map +1 -0
  38. package/lib/build/lwcJest.d.ts +25 -0
  39. package/lib/build/lwcJest.js +126 -0
  40. package/lib/build/lwcJest.js.map +1 -0
  41. package/lib/build/publishUtamPageObjects.d.ts +50 -0
  42. package/lib/build/publishUtamPageObjects.js +274 -0
  43. package/lib/build/publishUtamPageObjects.js.map +1 -0
  44. package/lib/build/pushScratch.d.ts +9 -0
  45. package/lib/build/pushScratch.js +60 -0
  46. package/lib/build/pushScratch.js.map +1 -0
  47. package/lib/build/scratchOrgAuth.d.ts +18 -0
  48. package/lib/build/scratchOrgAuth.js +52 -0
  49. package/lib/build/scratchOrgAuth.js.map +1 -0
  50. package/lib/build/scratchOrgInfo.d.ts +14 -0
  51. package/lib/build/scratchOrgInfo.js +21 -0
  52. package/lib/build/scratchOrgInfo.js.map +1 -0
  53. package/lib/build/skipGuard.d.ts +8 -0
  54. package/lib/build/skipGuard.js +42 -0
  55. package/lib/build/skipGuard.js.map +1 -0
  56. package/lib/build/testScratch.d.ts +15 -0
  57. package/lib/build/testScratch.js +42 -0
  58. package/lib/build/testScratch.js.map +1 -0
  59. package/lib/build/utamPageObjects.d.ts +143 -0
  60. package/lib/build/utamPageObjects.js +258 -0
  61. package/lib/build/utamPageObjects.js.map +1 -0
  62. package/lib/build/versionTagFormat.d.ts +57 -0
  63. package/lib/build/versionTagFormat.js +194 -0
  64. package/lib/build/versionTagFormat.js.map +1 -0
  65. package/lib/config/defaultDeploymentPlugins.d.ts +2 -0
  66. package/lib/config/defaultDeploymentPlugins.js +18 -0
  67. package/lib/config/defaultDeploymentPlugins.js.map +1 -0
  68. package/lib/config/trustedPlugins.d.ts +2 -0
  69. package/lib/config/trustedPlugins.js +18 -0
  70. package/lib/config/trustedPlugins.js.map +1 -0
  71. package/lib/deploy/deployCommon.d.ts +105 -0
  72. package/lib/deploy/deployCommon.js +358 -0
  73. package/lib/deploy/deployCommon.js.map +1 -0
  74. package/lib/deploy/deployHappySoup.d.ts +56 -0
  75. package/lib/deploy/deployHappySoup.js +159 -0
  76. package/lib/deploy/deployHappySoup.js.map +1 -0
  77. package/lib/deploy/deployProject.d.ts +27 -0
  78. package/lib/deploy/deployProject.js +114 -0
  79. package/lib/deploy/deployProject.js.map +1 -0
  80. package/lib/deploy/runDeployStage.d.ts +16 -0
  81. package/lib/deploy/runDeployStage.js +65 -0
  82. package/lib/deploy/runDeployStage.js.map +1 -0
  83. package/lib/deploy/stageOptions.d.ts +49 -0
  84. package/lib/deploy/stageOptions.js +70 -0
  85. package/lib/deploy/stageOptions.js.map +1 -0
  86. package/lib/deploy/validate.d.ts +11 -0
  87. package/lib/deploy/validate.js +54 -0
  88. package/lib/deploy/validate.js.map +1 -0
  89. package/lib/env.d.ts +9 -0
  90. package/lib/env.js +47 -0
  91. package/lib/env.js.map +1 -0
  92. package/lib/exec/sfCli.d.ts +27 -0
  93. package/lib/exec/sfCli.js +50 -0
  94. package/lib/exec/sfCli.js.map +1 -0
  95. package/lib/flags/env.d.ts +44 -0
  96. package/lib/flags/env.js +81 -0
  97. package/lib/flags/env.js.map +1 -0
  98. package/lib/git.d.ts +32 -0
  99. package/lib/git.js +106 -0
  100. package/lib/git.js.map +1 -0
  101. package/lib/happySoup/resolveOriginProject.d.ts +22 -0
  102. package/lib/happySoup/resolveOriginProject.js +61 -0
  103. package/lib/happySoup/resolveOriginProject.js.map +1 -0
  104. package/lib/index.d.ts +52 -0
  105. package/lib/index.js +64 -2
  106. package/lib/index.js.map +1 -1
  107. package/lib/logger.d.ts +10 -0
  108. package/lib/logger.js +33 -0
  109. package/lib/logger.js.map +1 -0
  110. package/lib/notify/buildNotification.d.ts +53 -0
  111. package/lib/notify/buildNotification.js +176 -0
  112. package/lib/notify/buildNotification.js.map +1 -0
  113. package/lib/notify/getCommitStories.d.ts +30 -0
  114. package/lib/notify/getCommitStories.js +70 -0
  115. package/lib/notify/getCommitStories.js.map +1 -0
  116. package/lib/notify/getRemoteCommitStories.d.ts +10 -0
  117. package/lib/notify/getRemoteCommitStories.js +45 -0
  118. package/lib/notify/getRemoteCommitStories.js.map +1 -0
  119. package/lib/notify/happySoupNotification.d.ts +26 -0
  120. package/lib/notify/happySoupNotification.js +140 -0
  121. package/lib/notify/happySoupNotification.js.map +1 -0
  122. package/lib/notify/projectNotification.d.ts +46 -0
  123. package/lib/notify/projectNotification.js +167 -0
  124. package/lib/notify/projectNotification.js.map +1 -0
  125. package/lib/notify/renderTemplate.d.ts +3 -0
  126. package/lib/notify/renderTemplate.js +24 -0
  127. package/lib/notify/renderTemplate.js.map +1 -0
  128. package/lib/notify/sendNotification.d.ts +2 -0
  129. package/lib/notify/sendNotification.js +50 -0
  130. package/lib/notify/sendNotification.js.map +1 -0
  131. package/lib/notify/templates.d.ts +13 -0
  132. package/lib/notify/templates.js +118 -0
  133. package/lib/notify/templates.js.map +1 -0
  134. package/lib/schemas/deployConfig.d.ts +25 -0
  135. package/lib/schemas/deployConfig.js +55 -0
  136. package/lib/schemas/deployConfig.js.map +1 -0
  137. package/lib/schemas/deployProgress.d.ts +33 -0
  138. package/lib/schemas/deployProgress.js +46 -0
  139. package/lib/schemas/deployProgress.js.map +1 -0
  140. package/lib/schemas/deployRules.d.ts +34 -0
  141. package/lib/schemas/deployRules.js +40 -0
  142. package/lib/schemas/deployRules.js.map +1 -0
  143. package/lib/sfApex.d.ts +22 -0
  144. package/lib/sfApex.js +169 -0
  145. package/lib/sfApex.js.map +1 -0
  146. package/lib/sfAuth.d.ts +19 -0
  147. package/lib/sfAuth.js +78 -0
  148. package/lib/sfAuth.js.map +1 -0
  149. package/lib/sfConfig.d.ts +23 -0
  150. package/lib/sfConfig.js +82 -0
  151. package/lib/sfConfig.js.map +1 -0
  152. package/lib/sfOrg.d.ts +13 -0
  153. package/lib/sfOrg.js +39 -0
  154. package/lib/sfOrg.js.map +1 -0
  155. package/lib/sfPackages.d.ts +63 -0
  156. package/lib/sfPackages.js +185 -0
  157. package/lib/sfPackages.js.map +1 -0
  158. package/lib/sfPlugins.d.ts +11 -0
  159. package/lib/sfPlugins.js +134 -0
  160. package/lib/sfPlugins.js.map +1 -0
  161. package/lib/sfdxDependabot/dependabotRun.d.ts +95 -0
  162. package/lib/sfdxDependabot/dependabotRun.js +287 -0
  163. package/lib/sfdxDependabot/dependabotRun.js.map +1 -0
  164. package/lib/sfdxDependabot/updater.d.ts +14 -0
  165. package/lib/sfdxDependabot/updater.js +94 -0
  166. package/lib/sfdxDependabot/updater.js.map +1 -0
  167. package/package.json +16 -4
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  [![NPM](https://img.shields.io/npm/v/@simplysf/simply-cicd-core?label=@simplysf/simply-cicd-core)](https://npmjs.com/@simplysf/simply-cicd-core) [![Downloads/week](https://img.shields.io/npm/dw/@simplysf/simply-cicd-core.svg)](https://npmjs.com/@simplysf/simply-cicd-core) [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](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)'s ALM/VCS integrations, 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.
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
- Only `alm/` and `vcs/` moved here — `@simplysf/simply-cicd` itself still owns everything CI-pipeline-shaped (running builds/deploys, shelling to `sf`/`git`, sending pipeline notifications). 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 boundary and why the rest stayed behind.
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. Zero runtime dependencies — `vcs/`'s GitHub/GitLab clients use the platform `fetch`.
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,6 @@
1
+ /**
2
+ * Cleans up scratch orgs older than 3 hours from every given Dev Hub.
3
+ *
4
+ * Every Dev Hub alias passed in must already be authenticated by the calling pipeline.
5
+ */
6
+ export declare function cleanupScratchOrgs(devHubAliases: string[]): Promise<void>;
@@ -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>;