How to set SourceVersion in CDK for CodeBuild - amazon-web-services

When creating a codebuild project with a codecommit source (as shown here: https://docs.aws.amazon.com/cdk/api/latest/docs/aws-codebuild-readme.html#codecommitsource), how can I set the SourceVersion for the codecommit repository?
I can specify the source version manually in console, and cloudformation supports it (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html#cfn-codebuild-project-sourceversion), but appears to be no option to set this through CDK in the default codebuild project constructor.

You can set the SourceVersion with default node.childDefaultChild. That is a reference for CloudFormation template or CfnProject. For example to reference master-branch:
const projectCnf = project.node.defaultChild as CfnProject;
projectCnf.sourceVersion = 'refs/heads/master';
More details here: https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html

Try branchOrRef as documented here
const codeBuildProject = new codeBuild.Project(
this,
"appWebsiteCodeBuild",
{
projectName: "app-website-code-build",
source: codeBuild.Source.codeCommit({
repository: options.repository,
branchOrRef: "refs/heads/master",
}),
},
);

Related

How to use AWS CDK CodePipeline without an oauthToken?

I have previously created a CodePipeline for building from a private GitHub Repo as below:
pipeline.addStage({
stageName: 'Source',
actions: [
new GitHubSourceAction({
actionName: 'Checkout',
owner: github.ardcOwner,
repo: github.raidoSrcRepo,
branch: "main",
oauthToken: SecretValue.secretsManager('personal-token' ),
output: outputSources,
trigger: GitHubTrigger.NONE,
}),
],
});
The repo in question is now public.
Given that no webhook is needed, since the trigger is set to NONE - how do I create new GitHubSourceAction without providing the oauthToken property?
The property is mandatory.
Is there a way to provide a "dummy" value to the GitHubSourceAction for oauthToken such that the account doesn't need to have an unnecessary/unused secret?
I tried to use a dummy value (as opposed to dummy "Secret"):
oauthToken: SecretValue.unsafePlainText("dummy"),
But that failed with "Could not access the GitHub repository".
It was then I remembered that CodePipeline doesn't do a clone, it downloads a zip archive of the HEAD of the repo.
Presumably, CodePipeline needs the secret to download the zip archive from GitHub.
So I don't think CodePipeline can be used with a public GitHub repo without using an OAuth token.

(#aws-cdk/aws-codepipeline) - Using "ShellScriptAction" equivalent in a Pipeline made with #aws-cdk/aws-codepipeline

Here's my problem. I'm currently struggling to run a basic shell script execution action in my pipeline.
The pipeline was created thru the Pipeline construct in #aws-cdk/aws-codepipeline
import { Artifact, IAction, Pipeline } from "#aws-cdk/aws-codepipeline"
const pipeline = new Pipeline(this, "backend-pipeline",{
...
});
Now, I'm running a cross deployment pipeline and would like to invoke a lambda right after it's been created. Before, a simple ShellScriptAction would've sufficed in the older (#aws-cdk/pipelines) package, but for some reason, both packages pipelines and aws-codepipeline are both maintained at the same time.
What I would like to know is how to run a simple basic command in the new (aws-codepipeline) package, ideally as an Action in a Stage.
Thanks in advance!
You would use a codebuild.PipelineProject in a codepipeline_actions.CodeBuildAction to run arbitrary shell commands in your pipeline. The CDK has several build tool constructs*, used in different places. pipelines.CodePipeline specializes in deploying CDK apps, while the lower-level codepipeline.Pipeline has a broader build capabilities:
Build tool construct
CloudFormation Resource
Can use where?
pipelines.ShellStep
AWS::CodeBuild::Project
pipelines.CodePipeline
pipelines.CodeBuildStep
AWS::CodeBuild::Project
pipelines.CodePipeline
codebuild.PipelineProject
AWS::CodeBuild::Project
codepipeline.Pipeline
codebuild.Project
AWS::CodeBuild::Project
codepipeline.Pipeline or standalone
In your case, the setup goes Pipeline > Stage > CodeBuildAction > PipelineProject.
// add to stage actions
new codepipeline_actions.CodeBuildAction({
actionName: 'CodeBuild',
project: new codebuild.PipelineProject(this, 'PipelineProject', {
buildSpec: codebuild.BuildSpec.fromObject({
version: '0.2',
phases: {
build: { commands: ['echo "[project foo] $PROJECT_FOO"'] },
},
}),
environmentVariables: {
PROJECT_FOO: {
value: 'Foo',
type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
},
},
}),
input: sourceOutput,
});
* The ShellScriptAction you mentioned is another one, now deprecated in v1 and removed from v2.
#aws-cdk/aws-codepipeline is for AWS Codepipeline. #aws-cdk/pipelines is for utilizing AWS Codepipeline to deploy CDK apps. Read more about the package and its justification here.
Regarding your question, you have some options here.
First of all, if you're looking for a simple CodeBuild action to run arbitrary commands, you can use CodeBuildAction.
There's a separate action specifically for invoking a lambda, too, it's LambdaInvokeAction.
Both are part of #aws-cdk/aws-codepipeline-actions module.

Environment variables in codebuild project are overridden by action level when using CDK

I am using CDK to deploy codepipeline and codebuild to AWS. I found the environment variables in project level are completely replaced by action level.
Below is the code:
new actions.CodeBuildAction({
actionName,
type: actions.CodeBuildActionType.BUILD,
input,
outputs,
project:
new codebuild.PipelineProject(this, name, {
projectName: name,
environment: {
...
},
environmentVariables: envs,
role: this.codeBuildRole,
buildSpec: codebuild.BuildSpec.fromSourceFilename(specFile),
}),
environmentVariables: additionalEnvs,
runOrder:1,
});
as you can see above code, there are two environmentVariables configurations one under CodeBuildAction and one is under PipelineProject. Based on AWS doc: https://docs.aws.amazon.com/cdk/api/v1/docs/#aws-cdk_aws-codepipeline-actions.CodeBuildActionProps.html#environmentvariables,
(optional, default: No additional environment variables are specified.)
The environment variables to pass to the CodeBuild project when this action executes.
If a variable with the same name was set both on the project level, and here, this value will take precedence.
the environmentVariables under CodeBuildAction should be additional variables. But what happens is the environment variable list in the codebuild project becomes empty. During execution, the environment variables on the running codebuild project only have the ones from the action level. It seems it is a complete replacement rather than appending. Does anyone know what I did wrong here?

How do you pass environment variables from the Source to the Build in AWS CodePipelines?

In AWS CodeBuild, it's incredibly easy to pass environment variables, as shown in the documentation. If I want to get the event trigger reference, I can use the variable CODEBUILD_WEBHOOK_TRIGGER, which is context-sensitive: for a GitHub PUSH event, this will be the branch name, but for a PULL_REQUEST_CREATED or PULL_REQUEST_UPDATED event, this will be the PR number.
So the problem is this: when using AWS CodePipeline, the CodeBuild project "source" is the CodePipeline instead of the GitHub webhook. Suddenly, CODEBUILD_WEBHOOK_TRIGGER is an empty string and doesn't seem to know about anything about the original GitHub webhook event that triggered the CodePipeline.
How does one access those environment variables using a CodeBuild project that is triggered by a CodePipeline? It seems to be a use case that AWS overlooked, so it might be a bug. Unfortunately, very difficult to submit a bug report with only a basic access account.
You are correct. In this particular case, CodePipeline is the one making start-build API call to start the build. CODEBUILD_WEBHOOK_TRIGGER is CodeBuild specific and will only be set when the webhook invokes CodeBuild.
If you want to know the webhook that triggered pipeline, you can use list-webhooks [1] API call with additional filters based on pipeline name to get the webhook details.
Ref:
[1] https://docs.aws.amazon.com/cli/latest/reference/codepipeline/list-webhooks.html
Edit 1:
I was wrong that list-webhooks will get you the required information. I did some tests and it only gives you the list of webhooks defined for the Source action.
The closest I can get is using "list-pipeline-executions" [2] CLI call in your CodeBuild buildspec.
If you run this command:
$ aws codepipeline list-pipeline-executions --pipeline-name <Pipeline_Name> --region us-east-1 --max-items 1
It will give you output similar to this:
{
"pipelineExecutionSummaries": [
{
"pipelineExecutionId": "ccdd87a0-41e4-4489-9332-0720dc526b37",
"status": "InProgress",
"startTime": 1573037463.245,
"lastUpdateTime": 1573037463.245,
"sourceRevisions": [
{
"actionName": "Source",
"revisionId": "4d3bcb17e4a71e3d4bf15215954172639716c326",
"revisionSummary": "Merge pull request #3 from shariqmus/readme-edits\n\nUpdate Code.py",
"revisionUrl": "https://github.com/shariqmus/hello-world/commit/4d3bcb17e4a71e3d4bf15215954172639716c326"
}
]
}
],
"NextToken": "eyJuZXh0VG9rZW4iOiBudWxsLCAiYm90b190cnVuY2F0ZV9hbW91bnQiOiAxfQ=="
}
The 'revisionSummary' has the PR details. You can filter this value using 'jq' [3], so the command in your build spec will look something like:
Make sure your CodeBuild project's service role has permission to do 'ListPipelineExecutions' on the Pipeline
Add the following in Buildspec 'Install' phase:
apt-get install jq
Add the following in Buildspec where you need to get the commit message:
COMMIT_MSG=$(aws codepipeline list-pipeline-executions --pipeline-name --max-items 1 | jq -r '.pipelineExecutionSummaries[0].sourceRevisions[0].revisionSummary')
echo $COMMIT_MSG
I hope this answer was helpful.
Ref:
[2] https://docs.aws.amazon.com/cli/latest/reference/codepipeline/list-pipeline-executions.html
[3] https://stedolan.github.io/jq/

How to disable encryption on AWS CodeBuild artifacts?

I'm using AWS CodeBuild to build an application, it is configured to push the build artifacts to an AWS S3 bucket.
On inspecting the artifcats/objects in the S3 bucket I realised that the objects has been encrypted.
Is it possible to disable to encryption on the artifcats/objects?
There is now a checkbox named "Disable artifacts encryption" under the artifacts section which allows you to disable encryption when pushing artifacts to S3.
https://docs.aws.amazon.com/codebuild/latest/APIReference/API_ProjectArtifacts.html
I know this is an old post but I'd like to add my experience in this regard.
My requirement was to get front end assets from a code commit repository, build them and put them in s3 bucket. s3 bucket is further connected with cloudfront for serving the static front end content (written in react in my case).
I found that cloudfront is unable to serve KMS encrypted content as I found KMS.UnrecognizedClientException when I hit the cloudfront Url. I tried to fix that and disabling encryption on aws codebuild artifacts seemed to be the easiest solution when I found this
However, I wanted to manage this using aws-cdk. This code snippet in TypeScript may come handy if you're trying to solve the same issue using aws-cdk
Firstly, get your necessary imports. For this answer it'd be the following:
import * as codecommit from '#aws-cdk/aws-codecommit';
import * as codebuild from '#aws-cdk/aws-codebuild';
Then, I used the following snippet in a class that extends to cdk Stack
Note: The same should work if your class extends to a cdk Construct
// replace these according to your requirement
const frontEndRepo = codecommit.Repository
.fromRepositoryName(this, 'ImportedRepo', 'FrontEnd');
const frontendCodeBuild = new codebuild.Project(this, 'FrontEndCodeBuild', {
source: codebuild.Source.codeCommit({ repository: frontEndRepo }),
buildSpec: codebuild.BuildSpec.fromObject({
version: '0.2',
phases: {
build: {
commands: [
'npm install && npm run build',
],
},
},
artifacts: {
files: 'build/**/*'
}
}),
artifacts: codebuild.Artifacts.s3({
bucket: this.bucket, // replace with s3 bucket object
includeBuildId: false,
packageZip: false,
identifier: 'frontEndAssetArtifact',
name: 'artifacts',
encryption: false // added this to disable the encryption on codebuild
}),
});
Also to ensure that everytime I push a code in the repository, a build is triggered, I added the following snippet in the same class.
// add the following line in your imports if you're using this snippet
// import * as targets from '#aws-cdk/aws-events-targets';
frontEndRepo.onCommit('OnCommit', {
target: new targets.CodeBuildProject(frontendCodeBuild),
});
Note: This may not be a perfect solution, but it's working well for me till now. I'll update this answer if I find a better solution using aws-cdk
Artifact encryption cannot be disabled in AWS CodeBuild