@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
@@ -0,0 +1,40 @@
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 { z } from 'zod';
17
+ export const deployStageSchema = z.enum(['unpackagedDeploy', 'postDeploy', 'preDestructive', 'postDestructive']);
18
+ const deployRuleSchema = z
19
+ .object({
20
+ deploymentName: z.string().optional(),
21
+ deploymentSlug: z.string().optional(),
22
+ requireStages: z.array(deployStageSchema),
23
+ })
24
+ .strict()
25
+ .superRefine((rule, ctx) => {
26
+ if (rule.deploymentName === undefined && rule.deploymentSlug === undefined) {
27
+ ctx.addIssue({
28
+ code: z.ZodIssueCode.custom,
29
+ message: 'Each rule must specify a "deploymentName" or "deploymentSlug".',
30
+ path: [],
31
+ });
32
+ }
33
+ });
34
+ /** Zod equivalent of the original `deploy-rules.schema.json`. */
35
+ export const deployRulesSchema = z
36
+ .object({
37
+ rules: z.array(deployRuleSchema),
38
+ })
39
+ .strict();
40
+ //# sourceMappingURL=deployRules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployRules.js","sourceRoot":"","sources":["../../src/schemas/deployRules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,kBAAkB,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEjH,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;CAC1C,CAAC;KACD,MAAM,EAAE;KACR,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACzB,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QAC3E,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,gEAAgE;YACzE,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,iEAAiE;AACjE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;CACjC,CAAC;KACD,MAAM,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ export type HasApexTestsOptions = {
2
+ debugMode?: boolean;
3
+ };
4
+ export type RunApexTestsOptions = {
5
+ alias?: string;
6
+ testLevel?: string;
7
+ testSuite?: string;
8
+ wait?: string;
9
+ debugMode?: boolean;
10
+ };
11
+ /**
12
+ * Checks if there are any Apex test classes defined in the package directories, by reading
13
+ * `sfdx-project.json` to identify the package directories and searching each recursively
14
+ * (case-insensitively) for `@isTest` in `.cls` files.
15
+ */
16
+ export declare function hasApexTests(options?: HasApexTestsOptions): Promise<boolean>;
17
+ /**
18
+ * Runs Apex tests in the specified target Salesforce organization. First checks that any Apex
19
+ * tests exist before initiating the run. Test results are written to `./test-results/apex` in
20
+ * JUnit and JSON formats. If tests fail, a detailed failure report is printed and this throws.
21
+ */
22
+ export declare function runApexTests(options: RunApexTestsOptions): Promise<void>;
package/lib/sfApex.js ADDED
@@ -0,0 +1,169 @@
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 path from 'node:path';
18
+ import { execa } from 'execa';
19
+ import { readSfdxProject } from '@simplysf/simply-core';
20
+ import { runSf } from './exec/sfCli.js';
21
+ import { logger } from './logger.js';
22
+ /**
23
+ * Checks if there are any Apex test classes defined in the package directories, by reading
24
+ * `sfdx-project.json` to identify the package directories and searching each recursively
25
+ * (case-insensitively) for `@isTest` in `.cls` files.
26
+ */
27
+ export async function hasApexTests(options) {
28
+ let packageDirs = ['force-app'];
29
+ try {
30
+ const sfdxProjectJson = await readSfdxProject();
31
+ packageDirs = sfdxProjectJson.packageDirectories.map((d) => d.path).filter((p) => Boolean(p));
32
+ }
33
+ catch {
34
+ if (options?.debugMode) {
35
+ logger.warn('Could not read sfdx-project.json to identify package directories. Using default force-app.');
36
+ }
37
+ }
38
+ for (const dir of packageDirs) {
39
+ try {
40
+ // eslint-disable-next-line no-await-in-loop -- stops at the first directory with a match
41
+ await execa('grep', ['-q', '-r', '-i', '--include=*.cls', '@isTest\\b', dir]);
42
+ return true;
43
+ }
44
+ catch (error) {
45
+ if (options?.debugMode) {
46
+ const err = error;
47
+ logger.log(`No Apex tests found in ${dir} or an error occurred during search.`, err.shortMessage);
48
+ }
49
+ }
50
+ }
51
+ return false;
52
+ }
53
+ /** Kicks off the `sf apex test run`, swallowing any failure so the run's artifacts (namely the
54
+ * test run ID file) can still be inspected afterward to distinguish an execution failure from a
55
+ * genuine test failure. */
56
+ async function executeTestRun(args) {
57
+ try {
58
+ await runSf(args, { stdio: 'pipe' });
59
+ return undefined;
60
+ }
61
+ catch (e) {
62
+ return e;
63
+ }
64
+ }
65
+ /** Reads the test run ID that `sf apex test run` writes out. If that fails, prefers surfacing
66
+ * the run's own execution error (if any) since a missing ID file is usually just a symptom of it. */
67
+ async function resolveTestRunId(testRunIdFile, execError) {
68
+ try {
69
+ return (await fs.readFile(testRunIdFile, 'utf-8')).trim();
70
+ }
71
+ catch (readIdError) {
72
+ if (execError) {
73
+ logger.error('Apex test run failed.', execError.shortMessage);
74
+ throw execError;
75
+ }
76
+ logger.error(`Failed to read test run ID from ${testRunIdFile}.`, readIdError.message);
77
+ throw readIdError;
78
+ }
79
+ }
80
+ function reportFailingTests(failingTests) {
81
+ logger.raw('\n' + '='.repeat(80));
82
+ logger.raw(`❌ APEX TEST FAILURE REPORT (${failingTests.length} failures found)`);
83
+ logger.raw('='.repeat(80));
84
+ failingTests.forEach((t, index) => {
85
+ logger.raw(`\n[${index + 1}/${failingTests.length}] ❌ ${t.FullName ?? 'Unknown test'}`);
86
+ logger.raw(` Message: ${t.Message ? t.Message.trim().replace(/\n/g, '\n ') : 'N/A'}`);
87
+ if (t.StackTrace) {
88
+ logger.raw(` Stack Trace: ${t.StackTrace.trim().replace(/\n/g, '\n ')}`);
89
+ }
90
+ logger.raw('-'.repeat(80));
91
+ });
92
+ logger.raw();
93
+ }
94
+ /** Reads and reports on the JUnit/JSON result file for a completed test run, returning the run's
95
+ * outcome. A read/parse failure here prefers surfacing the run's own execution error (if any). */
96
+ async function processTestResults(resultFilePath, execError) {
97
+ try {
98
+ const resultsContent = await fs.readFile(resultFilePath, 'utf-8');
99
+ const results = JSON.parse(resultsContent);
100
+ const testRunOutcome = results.summary?.outcome;
101
+ if (testRunOutcome !== 'Failed') {
102
+ logger.success('Apex tests completed successfully.');
103
+ return testRunOutcome;
104
+ }
105
+ logger.error('Apex test run failed.');
106
+ const failingTests = results.tests ? results.tests.filter((t) => t.Outcome === 'Fail') : [];
107
+ if (failingTests.length > 0) {
108
+ reportFailingTests(failingTests);
109
+ }
110
+ else {
111
+ logger.warn('Test run was marked as failed, but no individual test failures were found. This could indicate a compile error or issue.');
112
+ }
113
+ return testRunOutcome;
114
+ }
115
+ catch (fileError) {
116
+ logger.error(`Failed to read or parse test result file at ${resultFilePath}.`, fileError.message);
117
+ if (execError) {
118
+ throw execError;
119
+ }
120
+ throw fileError;
121
+ }
122
+ }
123
+ /**
124
+ * Runs Apex tests in the specified target Salesforce organization. First checks that any Apex
125
+ * tests exist before initiating the run. Test results are written to `./test-results/apex` in
126
+ * JUnit and JSON formats. If tests fail, a detailed failure report is printed and this throws.
127
+ */
128
+ export async function runApexTests(options) {
129
+ const { alias, testLevel = 'RunLocalTests', testSuite, wait = '60' } = options;
130
+ if (!(await hasApexTests(options))) {
131
+ logger.warn('No Apex test classes found. Skipping Apex tests.');
132
+ return;
133
+ }
134
+ logger.info('Running Apex tests...');
135
+ const testResultsDir = './test-results/apex';
136
+ await fs.mkdir(testResultsDir, { recursive: true });
137
+ const args = [
138
+ 'apex',
139
+ 'test',
140
+ 'run',
141
+ '--code-coverage',
142
+ '--result-format',
143
+ 'junit',
144
+ '--output-dir',
145
+ testResultsDir,
146
+ '--wait',
147
+ wait,
148
+ ];
149
+ if (alias) {
150
+ args.push('--target-org', alias);
151
+ }
152
+ if (testSuite) {
153
+ args.push('--suite-names', testSuite);
154
+ }
155
+ else {
156
+ args.push('--test-level', testLevel);
157
+ }
158
+ const execError = await executeTestRun(args);
159
+ const testRunId = await resolveTestRunId(path.join(testResultsDir, 'test-run-id.txt'), execError);
160
+ let testRunOutcome;
161
+ if (testRunId) {
162
+ const resultFilePath = path.join(testResultsDir, `test-result-${testRunId}.json`);
163
+ testRunOutcome = await processTestResults(resultFilePath, execError);
164
+ }
165
+ if (testRunOutcome === 'Failed') {
166
+ throw new Error('Apex test run included failures.');
167
+ }
168
+ }
169
+ //# sourceMappingURL=sfApex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfApex.js","sourceRoot":"","sources":["../src/sfApex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type AuthenticateOrgOptions = {
2
+ alias?: string;
3
+ authUrl?: string;
4
+ clientId?: string;
5
+ instanceUrl?: string;
6
+ jwtKeyFile?: string;
7
+ username?: string;
8
+ setDefault?: boolean;
9
+ setDefaultDevHub?: boolean;
10
+ debug?: boolean;
11
+ };
12
+ export type AuthenticateOrgResult = {
13
+ success: boolean;
14
+ username?: string;
15
+ result?: unknown;
16
+ message?: string;
17
+ };
18
+ /** Authenticates to a Salesforce organization using either a JWT flow or an SFDX auth URL. */
19
+ export declare function authenticateOrg(options: AuthenticateOrgOptions): Promise<AuthenticateOrgResult>;
package/lib/sfAuth.js ADDED
@@ -0,0 +1,78 @@
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 { mkdtemp, writeFile } from 'node:fs/promises';
17
+ import { tmpdir } from 'node:os';
18
+ import { join } from 'node:path';
19
+ import { runSf } from './exec/sfCli.js';
20
+ import { logger } from './logger.js';
21
+ /** Authenticates to a Salesforce organization using either a JWT flow or an SFDX auth URL. */
22
+ export async function authenticateOrg(options) {
23
+ const { alias, authUrl, clientId, instanceUrl, jwtKeyFile, username, setDefault, setDefaultDevHub, debug } = options;
24
+ const authEntity = alias ?? username ?? 'unknown org';
25
+ logger.info(`Authenticating to org: ${authEntity}`);
26
+ try {
27
+ let authArgs;
28
+ if (authUrl) {
29
+ const tempDir = await mkdtemp(join(tmpdir(), 'sfdx-auth-'));
30
+ const authUrlFile = join(tempDir, 'auth-url.txt');
31
+ await writeFile(authUrlFile, authUrl);
32
+ authArgs = ['org', 'login', 'sfdx-url', '--sfdx-url-file', authUrlFile, '--json'];
33
+ }
34
+ else {
35
+ authArgs = [
36
+ 'login',
37
+ 'org',
38
+ 'jwt',
39
+ '--username',
40
+ username ?? '',
41
+ '--jwt-key-file',
42
+ jwtKeyFile ?? '',
43
+ '--client-id',
44
+ clientId ?? '',
45
+ '--instance-url',
46
+ instanceUrl ?? '',
47
+ '--json',
48
+ ];
49
+ }
50
+ if (alias) {
51
+ authArgs.push('--alias', alias);
52
+ }
53
+ if (setDefault) {
54
+ authArgs.push('--set-default');
55
+ }
56
+ if (setDefaultDevHub) {
57
+ authArgs.push('--set-default-dev-hub');
58
+ }
59
+ const { stdout } = await runSf(authArgs);
60
+ if (debug) {
61
+ logger.raw(stdout);
62
+ }
63
+ const authResult = JSON.parse(stdout);
64
+ if (authResult.status > 0) {
65
+ logger.error(`Authentication failed for ${authEntity}: ${authResult.message ?? 'unknown error'}`);
66
+ // In cleanup, we don't want to exit the whole process.
67
+ return { success: false, message: authResult.message, username };
68
+ }
69
+ logger.success(`Successfully authenticated to org: ${authEntity}`);
70
+ return { success: true, username, result: authResult.result };
71
+ }
72
+ catch (error) {
73
+ logger.error(`Authentication failed for ${authEntity}`);
74
+ logger.error(String(error));
75
+ throw error; // Re-throw for build steps that should fail hard.
76
+ }
77
+ }
78
+ //# sourceMappingURL=sfAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfAuth.js","sourceRoot":"","sources":["../src/sfAuth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { VcsProviderKind } from './vcs/index.js';
2
+ /** Where a packaged dependency's source lives, for happy-soup story lookups. */
3
+ export type PackageOriginOverride = {
4
+ vcsProvider: VcsProviderKind;
5
+ host?: string;
6
+ projectPath: string;
7
+ };
8
+ /**
9
+ * Retrieves ALM project keys from the `.sfdevrc.json` configuration file, or falls back to a
10
+ * provided default. Reads a single or multiple project keys from the configuration, deduplicates
11
+ * them, and filters out empty values.
12
+ *
13
+ * The legacy `jiraProjectKey`/`jiraProjectKeys` fields are still honored, so existing repositories
14
+ * keep working, but `almProjectKey`/`almProjectKeys` win outright when present — the two sets are
15
+ * not merged, so a repository migrating one key at a time gets the new value rather than a blend.
16
+ */
17
+ export declare function getAlmProjectKeys(passedProjectKey?: string): string[];
18
+ /**
19
+ * Looks up an explicit VCS project override for a package name from `.sfdevrc.json`'s
20
+ * `packageOriginOverrides`. Returns `undefined` if the file, the field, or an entry for this
21
+ * package doesn't exist.
22
+ */
23
+ export declare function getPackageOriginOverride(packageName: string): PackageOriginOverride | undefined;
@@ -0,0 +1,82 @@
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 fs from 'node:fs';
17
+ import { logger } from './logger.js';
18
+ /** Reads and parses `.sfdevrc.json`, or returns `undefined` if it's missing or invalid. */
19
+ function readSfDevRcConfig() {
20
+ try {
21
+ if (!fs.existsSync('.sfdevrc.json')) {
22
+ return undefined;
23
+ }
24
+ return JSON.parse(fs.readFileSync('.sfdevrc.json', 'utf8'));
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
30
+ /** Collects a single-key and multi-key field into one deduplicated, non-empty list. */
31
+ function collectKeys(single, multiple) {
32
+ const keys = [];
33
+ if (single) {
34
+ keys.push(single);
35
+ }
36
+ if (Array.isArray(multiple)) {
37
+ keys.push(...multiple);
38
+ }
39
+ return [...new Set(keys.filter(Boolean))];
40
+ }
41
+ /**
42
+ * Retrieves ALM project keys from the `.sfdevrc.json` configuration file, or falls back to a
43
+ * provided default. Reads a single or multiple project keys from the configuration, deduplicates
44
+ * them, and filters out empty values.
45
+ *
46
+ * The legacy `jiraProjectKey`/`jiraProjectKeys` fields are still honored, so existing repositories
47
+ * keep working, but `almProjectKey`/`almProjectKeys` win outright when present — the two sets are
48
+ * not merged, so a repository migrating one key at a time gets the new value rather than a blend.
49
+ */
50
+ export function getAlmProjectKeys(passedProjectKey) {
51
+ let projectKeys = [];
52
+ try {
53
+ if (fs.existsSync('.sfdevrc.json')) {
54
+ const content = fs.readFileSync('.sfdevrc.json', 'utf8');
55
+ const config = JSON.parse(content);
56
+ projectKeys = collectKeys(config.almProjectKey, config.almProjectKeys);
57
+ if (projectKeys.length === 0) {
58
+ const legacyKeys = collectKeys(config.jiraProjectKey, config.jiraProjectKeys);
59
+ if (legacyKeys.length > 0) {
60
+ logger.warn('The .sfdevrc.json fields "jiraProjectKey" and "jiraProjectKeys" are deprecated. Rename them to "almProjectKey" and "almProjectKeys"; the old names will be removed in a future release.');
61
+ projectKeys = legacyKeys;
62
+ }
63
+ }
64
+ }
65
+ }
66
+ catch {
67
+ // Ignore and fall back to the passed command-line project key.
68
+ }
69
+ if (projectKeys.length > 0) {
70
+ return projectKeys;
71
+ }
72
+ return passedProjectKey ? [passedProjectKey] : [];
73
+ }
74
+ /**
75
+ * Looks up an explicit VCS project override for a package name from `.sfdevrc.json`'s
76
+ * `packageOriginOverrides`. Returns `undefined` if the file, the field, or an entry for this
77
+ * package doesn't exist.
78
+ */
79
+ export function getPackageOriginOverride(packageName) {
80
+ return readSfDevRcConfig()?.packageOriginOverrides?.[packageName];
81
+ }
82
+ //# sourceMappingURL=sfConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfConfig.js","sourceRoot":"","sources":["../src/sfConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAwBrC,2FAA2F;AAC3F,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACpC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAkB,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,uFAAuF;AACvF,SAAS,WAAW,CAAC,MAA0B,EAAE,QAA8B;IAC7E,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,gBAAyB;IACzD,IAAI,WAAW,GAAa,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;YAEpD,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;YAEvE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;gBAC9E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,MAAM,CAAC,IAAI,CACT,yLAAyL,CAC1L,CAAC;oBACF,WAAW,GAAG,UAAU,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;IACjE,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,OAAO,iBAAiB,EAAE,EAAE,sBAAsB,EAAE,CAAC,WAAW,CAAC,CAAC;AACpE,CAAC"}
package/lib/sfOrg.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The org's instance URL, e.g. `https://my-domain.my.salesforce.com`.
3
+ *
4
+ * @param aliasOrUsername - The org to look up. Omit (or pass `''`) to use the default target org.
5
+ */
6
+ export declare function getOrgInstanceUrl(aliasOrUsername?: string): Promise<string>;
7
+ /**
8
+ * How many more scratch orgs the Dev Hub may create today (its `DailyScratchOrgs` limit), or
9
+ * `undefined` when the org doesn't report that limit.
10
+ *
11
+ * @param hubAliasOrUsername - The Dev Hub. Must already be authenticated.
12
+ */
13
+ export declare function getRemainingDailyScratchOrgs(hubAliasOrUsername: string): Promise<number | undefined>;
package/lib/sfOrg.js ADDED
@@ -0,0 +1,39 @@
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 { Org } from '@salesforce/core';
17
+ /**
18
+ * The org's instance URL, e.g. `https://my-domain.my.salesforce.com`.
19
+ *
20
+ * @param aliasOrUsername - The org to look up. Omit (or pass `''`) to use the default target org.
21
+ */
22
+ export async function getOrgInstanceUrl(aliasOrUsername) {
23
+ // Callers pass '' for "no --alias given", which `sf org display --target-org ''` treated as the
24
+ // default target org; Org.create only does that for undefined.
25
+ const org = await Org.create({ aliasOrUsername: aliasOrUsername === '' ? undefined : aliasOrUsername });
26
+ return org.getConnection().instanceUrl;
27
+ }
28
+ /**
29
+ * How many more scratch orgs the Dev Hub may create today (its `DailyScratchOrgs` limit), or
30
+ * `undefined` when the org doesn't report that limit.
31
+ *
32
+ * @param hubAliasOrUsername - The Dev Hub. Must already be authenticated.
33
+ */
34
+ export async function getRemainingDailyScratchOrgs(hubAliasOrUsername) {
35
+ const org = await Org.create({ aliasOrUsername: hubAliasOrUsername });
36
+ const limits = (await org.getConnection().limits());
37
+ return limits.DailyScratchOrgs?.Remaining;
38
+ }
39
+ //# sourceMappingURL=sfOrg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfOrg.js","sourceRoot":"","sources":["../src/sfOrg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,eAAwB;IAC9D,gGAAgG;IAChG,+DAA+D;IAC/D,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;IACxG,OAAO,GAAG,CAAC,aAAa,EAAE,CAAC,WAAW,CAAC;AACzC,CAAC;AAID;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,kBAA0B;IAC3E,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,CAAyB,CAAC;IAC5E,OAAO,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { type PackageInstallType, type PackageInstallUpgradeType, type PackageToInstall } from '@simplysf/simply-package-core';
2
+ import { type PackageVersionReportResult } from '@salesforce/packaging';
3
+ import type { UpgradedPackage } from './schemas/deployProgress.js';
4
+ export type { PackageInstallUpgradeType, PackageToInstall };
5
+ export type InstallPackageDependenciesConfig = {
6
+ /** Alias or username of the target org. Omit to use the default target org. */
7
+ alias?: string;
8
+ /** Minutes to wait for each package install to complete. */
9
+ wait?: string;
10
+ installType?: PackageInstallType;
11
+ /** What happens to components an unlocked package upgrade removes. */
12
+ upgradeType?: PackageInstallUpgradeType;
13
+ };
14
+ export type { PackageVersionReportResult };
15
+ /**
16
+ * Installs the Salesforce package dependencies defined in `sfdx-project.json` into the target org,
17
+ * in-process via `@simplysf/simply-package-core`. The org must already be authenticated; every
18
+ * confirmation is auto-approved, as befits a pipeline.
19
+ *
20
+ * @returns The install outcome for every resolved dependency, including the ones skipped.
21
+ */
22
+ export declare function installPackageDependencies(config?: InstallPackageDependenciesConfig): Promise<PackageToInstall[]>;
23
+ export type ResolveUpgradedPackagesConfig = {
24
+ /** The packaging DevHub's alias. Must already be authenticated. */
25
+ packagingDevhub?: string;
26
+ };
27
+ /**
28
+ * The Dev Hub's report for one package version: what `sf package version report --json` returns,
29
+ * including the computed `Version` (`major.minor.patch.build`), `Tag`, `Description` and
30
+ * `CodeCoverage`.
31
+ *
32
+ * Unlike the CLI, `CodeCoverage` is `null` (not `'N/A'`) for a version that skipped validation or
33
+ * belongs to an org-dependent package.
34
+ *
35
+ * @param packageVersionId - A `04t` subscriber package version ID (or `05i` package version ID).
36
+ * @param devHubAliasOrUsername - The Dev Hub that owns the package. Must already be authenticated.
37
+ * @throws {SfError} If the Dev Hub can't be resolved or the version doesn't exist.
38
+ */
39
+ export declare function getPackageVersionReport(packageVersionId: string, devHubAliasOrUsername: string): Promise<PackageVersionReportResult>;
40
+ /** One row of {@link listInstalledPackages}: the fields `sf package installed list --json` returns. */
41
+ export type InstalledPackage = {
42
+ Id: string;
43
+ SubscriberPackageId: string;
44
+ SubscriberPackageName?: string;
45
+ SubscriberPackageNamespace?: string;
46
+ SubscriberPackageVersionId?: string;
47
+ SubscriberPackageVersionName?: string;
48
+ /** `major.minor.patch.build`. */
49
+ SubscriberPackageVersionNumber?: string;
50
+ };
51
+ /**
52
+ * The packages installed in an org, shaped like `sf package installed list --json`'s result rows.
53
+ *
54
+ * @param aliasOrUsername - The org to inspect. Must already be authenticated.
55
+ */
56
+ export declare function listInstalledPackages(aliasOrUsername: string): Promise<InstalledPackage[]>;
57
+ /**
58
+ * For every package an {@link installPackageDependencies} run upgraded, fetches the previous and
59
+ * target version's `sf package version report` (for the origin commit SHA and pipeline URL). A
60
+ * package whose version report can't be resolved is skipped with a warning rather than failing the
61
+ * whole deployment — this data only feeds a later notification.
62
+ */
63
+ export declare function resolveUpgradedPackages(installResults: PackageToInstall[], config: ResolveUpgradedPackagesConfig): Promise<UpgradedPackage[]>;