@devramps/cli 0.1.23 → 0.1.24
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/dist/index.js +91 -67
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1556,10 +1556,11 @@ function addOidcProviderResource(template, conditional = true, oidcProviderUrl)
|
|
|
1556
1556
|
}
|
|
1557
1557
|
};
|
|
1558
1558
|
}
|
|
1559
|
-
function buildOidcTrustPolicy(accountId, subject, oidcProviderUrl, additionalTrustedAccounts) {
|
|
1559
|
+
function buildOidcTrustPolicy(accountId, subject, oidcProviderUrl, additionalTrustedAccounts, skipOidc) {
|
|
1560
1560
|
const providerUrl = oidcProviderUrl || OIDC_PROVIDER_URL;
|
|
1561
|
-
const statements = [
|
|
1562
|
-
|
|
1561
|
+
const statements = [];
|
|
1562
|
+
if (!skipOidc) {
|
|
1563
|
+
statements.push({
|
|
1563
1564
|
Effect: "Allow",
|
|
1564
1565
|
Principal: {
|
|
1565
1566
|
Federated: `arn:aws:iam::${accountId}:oidc-provider/${providerUrl}`
|
|
@@ -1571,8 +1572,8 @@ function buildOidcTrustPolicy(accountId, subject, oidcProviderUrl, additionalTru
|
|
|
1571
1572
|
[`${providerUrl}:aud`]: "sts.amazonaws.com"
|
|
1572
1573
|
}
|
|
1573
1574
|
}
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1576
1577
|
if (additionalTrustedAccounts && additionalTrustedAccounts.length > 0) {
|
|
1577
1578
|
statements.push({
|
|
1578
1579
|
Effect: "Allow",
|
|
@@ -1948,7 +1949,7 @@ function createTerraformStateBucketPolicy(bucketName, cicdAccountId, allowedAcco
|
|
|
1948
1949
|
|
|
1949
1950
|
// src/templates/org-stack.ts
|
|
1950
1951
|
function generateOrgStackTemplate(options) {
|
|
1951
|
-
const { orgSlug, cicdAccountId, targetAccountIds, oidcProviderUrl, additionalTrustedAccounts } = options;
|
|
1952
|
+
const { orgSlug, cicdAccountId, targetAccountIds, oidcProviderUrl, additionalTrustedAccounts, skipOidc } = options;
|
|
1952
1953
|
const template = createBaseTemplate(`DevRamps Org Stack for ${orgSlug}`);
|
|
1953
1954
|
const kmsKeyPolicy = buildKmsKeyPolicy(cicdAccountId, targetAccountIds);
|
|
1954
1955
|
template.Resources.DevRampsKMSKey = createKmsKeyResource(
|
|
@@ -1978,7 +1979,7 @@ function generateOrgStackTemplate(options) {
|
|
|
1978
1979
|
PolicyDocument: bucketPolicy
|
|
1979
1980
|
}
|
|
1980
1981
|
};
|
|
1981
|
-
const trustPolicy = buildOidcTrustPolicy(cicdAccountId, `org:${orgSlug}/cicd`, oidcProviderUrl, additionalTrustedAccounts);
|
|
1982
|
+
const trustPolicy = buildOidcTrustPolicy(cicdAccountId, `org:${orgSlug}/cicd`, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
1982
1983
|
const orgRolePolicies = buildOrgRolePolicies(orgSlug);
|
|
1983
1984
|
template.Resources.DevRampsCICDDeploymentRole = createIamRoleResource(
|
|
1984
1985
|
getOrgRoleName(),
|
|
@@ -2444,13 +2445,14 @@ function generateStageStackTemplate(options) {
|
|
|
2444
2445
|
dockerArtifacts,
|
|
2445
2446
|
bundleArtifacts,
|
|
2446
2447
|
oidcProviderUrl,
|
|
2447
|
-
additionalTrustedAccounts
|
|
2448
|
+
additionalTrustedAccounts,
|
|
2449
|
+
skipOidc
|
|
2448
2450
|
} = options;
|
|
2449
2451
|
const template = createBaseTemplate(
|
|
2450
2452
|
`DevRamps Stage Stack for ${pipelineSlug}/${stageName}`
|
|
2451
2453
|
);
|
|
2452
2454
|
const roleName = generateStageRoleName(pipelineSlug, stageName);
|
|
2453
|
-
const trustPolicy = buildStageTrustPolicy(accountId, orgSlug, pipelineSlug, oidcProviderUrl, additionalTrustedAccounts);
|
|
2455
|
+
const trustPolicy = buildStageTrustPolicy(accountId, orgSlug, pipelineSlug, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
2454
2456
|
const policies = buildStagePolicies(steps, additionalPolicies);
|
|
2455
2457
|
template.Resources.StageDeploymentRole = createIamRoleResource(
|
|
2456
2458
|
roleName,
|
|
@@ -2494,8 +2496,6 @@ function generateStageStackTemplate(options) {
|
|
|
2494
2496
|
);
|
|
2495
2497
|
s3Outputs[artifact.name] = { resourceId };
|
|
2496
2498
|
}
|
|
2497
|
-
const providerUrl = oidcProviderUrl || OIDC_PROVIDER_URL;
|
|
2498
|
-
const oidcProviderArn = `arn:aws:iam::${accountId}:oidc-provider/${providerUrl}`;
|
|
2499
2499
|
template.Outputs = {
|
|
2500
2500
|
StageRoleArn: {
|
|
2501
2501
|
Description: "ARN of the stage deployment role",
|
|
@@ -2506,10 +2506,6 @@ function generateStageStackTemplate(options) {
|
|
|
2506
2506
|
Description: "Name of the stage deployment role",
|
|
2507
2507
|
Value: { Ref: "StageDeploymentRole" }
|
|
2508
2508
|
},
|
|
2509
|
-
OIDCProviderArn: {
|
|
2510
|
-
Description: "ARN of the OIDC provider (created by Account Bootstrap stack)",
|
|
2511
|
-
Value: oidcProviderArn
|
|
2512
|
-
},
|
|
2513
2509
|
PipelineSlug: {
|
|
2514
2510
|
Description: "Pipeline slug",
|
|
2515
2511
|
Value: pipelineSlug
|
|
@@ -2519,6 +2515,13 @@ function generateStageStackTemplate(options) {
|
|
|
2519
2515
|
Value: stageName
|
|
2520
2516
|
}
|
|
2521
2517
|
};
|
|
2518
|
+
if (!skipOidc) {
|
|
2519
|
+
const providerUrl = oidcProviderUrl || OIDC_PROVIDER_URL;
|
|
2520
|
+
template.Outputs.OIDCProviderArn = {
|
|
2521
|
+
Description: "ARN of the OIDC provider (created by Account Bootstrap stack)",
|
|
2522
|
+
Value: `arn:aws:iam::${accountId}:oidc-provider/${providerUrl}`
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2522
2525
|
for (const [artifactName, { resourceId }] of Object.entries(ecrOutputs)) {
|
|
2523
2526
|
const safeName = sanitizeResourceId(artifactName);
|
|
2524
2527
|
template.Outputs[`${safeName}RepoUri`] = {
|
|
@@ -2535,9 +2538,9 @@ function generateStageStackTemplate(options) {
|
|
|
2535
2538
|
}
|
|
2536
2539
|
return template;
|
|
2537
2540
|
}
|
|
2538
|
-
function buildStageTrustPolicy(accountId, orgSlug, pipelineSlug, oidcProviderUrl, additionalTrustedAccounts) {
|
|
2541
|
+
function buildStageTrustPolicy(accountId, orgSlug, pipelineSlug, oidcProviderUrl, additionalTrustedAccounts, skipOidc) {
|
|
2539
2542
|
const subject = `org:${orgSlug}/pipeline:${pipelineSlug}`;
|
|
2540
|
-
return buildOidcTrustPolicy(accountId, subject, oidcProviderUrl, additionalTrustedAccounts);
|
|
2543
|
+
return buildOidcTrustPolicy(accountId, subject, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
2541
2544
|
}
|
|
2542
2545
|
function buildStagePolicies(steps, additionalPolicies) {
|
|
2543
2546
|
const policies = [];
|
|
@@ -2606,12 +2609,12 @@ function buildStagePolicies(steps, additionalPolicies) {
|
|
|
2606
2609
|
|
|
2607
2610
|
// src/templates/import-stack.ts
|
|
2608
2611
|
function generateImportStackTemplate(options) {
|
|
2609
|
-
const { pipelineSlug, orgSlug, accountId, oidcProviderUrl, additionalTrustedAccounts } = options;
|
|
2612
|
+
const { pipelineSlug, orgSlug, accountId, oidcProviderUrl, additionalTrustedAccounts, skipOidc } = options;
|
|
2610
2613
|
const template = createBaseTemplate(
|
|
2611
2614
|
`DevRamps Import Stack for ${pipelineSlug} - grants read access for artifact imports`
|
|
2612
2615
|
);
|
|
2613
2616
|
const roleName = generateImportRoleName(pipelineSlug);
|
|
2614
|
-
const trustPolicy = buildOidcTrustPolicy(accountId, `org:${orgSlug}/cicd`, oidcProviderUrl, additionalTrustedAccounts);
|
|
2617
|
+
const trustPolicy = buildOidcTrustPolicy(accountId, `org:${orgSlug}/cicd`, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
2615
2618
|
const policies = buildImportRolePolicies();
|
|
2616
2619
|
template.Resources.ImportRole = createIamRoleResource(
|
|
2617
2620
|
roleName,
|
|
@@ -2739,6 +2742,15 @@ function getOidcProviderUrlFromEndpoint(endpointOverride) {
|
|
|
2739
2742
|
return void 0;
|
|
2740
2743
|
}
|
|
2741
2744
|
}
|
|
2745
|
+
function isLocalhostEndpoint(endpointOverride) {
|
|
2746
|
+
if (!endpointOverride) return false;
|
|
2747
|
+
try {
|
|
2748
|
+
const url = new URL(endpointOverride);
|
|
2749
|
+
return url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
2750
|
+
} catch {
|
|
2751
|
+
return false;
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2742
2754
|
async function bootstrapCommand(options) {
|
|
2743
2755
|
try {
|
|
2744
2756
|
if (options.verbose) {
|
|
@@ -2790,7 +2802,11 @@ async function bootstrapCommand(options) {
|
|
|
2790
2802
|
}
|
|
2791
2803
|
const oidcProviderUrl = getOidcProviderUrlFromEndpoint(options.endpointOverride);
|
|
2792
2804
|
const additionalTrustedAccounts = options.additionalTrustedAccounts ? options.additionalTrustedAccounts.split(",").map((s) => s.trim()) : void 0;
|
|
2793
|
-
|
|
2805
|
+
const skipOidc = isLocalhostEndpoint(options.endpointOverride);
|
|
2806
|
+
if (skipOidc) {
|
|
2807
|
+
info("Localhost endpoint detected \u2014 OIDC provider creation will be skipped");
|
|
2808
|
+
}
|
|
2809
|
+
await executeDeployment(plan, pipelines, pipelineArtifacts, authData, identity.accountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
2794
2810
|
} catch (error2) {
|
|
2795
2811
|
if (error2 instanceof DevRampsError) {
|
|
2796
2812
|
error(error2.message);
|
|
@@ -3063,48 +3079,53 @@ async function confirmDeploymentPlan(plan) {
|
|
|
3063
3079
|
]
|
|
3064
3080
|
});
|
|
3065
3081
|
}
|
|
3066
|
-
async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts) {
|
|
3082
|
+
async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc) {
|
|
3067
3083
|
const results = { success: 0, failed: 0 };
|
|
3068
3084
|
const remainingStacks = 1 + plan.pipelineStacks.length + plan.stageStacks.length + plan.importStacks.length;
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
success:
|
|
3087
|
-
|
|
3088
|
-
|
|
3085
|
+
if (skipOidc) {
|
|
3086
|
+
newline();
|
|
3087
|
+
header("Phase 1: Skipping Account Bootstrap Stacks (localhost endpoint, OIDC not needed)");
|
|
3088
|
+
} else {
|
|
3089
|
+
newline();
|
|
3090
|
+
header("Phase 1: Deploying Account Bootstrap Stacks");
|
|
3091
|
+
info(`Deploying ${plan.accountStacks.length} account stack(s) in parallel...`);
|
|
3092
|
+
newline();
|
|
3093
|
+
const accountProgress = getMultiStackProgress();
|
|
3094
|
+
for (const stack of plan.accountStacks) {
|
|
3095
|
+
accountProgress.addStack(stack.stackName, "account", stack.accountId, stack.region, 1);
|
|
3096
|
+
}
|
|
3097
|
+
accountProgress.start();
|
|
3098
|
+
const accountResults = await Promise.all(
|
|
3099
|
+
plan.accountStacks.map(async (stack) => {
|
|
3100
|
+
try {
|
|
3101
|
+
await deployAccountStack(stack, currentAccountId, options, oidcProviderUrl);
|
|
3102
|
+
return { stack: `${stack.stackName} (${stack.accountId})`, success: true };
|
|
3103
|
+
} catch (error2) {
|
|
3104
|
+
return {
|
|
3105
|
+
stack: `${stack.stackName} (${stack.accountId})`,
|
|
3106
|
+
success: false,
|
|
3107
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
3110
|
+
})
|
|
3111
|
+
);
|
|
3112
|
+
clearMultiStackProgress();
|
|
3113
|
+
newline();
|
|
3114
|
+
for (const result of accountResults) {
|
|
3115
|
+
if (result.success) {
|
|
3116
|
+
success(`${result.stack} deployed`);
|
|
3117
|
+
results.success++;
|
|
3118
|
+
} else {
|
|
3119
|
+
error(`${result.stack} failed: ${result.error}`);
|
|
3120
|
+
results.failed++;
|
|
3089
3121
|
}
|
|
3090
|
-
})
|
|
3091
|
-
);
|
|
3092
|
-
clearMultiStackProgress();
|
|
3093
|
-
newline();
|
|
3094
|
-
for (const result of accountResults) {
|
|
3095
|
-
if (result.success) {
|
|
3096
|
-
success(`${result.stack} deployed`);
|
|
3097
|
-
results.success++;
|
|
3098
|
-
} else {
|
|
3099
|
-
error(`${result.stack} failed: ${result.error}`);
|
|
3100
|
-
results.failed++;
|
|
3101
3122
|
}
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3123
|
+
if (results.failed > 0) {
|
|
3124
|
+
newline();
|
|
3125
|
+
header("Deployment Summary");
|
|
3126
|
+
error(`${results.failed} account stack(s) failed. Skipping remaining ${remainingStacks} stack(s).`);
|
|
3127
|
+
process.exit(1);
|
|
3128
|
+
}
|
|
3108
3129
|
}
|
|
3109
3130
|
newline();
|
|
3110
3131
|
header("Phase 2: Deploying Org, Pipeline, Stage, and Import Stacks");
|
|
@@ -3126,7 +3147,7 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
3126
3147
|
mainProgress.start();
|
|
3127
3148
|
const orgPromise = (async () => {
|
|
3128
3149
|
try {
|
|
3129
|
-
await deployOrgStack(plan, pipelines, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts);
|
|
3150
|
+
await deployOrgStack(plan, pipelines, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
3130
3151
|
return { stack: plan.orgStack.stackName, success: true };
|
|
3131
3152
|
} catch (error2) {
|
|
3132
3153
|
return {
|
|
@@ -3150,7 +3171,7 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
3150
3171
|
});
|
|
3151
3172
|
const stagePromises = plan.stageStacks.map(async (stack) => {
|
|
3152
3173
|
try {
|
|
3153
|
-
await deployStageStack(stack, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts);
|
|
3174
|
+
await deployStageStack(stack, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
3154
3175
|
return { stack: stack.stackName, success: true };
|
|
3155
3176
|
} catch (error2) {
|
|
3156
3177
|
return {
|
|
@@ -3162,7 +3183,7 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
3162
3183
|
});
|
|
3163
3184
|
const importPromises = plan.importStacks.map(async (stack) => {
|
|
3164
3185
|
try {
|
|
3165
|
-
await deployImportStack(stack, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts);
|
|
3186
|
+
await deployImportStack(stack, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc);
|
|
3166
3187
|
return { stack: `${stack.stackName} (${stack.accountId})`, success: true };
|
|
3167
3188
|
} catch (error2) {
|
|
3168
3189
|
return {
|
|
@@ -3199,7 +3220,7 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
3199
3220
|
process.exit(1);
|
|
3200
3221
|
}
|
|
3201
3222
|
}
|
|
3202
|
-
async function deployOrgStack(plan, pipelines, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts) {
|
|
3223
|
+
async function deployOrgStack(plan, pipelines, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc) {
|
|
3203
3224
|
const { orgSlug, cicdAccountId, cicdRegion } = authData;
|
|
3204
3225
|
const credentials = cicdAccountId !== currentAccountId ? (await assumeRoleForAccount({
|
|
3205
3226
|
targetAccountId: cicdAccountId,
|
|
@@ -3231,7 +3252,8 @@ async function deployOrgStack(plan, pipelines, authData, currentAccountId, optio
|
|
|
3231
3252
|
cicdAccountId,
|
|
3232
3253
|
targetAccountIds,
|
|
3233
3254
|
oidcProviderUrl,
|
|
3234
|
-
additionalTrustedAccounts
|
|
3255
|
+
additionalTrustedAccounts,
|
|
3256
|
+
skipOidc
|
|
3235
3257
|
});
|
|
3236
3258
|
const deployOptions = {
|
|
3237
3259
|
stackName: plan.orgStack.stackName,
|
|
@@ -3283,7 +3305,7 @@ async function deployAccountStack(stack, currentAccountId, options, oidcProvider
|
|
|
3283
3305
|
await previewStackChanges(deployOptions);
|
|
3284
3306
|
await deployStack(deployOptions);
|
|
3285
3307
|
}
|
|
3286
|
-
async function deployStageStack(stack, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts) {
|
|
3308
|
+
async function deployStageStack(stack, authData, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc) {
|
|
3287
3309
|
const credentials = stack.accountId !== currentAccountId ? (await assumeRoleForAccount({
|
|
3288
3310
|
targetAccountId: stack.accountId,
|
|
3289
3311
|
currentAccountId,
|
|
@@ -3299,7 +3321,8 @@ async function deployStageStack(stack, authData, currentAccountId, options, oidc
|
|
|
3299
3321
|
dockerArtifacts: stack.dockerArtifacts,
|
|
3300
3322
|
bundleArtifacts: stack.bundleArtifacts,
|
|
3301
3323
|
oidcProviderUrl,
|
|
3302
|
-
additionalTrustedAccounts
|
|
3324
|
+
additionalTrustedAccounts,
|
|
3325
|
+
skipOidc
|
|
3303
3326
|
});
|
|
3304
3327
|
const deployOptions = {
|
|
3305
3328
|
stackName: stack.stackName,
|
|
@@ -3311,7 +3334,7 @@ async function deployStageStack(stack, authData, currentAccountId, options, oidc
|
|
|
3311
3334
|
await previewStackChanges(deployOptions);
|
|
3312
3335
|
await deployStack(deployOptions);
|
|
3313
3336
|
}
|
|
3314
|
-
async function deployImportStack(stack, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts) {
|
|
3337
|
+
async function deployImportStack(stack, currentAccountId, options, oidcProviderUrl, additionalTrustedAccounts, skipOidc) {
|
|
3315
3338
|
const credentials = stack.accountId !== currentAccountId ? (await assumeRoleForAccount({
|
|
3316
3339
|
targetAccountId: stack.accountId,
|
|
3317
3340
|
currentAccountId,
|
|
@@ -3322,7 +3345,8 @@ async function deployImportStack(stack, currentAccountId, options, oidcProviderU
|
|
|
3322
3345
|
orgSlug: stack.orgSlug,
|
|
3323
3346
|
accountId: stack.accountId,
|
|
3324
3347
|
oidcProviderUrl,
|
|
3325
|
-
additionalTrustedAccounts
|
|
3348
|
+
additionalTrustedAccounts,
|
|
3349
|
+
skipOidc
|
|
3326
3350
|
});
|
|
3327
3351
|
const deployOptions = {
|
|
3328
3352
|
stackName: stack.stackName,
|