For this example, I merged two workflows provided by GitHub: .NET and Deploy to Amazon ECS. The idea is build a simple workflow like this:
Why Github Actions?
Github Actions offers workflows that can build the code in your repository and run your tests. Workflows can run on GitHub-hosted virtual machines, or on machines that you host yourself.
To start with Actions, create a new file in the .github/workflows directory named api-deployment.yml and copy the following YAML:
name: API workflow
on:
push:
branches: [ main ]
paths:
- 'src/**'
pull_request:
branches: [ main ]
paths:
- 'src/**'
jobs:
build:
name: Build API
runs-on: ubuntu-latest
env:
working-directory: './src'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- name: Restore dependencies
run: dotnet restore API.sln
working-directory: ${{env.working-directory}}
- run: dotnet build --no-restore
working-directory: ${{env.working-directory}}
- run: dotnet test --no-build --verbosity normal
working-directory: ${{env.working-directory}}
deploy-dev:
name: Deploy to Dev
if: github.event.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: your-ecr-name
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
docker build -f src/api/Dockerfile -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG src/api
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: .github/task-definitions/your-api-task-definition.json
container-name: your-container-name
image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: your-service-name
cluster: your-cluster-name
wait-for-service-stability: true
That is quite a long file, so let's start to dissect the most important lines.
Events
An event is an activity that triggers a workflow. To define the event (or events) we use the on keyword. Also, you can add constraints over those triggers.
Here we are setting that our action is going to be triggered on every push or pull request to main, and at least one modified file matches the configured paths.
Note: push and pull_request events support paths and paths-ignore filter, for more info read here
on:
push:
branches: [ main ]
paths:
- 'src/**'
pull_request:
branches: [ main ]
paths:
- 'src/**'
Jobs
A job is a set of steps that execute on the same runner. By default, a workflow with multiple jobs will run those jobs in parallel.
Build
Build is just a name for this job, you can set whatever you want. Here I'm using mostly the example from the .NET workflow. Will restore dependencies, build the code and run the unit tests.
build:
name: Build API
runs-on: ubuntu-latest
env:
working-directory: './src'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- name: Restore dependencies
run: dotnet restore API.sln
working-directory: ${{env.working-directory}}
- run: dotnet build --no-restore
working-directory: ${{env.working-directory}}
- run: dotnet test --no-build --verbosity normal
working-directory: ${{env.working-directory}}
Deploy-dev
Deploy-dev job is using the Github workflows templates,
an upcoming post will cover how to create this infrastructure in detail to complete a full deployment.
But I want to highlight the following block:
deploy-dev:
name: Deploy to Dev
if: github.event.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: [build]
Using the needs keyword we define a dependency to the previous job build, only if the build was successfully completed this job is going to be executed. In that form, we change the default behavior of running the jobs in parallel to run sequentially.
On the other way, the if conditional allows avoiding the execution of a job unless a condition is met.
Here we use the github context to get the branch that is triggering the workflow, if the branch is "main" means that the PR was merged, so we can complete our deployment to our dev environment.
So that's it!
You can find a public repo with the example here
Top comments (0)