Skip to content

Commit

Permalink
feat: Add support to provide GHA role per stage
Browse files Browse the repository at this point in the history
  • Loading branch information
danieljamesscott committed Aug 19, 2022
1 parent 920adb6 commit 69f19cf
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export class GitHubWorkflow extends PipelineBase {
this.addStackProps(stacks, 'environment', options?.gitHubEnvironment);
this.addStackProps(stacks, 'capabilities', options?.stackCapabilities);
this.addStackProps(stacks, 'settings', options?.jobSettings);
this.addStackProps(stacks, 'role', options?.role);

return stageDeployment;
}
Expand Down Expand Up @@ -370,6 +371,7 @@ export class GitHubWorkflow extends PipelineBase {
const cdkoutDir = options.assemblyDir;
const jobId = node.uniqueId;
const assetId = assets[0].assetId;
const stageRoleArn = this.ghaStageRoleArn();

// check if asset is docker asset and if we have docker credentials
const dockerLoginSteps: github.JobStep[] = [];
Expand Down Expand Up @@ -419,7 +421,7 @@ export class GitHubWorkflow extends PipelineBase {
name: 'Install',
run: `npm install --no-save cdk-assets${installSuffix}`,
},
...this.stepsToConfigureAws(this.useGitHubActionRole, { region: this.publishAssetsAuthRegion }),
...this.stepsToConfigureAws(this.useGitHubActionRole, { region: this.publishAssetsAuthRegion, stageRoleArn: stageRoleArn }),
...dockerLoginSteps,
publishStep,
],
Expand Down Expand Up @@ -470,6 +472,8 @@ export class GitHubWorkflow extends PipelineBase {
}
const assumeRoleArn = stack.assumeRoleArn ? resolve(stack.assumeRoleArn) : undefined;

const stageRoleArn = this.ghaStageRoleArn();

return {
id: node.uniqueId,
definition: {
Expand All @@ -486,7 +490,7 @@ export class GitHubWorkflow extends PipelineBase {
needs: this.renderDependencies(node),
runsOn: this.runner.runsOn,
steps: [
...this.stepsToConfigureAws(this.useGitHubActionRole, { region, assumeRoleArn }),
...this.stepsToConfigureAws(this.useGitHubActionRole, { region, assumeRoleArn, stageRoleArn }),
{
id: 'Deploy',
uses: 'aws-actions/aws-cloudformation-github-deploy@v1',
Expand Down Expand Up @@ -639,7 +643,16 @@ export class GitHubWorkflow extends PipelineBase {
};
}

private stepsToConfigureAws(openId: boolean, { region, assumeRoleArn }: { region: string; assumeRoleArn?: string }): github.JobStep[] {
private ghaStageRoleArn(): string {
const stageRoleArn = Object.entries(this.stackProperties)[0][1].role;
return stageRoleArn || this.gitHubActionRoleArn;
}

private stepsToConfigureAws(openId: boolean, {
region,
assumeRoleArn,
stageRoleArn,
}: { region: string; assumeRoleArn?: string; stageRoleArn?: string }): github.JobStep[] {
function getDeployRole(arn: string) {
return arn.replace('cfn-exec', 'deploy');
}
Expand All @@ -649,7 +662,7 @@ export class GitHubWorkflow extends PipelineBase {
if (openId) {
steps.push(awsCredentialStep('Authenticate Via OIDC Role', {
region,
gitHubActionRoleArn: this.gitHubActionRoleArn,
gitHubActionRoleArn: stageRoleArn,
}));

if (assumeRoleArn) {
Expand Down
7 changes: 7 additions & 0 deletions src/stage-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ export interface AddGitHubStageOptions extends AddStageOpts {
* Currently the only valid setting is 'if'.
*/
readonly jobSettings?: JobSettings;

/**
* Role used by stage
*
* @default - The pipeline role
*/
readonly role?: string;
}

/**
Expand Down
97 changes: 97 additions & 0 deletions test/__snapshots__/stage-options.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions test/stage-options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,64 @@ describe('job settings', () => {
});
});
});

describe('role settings', () => {
test('can specify gha role', () => {
withTemporaryDirectory((dir) => {
const pipeline = new GitHubWorkflow(app, 'Pipeline', {
workflowPath: `${dir}/.github/workflows/deploy.yml`,
synth: new ShellStep('Build', {
installCommands: ['yarn'],
commands: ['yarn build'],
}),
gitHubActionRoleArn: 'my-pipeline-role',
});

const stage = new Stage(app, 'MyStack', {
env: { account: '111111111111', region: 'us-east-1' },
});

new Stack(stage, 'MyStack');

pipeline.addStageWithGitHubOptions(stage, {
jobSettings: {
if: 'github.repository == \'github/repo\'',
},
});

app.synth();

expect(readFileSync(pipeline.workflowPath, 'utf-8')).toContain('if: github.repository == \'github/repo\'\n');
});
});

test('can specify role override settings at stage level', () => {
withTemporaryDirectory((dir) => {
const pipeline = new GitHubWorkflow(app, 'Pipeline', {
workflowPath: `${dir}/.github/workflows/deploy.yml`,
synth: new ShellStep('Build', {
installCommands: ['yarn'],
commands: ['yarn build'],
}),
gitHubActionRoleArn: 'my-pipeline-role',
});

const stage = new Stage(app, 'MyStack', {
env: { account: '111111111111', region: 'us-east-1' },
});

new Stack(stage, 'MyStack');

pipeline.addStageWithGitHubOptions(stage, {
jobSettings: {
if: 'github.repository == \'github/repo\'',
},
role: 'my-stage-role',
});

app.synth();

expect(readFileSync(pipeline.workflowPath, 'utf-8')).toMatchSnapshot();
});
});
});

0 comments on commit 69f19cf

Please sign in to comment.