@devramps/cli 0.1.20 → 0.1.22
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 +263 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -237,6 +237,8 @@ var MultiStackProgress = class {
|
|
|
237
237
|
return "ACCT";
|
|
238
238
|
case "stage":
|
|
239
239
|
return "STAGE";
|
|
240
|
+
case "import":
|
|
241
|
+
return "IMPORT";
|
|
240
242
|
}
|
|
241
243
|
}
|
|
242
244
|
/**
|
|
@@ -268,7 +270,7 @@ var MultiStackProgress = class {
|
|
|
268
270
|
const filled = Math.round(this.barWidth * percentage);
|
|
269
271
|
const empty = this.barWidth - filled;
|
|
270
272
|
const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
271
|
-
const typeLabel = this.getTypeLabel(stackType).padEnd(
|
|
273
|
+
const typeLabel = this.getTypeLabel(stackType).padEnd(6);
|
|
272
274
|
const accountLabel = `${accountId} ${region.padEnd(12)}`;
|
|
273
275
|
const countLabel = `${completed}/${total}`;
|
|
274
276
|
const displayName = stackName.padEnd(this.maxStackNameLen);
|
|
@@ -1481,6 +1483,26 @@ function getArtifactId(artifact) {
|
|
|
1481
1483
|
}
|
|
1482
1484
|
return artifact.name.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
1483
1485
|
}
|
|
1486
|
+
function extractImportSourceAccounts(artifacts) {
|
|
1487
|
+
const accountIds = /* @__PURE__ */ new Set();
|
|
1488
|
+
for (const artifact of artifacts.docker) {
|
|
1489
|
+
if (artifact.type !== "DEVRAMPS:DOCKER:IMPORT") continue;
|
|
1490
|
+
const url = artifact.params?.source_image_url;
|
|
1491
|
+
if (!url) continue;
|
|
1492
|
+
const match = url.match(/^(\d+)\.dkr\.ecr\./);
|
|
1493
|
+
if (match) {
|
|
1494
|
+
accountIds.add(match[1]);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
for (const artifact of artifacts.bundle) {
|
|
1498
|
+
if (artifact.type !== "DEVRAMPS:BUNDLE:IMPORT") continue;
|
|
1499
|
+
const account = artifact.params?.source_account;
|
|
1500
|
+
if (account && typeof account === "string") {
|
|
1501
|
+
accountIds.add(account);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
return Array.from(accountIds).map((accountId) => ({ accountId }));
|
|
1505
|
+
}
|
|
1484
1506
|
|
|
1485
1507
|
// src/aws/oidc-provider.ts
|
|
1486
1508
|
import {
|
|
@@ -1697,6 +1719,12 @@ function getStageStackName(pipelineSlug, stageName) {
|
|
|
1697
1719
|
function getAccountStackName() {
|
|
1698
1720
|
return "DevRamps-Account-Bootstrap";
|
|
1699
1721
|
}
|
|
1722
|
+
function getImportStackName(pipelineSlug) {
|
|
1723
|
+
return truncateName(`DevRamps-${pipelineSlug}-Import`, CF_STACK_MAX_LENGTH);
|
|
1724
|
+
}
|
|
1725
|
+
function generateImportRoleName(pipelineSlug) {
|
|
1726
|
+
return truncateName(`DevRamps-${pipelineSlug}-ImportRole`, IAM_ROLE_MAX_LENGTH);
|
|
1727
|
+
}
|
|
1700
1728
|
function getKmsKeyAlias(orgSlug) {
|
|
1701
1729
|
return `alias/devramps-${normalizeName(orgSlug)}`;
|
|
1702
1730
|
}
|
|
@@ -2314,6 +2342,38 @@ var DOCKER_IMPORT_PERMISSIONS = {
|
|
|
2314
2342
|
resources: ["*"]
|
|
2315
2343
|
};
|
|
2316
2344
|
|
|
2345
|
+
// src/permissions/lambda-deploy.ts
|
|
2346
|
+
var LAMBDA_DEPLOY_PERMISSIONS = {
|
|
2347
|
+
actions: [
|
|
2348
|
+
// Update function code (S3 bundle or container image)
|
|
2349
|
+
"lambda:UpdateFunctionCode",
|
|
2350
|
+
// Poll for update completion
|
|
2351
|
+
"lambda:GetFunctionConfiguration",
|
|
2352
|
+
"lambda:GetFunction"
|
|
2353
|
+
],
|
|
2354
|
+
resources: ["*"]
|
|
2355
|
+
};
|
|
2356
|
+
|
|
2357
|
+
// src/permissions/lambda-invoke.ts
|
|
2358
|
+
var LAMBDA_INVOKE_PERMISSIONS = {
|
|
2359
|
+
actions: [
|
|
2360
|
+
// Invoke the Lambda function
|
|
2361
|
+
"lambda:InvokeFunction"
|
|
2362
|
+
],
|
|
2363
|
+
resources: ["*"]
|
|
2364
|
+
};
|
|
2365
|
+
|
|
2366
|
+
// src/permissions/cloudfront-invalidate.ts
|
|
2367
|
+
var CLOUDFRONT_INVALIDATE_PERMISSIONS = {
|
|
2368
|
+
actions: [
|
|
2369
|
+
// Create invalidation
|
|
2370
|
+
"cloudfront:CreateInvalidation",
|
|
2371
|
+
// Poll for invalidation completion
|
|
2372
|
+
"cloudfront:GetInvalidation"
|
|
2373
|
+
],
|
|
2374
|
+
resources: ["*"]
|
|
2375
|
+
};
|
|
2376
|
+
|
|
2317
2377
|
// src/permissions/custom.ts
|
|
2318
2378
|
function getCustomPermissions(stepType) {
|
|
2319
2379
|
verbose(
|
|
@@ -2331,6 +2391,9 @@ var PERMISSIONS_REGISTRY = {
|
|
|
2331
2391
|
"DEVRAMPS:EKS:DEPLOY": EKS_DEPLOY_PERMISSIONS,
|
|
2332
2392
|
"DEVRAMPS:EKS:HELM": EKS_HELM_PERMISSIONS,
|
|
2333
2393
|
"DEVRAMPS:ECS:DEPLOY": ECS_DEPLOY_PERMISSIONS,
|
|
2394
|
+
"DEVRAMPS:LAMBDA:DEPLOY": LAMBDA_DEPLOY_PERMISSIONS,
|
|
2395
|
+
"DEVRAMPS:LAMBDA:INVOKE": LAMBDA_INVOKE_PERMISSIONS,
|
|
2396
|
+
"DEVRAMPS:CLOUDFRONT:INVALIDATE": CLOUDFRONT_INVALIDATE_PERMISSIONS,
|
|
2334
2397
|
// Artifact mirroring steps (CI/CD account -> deployment account)
|
|
2335
2398
|
"DEVRAMPS:MIRROR:ECR": MIRROR_ECR_PERMISSIONS,
|
|
2336
2399
|
"DEVRAMPS:MIRROR:S3": MIRROR_S3_PERMISSIONS,
|
|
@@ -2530,6 +2593,74 @@ function buildStagePolicies(steps, additionalPolicies) {
|
|
|
2530
2593
|
return policies;
|
|
2531
2594
|
}
|
|
2532
2595
|
|
|
2596
|
+
// src/templates/import-stack.ts
|
|
2597
|
+
function generateImportStackTemplate(options) {
|
|
2598
|
+
const { pipelineSlug, orgSlug, accountId, oidcProviderUrl } = options;
|
|
2599
|
+
const template = createBaseTemplate(
|
|
2600
|
+
`DevRamps Import Stack for ${pipelineSlug} - grants read access for artifact imports`
|
|
2601
|
+
);
|
|
2602
|
+
const roleName = generateImportRoleName(pipelineSlug);
|
|
2603
|
+
const trustPolicy = buildOidcTrustPolicy(accountId, `org:${orgSlug}/cicd`, oidcProviderUrl);
|
|
2604
|
+
const policies = buildImportRolePolicies();
|
|
2605
|
+
template.Resources.ImportRole = createIamRoleResource(
|
|
2606
|
+
roleName,
|
|
2607
|
+
trustPolicy,
|
|
2608
|
+
policies,
|
|
2609
|
+
[
|
|
2610
|
+
{ Key: "Pipeline", Value: pipelineSlug },
|
|
2611
|
+
{ Key: "Organization", Value: orgSlug }
|
|
2612
|
+
]
|
|
2613
|
+
);
|
|
2614
|
+
template.Outputs = {
|
|
2615
|
+
ImportRoleArn: {
|
|
2616
|
+
Description: "ARN of the import role",
|
|
2617
|
+
Value: { "Fn::GetAtt": ["ImportRole", "Arn"] }
|
|
2618
|
+
},
|
|
2619
|
+
ImportRoleName: {
|
|
2620
|
+
Description: "Name of the import role",
|
|
2621
|
+
Value: { Ref: "ImportRole" }
|
|
2622
|
+
},
|
|
2623
|
+
PipelineSlug: {
|
|
2624
|
+
Description: "Pipeline slug",
|
|
2625
|
+
Value: pipelineSlug
|
|
2626
|
+
}
|
|
2627
|
+
};
|
|
2628
|
+
return template;
|
|
2629
|
+
}
|
|
2630
|
+
function buildImportRolePolicies() {
|
|
2631
|
+
return [
|
|
2632
|
+
{
|
|
2633
|
+
PolicyName: "DevRampsImportPolicy",
|
|
2634
|
+
PolicyDocument: {
|
|
2635
|
+
Version: "2012-10-17",
|
|
2636
|
+
Statement: [
|
|
2637
|
+
{
|
|
2638
|
+
Sid: "AllowECRRead",
|
|
2639
|
+
Effect: "Allow",
|
|
2640
|
+
Action: [
|
|
2641
|
+
"ecr:GetAuthorizationToken",
|
|
2642
|
+
"ecr:DescribeImages",
|
|
2643
|
+
"ecr:BatchGetImage",
|
|
2644
|
+
"ecr:GetDownloadUrlForLayer",
|
|
2645
|
+
"ecr:BatchCheckLayerAvailability"
|
|
2646
|
+
],
|
|
2647
|
+
Resource: "*"
|
|
2648
|
+
},
|
|
2649
|
+
{
|
|
2650
|
+
Sid: "AllowS3Read",
|
|
2651
|
+
Effect: "Allow",
|
|
2652
|
+
Action: [
|
|
2653
|
+
"s3:GetObject",
|
|
2654
|
+
"s3:HeadObject"
|
|
2655
|
+
],
|
|
2656
|
+
Resource: "*"
|
|
2657
|
+
}
|
|
2658
|
+
]
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
];
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2533
2664
|
// src/merge/index.ts
|
|
2534
2665
|
var MERGE_STRATEGIES = /* @__PURE__ */ new Map();
|
|
2535
2666
|
var bucketPolicyStrategy = new BucketPolicyMergeStrategy();
|
|
@@ -2718,33 +2849,50 @@ async function buildDeploymentPlan(pipelines, pipelineArtifacts, authData, curre
|
|
|
2718
2849
|
region: cicdRegion,
|
|
2719
2850
|
action: await determineStackAction(accountStackName, cicdCredentials, cicdRegion)
|
|
2720
2851
|
});
|
|
2852
|
+
const importSourceAccountsByPipeline = /* @__PURE__ */ new Map();
|
|
2721
2853
|
for (const pipeline of pipelines) {
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2854
|
+
const artifacts = pipelineArtifacts.get(pipeline.slug);
|
|
2855
|
+
const importSources = extractImportSourceAccounts(artifacts);
|
|
2856
|
+
if (importSources.length > 0) {
|
|
2857
|
+
importSourceAccountsByPipeline.set(
|
|
2858
|
+
pipeline.slug,
|
|
2859
|
+
importSources.map((s) => s.accountId)
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
const addAccountStackIfNew = async (accountId) => {
|
|
2864
|
+
if (accountsWithStacks.has(accountId)) return;
|
|
2865
|
+
accountsWithStacks.add(accountId);
|
|
2866
|
+
let accountCredentials;
|
|
2867
|
+
try {
|
|
2868
|
+
if (accountId !== currentAccountId) {
|
|
2869
|
+
const assumed = await assumeRoleForAccount({
|
|
2870
|
+
targetAccountId: accountId,
|
|
2871
|
+
currentAccountId,
|
|
2872
|
+
targetRoleName
|
|
2873
|
+
});
|
|
2874
|
+
accountCredentials = assumed?.credentials;
|
|
2739
2875
|
}
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2876
|
+
} catch {
|
|
2877
|
+
verbose(`Could not assume role in ${accountId} for status check`);
|
|
2878
|
+
}
|
|
2879
|
+
accountStacks.push({
|
|
2880
|
+
stackType: "Account" /* ACCOUNT */,
|
|
2881
|
+
stackName: accountStackName,
|
|
2882
|
+
accountId,
|
|
2883
|
+
region: cicdRegion,
|
|
2884
|
+
// Deploy in CI/CD region for consistency
|
|
2885
|
+
action: await determineStackAction(accountStackName, accountCredentials, cicdRegion)
|
|
2886
|
+
});
|
|
2887
|
+
};
|
|
2888
|
+
for (const pipeline of pipelines) {
|
|
2889
|
+
for (const stage of pipeline.stages) {
|
|
2890
|
+
await addAccountStackIfNew(stage.account_id);
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
for (const [, sourceAccountIds] of importSourceAccountsByPipeline) {
|
|
2894
|
+
for (const accountId of sourceAccountIds) {
|
|
2895
|
+
await addAccountStackIfNew(accountId);
|
|
2748
2896
|
}
|
|
2749
2897
|
}
|
|
2750
2898
|
const stageStacks = [];
|
|
@@ -2781,6 +2929,35 @@ async function buildDeploymentPlan(pipelines, pipelineArtifacts, authData, curre
|
|
|
2781
2929
|
});
|
|
2782
2930
|
}
|
|
2783
2931
|
}
|
|
2932
|
+
const importStacks = [];
|
|
2933
|
+
for (const [pipelineSlug, sourceAccountIds] of importSourceAccountsByPipeline) {
|
|
2934
|
+
const importStackName = getImportStackName(pipelineSlug);
|
|
2935
|
+
for (const sourceAccountId of sourceAccountIds) {
|
|
2936
|
+
let importCredentials;
|
|
2937
|
+
try {
|
|
2938
|
+
if (sourceAccountId !== currentAccountId) {
|
|
2939
|
+
const assumed = await assumeRoleForAccount({
|
|
2940
|
+
targetAccountId: sourceAccountId,
|
|
2941
|
+
currentAccountId,
|
|
2942
|
+
targetRoleName
|
|
2943
|
+
});
|
|
2944
|
+
importCredentials = assumed?.credentials;
|
|
2945
|
+
}
|
|
2946
|
+
} catch {
|
|
2947
|
+
verbose(`Could not assume role in ${sourceAccountId} for status check`);
|
|
2948
|
+
}
|
|
2949
|
+
importStacks.push({
|
|
2950
|
+
stackType: "Import" /* IMPORT */,
|
|
2951
|
+
stackName: importStackName,
|
|
2952
|
+
accountId: sourceAccountId,
|
|
2953
|
+
region: cicdRegion,
|
|
2954
|
+
// Deploy in CI/CD region (IAM is global)
|
|
2955
|
+
action: await determineStackAction(importStackName, importCredentials, cicdRegion),
|
|
2956
|
+
pipelineSlug,
|
|
2957
|
+
orgSlug
|
|
2958
|
+
});
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2784
2961
|
return {
|
|
2785
2962
|
orgSlug,
|
|
2786
2963
|
cicdAccountId,
|
|
@@ -2788,7 +2965,8 @@ async function buildDeploymentPlan(pipelines, pipelineArtifacts, authData, curre
|
|
|
2788
2965
|
orgStack,
|
|
2789
2966
|
pipelineStacks,
|
|
2790
2967
|
accountStacks,
|
|
2791
|
-
stageStacks
|
|
2968
|
+
stageStacks,
|
|
2969
|
+
importStacks
|
|
2792
2970
|
};
|
|
2793
2971
|
}
|
|
2794
2972
|
async function determineStackAction(stackName, credentials, region) {
|
|
@@ -2836,34 +3014,46 @@ async function showDryRunPlan(plan) {
|
|
|
2836
3014
|
info(` ECR repos: ${stack.dockerArtifacts.length}, S3 buckets: ${stack.bundleArtifacts.length}`);
|
|
2837
3015
|
}
|
|
2838
3016
|
}
|
|
2839
|
-
|
|
3017
|
+
if (plan.importStacks.length > 0) {
|
|
3018
|
+
newline();
|
|
3019
|
+
info("Import Stacks:");
|
|
3020
|
+
for (const stack of plan.importStacks) {
|
|
3021
|
+
info(` ${stack.action}: ${stack.stackName}`);
|
|
3022
|
+
info(` Account: ${stack.accountId}, Region: ${stack.region} (import role)`);
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
const totalStacks = 1 + plan.pipelineStacks.length + plan.accountStacks.length + plan.stageStacks.length + plan.importStacks.length;
|
|
3026
|
+
const phase2Stacks = 1 + plan.pipelineStacks.length + plan.stageStacks.length + plan.importStacks.length;
|
|
2840
3027
|
newline();
|
|
2841
3028
|
info(`Total stacks to deploy: ${totalStacks}`);
|
|
2842
3029
|
info(` Phase 1: ${plan.accountStacks.length} Account stack(s) (deployed first)`);
|
|
2843
|
-
info(` Phase 2: ${
|
|
3030
|
+
info(` Phase 2: ${phase2Stacks} Org/Pipeline/Stage/Import stack(s) (deployed in parallel after Phase 1)`);
|
|
2844
3031
|
}
|
|
2845
3032
|
async function confirmDeploymentPlan(plan) {
|
|
2846
|
-
const totalStacks = 1 + plan.pipelineStacks.length + plan.accountStacks.length + plan.stageStacks.length;
|
|
3033
|
+
const totalStacks = 1 + plan.pipelineStacks.length + plan.accountStacks.length + plan.stageStacks.length + plan.importStacks.length;
|
|
2847
3034
|
newline();
|
|
2848
3035
|
info(`About to deploy ${totalStacks} stack(s):`);
|
|
2849
3036
|
info(` - 1 Org stack (${plan.orgStack.action})`);
|
|
2850
3037
|
info(` - ${plan.pipelineStacks.length} Pipeline stack(s)`);
|
|
2851
3038
|
info(` - ${plan.accountStacks.length} Account stack(s) (OIDC provider)`);
|
|
2852
3039
|
info(` - ${plan.stageStacks.length} Stage stack(s)`);
|
|
3040
|
+
if (plan.importStacks.length > 0) {
|
|
3041
|
+
info(` - ${plan.importStacks.length} Import stack(s)`);
|
|
3042
|
+
}
|
|
2853
3043
|
return confirmDeployment({
|
|
2854
3044
|
orgSlug: plan.orgSlug,
|
|
2855
3045
|
stacks: [
|
|
2856
3046
|
{ ...plan.orgStack, pipelineSlug: "org", steps: [], additionalPoliciesCount: 0 },
|
|
2857
3047
|
...plan.pipelineStacks.map((s) => ({ ...s, steps: [], additionalPoliciesCount: 0 })),
|
|
2858
3048
|
...plan.accountStacks.map((s) => ({ ...s, pipelineSlug: "account", steps: [], additionalPoliciesCount: 0 })),
|
|
2859
|
-
...plan.stageStacks.map((s) => ({ ...s, steps: s.steps.map((st) => st.name), additionalPoliciesCount: s.additionalPolicies.length }))
|
|
3049
|
+
...plan.stageStacks.map((s) => ({ ...s, steps: s.steps.map((st) => st.name), additionalPoliciesCount: s.additionalPolicies.length })),
|
|
3050
|
+
...plan.importStacks.map((s) => ({ ...s, steps: [], additionalPoliciesCount: 0 }))
|
|
2860
3051
|
]
|
|
2861
3052
|
});
|
|
2862
3053
|
}
|
|
2863
3054
|
async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, currentAccountId, options, oidcProviderUrl) {
|
|
2864
3055
|
const results = { success: 0, failed: 0 };
|
|
2865
|
-
const
|
|
2866
|
-
const remainingStacks = 1 + plan.pipelineStacks.length + plan.stageStacks.length;
|
|
3056
|
+
const remainingStacks = 1 + plan.pipelineStacks.length + plan.stageStacks.length + plan.importStacks.length;
|
|
2867
3057
|
newline();
|
|
2868
3058
|
header("Phase 1: Deploying Account Bootstrap Stacks");
|
|
2869
3059
|
info(`Deploying ${plan.accountStacks.length} account stack(s) in parallel...`);
|
|
@@ -2905,7 +3095,7 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
2905
3095
|
process.exit(1);
|
|
2906
3096
|
}
|
|
2907
3097
|
newline();
|
|
2908
|
-
header("Phase 2: Deploying Org, Pipeline, and
|
|
3098
|
+
header("Phase 2: Deploying Org, Pipeline, Stage, and Import Stacks");
|
|
2909
3099
|
info(`Deploying ${remainingStacks} stack(s) in parallel...`);
|
|
2910
3100
|
newline();
|
|
2911
3101
|
const mainProgress = getMultiStackProgress();
|
|
@@ -2918,6 +3108,9 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
2918
3108
|
const resourceCount = stack.dockerArtifacts.length + stack.bundleArtifacts.length + 2;
|
|
2919
3109
|
mainProgress.addStack(stack.stackName, "stage", stack.accountId, stack.region, resourceCount);
|
|
2920
3110
|
}
|
|
3111
|
+
for (const stack of plan.importStacks) {
|
|
3112
|
+
mainProgress.addStack(stack.stackName, "import", stack.accountId, stack.region, 1);
|
|
3113
|
+
}
|
|
2921
3114
|
mainProgress.start();
|
|
2922
3115
|
const orgPromise = (async () => {
|
|
2923
3116
|
try {
|
|
@@ -2955,10 +3148,23 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
2955
3148
|
};
|
|
2956
3149
|
}
|
|
2957
3150
|
});
|
|
3151
|
+
const importPromises = plan.importStacks.map(async (stack) => {
|
|
3152
|
+
try {
|
|
3153
|
+
await deployImportStack(stack, currentAccountId, options, oidcProviderUrl);
|
|
3154
|
+
return { stack: `${stack.stackName} (${stack.accountId})`, success: true };
|
|
3155
|
+
} catch (error2) {
|
|
3156
|
+
return {
|
|
3157
|
+
stack: `${stack.stackName} (${stack.accountId})`,
|
|
3158
|
+
success: false,
|
|
3159
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
3160
|
+
};
|
|
3161
|
+
}
|
|
3162
|
+
});
|
|
2958
3163
|
const mainResults = await Promise.all([
|
|
2959
3164
|
orgPromise,
|
|
2960
3165
|
...pipelinePromises,
|
|
2961
|
-
...stagePromises
|
|
3166
|
+
...stagePromises,
|
|
3167
|
+
...importPromises
|
|
2962
3168
|
]);
|
|
2963
3169
|
clearMultiStackProgress();
|
|
2964
3170
|
newline();
|
|
@@ -3091,6 +3297,28 @@ async function deployStageStack(stack, authData, currentAccountId, options, oidc
|
|
|
3091
3297
|
await previewStackChanges(deployOptions);
|
|
3092
3298
|
await deployStack(deployOptions);
|
|
3093
3299
|
}
|
|
3300
|
+
async function deployImportStack(stack, currentAccountId, options, oidcProviderUrl) {
|
|
3301
|
+
const credentials = stack.accountId !== currentAccountId ? (await assumeRoleForAccount({
|
|
3302
|
+
targetAccountId: stack.accountId,
|
|
3303
|
+
currentAccountId,
|
|
3304
|
+
targetRoleName: options.targetAccountRoleName
|
|
3305
|
+
}))?.credentials : void 0;
|
|
3306
|
+
const template = generateImportStackTemplate({
|
|
3307
|
+
pipelineSlug: stack.pipelineSlug,
|
|
3308
|
+
orgSlug: stack.orgSlug,
|
|
3309
|
+
accountId: stack.accountId,
|
|
3310
|
+
oidcProviderUrl
|
|
3311
|
+
});
|
|
3312
|
+
const deployOptions = {
|
|
3313
|
+
stackName: stack.stackName,
|
|
3314
|
+
template,
|
|
3315
|
+
accountId: stack.accountId,
|
|
3316
|
+
region: stack.region,
|
|
3317
|
+
credentials
|
|
3318
|
+
};
|
|
3319
|
+
await previewStackChanges(deployOptions);
|
|
3320
|
+
await deployStack(deployOptions);
|
|
3321
|
+
}
|
|
3094
3322
|
|
|
3095
3323
|
// src/index.ts
|
|
3096
3324
|
program.name("devramps").description("DevRamps CLI - Bootstrap AWS infrastructure for CI/CD pipelines").version("0.1.0");
|