@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.
- package/README.md +35 -7
- package/lib/build/checkPermissionSets.d.ts +22 -0
- package/lib/build/checkPermissionSets.js +102 -0
- package/lib/build/checkPermissionSets.js.map +1 -0
- package/lib/build/cleanupScratchOrgs.d.ts +6 -0
- package/lib/build/cleanupScratchOrgs.js +91 -0
- package/lib/build/cleanupScratchOrgs.js.map +1 -0
- package/lib/build/createFallbackTag.d.ts +24 -0
- package/lib/build/createFallbackTag.js +147 -0
- package/lib/build/createFallbackTag.js.map +1 -0
- package/lib/build/createPackageVersion.d.ts +42 -0
- package/lib/build/createPackageVersion.js +198 -0
- package/lib/build/createPackageVersion.js.map +1 -0
- package/lib/build/createScratchOrg.d.ts +14 -0
- package/lib/build/createScratchOrg.js +192 -0
- package/lib/build/createScratchOrg.js.map +1 -0
- package/lib/build/deleteScratchOrg.d.ts +13 -0
- package/lib/build/deleteScratchOrg.js +62 -0
- package/lib/build/deleteScratchOrg.js.map +1 -0
- package/lib/build/deltaRunner.d.ts +73 -0
- package/lib/build/deltaRunner.js +109 -0
- package/lib/build/deltaRunner.js.map +1 -0
- package/lib/build/determinePackageChanges.d.ts +11 -0
- package/lib/build/determinePackageChanges.js +90 -0
- package/lib/build/determinePackageChanges.js.map +1 -0
- package/lib/build/devHubs.d.ts +12 -0
- package/lib/build/devHubs.js +42 -0
- package/lib/build/devHubs.js.map +1 -0
- package/lib/build/flexipageDelta.d.ts +18 -0
- package/lib/build/flexipageDelta.js +35 -0
- package/lib/build/flexipageDelta.js.map +1 -0
- package/lib/build/flowDelta.d.ts +17 -0
- package/lib/build/flowDelta.js +34 -0
- package/lib/build/flowDelta.js.map +1 -0
- package/lib/build/installDependencies.d.ts +10 -0
- package/lib/build/installDependencies.js +39 -0
- package/lib/build/installDependencies.js.map +1 -0
- package/lib/build/lwcJest.d.ts +25 -0
- package/lib/build/lwcJest.js +126 -0
- package/lib/build/lwcJest.js.map +1 -0
- package/lib/build/publishUtamPageObjects.d.ts +50 -0
- package/lib/build/publishUtamPageObjects.js +283 -0
- package/lib/build/publishUtamPageObjects.js.map +1 -0
- package/lib/build/pushScratch.d.ts +9 -0
- package/lib/build/pushScratch.js +60 -0
- package/lib/build/pushScratch.js.map +1 -0
- package/lib/build/scratchOrgAuth.d.ts +18 -0
- package/lib/build/scratchOrgAuth.js +52 -0
- package/lib/build/scratchOrgAuth.js.map +1 -0
- package/lib/build/scratchOrgInfo.d.ts +14 -0
- package/lib/build/scratchOrgInfo.js +21 -0
- package/lib/build/scratchOrgInfo.js.map +1 -0
- package/lib/build/skipGuard.d.ts +8 -0
- package/lib/build/skipGuard.js +42 -0
- package/lib/build/skipGuard.js.map +1 -0
- package/lib/build/testScratch.d.ts +15 -0
- package/lib/build/testScratch.js +42 -0
- package/lib/build/testScratch.js.map +1 -0
- package/lib/build/utamPageObjects.d.ts +143 -0
- package/lib/build/utamPageObjects.js +258 -0
- package/lib/build/utamPageObjects.js.map +1 -0
- package/lib/build/versionTagFormat.d.ts +57 -0
- package/lib/build/versionTagFormat.js +194 -0
- package/lib/build/versionTagFormat.js.map +1 -0
- package/lib/config/defaultDeploymentPlugins.d.ts +2 -0
- package/lib/config/defaultDeploymentPlugins.js +18 -0
- package/lib/config/defaultDeploymentPlugins.js.map +1 -0
- package/lib/config/trustedPlugins.d.ts +2 -0
- package/lib/config/trustedPlugins.js +18 -0
- package/lib/config/trustedPlugins.js.map +1 -0
- package/lib/deploy/deployCommon.d.ts +105 -0
- package/lib/deploy/deployCommon.js +358 -0
- package/lib/deploy/deployCommon.js.map +1 -0
- package/lib/deploy/deployHappySoup.d.ts +56 -0
- package/lib/deploy/deployHappySoup.js +160 -0
- package/lib/deploy/deployHappySoup.js.map +1 -0
- package/lib/deploy/deployProject.d.ts +27 -0
- package/lib/deploy/deployProject.js +114 -0
- package/lib/deploy/deployProject.js.map +1 -0
- package/lib/deploy/runDeployStage.d.ts +16 -0
- package/lib/deploy/runDeployStage.js +65 -0
- package/lib/deploy/runDeployStage.js.map +1 -0
- package/lib/deploy/stageOptions.d.ts +49 -0
- package/lib/deploy/stageOptions.js +70 -0
- package/lib/deploy/stageOptions.js.map +1 -0
- package/lib/deploy/validate.d.ts +11 -0
- package/lib/deploy/validate.js +54 -0
- package/lib/deploy/validate.js.map +1 -0
- package/lib/env.d.ts +9 -0
- package/lib/env.js +47 -0
- package/lib/env.js.map +1 -0
- package/lib/exec/sfCli.d.ts +27 -0
- package/lib/exec/sfCli.js +50 -0
- package/lib/exec/sfCli.js.map +1 -0
- package/lib/flags/env.d.ts +44 -0
- package/lib/flags/env.js +81 -0
- package/lib/flags/env.js.map +1 -0
- package/lib/git.d.ts +32 -0
- package/lib/git.js +106 -0
- package/lib/git.js.map +1 -0
- package/lib/happySoup/resolveOriginProject.d.ts +22 -0
- package/lib/happySoup/resolveOriginProject.js +61 -0
- package/lib/happySoup/resolveOriginProject.js.map +1 -0
- package/lib/index.d.ts +51 -0
- package/lib/index.js +63 -2
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +10 -0
- package/lib/logger.js +33 -0
- package/lib/logger.js.map +1 -0
- package/lib/notify/buildNotification.d.ts +53 -0
- package/lib/notify/buildNotification.js +176 -0
- package/lib/notify/buildNotification.js.map +1 -0
- package/lib/notify/getCommitStories.d.ts +30 -0
- package/lib/notify/getCommitStories.js +70 -0
- package/lib/notify/getCommitStories.js.map +1 -0
- package/lib/notify/getRemoteCommitStories.d.ts +10 -0
- package/lib/notify/getRemoteCommitStories.js +45 -0
- package/lib/notify/getRemoteCommitStories.js.map +1 -0
- package/lib/notify/happySoupNotification.d.ts +26 -0
- package/lib/notify/happySoupNotification.js +140 -0
- package/lib/notify/happySoupNotification.js.map +1 -0
- package/lib/notify/projectNotification.d.ts +46 -0
- package/lib/notify/projectNotification.js +177 -0
- package/lib/notify/projectNotification.js.map +1 -0
- package/lib/notify/renderTemplate.d.ts +3 -0
- package/lib/notify/renderTemplate.js +24 -0
- package/lib/notify/renderTemplate.js.map +1 -0
- package/lib/notify/sendNotification.d.ts +2 -0
- package/lib/notify/sendNotification.js +50 -0
- package/lib/notify/sendNotification.js.map +1 -0
- package/lib/notify/templates.d.ts +13 -0
- package/lib/notify/templates.js +118 -0
- package/lib/notify/templates.js.map +1 -0
- package/lib/schemas/deployConfig.d.ts +25 -0
- package/lib/schemas/deployConfig.js +55 -0
- package/lib/schemas/deployConfig.js.map +1 -0
- package/lib/schemas/deployProgress.d.ts +33 -0
- package/lib/schemas/deployProgress.js +46 -0
- package/lib/schemas/deployProgress.js.map +1 -0
- package/lib/schemas/deployRules.d.ts +34 -0
- package/lib/schemas/deployRules.js +40 -0
- package/lib/schemas/deployRules.js.map +1 -0
- package/lib/sfApex.d.ts +22 -0
- package/lib/sfApex.js +169 -0
- package/lib/sfApex.js.map +1 -0
- package/lib/sfAuth.d.ts +19 -0
- package/lib/sfAuth.js +78 -0
- package/lib/sfAuth.js.map +1 -0
- package/lib/sfConfig.d.ts +23 -0
- package/lib/sfConfig.js +82 -0
- package/lib/sfConfig.js.map +1 -0
- package/lib/sfPackages.d.ts +31 -0
- package/lib/sfPackages.js +143 -0
- package/lib/sfPackages.js.map +1 -0
- package/lib/sfPlugins.d.ts +11 -0
- package/lib/sfPlugins.js +134 -0
- package/lib/sfPlugins.js.map +1 -0
- package/lib/sfdxDependabot/dependabotRun.d.ts +95 -0
- package/lib/sfdxDependabot/dependabotRun.js +287 -0
- package/lib/sfdxDependabot/dependabotRun.js.map +1 -0
- package/lib/sfdxDependabot/updater.d.ts +14 -0
- package/lib/sfdxDependabot/updater.js +94 -0
- package/lib/sfdxDependabot/updater.js.map +1 -0
- package/package.json +18 -7
|
@@ -0,0 +1,358 @@
|
|
|
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 chalk from 'chalk';
|
|
19
|
+
import { execa } from 'execa';
|
|
20
|
+
import { createVcsProvider } from '../vcs/index.js';
|
|
21
|
+
import { cloneRepo } from '../git.js';
|
|
22
|
+
import { logger } from '../logger.js';
|
|
23
|
+
import { runApexTests as runApexTestsCommon } from '../sfApex.js';
|
|
24
|
+
import { installPackageDependencies as installPackageDependenciesCommon } from '../sfPackages.js';
|
|
25
|
+
import { installDeploymentPlugins } from '../sfPlugins.js';
|
|
26
|
+
import { deployConfigSchema } from '../schemas/deployConfig.js';
|
|
27
|
+
import { deployProgressSchema } from '../schemas/deployProgress.js';
|
|
28
|
+
import { deployRulesSchema } from '../schemas/deployRules.js';
|
|
29
|
+
/** Validates `data` against a zod schema, throwing a formatted error (one bullet per issue) if it fails. */
|
|
30
|
+
export function validateWithSchema(schema, data, fileName) {
|
|
31
|
+
const result = schema.safeParse(data);
|
|
32
|
+
if (!result.success) {
|
|
33
|
+
const errorMessages = result.error.issues
|
|
34
|
+
.map((issue) => ` - ${issue.path.join('.') || 'root'}: ${issue.message}`)
|
|
35
|
+
.join('');
|
|
36
|
+
throw new Error(`Invalid format for ${fileName}: ${errorMessages}`);
|
|
37
|
+
}
|
|
38
|
+
return result.data;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read a JSON file and validate it against a zod schema.
|
|
42
|
+
*
|
|
43
|
+
* @param filePath - The file to read. Its name appears in the error on a schema violation.
|
|
44
|
+
* @param schema - The schema to validate against.
|
|
45
|
+
* @returns The validated contents.
|
|
46
|
+
* @throws {Error} With one bullet per schema issue, via {@link validateWithSchema}.
|
|
47
|
+
* @throws {NodeJS.ErrnoException} If the file can't be read — callers check for `ENOENT` to
|
|
48
|
+
* treat a missing file as non-fatal.
|
|
49
|
+
* @throws {SyntaxError} If the file isn't valid JSON.
|
|
50
|
+
*/
|
|
51
|
+
export async function loadValidatedJsonFile(filePath, schema) {
|
|
52
|
+
const contents = await fs.readFile(filePath, 'utf-8');
|
|
53
|
+
return validateWithSchema(schema, JSON.parse(contents), filePath);
|
|
54
|
+
}
|
|
55
|
+
/** Validates a deployment configuration against a set of deployment rules (e.g. "prod must run postDeploy"). */
|
|
56
|
+
export async function validateDeploymentRules(deploymentConfig, rulesFile) {
|
|
57
|
+
let rulesConfig;
|
|
58
|
+
try {
|
|
59
|
+
rulesConfig = await loadValidatedJsonFile(rulesFile, deployRulesSchema);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error.code === 'ENOENT') {
|
|
63
|
+
logger.info(`Deployment rules file not found at ${rulesFile}. Skipping rules validation.`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
logger.error(`Failed to read or validate ${rulesFile}: ${error.message}`);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
const errors = [];
|
|
70
|
+
for (const rule of rulesConfig.rules) {
|
|
71
|
+
const deployment = deploymentConfig.deployments.find((d) => {
|
|
72
|
+
const matchesName = Boolean(rule.deploymentName) && d.name === rule.deploymentName;
|
|
73
|
+
const matchesSlug = Boolean(rule.deploymentSlug) && d.slug === rule.deploymentSlug;
|
|
74
|
+
return matchesName || matchesSlug;
|
|
75
|
+
});
|
|
76
|
+
if (deployment) {
|
|
77
|
+
for (const requiredStage of rule.requireStages) {
|
|
78
|
+
if (!deployment[requiredStage]) {
|
|
79
|
+
let identifier;
|
|
80
|
+
if (rule.deploymentName && rule.deploymentSlug) {
|
|
81
|
+
identifier = `name '${rule.deploymentName}' or slug '${rule.deploymentSlug}'`;
|
|
82
|
+
}
|
|
83
|
+
else if (rule.deploymentName) {
|
|
84
|
+
identifier = `name '${rule.deploymentName}'`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
identifier = `slug '${rule.deploymentSlug ?? 'unknown'}'`;
|
|
88
|
+
}
|
|
89
|
+
errors.push(`Deployment with ${identifier} is missing required stage '${requiredStage}'.`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (errors.length > 0) {
|
|
95
|
+
throw new Error(`Deployment configuration failed validation against deployment rules:\n${errors.join('\n')}`);
|
|
96
|
+
}
|
|
97
|
+
logger.success('Deployment configuration passed validation against deployment rules.');
|
|
98
|
+
}
|
|
99
|
+
export const STAGE_TO_SCRIPT_NAME_MAP = {
|
|
100
|
+
'pre-destructive': 'preDestructive.sh',
|
|
101
|
+
'deploy-unpackaged': 'unpackagedDeploy.sh',
|
|
102
|
+
'post-deploy': 'postDeploy.sh',
|
|
103
|
+
'post-destructive': 'postDestructive.sh',
|
|
104
|
+
};
|
|
105
|
+
export const STAGE_TO_PROPERTY_MAP = {
|
|
106
|
+
'pre-destructive': 'preDestructive',
|
|
107
|
+
'install-packaged': 'installPackaged',
|
|
108
|
+
'deploy-unpackaged': 'unpackagedDeploy',
|
|
109
|
+
'post-deploy': 'postDeploy',
|
|
110
|
+
'post-destructive': 'postDestructive',
|
|
111
|
+
};
|
|
112
|
+
export const STAGE_CONFIG = {
|
|
113
|
+
'pre-destructive': { property: 'preDestructive' },
|
|
114
|
+
'deploy-unpackaged': { property: 'unpackagedDeploy' },
|
|
115
|
+
'post-deploy': { property: 'postDeploy' },
|
|
116
|
+
'post-destructive': { property: 'postDestructive' },
|
|
117
|
+
};
|
|
118
|
+
/** Atomically updates a progress file: writes to a temp file first, then renames it into place. */
|
|
119
|
+
export async function updateProgress(deployProgressFile, newProgress) {
|
|
120
|
+
const tempFile = `${deployProgressFile}.${Date.now()}.tmp`;
|
|
121
|
+
await fs.writeFile(tempFile, JSON.stringify(newProgress, null, 2));
|
|
122
|
+
await fs.rename(tempFile, deployProgressFile);
|
|
123
|
+
}
|
|
124
|
+
const DIRS_TO_CHMOD = [
|
|
125
|
+
{ dir: 'logs', mode: '+rw' },
|
|
126
|
+
{ dir: 'data', mode: '+rw' },
|
|
127
|
+
{ dir: 'bin', mode: '+rx' },
|
|
128
|
+
{ dir: 'scripts', mode: '+rw' },
|
|
129
|
+
];
|
|
130
|
+
async function chmodStageDirectories(repoDir, jobName) {
|
|
131
|
+
for (const { dir, mode } of DIRS_TO_CHMOD) {
|
|
132
|
+
const dirPath = path.join(repoDir, dir);
|
|
133
|
+
try {
|
|
134
|
+
// eslint-disable-next-line no-await-in-loop
|
|
135
|
+
await fs.access(dirPath);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
logger.info(`[${jobName}] Modifying permissions of ${dir} to ${mode}...`);
|
|
142
|
+
// eslint-disable-next-line no-await-in-loop
|
|
143
|
+
await execa('chmod', ['-R', mode, `./${dir}`], { cwd: repoDir });
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
logger.warn(`[${jobName}] Could not modify permissions for ${dir}. This might cause issues on non-Windows systems.`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Executes a stage-specific script (e.g. `bin/preDestructive.sh`) for a deployment: installs npm
|
|
152
|
+
* production dependencies if a `package.json` exists, sets executable/writable permissions on the
|
|
153
|
+
* repo's working directories, and runs the script with `--target-org`/`--test-level`/`--tests`.
|
|
154
|
+
*/
|
|
155
|
+
export async function executeStageScript(deployment, stage, repoDir, config) {
|
|
156
|
+
const { alias } = config;
|
|
157
|
+
const jobName = deployment.name.toUpperCase();
|
|
158
|
+
const scriptName = STAGE_TO_SCRIPT_NAME_MAP[stage];
|
|
159
|
+
if (!scriptName) {
|
|
160
|
+
logger.info(`No script configured for stage ${stage}, skipping script execution.`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const scriptPath = path.join(repoDir, 'bin', scriptName);
|
|
164
|
+
try {
|
|
165
|
+
await fs.access(scriptPath);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
logger.info(`Script ${scriptPath} not found for deployment ${deployment.name}, skipping.`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
logger.info(`[${jobName}] Preparing to run ${scriptName}`);
|
|
172
|
+
const packageJsonPath = path.join(repoDir, 'package.json');
|
|
173
|
+
try {
|
|
174
|
+
await fs.access(packageJsonPath);
|
|
175
|
+
logger.info(`[${jobName}] Installing npm dependencies...`);
|
|
176
|
+
await execa('npm', ['install', '--omit=dev'], { cwd: repoDir, env: { HUSKY_SKIP_INSTALL: '1' } });
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// No package.json for this repo; nothing to install.
|
|
180
|
+
}
|
|
181
|
+
await chmodStageDirectories(repoDir, jobName);
|
|
182
|
+
const testLevel = deployment.testLevel ?? config.testLevel ?? 'RunLocalTests';
|
|
183
|
+
const tests = deployment.tests ?? config.tests ?? '';
|
|
184
|
+
const scriptArgs = ['--target-org', alias ?? '', '--test-level', testLevel];
|
|
185
|
+
if (tests) {
|
|
186
|
+
scriptArgs.push('--tests', tests);
|
|
187
|
+
}
|
|
188
|
+
logger.info(`[${jobName}] Executing: ./${path.join('bin', scriptName)} ${scriptArgs.join(' ')}`);
|
|
189
|
+
await execa(path.resolve(scriptPath), scriptArgs, { cwd: repoDir, stdio: 'inherit' });
|
|
190
|
+
}
|
|
191
|
+
/** Installs the target org's packaged dependencies. The org must already be authenticated. */
|
|
192
|
+
export async function installDeployPackageDependencies(config) {
|
|
193
|
+
const { alias, wait = '120', installType = 'Upgrade', upgradeType } = config;
|
|
194
|
+
await installPackageDependenciesCommon({ alias, wait, installType, upgradeType });
|
|
195
|
+
}
|
|
196
|
+
/** Logs a per-job duration summary for the given stage, from the recorded progress file durations. */
|
|
197
|
+
export function printDeploymentSummary(deployProgress, stage) {
|
|
198
|
+
try {
|
|
199
|
+
const stageConfig = STAGE_CONFIG[stage];
|
|
200
|
+
if (!stageConfig) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const stageProperty = stageConfig.property;
|
|
204
|
+
if (!deployProgress.durations) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const jobs = [];
|
|
208
|
+
for (const [jobName, durations] of Object.entries(deployProgress.durations)) {
|
|
209
|
+
if (durations?.[stageProperty] !== undefined) {
|
|
210
|
+
jobs.push({ name: jobName.toUpperCase(), duration: durations[stageProperty] });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (jobs.length === 0) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
logger.raw('\n');
|
|
217
|
+
logger.info(`Job Summary: ${chalk.bold(stage)}`);
|
|
218
|
+
for (const job of jobs) {
|
|
219
|
+
logger.info(` - Job: ${job.name} | Duration: ${job.duration}s`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
logger.warn(`Could not generate deployment summary: ${error.message}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** Runs Apex tests on the target org. The org must already be authenticated. */
|
|
227
|
+
export async function runDeployApexTests(config) {
|
|
228
|
+
const { alias, testLevel = 'RunLocalTests', testSuite, wait = '360' } = config;
|
|
229
|
+
logger.info(`Running Apex tests on org ${alias ?? 'unknown'}...`);
|
|
230
|
+
await runApexTestsCommon({ alias, testLevel, testSuite, wait, debugMode: config.debugMode });
|
|
231
|
+
}
|
|
232
|
+
export async function loadProgress(deployProgressFile) {
|
|
233
|
+
try {
|
|
234
|
+
return await loadValidatedJsonFile(deployProgressFile, deployProgressSchema);
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
if (error.code === 'ENOENT') {
|
|
238
|
+
return {};
|
|
239
|
+
}
|
|
240
|
+
logger.warn(`Could not read or validate ${deployProgressFile}: ${error.message}. Starting fresh.`);
|
|
241
|
+
return {};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async function loadDeployConfig(deployConfigFile, deployRulesFile) {
|
|
245
|
+
try {
|
|
246
|
+
const deploymentConfig = await loadValidatedJsonFile(deployConfigFile, deployConfigSchema);
|
|
247
|
+
await validateDeploymentRules(deploymentConfig, deployRulesFile);
|
|
248
|
+
return { found: true, config: deploymentConfig };
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
if (error.code === 'ENOENT') {
|
|
252
|
+
logger.warn(`Deployment config file not found at ${deployConfigFile}. Skipping deployments from config for this stage.`);
|
|
253
|
+
return { found: false };
|
|
254
|
+
}
|
|
255
|
+
logger.error(`Failed to read or validate ${deployConfigFile}: ${error.message}`);
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function resolveStartFrom(progress, stage, stageProperty, startFrom) {
|
|
260
|
+
if (startFrom) {
|
|
261
|
+
logger.info(`Starting ${chalk.bold(stage)} from job: ${chalk.bold(startFrom)} (forced by CLI option)`);
|
|
262
|
+
return { effectiveStartFrom: startFrom, idxOffset: 0 };
|
|
263
|
+
}
|
|
264
|
+
const resumePoint = progress[stageProperty];
|
|
265
|
+
if (resumePoint && resumePoint !== 'COMPLETE') {
|
|
266
|
+
logger.info(`Resuming ${chalk.bold(stage)} from job: ${chalk.bold(resumePoint)} (offset 1) based on progress file`);
|
|
267
|
+
return { effectiveStartFrom: resumePoint, idxOffset: 1 };
|
|
268
|
+
}
|
|
269
|
+
return { idxOffset: 0 };
|
|
270
|
+
}
|
|
271
|
+
function buildDeploymentsToRun(deploymentConfig, isProjectDeployment, stageProperty, effectiveStartFrom, idxOffset) {
|
|
272
|
+
let deploymentsToRun = deploymentConfig?.deployments ?? [];
|
|
273
|
+
if (isProjectDeployment) {
|
|
274
|
+
const localDeployment = { name: 'local' };
|
|
275
|
+
localDeployment[stageProperty] = true;
|
|
276
|
+
deploymentsToRun = [...deploymentsToRun, localDeployment];
|
|
277
|
+
}
|
|
278
|
+
if (effectiveStartFrom) {
|
|
279
|
+
const startIndex = deploymentsToRun.findIndex((d) => d.name === effectiveStartFrom);
|
|
280
|
+
if (startIndex === -1) {
|
|
281
|
+
throw new Error(`Start job ${chalk.bold(effectiveStartFrom)} not found in deployments configuration.`);
|
|
282
|
+
}
|
|
283
|
+
deploymentsToRun = deploymentsToRun.slice(startIndex + idxOffset);
|
|
284
|
+
}
|
|
285
|
+
return deploymentsToRun.filter((d) => Boolean(d[stageProperty]));
|
|
286
|
+
}
|
|
287
|
+
async function runDeploymentJob(deployment, stage, stageProperty, progress, deployProgressFile, config, vcsProvider) {
|
|
288
|
+
const jobName = deployment.name.toUpperCase();
|
|
289
|
+
logger.raw('\n' + '='.repeat(80));
|
|
290
|
+
logger.info(`>>> Starting Job: ${chalk.bold(jobName)} <<<`);
|
|
291
|
+
logger.raw('='.repeat(80) + '\n');
|
|
292
|
+
const startTime = Date.now();
|
|
293
|
+
try {
|
|
294
|
+
const repoDir = deployment.name.toLowerCase() === 'local'
|
|
295
|
+
? process.cwd()
|
|
296
|
+
: await cloneRepo({ name: deployment.name, slug: deployment.slug ?? '', ref: deployment.ref }, { ciJobToken: config.ciJobToken, vcsProvider });
|
|
297
|
+
await installDeploymentPlugins(config.debug, repoDir);
|
|
298
|
+
await executeStageScript(deployment, stage, repoDir, config);
|
|
299
|
+
const durationSeconds = Number(((Date.now() - startTime) / 1000).toFixed(2));
|
|
300
|
+
progress[stageProperty] = deployment.name;
|
|
301
|
+
progress.durations ??= {};
|
|
302
|
+
progress.durations[deployment.name] ??= {};
|
|
303
|
+
progress.durations[deployment.name][stageProperty] = durationSeconds;
|
|
304
|
+
await updateProgress(deployProgressFile, progress);
|
|
305
|
+
logger.raw('\n' + '='.repeat(80));
|
|
306
|
+
logger.success(`Completed Job: ${chalk.bold(jobName)} in ${durationSeconds}s`);
|
|
307
|
+
logger.raw('='.repeat(80) + '\n');
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
error.job = jobName;
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Runs a complete set of deployment jobs for a stage: loads (and validates) the progress and
|
|
316
|
+
* config files, determines where to resume from, then clones/prepares/executes each job in order
|
|
317
|
+
* — persisting progress after every job so a mid-run crash can resume cleanly. The target org
|
|
318
|
+
* (`config.alias`) must already be authenticated.
|
|
319
|
+
*/
|
|
320
|
+
export async function runDeploymentSteps(config) {
|
|
321
|
+
const { deployConfigFile, deployRulesFile, isProjectDeployment, deployProgressFile, stage, startFrom } = config;
|
|
322
|
+
const progress = await loadProgress(deployProgressFile);
|
|
323
|
+
const deployConfigResult = await loadDeployConfig(deployConfigFile, deployRulesFile);
|
|
324
|
+
if (!deployConfigResult.found && !isProjectDeployment) {
|
|
325
|
+
return { deployProgress: progress };
|
|
326
|
+
}
|
|
327
|
+
const stageConfig = STAGE_CONFIG[stage];
|
|
328
|
+
if (!stageConfig) {
|
|
329
|
+
throw new Error(`Invalid or unsupported stage for deployment jobs: ${chalk.bold(stage)}`);
|
|
330
|
+
}
|
|
331
|
+
const stageProperty = stageConfig.property;
|
|
332
|
+
const { effectiveStartFrom, idxOffset } = resolveStartFrom(progress, stage, stageProperty, startFrom);
|
|
333
|
+
const deploymentsToRun = buildDeploymentsToRun(deployConfigResult.found ? deployConfigResult.config : undefined, isProjectDeployment, stageProperty, effectiveStartFrom, idxOffset);
|
|
334
|
+
if (deploymentsToRun.length === 0) {
|
|
335
|
+
logger.info(`No deployments configured for ${chalk.bold(stage)}.`);
|
|
336
|
+
return { deployProgress: progress };
|
|
337
|
+
}
|
|
338
|
+
const vcsProvider = createVcsProvider(config.vcsProvider, { host: config.vcsHost, token: config.ciJobToken });
|
|
339
|
+
for (const deployment of deploymentsToRun) {
|
|
340
|
+
// eslint-disable-next-line no-await-in-loop
|
|
341
|
+
await runDeploymentJob(deployment, stage, stageProperty, progress, deployProgressFile, config, vcsProvider);
|
|
342
|
+
}
|
|
343
|
+
progress[stageProperty] = 'COMPLETE';
|
|
344
|
+
await updateProgress(deployProgressFile, progress);
|
|
345
|
+
return { deployProgress: progress };
|
|
346
|
+
}
|
|
347
|
+
/** Determines the deploy config file path: explicit path wins, else derived from the branch name. */
|
|
348
|
+
export function determineDeployConfigFile(sourceBranchName, deployConfigFile) {
|
|
349
|
+
if (deployConfigFile) {
|
|
350
|
+
return deployConfigFile;
|
|
351
|
+
}
|
|
352
|
+
if (!sourceBranchName) {
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
const branchNamePart = sourceBranchName.includes('/') ? sourceBranchName.split('/')[1] : sourceBranchName;
|
|
356
|
+
return `deployment-configs/${branchNamePart}.json`;
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=deployCommon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployCommon.js","sourceRoot":"","sources":["../../src/deploy/deployCommon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type VcsProviderKind } from '../vcs/index.js';
|
|
2
|
+
import { type OrgAuthConfig } from './deployCommon.js';
|
|
3
|
+
export type DeploymentCloseOutConfig = {
|
|
4
|
+
projectAccessToken: string;
|
|
5
|
+
ciPipelineId: string;
|
|
6
|
+
ciProjectPath: string;
|
|
7
|
+
ciCommitRefName: string;
|
|
8
|
+
deployReleaseDate?: string;
|
|
9
|
+
deployConfigFile?: string;
|
|
10
|
+
vcsHost?: string;
|
|
11
|
+
vcsProvider: VcsProviderKind;
|
|
12
|
+
};
|
|
13
|
+
export type TagDeploymentConfig = OrgAuthConfig & {
|
|
14
|
+
projectAccessToken: string;
|
|
15
|
+
ciPipelineId: string;
|
|
16
|
+
ciProjectPath: string;
|
|
17
|
+
ciPipelineUrl?: string;
|
|
18
|
+
ciMergeRequestProjectUrl?: string;
|
|
19
|
+
ciMergeRequestIid?: string;
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
vcsHost?: string;
|
|
22
|
+
vcsProvider: VcsProviderKind;
|
|
23
|
+
};
|
|
24
|
+
export type DeployHappySoupOptions = OrgAuthConfig & {
|
|
25
|
+
stage: string;
|
|
26
|
+
sourceBranchName?: string;
|
|
27
|
+
deployConfigFile?: string;
|
|
28
|
+
deployRulesFile?: string;
|
|
29
|
+
deployProgressFile?: string;
|
|
30
|
+
startFrom?: string;
|
|
31
|
+
debug?: boolean;
|
|
32
|
+
testLevel?: string;
|
|
33
|
+
tests?: string;
|
|
34
|
+
ciJobToken?: string;
|
|
35
|
+
vcsHost?: string;
|
|
36
|
+
vcsProvider: VcsProviderKind;
|
|
37
|
+
installType?: 'All' | 'Delta' | 'Upgrade';
|
|
38
|
+
upgradeType?: 'DeprecateOnly' | 'Mixed' | 'Delete';
|
|
39
|
+
wait?: string;
|
|
40
|
+
packagingDevhub?: string;
|
|
41
|
+
projectAccessToken?: string;
|
|
42
|
+
ciPipelineId?: string;
|
|
43
|
+
ciProjectPath?: string;
|
|
44
|
+
ciPipelineUrl?: string;
|
|
45
|
+
ciMergeRequestProjectUrl?: string;
|
|
46
|
+
ciMergeRequestIid?: string;
|
|
47
|
+
ciCommitRefName?: string;
|
|
48
|
+
deployReleaseDate?: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Runs a "happy-soup" (multi-repo, unlocked-package) deployment stage. `install-packaged` installs
|
|
52
|
+
* dependencies only; `tag-deployment` and `deployment-close-out` have their own git-native logic;
|
|
53
|
+
* every other stage runs through the resumable deployment-steps loop against the branch-derived
|
|
54
|
+
* (or explicit) deploy config file.
|
|
55
|
+
*/
|
|
56
|
+
export declare function deployHappySoup(options: DeployHappySoupOptions): Promise<void>;
|
|
@@ -0,0 +1,160 @@
|
|
|
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 { createVcsProvider } from '../vcs/index.js';
|
|
19
|
+
import { runSf } from '../exec/sfCli.js';
|
|
20
|
+
import { addGitRemote } from '../git.js';
|
|
21
|
+
import { logger } from '../logger.js';
|
|
22
|
+
import { installPackageDependencies as installPackageDependenciesCommon, resolveUpgradedPackages, } from '../sfPackages.js';
|
|
23
|
+
import { runDeployStage } from './runDeployStage.js';
|
|
24
|
+
import { determineDeployConfigFile, loadProgress, printDeploymentSummary, runDeploymentSteps, updateProgress, } from './deployCommon.js';
|
|
25
|
+
async function archiveOrRemoveDeployConfig(finalDeployConfigFile, remoteAlias) {
|
|
26
|
+
if (finalDeployConfigFile) {
|
|
27
|
+
try {
|
|
28
|
+
await fs.access(finalDeployConfigFile);
|
|
29
|
+
const newDeployPath = 'config/deploy.json';
|
|
30
|
+
await fs.copyFile(finalDeployConfigFile, newDeployPath);
|
|
31
|
+
await execa('git', ['add', newDeployPath]);
|
|
32
|
+
await execa('git', ['commit', '-m', 'Archiving deploy.json [skip ci]', newDeployPath]);
|
|
33
|
+
await execa('git', ['push', remoteAlias]);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Fall through and try to remove an obsolete config/deploy.json instead.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
await fs.access('config/deploy.json');
|
|
42
|
+
await execa('git', ['rm', 'config/deploy.json']);
|
|
43
|
+
await execa('git', ['commit', '-m', 'Removing obsolete config/deploy.json [skip ci]', 'config/deploy.json']);
|
|
44
|
+
await execa('git', ['push', remoteAlias]);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
logger.warn('Unable to find a deploy.json to archive.');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Fetches/switches to the release branch, then archives (or removes an obsolete) `config/deploy.json`. */
|
|
51
|
+
async function deploymentCloseOut(config) {
|
|
52
|
+
const { projectAccessToken, ciPipelineId, ciProjectPath, ciCommitRefName, deployReleaseDate, deployConfigFile, vcsHost, vcsProvider: vcsProviderKind, } = config;
|
|
53
|
+
const vcsProvider = createVcsProvider(vcsProviderKind, { host: vcsHost, token: projectAccessToken });
|
|
54
|
+
const remoteAlias = await addGitRemote(ciPipelineId, projectAccessToken, ciProjectPath, vcsProvider);
|
|
55
|
+
await execa('git', ['fetch']);
|
|
56
|
+
await execa('git', ['switch', ciCommitRefName]);
|
|
57
|
+
const finalDeployConfigFile = deployReleaseDate ? `deployment-configs/${deployReleaseDate}.json` : deployConfigFile;
|
|
58
|
+
await archiveOrRemoveDeployConfig(finalDeployConfigFile, remoteAlias);
|
|
59
|
+
}
|
|
60
|
+
function formatDeploymentTimestamp(date) {
|
|
61
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
62
|
+
timeZone: 'America/New_York',
|
|
63
|
+
year: 'numeric',
|
|
64
|
+
month: '2-digit',
|
|
65
|
+
day: '2-digit',
|
|
66
|
+
hour: '2-digit',
|
|
67
|
+
minute: '2-digit',
|
|
68
|
+
hourCycle: 'h23',
|
|
69
|
+
});
|
|
70
|
+
const parts = formatter.formatToParts(date);
|
|
71
|
+
const partMap = Object.fromEntries(parts.map((p) => [p.type, p.value]));
|
|
72
|
+
return `${partMap.year}${partMap.month}${partMap.day}.${partMap.hour}${partMap.minute}`;
|
|
73
|
+
}
|
|
74
|
+
function buildDeploymentTagMessage(orgDomainPrefix, currentTime, config, vcsProvider) {
|
|
75
|
+
let message = `deployed to org ${orgDomainPrefix} at ${currentTime}`;
|
|
76
|
+
if (config.ciPipelineUrl) {
|
|
77
|
+
message += ` Associated pipeline - ${config.ciPipelineUrl}`;
|
|
78
|
+
}
|
|
79
|
+
if (config.ciMergeRequestProjectUrl && config.ciMergeRequestIid) {
|
|
80
|
+
// Both the wording and the URL path differ per platform, so both come from the provider.
|
|
81
|
+
const changeRequestUrl = vcsProvider.buildChangeRequestUrl(config.ciMergeRequestProjectUrl, config.ciMergeRequestIid);
|
|
82
|
+
message += ` Associated ${vcsProvider.terminology.changeRequest} - ${changeRequestUrl}`;
|
|
83
|
+
}
|
|
84
|
+
return message;
|
|
85
|
+
}
|
|
86
|
+
/** Tags the current commit with deployment details (org, timestamp, pipeline/MR links) and pushes the tag. */
|
|
87
|
+
async function tagDeployment(config) {
|
|
88
|
+
const { alias, projectAccessToken, ciPipelineId, ciProjectPath, vcsHost, vcsProvider: vcsProviderKind } = config;
|
|
89
|
+
const vcsProvider = createVcsProvider(vcsProviderKind, { host: vcsHost, token: projectAccessToken });
|
|
90
|
+
const remoteAlias = await addGitRemote(ciPipelineId, projectAccessToken, ciProjectPath, vcsProvider);
|
|
91
|
+
const { stdout: orgDisplay } = await runSf(['org', 'display', '--target-org', alias ?? '', '--json']);
|
|
92
|
+
const instanceUrlResult = JSON.parse(orgDisplay).result.instanceUrl;
|
|
93
|
+
const instanceSlug = instanceUrlResult.split('.')[0];
|
|
94
|
+
const orgDomainPrefix = instanceSlug.replace('https://', '');
|
|
95
|
+
if (!orgDomainPrefix) {
|
|
96
|
+
throw new Error('Unable to determine org domain prefix.');
|
|
97
|
+
}
|
|
98
|
+
const currentTime = formatDeploymentTimestamp(new Date());
|
|
99
|
+
const gitMessage = buildDeploymentTagMessage(orgDomainPrefix, currentTime, config, vcsProvider);
|
|
100
|
+
const tagName = `deployed--${orgDomainPrefix}-${currentTime}`;
|
|
101
|
+
await execa('git', ['tag', '-m', gitMessage, tagName]);
|
|
102
|
+
await execa('git', ['push', remoteAlias, '--tags']);
|
|
103
|
+
logger.log(`Deployment tagged as ${tagName}`);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Installs the target org's packaged dependencies, and — for every dependency that upgraded an
|
|
107
|
+
* already-installed package — resolves the previous/target version's origin commit SHA and
|
|
108
|
+
* pipeline URL via `sf package version report`. Detection only: the remote commit compare and
|
|
109
|
+
* story extraction happen later, at notify time (`notify happy-soup`), once the origin repo per
|
|
110
|
+
* package can be resolved. The target org must already be authenticated.
|
|
111
|
+
*/
|
|
112
|
+
async function installPackagedAndDetectUpgrades(config) {
|
|
113
|
+
const { alias, wait, installType, upgradeType } = config;
|
|
114
|
+
const installResults = await installPackageDependenciesCommon({ alias, wait, installType, upgradeType });
|
|
115
|
+
return resolveUpgradedPackages(installResults, { packagingDevhub: config.packagingDevhub });
|
|
116
|
+
}
|
|
117
|
+
async function runHappySoupStage(stage, config, deployConfigFile) {
|
|
118
|
+
if (stage === 'install-packaged') {
|
|
119
|
+
const upgradedPackages = await installPackagedAndDetectUpgrades(config);
|
|
120
|
+
const deployProgressFile = config.deployProgressFile ?? 'DEPLOY_PROGRESS.json';
|
|
121
|
+
const progress = await loadProgress(deployProgressFile);
|
|
122
|
+
progress.upgradedPackages = upgradedPackages;
|
|
123
|
+
await updateProgress(deployProgressFile, progress);
|
|
124
|
+
}
|
|
125
|
+
else if (stage === 'tag-deployment') {
|
|
126
|
+
// The CLI layer requires projectAccessToken/ciPipelineId/ciProjectPath for this stage.
|
|
127
|
+
await tagDeployment(config);
|
|
128
|
+
}
|
|
129
|
+
else if (stage === 'deployment-close-out') {
|
|
130
|
+
// The CLI layer requires projectAccessToken/ciPipelineId/ciProjectPath/ciCommitRefName for this stage.
|
|
131
|
+
await deploymentCloseOut({ ...config, deployConfigFile });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// The CLI layer requires ciJobToken for every other stage.
|
|
135
|
+
const stepsConfig = {
|
|
136
|
+
...config,
|
|
137
|
+
ciJobToken: config.ciJobToken ?? '',
|
|
138
|
+
stage,
|
|
139
|
+
deployConfigFile: deployConfigFile ?? '',
|
|
140
|
+
deployProgressFile: config.deployProgressFile ?? 'DEPLOY_PROGRESS.json',
|
|
141
|
+
deployRulesFile: config.deployRulesFile ?? 'config/deploy-rules.json',
|
|
142
|
+
};
|
|
143
|
+
const { deployProgress } = await runDeploymentSteps(stepsConfig);
|
|
144
|
+
printDeploymentSummary(deployProgress, stage);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Runs a "happy-soup" (multi-repo, unlocked-package) deployment stage. `install-packaged` installs
|
|
149
|
+
* dependencies only; `tag-deployment` and `deployment-close-out` have their own git-native logic;
|
|
150
|
+
* every other stage runs through the resumable deployment-steps loop against the branch-derived
|
|
151
|
+
* (or explicit) deploy config file.
|
|
152
|
+
*/
|
|
153
|
+
export async function deployHappySoup(options) {
|
|
154
|
+
const { stage, ...config } = options;
|
|
155
|
+
await runDeployStage(stage, options, async () => {
|
|
156
|
+
const deployConfigFile = determineDeployConfigFile(config.sourceBranchName, config.deployConfigFile);
|
|
157
|
+
await runHappySoupStage(stage, config, deployConfigFile);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=deployHappySoup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployHappySoup.js","sourceRoot":"","sources":["../../src/deploy/deployHappySoup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VcsProviderKind } from '../vcs/index.js';
|
|
2
|
+
import { type OrgAuthConfig, type RunApexTestsConfig } from './deployCommon.js';
|
|
3
|
+
type UpgradeType = 'DeprecateOnly' | 'Mixed' | 'Delete';
|
|
4
|
+
export type InstallProjectPackageConfig = OrgAuthConfig & {
|
|
5
|
+
subscriberPackageVersionId?: string;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
upgradeType?: UpgradeType;
|
|
8
|
+
};
|
|
9
|
+
export type DeployProjectOptions = OrgAuthConfig & RunApexTestsConfig & InstallProjectPackageConfig & {
|
|
10
|
+
stage: string;
|
|
11
|
+
deployConfigFile?: string;
|
|
12
|
+
deployRulesFile?: string;
|
|
13
|
+
deployProgressFile?: string;
|
|
14
|
+
startFrom?: string;
|
|
15
|
+
tests?: string;
|
|
16
|
+
ciJobToken: string;
|
|
17
|
+
vcsHost?: string;
|
|
18
|
+
vcsProvider: VcsProviderKind;
|
|
19
|
+
installType?: 'All' | 'Delta' | 'Upgrade';
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Runs a single-package "project" deployment stage: `install-packaged` installs dependencies plus
|
|
23
|
+
* the project's own package, `run-apex-tests` delegates to the shared Apex test runner, and every
|
|
24
|
+
* other stage runs through the resumable deployment-steps loop against `config/deploy.json`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function deployProject(options: DeployProjectOptions): Promise<void>;
|
|
27
|
+
export {};
|