Dinero
Dinero

Reputation: 1160

Trigger unit test for every pull request in aws codepipeline

Background

I have a git repo bio-dev. Currently in my pipeline.yaml file shown below I basically download my latest code zip it and upload it to s3 and later it gets deployed.

In its root directory i have a simple unit test named test_hello_world.py

My pipeline yaml file currently

# This describes an AWS "CodePipeline" -- an AWS continuous-deployment service
# A CodePipeline generated with this template will:
#  * subscribe to github push notifications on the bio-dev repo via a webhook
#  * when a commit is pushed to the specified branch:
#    * download the source code from that branch
#    * zip it up and copy it to the source-code S3 location for that branch

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  RepositoryBranch:
    Type: String
    Description: >
      Branch of the bio-dev repository to monitor
  OAuthToken:
    Type: String
    Description: >
      OAuth Token for this code pipeline to connect to GitHub to download the source code
      when the webhook publishes a push event
    NoEcho: true

Resources:

  # NOTE: despite several Region properties, none of the elements of this Resource (or stack)
  # are region-specific -- S3 and IAM are global
  DeployFromGithubToS3CodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub 'bio-dev-github-${RepositoryBranch}-to-s3'
      ArtifactStore:
        Location: 'source-code-for-download-by-ec2s'
        Type: S3
      RestartExecutionOnUpdate: true
      RoleArn: !ImportValue CodePipelineServiceRoleArn  # This is exported by the code_pipeline_role_and_policy.yaml stack
      Stages: 
        - Name: Source
          Actions:
            - Name: download_and_zip_code_from_github
              Region: !Ref "AWS::Region"
              ActionTypeId:
                Category: Source
                Owner: ThirdParty
                Version: 1
                Provider: GitHub
              Configuration:
                Owner: ProjectBatman
                Repo: 'bio-dev'
                PollForSourceChanges: false
                Branch: !Sub '${RepositoryBranch}'
                OAuthToken: !Sub '${OAuthToken}'
              RunOrder: 1
              InputArtifacts: []
              OutputArtifacts:
                - Name: zip_of_source_code
        - Name: Deploy
          Actions:
            - Name: copy_zip_of_source_code_to_s3
              Region: !Ref "AWS::Region"
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Version: 1
                Provider: S3
              Configuration:
                ObjectKey: !Sub 'BRANCHES/${RepositoryBranch}/repo.zip'  # ec2_init_user_data.sh depends on this, and there's a python abstraction to retrieve it in s3.py
                Extract: false
                BucketName: 'source-code-for-download-by-ec2s'
              RunOrder: 1
              InputArtifacts: 
                - Name: 'zip_of_source_code'
              OutputArtifacts: []

  AppPipelineWebhook:
    # TO DO: can all CodePipelines share a single github webhook, and filter to the branch-of-interest?
    # If not, every time we create a CodePipeline with CloudFormation, AWS creates another webhook
    # for the bio-dev repository, displayed here: https://github.com/ProjectBatman/bio-dev/settings/hooks
    Type: AWS::CodePipeline::Webhook
    Properties:
      Authentication: GITHUB_HMAC
      AuthenticationConfiguration:
        SecretToken: !Sub '${OAuthToken}'
      Filters:
        - 
          JsonPath: "$.ref"
          MatchEquals: !Sub 'refs/heads/${RepositoryBranch}'
      TargetPipeline: !Ref DeployFromGithubToS3CodePipeline
      TargetAction: download_and_zip_code_from_github
      Name: !Sub 'webhook-for-branch-${RepositoryBranch}'
      # NOTE: this appears to reference a "Version" property of the CodePipeline resource
      # But "Version" is not a valid property of an AWS::CodePipeline::Pipeline CloudFormation object
      # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-pipeline.html
      # So I guess "Version" is managed dynamically by the CodePipeline service, and the reference in this webhook
      # automatically points to the latest version of the Pipeline
      TargetPipelineVersion: !GetAtt DeployFromGithubToS3CodePipeline.Version
      RegisterWithThirdParty: true

OBJECTIVE

Ideally i want to run this test on every pull request and I was not sure how to get started on this.

I did a bit of research by going through aws documents. From what I understand is I would need to create a lambda function and add it as a custom action for one of the stages. Do I understand correctly or am i off?

I would love to hear all inputs as I am very new to aws and i am overwhelmed by the information on aws as I am not able to find the right direction to get started.

Upvotes: 2

Views: 3225

Answers (2)

Yep_It's_Me
Yep_It's_Me

Reputation: 4801

@solsglasses answer is correct in that you actually want to use CodeBuild and not CodePipeline. In order to just run the tests on every PR, you don't need CodePipeline at all.

Set up a CodeBuild Project

  1. Create a CodeBuild Project
    • Be sure to specify your remote git repo as the source (eg. GitHub, BitBucket, etc)
    • Set an environment variable to give CodeBuild access to the repo (eg. for GitHub you need GITHUB_TOKEN
  2. Add the build specification to you git repo

Now you can jump into the AWS console and manually trigger a build using the Start Build button in the top right of your build project.

Trigger CodeBuild on a pull request

To trigger the CodeBuild project on every pull request, you need to setup a Project Trigger with a Webhook Filter. You molt likely want the PULL_REQUEST_CREATED and PULL_REQUEST_UPDATED filters, otherwise your build will trigger on any push to any branch even if a pull request isn't created (which will cost money and provide no value).

Using CodePipeline

This part is optional, but often used with CodeBuild.

  1. Configure CodePipeline to run on pushes to the master branch
  2. Add a stage for your CodeBuild project which you've already created
  3. Update your buildspec file to create an artifact
  4. Update the CodeBuild project to store the artifact in S3

This is the part where you can trigger a deploy using whatever tool you want. The tool can pull the build artifact (just a normal zip file) from S3 and copy it onto your server, then run your deployment steps. You can trigger this manually by running some script or clicking a button in your deployment application of choice, or you can configure CodePipeline to do the deploy for you if you use a supported deployment service.

Upvotes: 2

Sean Linguine
Sean Linguine

Reputation: 459

I did a bit of research by going through aws documents. From what I understand is I would need to create a lambda function and add it as a custom action for one of the stages. Do I understand correctly or am i off?

No, this is incorrect. This is easier than you think. You do not need to create any Lambda functions.

I notice that you did not mention AWS CodeBuild anywhere in your original post. This is the concept that you are missing. AWS CodePipeline is not designed to test Pull Requests. In fact, AWS CodePipeline stages usually include CodeBuild jobs.

AWS CodeBuild will use a configuration file at the root of your project (buildspec.yaml) and use it to run build processes, test procedures, anything you want really. It will run a CodeBuild job upon every Pull Request create/update. CodeBuild will report back to GitHub whether the test passed or not.

Optionally: At the end of the CodeBuild execution, you can have it produce an artifact.zip with your build files and be passed to other stages of your CodePipeline for further handling.

Here's an example buildspec.yaml for illustration:

version: 0.2

phases:
  install:
    commands:
      - npm install
  pre_build:
    commands:
      - ./myscript.sh
  build:
    commands:
      - npm test
      - npm build

Upvotes: 5

Related Questions