Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(codepipeline-actions): add elastic beanstalk deploy action #22135

Merged
merged 11 commits into from
Oct 4, 2022
Merged
22 changes: 22 additions & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,28 @@ new codepipeline.Pipeline(this, 'Pipeline', {
});
```

### Elastic Beanstalk Deployment

To deploy an Elastic Beanstalk Application in CodePipeline:

```ts
const sourceOutput = new codepipeline.Artifact();
const targetBucket = new s3.Bucket(this, 'MyBucket');

const pipeline = new codepipeline.Pipeline(this, 'MyPipeline');
const deployAction = new codepipeline_actions.ElasticBeanstalkDeployAction({
actionName: 'ElasticBeanstalkDeploy',
input: sourceOutput,
environmentName: 'envName',
applicationName: 'appName',
});

const deployStage = pipeline.addStage({
stageName: 'Deploy',
actions: [deployAction],
});
```

### Alexa Skill

You can deploy to Alexa using CodePipeline with the following Action:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import { Construct } from 'constructs';
import { Action } from '../action';
import { deployArtifactBounds } from '../common';

/**
* Construction properties of the {@link ElasticBeanstalkDeployAction Elastic Beanstalk deploy CodePipeline Action}.
*/
export interface ElasticBeanstalkDeployActionProps extends codepipeline.CommonAwsActionProps {
/**
* The source to use as input for deployment.
*/
readonly input: codepipeline.Artifact;

/**
* The name of the AWS Elastic Beanstalk application to deploy.
*/
readonly applicationName: string;

/**
* The name of the AWS Elastic Beanstalk environment to deploy to.
*/
readonly environmentName: string;
}

/**
* CodePipeline action to deploy an AWS ElasticBeanstalk Application.
*/
export class ElasticBeanstalkDeployAction extends Action {
private readonly applicationName: string;
private readonly environmentName: string;

constructor(props: ElasticBeanstalkDeployActionProps) {
super({
...props,
category: codepipeline.ActionCategory.DEPLOY,
provider: 'ElasticBeanstalk',
artifactBounds: deployArtifactBounds(),
inputs: [props.input],
});

this.applicationName = props.applicationName;
this.environmentName = props.environmentName;
}

protected bound(
_scope: Construct,
_stage: codepipeline.IStage,
options: codepipeline.ActionBindOptions,
): codepipeline.ActionConfig {

// Per https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.iam.managed-policies.html
// it doesn't seem we can scope this down further for the codepipeline action.
options.role.addManagedPolicy({ managedPolicyArn: 'arn:aws:iam::aws:policy/AdministratorAccess-AWSElasticBeanstalk' });

// the Action's Role needs to read from the Bucket to get artifacts
options.bucket.grantRead(options.role);

return {
configuration: {
ApplicationName: this.applicationName,
EnvironmentName: this.environmentName,
},
};
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './codedeploy/ecs-deploy-action';
export * from './codedeploy/server-deploy-action';
export * from './ecr/source-action';
export * from './ecs/deploy-action';
export * from './elastic-beanstalk/deploy-action';
export * from './github/source-action';
export * from './jenkins/jenkins-action';
export * from './jenkins/jenkins-provider';
Expand Down
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@aws-cdk/aws-cloudtrail": "0.0.0",
"@aws-cdk/aws-codestarnotifications": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/aws-s3-deployment": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/integ-runner": "0.0.0",
"@aws-cdk/integ-tests": "0.0.0",
Expand All @@ -99,6 +100,7 @@
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-ecr": "0.0.0",
"@aws-cdk/aws-ecs": "0.0.0",
"@aws-cdk/aws-elasticbeanstalk": "0.0.0",
"@aws-cdk/aws-events": "0.0.0",
"@aws-cdk/aws-events-targets": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
Expand All @@ -122,6 +124,7 @@
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-ecr": "0.0.0",
"@aws-cdk/aws-ecs": "0.0.0",
"@aws-cdk/aws-elasticbeanstalk": "0.0.0",
"@aws-cdk/aws-events": "0.0.0",
"@aws-cdk/aws-events-targets": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Template } from '@aws-cdk/assertions';
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import { Bucket } from '@aws-cdk/aws-s3';
import { App, Stack } from '@aws-cdk/core';
import { ElasticBeanstalkDeployAction, S3SourceAction, S3Trigger } from '../../lib';

describe('elastic beanstalk deploy action tests', () => {
test('region and account are action region and account when set', () => {
const stack = buildPipelineStack();
Template.fromStack(stack).hasResourceProperties('AWS::CodePipeline::Pipeline', {
Stages: [
{
Actions: [
{
ActionTypeId: {
Category: 'Source',
Owner: 'AWS',
Provider: 'S3',
Version: '1',
},
Configuration: {
S3Bucket: {
Ref: 'MyBucketF68F3FF0',
},
S3ObjectKey: 'some/path/to',
PollForSourceChanges: true,
},
Name: 'Source',
OutputArtifacts: [
{
Name: 'Artifact_Source_Source',
},
],
RoleArn: {
'Fn::GetAtt': [
'MyPipelineSourceCodePipelineActionRoleAA05D76F',
'Arn',
],
},
RunOrder: 1,
},
],
Name: 'Source',
},
{
Actions: [
{
ActionTypeId: {
Category: 'Deploy',
Owner: 'AWS',
Provider: 'ElasticBeanstalk',
Version: '1',
},
Configuration: {
ApplicationName: 'testApplication',
EnvironmentName: 'env-testApplication',
},
InputArtifacts: [
{
Name: 'Artifact_Source_Source',
},
],
Name: 'Deploy',
RoleArn: {
'Fn::GetAtt': [
'MyPipelineDeployCodePipelineActionRole742BD48A',
'Arn',
],
},
RunOrder: 1,
},
],
Name: 'Deploy',
},
],
ArtifactStore: {
EncryptionKey: {
Id: {
'Fn::GetAtt': [
'MyPipelineArtifactsBucketEncryptionKey8BF0A7F3',
'Arn',
],
},
Type: 'KMS',
},
Location: {
Ref: 'MyPipelineArtifactsBucket727923DD',
},
Type: 'S3',
},
});
});
});

function buildPipelineStack(): Stack {
const app = new App();
const stack = new Stack(app);
const sourceOutput = new codepipeline.Artifact();
const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline');
pipeline.addStage({
stageName: 'Source',
actions: [
new S3SourceAction({
actionName: 'Source',
bucket: new Bucket(stack, 'MyBucket'),
bucketKey: 'some/path/to',
output: sourceOutput,
trigger: S3Trigger.POLL,
}),
],
});

pipeline.addStage({
stageName: 'Deploy',
actions: [
new ElasticBeanstalkDeployAction({
actionName: 'Deploy',
applicationName: 'testApplication',
environmentName: 'env-testApplication',
input: sourceOutput,
}),
],
});

return stack;
}
Loading