Skip to content

Commit

Permalink
feat: v1 release
Browse files Browse the repository at this point in the history
  • Loading branch information
corymhall committed Nov 3, 2023
1 parent b41bd4b commit ab87abc
Show file tree
Hide file tree
Showing 15 changed files with 617 additions and 371 deletions.
3 changes: 2 additions & 1 deletion .projen/tasks.json

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

14 changes: 8 additions & 6 deletions .projenrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,28 @@ import { Transform } from 'projen/lib/javascript';
import { JsonPatch } from 'projen/lib/json-patch';
import { GitHubActionTypeScriptProject, RunsUsing } from 'projen-github-action-typescript';
const project = new GitHubActionTypeScriptProject({
majorVersion: 1,
defaultReleaseBranch: 'main',
authorEmail: '[email protected]',
authorName: 'Cory Hall',
name: 'cdk-diff-action',
projenrcTs: true,
actionMetadata: {
author: 'Cory Hall',
branding: {
color: 'orange',
icon: 'message-square',
},
description:
'The CDK Diff GitHub Action allows you to run CDK diff as part of your CI/CD workflow.',
name: 'cdk-diff-action',
inputs: {
githubToken: {
description: 'github token',
required: true,
},
allowedDestroyTypes: {
description: 'Resource types that are allowed to be destroyed',
description: 'Comma delimited list of resource types that are allowed to be destroyed',
required: false,
default: '',
},
Expand All @@ -29,7 +35,7 @@ const project = new GitHubActionTypeScriptProject({
},
},
runs: {
using: RunsUsing.NODE_16, // overwrite to node18
using: RunsUsing.NODE_16, // overwrite to node20
main: 'dist/index.js',
},
},
Expand Down Expand Up @@ -60,10 +66,6 @@ const project = new GitHubActionTypeScriptProject({
configFilePath: 'jest.config.json',
},
minNodeVersion: '18.12.0',

// deps: [], /* Runtime dependencies of this module. */
// description: undefined, /* The description is just a string that helps people understand the purpose of the package. */
// packageName: undefined, /* The "name" in package.json. */
});

const projenProject = project as unknown as typescript.TypeScriptProject;
Expand Down
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,59 @@
# replace this
# CDK Diff Action

GitHub action to comment on PRs with the stack diff.

![](./diff-screenshot.png)

## :sparkles: Features

- :speech_balloon: Create a single comment per CDK stage
- :recycle: Updates the same comment on each commit, reducing clutter
- :bangbang: Calls out any destructive changes to resources
- :x: Fail workflow if there are destructive changes
- :thread: Summary of stack changes with expandable details
- :see_no_evil: Allow destructive changes for certain resource types

## Example Configurations

The `cdk-diff-action` handles performing the diff and commenting on the PR. In
order to do so it requires credentials to AWS and the synthesized CDK cloud
assembly (cdk.out). Below is a minimal example

```yml
name: diff
on:
pull_request:
branches:
- main
jobs:
Synth:
name: Synthesize
permissions:
contents: read
pull-requests: write
id-token: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 20
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Synth
run: npx cdk synth
- name: Authenticate Via OIDC Role
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-2
role-duration-seconds: 1800
role-skip-session-tagging: true
role-to-assume: arn:aws:iam::1234567891012:role/cdk_github_actions
role-session-name: github
- name: Diff
uses: corymhall/cdk-diff-action@v1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
```
5 changes: 4 additions & 1 deletion action.yml

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

Binary file added diff-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
241 changes: 151 additions & 90 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { getInput, getBooleanInput } from '@actions/core';
import * as github from '@actions/github';
import { AssemblyManifestReader } from './assembly';
import { Comments } from './comment';
import { StageProcessor } from './diff';
import { Inputs } from './inputs';
import { StageProcessor } from './stage-processor';

export async function run() {
const inputs: Inputs = {
Expand Down
60 changes: 41 additions & 19 deletions src/assembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,48 @@ import { AssemblyManifest, Manifest, ArtifactType, AwsCloudFormationStackPropert
import * as fs from 'fs-extra';

/**
* Trace information for stack
* map of resource logicalId to trace message
* Information on the CDK Stage
*/
export type StackTrace = Map<string, string>;
export interface StageInfo {
/**
* The name of the stage
*/
name: string;

/**
* The stacks within the stage
*/
stacks: StackInfo[];
}

/**
* Trace information for a assembly
*
* map of stackId to StackTrace
* Information on a stack
*/
export type ManifestTrace = Map<string, StackTrace>;
export interface StackInfo {
/**
* The name of the stack
*/
name: string;

/**
* The region the stack is deployed to
*
* @default - unknown-region
*/
region?: string;

/**
* The lookup role to use
*
* @default - no lookup role
*/
lookupRole?: BootstrapRole;

/**
* The JSON content of the stack
*/
content: { [key: string]: any };
}

/**
* Reads a Cloud Assembly manifest
Expand Down Expand Up @@ -86,6 +117,9 @@ export class AssemblyManifestReader {
return stacks;
}

/**
* Get the stages in the assembly
*/
public get stages(): StageInfo[] {
const stages: StageInfo[] = [];
for (const [artifactId, artifact] of Object.entries(this.manifest.artifacts ?? {})) {
Expand All @@ -100,15 +134,3 @@ export class AssemblyManifestReader {
return stages;
}
}

export interface StageInfo {
name: string;
stacks: StackInfo[];
}

export interface StackInfo {
name: string;
region?: string;
lookupRole?: BootstrapRole;
content: { [key: string]: any };
}
23 changes: 22 additions & 1 deletion src/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { Context } from '@actions/github/lib/context';
import { GitHub } from '@actions/github/lib/utils';
import { PullRequestEvent } from '@octokit/webhooks-definitions/schema';

/**
* Comments controls interacting with GitHub to make comments
*/
export class Comments {
private readonly issueNumber: number;
private readonly commitSha: string;
Expand All @@ -17,6 +20,12 @@ export class Comments {
this.issueNumber = this.context.payload.pull_request?.number!;
}

/**
* Find the previous comment with the given hash
*
* @param hash the unique hash identifying the stage comment to look for
* @returns the PR comment id or undefined if there is no previous comment
*/
public async findPrevious(hash: string): Promise<number | undefined> {
const comments = await this.octokit.rest.issues.listComments({
...this.context.repo,
Expand All @@ -25,6 +34,13 @@ export class Comments {
return comments.data.find(comment => comment.body?.includes(hash))?.id;
}

/**
* Update an existing comment
*
* @param hash the unique hash identifying the stage comment to look for
* @param content the content of the comment
* @param commentId the id of the comment to update
*/
public async updateComment(commentId: number, hash: string, content: string[]) {
await this.octokit.rest.issues.updateComment({
...this.context.repo,
Expand All @@ -38,6 +54,12 @@ export class Comments {
});
}

/**
* Create a new comment
*
* @param hash the unique hash identifying the stage comment to look for
* @param content the content of the comment
*/
public async createComment(hash: string, content: string[]) {
await this.octokit.rest.issues.createComment({
...this.context.repo,
Expand All @@ -50,5 +72,4 @@ export class Comments {
issue_number: this.issueNumber,
});
}

}
Loading

0 comments on commit ab87abc

Please sign in to comment.