Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 into fix/stage-scoped-asset-scripts
  • Loading branch information
NathanTCz committed Mar 6, 2023
2 parents d16c2ec + d6e137d commit 4b74b0d
Show file tree
Hide file tree
Showing 17 changed files with 6,185 additions and 1,202 deletions.
139 changes: 101 additions & 38 deletions .jsii.tabl.json

Large diffs are not rendered by default.

5,451 changes: 4,643 additions & 808 deletions API.md

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions GITHUB_ACTION_ROLE_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ construct that this library provides.
left is to send that role's arn into your GitHub Workflow, so it knows to use it:

```ts
import { App } from 'aws-cdk-lib';
import { ShellStep } from 'aws-cdk-lib/pipelines';
import { GitHubWorkflow } from 'cdk-pipelines-github';

const app = new App();

Expand Down
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Workflows.
- [Additional Features](#additional-features)
- [GitHub Action Step](#github-action-step)
- [Configure GitHub Environment](#configure-github-environment)
- [Waves for Parallel Builds](#waves-for-parallel-builds)
- [Manual Approval Step](#manual-approval-step)
- [Pipeline YAML Comments](#pipeline-yaml-comments)
- [Tutorial](#tutorial)
Expand Down Expand Up @@ -71,8 +72,18 @@ const pipeline = new GitHubWorkflow(app, 'Pipeline', {
}),
});

pipeline.addStage(new MyStage(app, 'Beta', { env: BETA_ENV }));
pipeline.addStage(new MyStage(app, 'Prod', { env: PROD_ENV }));
// Build the stages
const betaStage = new MyStage(app, 'Beta', { env: BETA_ENV });
const prodStage = new MyStage(app, 'Prod', { env: PROD_ENV });

// Add the stages for sequential build - earlier stages failing will stop later ones:
pipeline.addStage(betaStage);
pipeline.addStage(prodStage);

// OR add the stages for parallel building of multiple stages with a Wave:
const wave = pipeline.addWave('Wave');
wave.addStage(betaStage);
wave.addStage(prodStage);

app.synth();
```
Expand All @@ -89,6 +100,15 @@ Pipelines class, so most features should be supported out of the box. See the
[CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html)
documentation for more details.

