Skip to content

Commit

Permalink
feat(aws-codepipeline): make input and output artifact names optional…
Browse files Browse the repository at this point in the history
… when creating Actions. (#845)

BREAKING CHANGE: this commit contains the following breaking changes:
* Rename 'artifactName' in Action construction properties to 'outputArtifactName'
* Rename the 'artifact' property of Actions to 'outputArtifact'
* No longer allow adding output artifacts to Actions by instantiating the Artifact class
* Rename Action#input/outputArtifacts properties to _input/_outputArtifacts

Previously, we always required customers to explicitly name the output artifacts the Actions used in the Pipeline,
and to explicitly "wire together" the outputs of one Action as inputs to another.
With this change, the CodePipeline Construct generates artifact names,
if the customer didn't provide one explicitly,
and tries to find the first available output artifact to use as input to a newly created Action that needs it,
thus turning both the input and output artifacts from required to optional properties.
  • Loading branch information
skinny85 committed Oct 11, 2018
1 parent 89ba45d commit 3d91c93
Show file tree
Hide file tree
Showing 36 changed files with 330 additions and 221 deletions.
7 changes: 4 additions & 3 deletions packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ export interface PipelineCloudFormationActionProps extends codepipeline.CommonAc
/**
* Base class for Actions that execute CloudFormation
*/
export abstract class PipelineCloudFormationAction extends codepipeline.DeployAction {
export abstract class PipelineCloudFormationAction extends codepipeline.Action {
/**
* Output artifact containing the CloudFormation call response
*
* Only present if configured by passing `outputFileName`.
*/
public artifact?: codepipeline.Artifact;
public outputArtifact?: codepipeline.Artifact;

constructor(parent: cdk.Construct, id: string, props: PipelineCloudFormationActionProps, configuration?: any) {
super(parent, id, {
Expand All @@ -57,6 +57,7 @@ export abstract class PipelineCloudFormationAction extends codepipeline.DeployAc
maxOutputs: 1,
},
provider: 'CloudFormation',
category: codepipeline.ActionCategory.Deploy,
configuration: {
StackName: props.stackName,
OutputFileName: props.outputFileName,
Expand All @@ -65,7 +66,7 @@ export abstract class PipelineCloudFormationAction extends codepipeline.DeployAc
});

if (props.outputFileName) {
this.artifact = this.addOutputArtifact(props.outputArtifactName ||
this.outputArtifact = this.addOutputArtifact(props.outputArtifactName ||
(props.stage.name + this.id + 'Artifact'));
}
}
Expand Down
13 changes: 11 additions & 2 deletions packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export = nodeunit.testCase({
_assertPermissionGranted(test, pipelineRole.statements, 'cloudformation:CreateChangeSet', stackArn, changeSetCondition);
_assertPermissionGranted(test, pipelineRole.statements, 'cloudformation:DeleteChangeSet', stackArn, changeSetCondition);

test.deepEqual(action.inputArtifacts, [artifact],
test.deepEqual(action._inputArtifacts, [artifact],
'The inputArtifact was correctly registered');

_assertActionMatches(test, stage.actions, 'AWS', 'CloudFormation', 'Deploy', {
Expand Down Expand Up @@ -145,10 +145,11 @@ function _isOrContains(entity: string | string[], value: string): boolean {
return false;
}

class StageDouble implements cpapi.IStage {
class StageDouble implements cpapi.IStage, cpapi.IInternalStage {
public readonly name: string;
public readonly pipelineArn: string;
public readonly pipelineRole: iam.Role;
public readonly _internal = this;

public readonly actions = new Array<cpapi.Action>();

Expand All @@ -165,6 +166,14 @@ class StageDouble implements cpapi.IStage {
public _attachAction(action: cpapi.Action) {
this.actions.push(action);
}

public _generateOutputArtifactName(): string {
throw new Error('Unsupported');
}

public _findInputArtifact(): cpapi.Artifact {
throw new Error('Unsupported');
}
}

class RoleDouble extends iam.Role {
Expand Down
19 changes: 4 additions & 15 deletions packages/@aws-cdk/aws-codebuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,12 @@ const project = new codebuild.PipelineProject(this, 'MyProject');

const pipeline = new codepipeline.Pipeline(this, 'MyPipeline');

const sourceStage = new codepipeline.Stage(this, 'Source', {
pipeline,
});
const sourceAction = new codecommit.PipelineSourceAction(this, 'CodeCommit', {
stage: sourceStage,
artifactName: 'SourceOutput',
repository,
});
const sourceStage = pipeline.addStage('Source');
repository.addToPipeline(sourceStage, 'CodeCommit');

const buildStage = new codepipeline.Stage(this, 'Build', {
pipeline,
});
const buildStage = pipeline.addStage('Build');
new codebuild.PipelineBuildAction(this, 'CodeBuild', {
stage: buildStage,
inputArtifact: sourceAction.artifact,
project,
});
```
Expand All @@ -84,9 +75,7 @@ You can also add the Project to the Pipeline directly:
```ts
// equivalent to the code above:
project.addBuildToPipeline(buildStage, 'CodeBuild', {
inputArtifact: sourceAction.artifact,
})
project.addBuildToPipeline(buildStage, 'CodeBuild');
```
### Using Project as an event target
Expand Down
14 changes: 9 additions & 5 deletions packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ import { ProjectRef } from './project';
*/
export interface CommonPipelineBuildActionProps extends codepipeline.CommonActionProps {
/**
* The source to use as input for this build
* The source to use as input for this build.
*
* @default CodePipeline will use the output of the last Action from a previous Stage as input
*/
inputArtifact: codepipeline.Artifact;
inputArtifact?: codepipeline.Artifact;

/**
* The name of the build's output artifact
* The name of the build's output artifact.
*
* @default an auto-generated name will be used
*/
artifactName?: string;
outputArtifactName?: string;
}

/**
Expand All @@ -44,7 +48,7 @@ export class PipelineBuildAction extends codepipeline.BuildAction {
runOrder: props.runOrder,
provider: 'CodeBuild',
inputArtifact: props.inputArtifact,
artifactName: props.artifactName,
outputArtifactName: props.outputArtifactName,
configuration: {
ProjectName: props.project.projectName
}
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-codebuild/lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ export abstract class ProjectRef extends cdk.Construct implements events.IEventR
* @param props the properties of the new Action
* @returns the newly created {@link PipelineBuildAction} build Action
*/
public addBuildToPipeline(stage: codepipeline.IStage, name: string, props: CommonPipelineBuildActionProps): PipelineBuildAction {
return new PipelineBuildAction(this.parent!, name, {
public addBuildToPipeline(stage: codepipeline.IStage, name: string, props: CommonPipelineBuildActionProps = {}): PipelineBuildAction {
return new PipelineBuildAction(this, name, {
stage,
project: this,
...props,
Expand Down
30 changes: 7 additions & 23 deletions packages/@aws-cdk/aws-codecommit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,41 @@ To add a CodeCommit Repository to your stack:
```ts
import codecommit = require('@aws-cdk/aws-codecommit');

const repository = new codecommit.Repository(this, 'Repository' ,{
repositoryName: 'MyRepositoryName'
const repo = new codecommit.Repository(this, 'Repository' ,{
repositoryName: 'MyRepositoryName',
description: 'Some description.', // optional property
});
```

To add an SNS trigger to your repository:

```ts
import codecommit = require('@aws-cdk/aws-codecommit');

const repository = new codecommit.Repository(this, 'Repository', {
repositoryName: 'MyRepositoryName'
});

// trigger is established for all repository actions on all branches by default.
repository.notify('arn:aws:sns:*:123456789012:my_topic');
repo.notify('arn:aws:sns:*:123456789012:my_topic');
```

### CodePipeline

To use a CodeCommit Repository in a CodePipeline:

```ts
import codecommit = require('@aws-cdk/aws-codecommit');
import codepipeline = require('@aws-cdk/aws-codepipeline');

// see above for the details...
const repository = new codecommit.Repository( // ...
);

const pipeline = new codepipeline.Pipeline(this, 'MyPipeline', {
pipelineName: 'MyPipeline',
});
const sourceStage = new codepipeline.Stage(this, 'Source', {
pipeline,
});
const sourceStage = pipeline.addStage('Source');
const sourceAction = new codecommit.PipelineSourceAction(this, 'CodeCommit', {
stage: sourceStage,
artifactName: 'SourceOutput', // name can be arbitrary
repository,
repository: repo,
});
// use sourceAction.artifact as the inputArtifact to later Actions...
```

You can also add the Repository to the Pipeline directly:

```ts
// equivalent to the code above:
const sourceAction = repository.addToPipeline(sourceStage, 'CodeCommit', {
artifactName: 'SourceOutput',
});
const sourceAction = repo.addToPipeline(sourceStage, 'CodeCommit');
```

### Events
Expand Down
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ export interface CommonPipelineSourceActionProps extends codepipeline.CommonActi
/**
* The name of the source's output artifact.
* Output artifacts are used by CodePipeline as inputs into other actions.
*
* @default a name will be auto-generated
*/
artifactName: string;
outputArtifactName?: string;

/**
* @default 'master'
Expand Down Expand Up @@ -54,7 +56,7 @@ export class PipelineSourceAction extends codepipeline.SourceAction {
BranchName: props.branch || 'master',
PollForSourceChanges: props.pollForSourceChanges !== undefined ? props.pollForSourceChanges : true
},
artifactName: props.artifactName
outputArtifactName: props.outputArtifactName
});

// https://docs.aws.amazon.com/codecommit/latest/userguide/auth-and-access-control-permissions-reference.html#aa-acp
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-codecommit/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ export abstract class RepositoryRef extends cdk.Construct {
* @param props the properties of the new Action
* @returns the newly created {@link PipelineSourceAction}
*/
public addToPipeline(stage: actions.IStage, name: string, props: CommonPipelineSourceActionProps): PipelineSourceAction {
return new PipelineSourceAction(this.parent!, name, {
public addToPipeline(stage: actions.IStage, name: string, props: CommonPipelineSourceActionProps = {}): PipelineSourceAction {
return new PipelineSourceAction(this, name, {
stage,
repository: this,
...props,
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-codecommit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
"nyc": {
"lines": 30,
"branches": 48
"branches": 40
},
"keywords": [
"aws",
Expand Down
5 changes: 1 addition & 4 deletions packages/@aws-cdk/aws-codedeploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,9 @@ const pipeline = new codepipeline.Pipeline(this, 'MyPipeline', {

// add the source and build Stages to the Pipeline...

const deployStage = new codepipeline.Stage(this, 'Deploy', {
pipeline,
}));
const deployStage = pipeline.addStage('Deploy');
new codedeploy.PipelineDeployAction(this, 'CodeDeploy', {
stage: deployStage,
inputArtifact: buildAction.artifact, // taken from a build Action in a previous Stage
applicationName: 'YourCodeDeployApplicationName',
deploymentGroupName: 'YourCodeDeployDeploymentGroupName',
});
Expand Down
4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-codedeploy/lib/pipeline-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export interface PipelineDeployActionProps extends codepipeline.CommonActionProp

/**
* The source to use as input for deployment.
*
* @default CodePipeline will use the output of the last Action from a previous Stage as input
*/
inputArtifact: codepipeline.Artifact;
inputArtifact?: codepipeline.Artifact;
}

export class PipelineDeployAction extends codepipeline.DeployAction {
Expand Down
Loading

0 comments on commit 3d91c93

Please sign in to comment.