@simplysf/simply-cicd-core 0.2.1 → 0.3.1

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 (164) hide show
  1. package/README.md +35 -7
  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 +198 -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 +192 -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 +283 -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 +160 -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 +51 -0
  105. package/lib/index.js +63 -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 +177 -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/sfPackages.d.ts +31 -0
  153. package/lib/sfPackages.js +143 -0
  154. package/lib/sfPackages.js.map +1 -0
  155. package/lib/sfPlugins.d.ts +11 -0
  156. package/lib/sfPlugins.js +134 -0
  157. package/lib/sfPlugins.js.map +1 -0
  158. package/lib/sfdxDependabot/dependabotRun.d.ts +95 -0
  159. package/lib/sfdxDependabot/dependabotRun.js +287 -0
  160. package/lib/sfdxDependabot/dependabotRun.js.map +1 -0
  161. package/lib/sfdxDependabot/updater.d.ts +14 -0
  162. package/lib/sfdxDependabot/updater.js +94 -0
  163. package/lib/sfdxDependabot/updater.js.map +1 -0
  164. package/package.json +18 -7
@@ -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"}
@@ -0,0 +1,31 @@
1
+ import { type PackageInstallType, type PackageInstallUpgradeType, type PackageToInstall } from '@simplysf/simply-package-core';
2
+ import type { UpgradedPackage } from './schemas/deployProgress.js';
3
+ export type { PackageInstallUpgradeType, PackageToInstall };
4
+ export type InstallPackageDependenciesConfig = {
5
+ /** Alias or username of the target org. Omit to use the default target org. */
6
+ alias?: string;
7
+ /** Minutes to wait for each package install to complete. */
8
+ wait?: string;
9
+ installType?: PackageInstallType;
10
+ /** What happens to components an unlocked package upgrade removes. */
11
+ upgradeType?: PackageInstallUpgradeType;
12
+ };
13
+ /**
14
+ * Installs the Salesforce package dependencies defined in `sfdx-project.json` into the target org,
15
+ * in-process via `@simplysf/simply-package-core`. The org must already be authenticated; every
16
+ * confirmation is auto-approved, as befits a pipeline.
17
+ *
18
+ * @returns The install outcome for every resolved dependency, including the ones skipped.
19
+ */
20
+ export declare function installPackageDependencies(config?: InstallPackageDependenciesConfig): Promise<PackageToInstall[]>;
21
+ export type ResolveUpgradedPackagesConfig = {
22
+ /** The packaging DevHub's alias. Must already be authenticated. */
23
+ packagingDevhub?: string;
24
+ };
25
+ /**
26
+ * For every package an {@link installPackageDependencies} run upgraded, fetches the previous and
27
+ * target version's `sf package version report` (for the origin commit SHA and pipeline URL). A
28
+ * package whose version report can't be resolved is skipped with a warning rather than failing the
29
+ * whole deployment — this data only feeds a later notification.
30
+ */
31
+ export declare function resolveUpgradedPackages(installResults: PackageToInstall[], config: ResolveUpgradedPackagesConfig): Promise<UpgradedPackage[]>;
@@ -0,0 +1,143 @@
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, SfProject } from '@salesforce/core';
17
+ import { Duration } from '@salesforce/kit';
18
+ import { installPackageDependencies as installPackageDependenciesCore, } from '@simplysf/simply-package-core';
19
+ import { runSfJson } from './exec/sfCli.js';
20
+ import { logger } from './logger.js';
21
+ /**
22
+ * Adapts the library's progress callbacks onto this package's logger. Step boundaries become info
23
+ * lines; in-flight status (which fires on every poll) is logged only when its text changes.
24
+ */
25
+ function loggerProgress() {
26
+ let lastStatus;
27
+ return {
28
+ info: (message) => logger.info(message),
29
+ warn: (message) => logger.warn(message),
30
+ stepStart: (message) => {
31
+ lastStatus = undefined;
32
+ logger.info(message);
33
+ },
34
+ stepStatus: (message) => {
35
+ if (message !== lastStatus) {
36
+ lastStatus = message;
37
+ logger.info(message);
38
+ }
39
+ },
40
+ stepStop: (message) => {
41
+ if (message) {
42
+ logger.warn(message);
43
+ }
44
+ },
45
+ };
46
+ }
47
+ /**
48
+ * Installs the Salesforce package dependencies defined in `sfdx-project.json` into the target org,
49
+ * in-process via `@simplysf/simply-package-core`. The org must already be authenticated; every
50
+ * confirmation is auto-approved, as befits a pipeline.
51
+ *
52
+ * @returns The install outcome for every resolved dependency, including the ones skipped.
53
+ */
54
+ export async function installPackageDependencies(config = {}) {
55
+ const { alias, wait = '120', installType = 'Upgrade', upgradeType = 'Mixed' } = config;
56
+ logger.info('Installing packaged dependencies...');
57
+ try {
58
+ const org = await Org.create({ aliasOrUsername: alias });
59
+ const project = await SfProject.resolve();
60
+ const results = await installPackageDependenciesCore({
61
+ project,
62
+ targetOrgConnection: org.getConnection(),
63
+ apexCompile: 'package',
64
+ installType,
65
+ upgradeType,
66
+ wait: Duration.minutes(parseInt(wait, 10)),
67
+ progress: loggerProgress(),
68
+ });
69
+ logger.success('Packaged dependencies installed successfully.');
70
+ return results;
71
+ }
72
+ catch (error) {
73
+ logger.error('Failed to install packaged dependencies.');
74
+ logger.error(String(error));
75
+ throw error;
76
+ }
77
+ }
78
+ /** @returns The install results that upgraded an already-installed package. */
79
+ function upgradedEntries(installResults) {
80
+ return installResults.filter((entry) => entry.Status === 'Installed' &&
81
+ Boolean(entry.ExistingSubscriberPackageVersionId) &&
82
+ entry.ExistingSubscriberPackageVersionId !== entry.SubscriberPackageVersionId);
83
+ }
84
+ /** Runs `sf package version report` for one subscriber package version. Returns `undefined` on failure. */
85
+ async function reportPackageVersion(subscriberPackageVersionId, packagingDevhub) {
86
+ try {
87
+ const { result } = await runSfJson([
88
+ 'package',
89
+ 'version',
90
+ 'report',
91
+ '--package',
92
+ subscriberPackageVersionId,
93
+ '--target-dev-hub',
94
+ packagingDevhub,
95
+ '--json',
96
+ ]);
97
+ return result;
98
+ }
99
+ catch (error) {
100
+ logger.warn(`Could not get package version report for ${subscriberPackageVersionId}: ${error.message}`);
101
+ return undefined;
102
+ }
103
+ }
104
+ /**
105
+ * For every package an {@link installPackageDependencies} run upgraded, fetches the previous and
106
+ * target version's `sf package version report` (for the origin commit SHA and pipeline URL). A
107
+ * package whose version report can't be resolved is skipped with a warning rather than failing the
108
+ * whole deployment — this data only feeds a later notification.
109
+ */
110
+ export async function resolveUpgradedPackages(installResults, config) {
111
+ const upgraded = upgradedEntries(installResults);
112
+ if (upgraded.length === 0) {
113
+ return [];
114
+ }
115
+ const { packagingDevhub } = config;
116
+ if (!packagingDevhub) {
117
+ logger.warn('No --packaging-devhub given. Skipping origin lookup for upgraded packages.');
118
+ return [];
119
+ }
120
+ const upgradedPackages = [];
121
+ for (const entry of upgraded) {
122
+ // eslint-disable-next-line no-await-in-loop -- each package's prev/target reports are fetched concurrently, but packages themselves are processed one at a time
123
+ const [prevReport, targetReport] = await Promise.all([
124
+ reportPackageVersion(entry.ExistingSubscriberPackageVersionId, packagingDevhub),
125
+ reportPackageVersion(entry.SubscriberPackageVersionId, packagingDevhub),
126
+ ]);
127
+ if (!prevReport || !targetReport) {
128
+ continue;
129
+ }
130
+ upgradedPackages.push({
131
+ packageName: entry.PackageName,
132
+ prevVersionId: entry.ExistingSubscriberPackageVersionId,
133
+ prevVersionNumber: prevReport.Version,
134
+ prevTag: prevReport.Tag,
135
+ targetVersionId: entry.SubscriberPackageVersionId,
136
+ targetVersionNumber: targetReport.Version,
137
+ targetTag: targetReport.Tag,
138
+ targetDescription: targetReport.Description,
139
+ });
140
+ }
141
+ return upgradedPackages;
142
+ }
143
+ //# sourceMappingURL=sfPackages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfPackages.js","sourceRoot":"","sources":["../src/sfPackages.ts"],"names":[],"mappings":"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"}