Skip to content

Commit 443f8b0

Browse files
committed
feat: add title and defaultStageDisplayName inputs
This adds two new inputs to the action. 1. `title` an optional title to include with each stage comment 2. `defaultStageDisplayName` an optional name to use for the default stage instead of `DefaultStage` closes #130
1 parent 3ef1921 commit 443f8b0

File tree

10 files changed

+1056
-795
lines changed

10 files changed

+1056
-795
lines changed

.projen/tasks.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.projenrc.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ const project = new GitHubActionTypeScriptProject({
8989
required: false,
9090
default: 'change-set',
9191
},
92+
defaultStageDisplayName: {
93+
description: 'An optional display name for the CDK default stage.',
94+
required: false,
95+
default: 'DefaultStage',
96+
},
97+
title: {
98+
description: 'An optional title for each diff comment on the PR.',
99+
required: false,
100+
default: '',
101+
},
92102
},
93103
runs: {
94104
using: RunsUsing.NODE_20,
@@ -252,6 +262,6 @@ workflow?.on({
252262
});
253263

254264
projenProject.packageTask.reset();
255-
projenProject.packageTask.exec('cp node_modules/@aws-cdk/aws-service-spec/db.json.gz ./ && ncc build src/index.ts --source-map --transpile-only --license licenses.txt');
265+
projenProject.packageTask.exec('cp node_modules/@aws-cdk/aws-service-spec/db.json.gz ./ && ncc build --source-map --license licenses.txt');
256266
workflow?.addJobs({ enableAutoMerge: autoMergeJob });
257267
project.synth();

action.yml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js

Lines changed: 879 additions & 781 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/licenses.txt

Lines changed: 26 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/action.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { AssemblyProcessor } from './stage-processor';
77

88
export async function run() {
99
const inputs: Inputs = {
10+
title: getInput('title') || undefined,
11+
defaultStageDisplayName: getInput('defaultStageDisplayName', { required: true }),
1012
allowedDestroyTypes: getMultilineInput('allowedDestroyTypes'),
1113
failOnDestructiveChanges: getBooleanInput('failOnDestructiveChanges'),
1214
githubToken: getInput('githubToken'),

src/inputs.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,18 @@ export interface Inputs {
6969
* @default cdk.out
7070
*/
7171
cdkOutDir: string;
72+
73+
/**
74+
* An optional display name for the CDK default stage.
75+
*
76+
* @default DefaultStage
77+
*/
78+
defaultStageDisplayName: string;
79+
80+
/**
81+
* An optional title for each diff comment on the PR.
82+
*
83+
* @default - no title
84+
*/
85+
title?: string;
7286
}

src/stage-processor.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ interface StageComment {
2222
*/
2323
stackComments: { [stackName: string]: string[] };
2424

25+
/**
26+
* The title of the comment
27+
*/
28+
title?: string;
29+
2530
/**
2631
* The unique hash for the stage comment
2732
* This will be used to lookup the stage comment on the PR
@@ -38,6 +43,7 @@ interface StageComment {
3843
export interface AssemblyProcessorOptions extends Omit<Inputs, 'githubToken' | 'diffMethod'> {
3944
diffMethod: DiffMethod;
4045
toolkit: Toolkit;
46+
defaultStageDisplayName: string;
4147
}
4248

4349
/**
@@ -63,7 +69,7 @@ export class AssemblyProcessor {
6369
this._stageInfo = assembly.stages;
6470
if (assembly.stacks.length) {
6571
this.stageInfo.push({
66-
name: 'DefaultStage',
72+
name: this.options.defaultStageDisplayName,
6773
stacks: assembly.stacks,
6874
});
6975
}
@@ -83,13 +89,15 @@ export class AssemblyProcessor {
8389
}
8490
this._stages = this.stageInfo.flatMap(stage => {
8591
this.stageComments[stage.name] = {
92+
title: this.options.title,
8693
destructiveChanges: 0,
8794
stackComments: stage.stacks.reduce((prev, curr) => {
8895
prev[curr.name] = [];
8996
return prev;
9097
}, {} as { [stackName: string]: string[] }),
9198
hash: md5Hash(JSON.stringify({
9299
stageName: stage.name,
100+
title: this.options.title,
93101
...stage.stacks.reduce((prev, curr) => {
94102
prev.stacks.push({
95103
name: curr.name,
@@ -256,6 +264,10 @@ export class AssemblyProcessor {
256264
private formatStackComment(stackName: string, diff: TemplateDiff, changes: ChangeDetails): string[] {
257265
const output: string[] = [];
258266
const emoji = this.getEmoji(changes);
267+
if (this.options.title) {
268+
output.push(`## ${this.options.title}`);
269+
output.push('');
270+
}
259271
if (diff.isEmpty) {
260272
output.push(`No Changes for stack: ${stackName} ${emoji}`);
261273
return output;

test/stage-processor.test.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ describe('StageProcessor', () => {
101101
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
102102
});
103103
const processor = new AssemblyProcessor({
104+
defaultStageDisplayName: 'DefaultStage',
104105
toolkit,
105106
allowedDestroyTypes: [],
106107
cdkOutDir: 'cdk.out',
@@ -134,6 +135,7 @@ describe('StageProcessor', () => {
134135
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
135136
});
136137
const processor = new AssemblyProcessor({
138+
defaultStageDisplayName: 'DefaultStage',
137139
toolkit,
138140
allowedDestroyTypes: [],
139141
cdkOutDir: 'cdk.out',
@@ -168,6 +170,7 @@ describe('StageProcessor', () => {
168170
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
169171
});
170172
const processor = new AssemblyProcessor({
173+
defaultStageDisplayName: 'DefaultStage',
171174
toolkit,
172175
allowedDestroyTypes: [],
173176
cdkOutDir: 'cdk.out',
@@ -202,6 +205,7 @@ describe('StageProcessor', () => {
202205
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
203206
});
204207
const processor = new AssemblyProcessor({
208+
defaultStageDisplayName: 'DefaultStage',
205209
toolkit,
206210
allowedDestroyTypes: [],
207211
cdkOutDir: 'cdk.out',
@@ -234,6 +238,7 @@ describe('StageProcessor', () => {
234238
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
235239
});
236240
const processor = new AssemblyProcessor({
241+
defaultStageDisplayName: 'DefaultStage',
237242
toolkit,
238243
allowedDestroyTypes: [],
239244
cdkOutDir: 'cdk.out',
@@ -342,6 +347,7 @@ describe('StageProcessor', () => {
342347
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
343348
});
344349
const processor = new AssemblyProcessor({
350+
defaultStageDisplayName: 'DefaultStage',
345351
toolkit,
346352
allowedDestroyTypes: [],
347353
cdkOutDir: 'cdk.out',
@@ -360,6 +366,100 @@ describe('StageProcessor', () => {
360366
expect(p.SomeStage.stackComments['SomeOtherStage-test-stack']).toEqual(undefined);
361367
expect(p.SomeStage.destructiveChanges).toEqual(1);
362368
});
369+
370+
});
371+
372+
describe('default stage', () => {
373+
beforeEach(() => {
374+
375+
mockOutDir = {
376+
'manifest.json': JSON.stringify({
377+
version: '36.0.0',
378+
artifacts: {
379+
'test-stack': {
380+
type: 'aws:cloudformation:stack',
381+
environment: 'aws://unknown-account/unknown-region',
382+
properties: {
383+
templateFile: 'test-stack.template.json',
384+
validateOnSynth: false,
385+
stackName: 'test-stack',
386+
},
387+
displayName: 'test-stack',
388+
},
389+
},
390+
}),
391+
['test-stack.template.json']: JSON.stringify({
392+
Resources: {
393+
MyRole: {
394+
Type: 'AWS::IAM::Role',
395+
Properties: {
396+
RoleName: 'MyCustomName',
397+
},
398+
},
399+
},
400+
}),
401+
};
402+
403+
mockOutDir['SomeStage-test-stack.template.json'] = JSON.stringify({
404+
Resources: {
405+
MyRole: {
406+
Type: 'AWS::IAM::Role',
407+
Properties: {
408+
RoleName: 'MyCustomName',
409+
},
410+
},
411+
},
412+
});
413+
});
414+
415+
test('with defaults', async () => {
416+
mock({
417+
'cdk.out': mockOutDir,
418+
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
419+
});
420+
const processor = new AssemblyProcessor({
421+
defaultStageDisplayName: 'DefaultStage',
422+
toolkit,
423+
allowedDestroyTypes: [],
424+
cdkOutDir: 'cdk.out',
425+
diffMethod: DiffMethod.LocalFile('cdk.out/SomeStage-test-stack.template.json'),
426+
failOnDestructiveChanges: true,
427+
stackSelectorPatterns: [],
428+
stackSelectionStrategy: 'all-stacks',
429+
noFailOnDestructiveChanges: [],
430+
});
431+
await processor.processStages();
432+
const p = (processor as any).stageComments;
433+
expect(p).toEqual({
434+
DefaultStage: expect.any(Object),
435+
});
436+
expect(p.DefaultStage.stackComments['test-stack']).toEqual(['No Changes for stack: test-stack :white_check_mark:']);
437+
});
438+
439+
test('with custom', async () => {
440+
mock({
441+
'cdk.out': mockOutDir,
442+
'node_modules': mock.load(path.join(__dirname, '..', 'node_modules')),
443+
});
444+
const processor = new AssemblyProcessor({
445+
defaultStageDisplayName: 'MyStage',
446+
title: 'Diff for MyStage',
447+
toolkit,
448+
allowedDestroyTypes: [],
449+
cdkOutDir: 'cdk.out',
450+
diffMethod: DiffMethod.LocalFile('cdk.out/SomeStage-test-stack.template.json'),
451+
failOnDestructiveChanges: true,
452+
stackSelectorPatterns: [],
453+
stackSelectionStrategy: 'all-stacks',
454+
noFailOnDestructiveChanges: [],
455+
});
456+
await processor.processStages();
457+
const p = (processor as any).stageComments;
458+
expect(p).toEqual({
459+
MyStage: expect.any(Object),
460+
});
461+
expect(p.MyStage.stackComments['test-stack']).toEqual(['## Diff for MyStage', '', 'No Changes for stack: test-stack :white_check_mark:']);
462+
});
363463
});
364464

365465
describe('stack comments', () => {
@@ -403,6 +503,7 @@ describe('stack comments', () => {
403503

404504
jest.spyOn(Toolkit.prototype, 'diff').mockResolvedValue(templateDiff);
405505
const processor = new AssemblyProcessor({
506+
defaultStageDisplayName: 'DefaultStage',
406507
toolkit,
407508
allowedDestroyTypes: [],
408509
cdkOutDir: 'cdk.out',

0 commit comments

Comments
 (0)