To express GitHub-specifc details, such as those outlined in [Additional Features](#additional-features), you have a few options:

- Use a `GitHubStage` instead of `Stage` (or make a `GitHubStage` subclass instead of a `Stage` subclass) - this adds the `GitHubCommonProps` to the `Stage` properties
- With this you can use `pipeline.addStage(myGitHubStage)` or `wave.addStage(myGitHubStage)` and the properties of the
stage will be used
- Using a `Stage` (or subclass thereof) or a `GitHubStage` (or subclass thereof) you can call `pipeline.addStageWithGitHubOptions(stage, stageOptions)` or `wave.addStageWithGitHubOptions(stage, stageOptions)`
- In this case you're providing the same options along with the stage instead of embedded in the stage.
- Note that properties of a `GitHubStage` added with `addStageWithGitHubOptions()` will override the options provided to `addStageWithGitHubOptions()`

**NOTES:**

* Environments must be bootstrapped separately using `cdk bootstrap`. See [CDK
Expand Down Expand Up @@ -476,6 +496,35 @@ pipeline.addStageWithGitHubOptions(new MyStage(this, 'Prod', {
app.synth();
```

#### Waves for Parallel Builds

You can add a Wave to a pipeline, where each stage of a wave will build in parallel.

> **Note**: The `pipeline.addWave()` call will return a `Wave` object that is actually a `GitHubWave` object, but
> due to JSII rules the return type of `addWave()` cannot be changed. If you need to use
> `wave.addStageWithGitHubOptions()` then you should call `pipeline.addGitHubWave()` instead, or you can
> use `GitHubStage`s to carry the GitHub properties.
When deploying to multiple accounts or otherwise deploying mostly-unrelated stacks, using waves can be a huge win.

Here's a relatively large (but real) example, **without** a wave:

<img width="1955" alt="without-waves-light-mode" src="https://user-images.githubusercontent.com/386001/217436992-d8e46c23-6295-48ec-b139-add60b1f5a14.png">

You can see how dependencies get chained unnecessarily, where the `cUrl` step should be the final step (a test) for an account:

<img width="1955" alt="without-waves-deps-light-mode" src="https://user-images.githubusercontent.com/386001/217437074-3c86d88e-6be7-4b10-97b1-6b51b100e4d6.png">

Here's the exact same stages deploying the same stacks to the same accounts, but **with** a wave:

<img width="1955" alt="with-waves" src="https://user-images.githubusercontent.com/386001/217437228-72f6c278-7e97-4a88-91fa-089628ea0381.png">

And the dependency chains are reduced to only what is actually needed, with the `cUrl` calls as the final stage for each account:

<img width="1955" alt="deps" src="https://user-images.githubusercontent.com/386001/217437265-1c10cd5f-3c7d-4e3a-af5c-acbdf3acff1b.png">

For additional information and a code example see [here](docs/waves.md).

#### Manual Approval Step

One use case for using GitHub Environments with your CDK Pipeline is to create a
Expand Down
115 changes: 115 additions & 0 deletions docs/waves.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Example of how to add a Wave to a pipeline

You can add a Wave to a pipeline, where each stage of a wave will build in parallel.

> **Note**: The `pipeline.addWave()` call will return a `Wave` object that is actually a `GitHubWave` object, but
> due to JSII rules the return type of `addWave()` cannot be changed. If you need to use
> `wave.addStageWithGitHubOptions()` then you should call `pipeline.addGitHubWave()` instead, or you can
> use `GitHubStage`s to carry the GitHub properties.
Example usage in TypeScript:

```ts
// make a new pipeline
import { ShellStep } from 'aws-cdk-lib/pipelines';

const app = new App();

const pipeline = new GitHubWorkflow(app, 'Pipeline', {
synth: new ShellStep('Build', {
commands: [
'yarn install',
'yarn build',
],
}),
awsCreds: AwsCredentials.fromOpenIdConnect({
gitHubActionRoleArn: 'arn:aws:iam::<account-id>:role/GitHubActionRole',
}),
});

// make a stage
const stageA = new GitHubStage(app, 'MyStageA', {
env: { account: '111111111111', region: 'us-east-1' },
{
jobSettings: {
if: "success() && contains(github.event.issue.labels.*.name, 'deployToA')",
},
}
});
// add a stack
new Stack(stageA, 'MyStackA');

// make a second stage
const stageB = new GitHubStage(app, 'MyStageB', {
env: { account: '12345678901', region: 'us-east-1' },
jobSettings: {
if: "success() && contains(github.event.issue.labels.*.name, 'deployToB')",
},
});
// add a stack to that second stage
new Stack(stageB, 'MyStackB');

// Make a wave to have the stages run in parallel (and not depend on each other)
// We can also add steps to be run once before and once after ALL of the stages in this wave
const wave = pipeline.addWave('MyWave', {
pre: [
// add a pre-wave actions
new GitHubActionStep('PreWaveAction', {
jobSteps: [
{
name: 'pre wave action',
uses: '[email protected]',
with: {
'app-id': 1234,
'secrets': 'my-secrets',
},
},
],
}),
],

post: [
new GitHubActionStep('PostWaveAction', {
jobSteps: [
{
name: 'Checkout',
uses: 'actions/checkout@v3',
},
{
name: 'post wave action',
uses: '[email protected]',
with: {
'app-id': 4321,
'secrets': 'secrets',
},
},
],
}),
],
});

// Now add both stages to the wave - they will build in parallel
wave.addStage(stageA);
wave.addStage(stageB);

// pre- and post-wave actions can both be added after the wave is constructed
// with wave.addPre() and wave.addPost()
wave.addPost([
new GitHubActionStep('PostWaveAction', {
jobSteps: [
{
name: 'Checkout',
uses: 'actions/checkout@v3',
},
{
name: 'post wave action',
uses: '[email protected]',
with: {
'app-id': 4321,
'secrets': 'secrets',
},
},
],
}),
]);
```
12 changes: 6 additions & 6 deletions package.json

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

47 changes: 47 additions & 0 deletions src/github-common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { AddStageOpts } from 'aws-cdk-lib/pipelines';
import { JobSettings } from './pipeline';
import { StackCapabilities } from './stage-options';

/**
* Common properties to extend both StageProps and AddStageOpts
*/

export interface GitHubCommonProps {
/**
* Run the stage in a specific GitHub Environment. If specified,
* any protection rules configured for the environment must pass
* before the job is set to a runner. For example, if the environment
* has a manual approval rule configured, then the workflow will
* wait for the approval before sending the job to the runner.
*
* Running a workflow that references an environment that does not
* exist will create an environment with the referenced name.
* @see https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment
*
* @default - no GitHub environment
*/
readonly gitHubEnvironment?: string;

/**
* In some cases, you must explicitly acknowledge that your CloudFormation
* stack template contains certain capabilities in order for CloudFormation
* to create the stack.
*
* If insufficiently specified, CloudFormation returns an `InsufficientCapabilities`
* error.
*
* @default ['CAPABILITY_IAM']
*/
readonly stackCapabilities?: StackCapabilities[];

/**
* Job level settings that will be applied to all jobs in the stage.
* Currently the only valid setting is 'if'.
*/
readonly jobSettings?: JobSettings;
}

/**
* Options to pass to `addStageWithGitHubOpts`.
*/
export interface AddGitHubStageOptions extends AddStageOpts, GitHubCommonProps {}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ export * from './pipeline';
export * from './workflows-model';
export * from './oidc-provider';
export * from './docker-credentials';
export * from './stage';
export * from './wave';
export * from './stage-options';
export * from './yaml-file';
export * from './json-patch';
export * from './steps/github-action-step';
export * from './aws-credentials';
export * from './github-common';
Loading

0 comments on commit 4b74b0d

Please sign in to comment.