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

DOE-150: Add reusable container build workflow #3

Merged
merged 16 commits into from
Nov 11, 2024
17 changes: 17 additions & 0 deletions .github/workflows/_skip_test-container-image-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: "Test Build Container Image"

on:
pull_request:
branches:
- main
paths-ignore:
- .github/workflows/_test-container-image-build.yml
- .github/workflows/container-image-build.yml
- .github/workflows/container-image-release.yml

jobs:
container_image_build_regression_test:
name: Test using devops-terraform-ci@main
runs-on: ubuntu-latest
steps:
- run: 'echo "No build required" '
2 changes: 1 addition & 1 deletion .github/workflows/_skip_test-terraform-destroy.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "[Test] Skip Destroy Terraform stacks"
name: "Test Destroy Terraform stacks"

on:
pull_request:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/_skip_test-terraform-plan-apply.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "[Test] Skip Deploy Terraform stacks"
name: "Test Deploy Terraform stacks"

on:
pull_request:
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/_test-container-image-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "Test Build Container Image"
# Regression testing to try and catch and breaking changes

on:
pull_request:
branches:
- main
paths:
- .github/workflows/_test-container-image-build.yml
- .github/workflows/container-image-build.yml
- .github/workflows/container-image-release.yml

jobs:
container_image_build_regression_test:
name: Test using devops-terraform-ci@main
uses: ./.github/workflows/container-image-build.yml
with:
repo: ukhsa-collaboration/devops-terraform-ci
ref: "main"
release_after_build: false
permissions:
id-token: write
contents: write
actions: read
2 changes: 1 addition & 1 deletion .github/workflows/_test-terraform-destroy.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "[Test] Destroy Terraform stacks"
name: "Test Destroy Terraform stacks"
# Regression testing to try and catch and breaking changes. Will only run a destroy plan.

on:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/_test-terraform-plan-apply.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "[Test] Deploy Terraform stacks"
name: "Test Deploy Terraform stacks"
# Regression testing to try and catch and breaking changes

on:
Expand Down
99 changes: 99 additions & 0 deletions .github/workflows/container-image-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: "Build, Test and Push Container Image"
on:
workflow_call:
inputs:
image_name:
description: "The name of the image"
type: string
unit_tests_command:
description: "The command to run unit tests of the application"
type: string
default: echo docker run container:latest pytest || exit 1
release_after_build:
description: "Whether or not to generate a tag and release after building the image"
type: boolean
default: false
dockerfile:
description: "Name of the Dockerfile relative to the build context"
type: string
default: "Dockerfile"
docker_build_context:
description: "The context of the Docker build command"
type: string
default: "."
repo:
required: false
type: string
default: ${{ github.repository }}
description: "Specify the org/repo of the repo containing Terraform code. Normally left blank to clone calling repo."
ref:
required: false
type: string
default: ${{ github.ref }}
description: "Specify the branch of the Terraform code. Normally left blank to use calling ref."
outputs:
artifact_url:
value: ${{ jobs.build.outputs.artifact_url }}
secrets:
AWS_ROLE_NAME:
required: false
description: "The name of the role used to push the image. Only used if `release_after_build` is true."
AWS_ACCOUNT_ID:
required: false
description: "The account ID hosting the ECR repository. Only used if `release_after_build` is true."


jobs:
build:
name: Docker build image
runs-on: ubuntu-latest
outputs:
artifact_url: ${{ steps.upload.outputs.artifact-url }}
permissions:
id-token: write
contents: write
actions: read
steps:
- uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: ${{ inputs.docker_build_context }}
push: false
tags: "container:latest"
load: true
file: "${{ inputs.docker_build_context }}/${{ inputs.dockerfile }}"
outputs: type=docker,dest=/tmp/container-image.tar

- name: Unit tests
if: inputs.unit_tests_command != ''
run: |
${{ inputs.unit_tests_command }}

- uses: actions/upload-artifact@v4
if: inputs.release_after_build
id: upload
with:
name: container-image
path: /tmp/container-image.tar
retention-days: 1

release:
uses: ./.github/workflows/container-image-release.yml
if: inputs.release_after_build
needs:
- build
with:
artifact_run_id: ${{ github.run_id }}
image_name: ${{ inputs.image_name }}
secrets:
AWS_ROLE_NAME: ${{ secrets.AWS_ROLE_NAME }}
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
85 changes: 85 additions & 0 deletions .github/workflows/container-image-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: "Tag and Release image"
on:
workflow_call:
inputs:
artifact_run_id:
description: "The run ID of the workflow that generated a container-image artifact"
type: string
aws_region:
description: "The AWS region containing the ECR repo"
type: string
default: "eu-west-2"
image_name:
description: "The name of the container image"
type: string
repo:
required: false
type: string
default: ${{ github.repository }}
description: "Specify the org/repo of the repo containing Terraform code. Normally left blank to clone calling repo."
ref:
required: false
type: string
default: ${{ github.ref }}
description: "Specify the branch of the Terraform code. Normally left blank to use calling ref."
secrets:
AWS_ROLE_NAME:
required: false
description: "The name of the role used to push the image."
AWS_ACCOUNT_ID:
required: false
description: "The account ID hosting the ECR repository."


permissions:
id-token: write
contents: write
actions: read

jobs:
release:
name: Tag and release
runs-on: ubuntu-latest
outputs:
release_tag: ${{ steps.tag_bump.outputs.new_tag }}
image: ${{ steps.push.outputs.image }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
repository: ${{ inputs.repo }}

- uses: ukhsa-collaboration/devops-github-actions/.github/actions/[email protected]
id: tag_bump
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WITH_V: true

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }}
role-session-name: build-and-push-${{ github.sha }}
aws-region: ${{ inputs.aws_region }}

- uses: actions/download-artifact@v4
with:
name: container-image
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Load, tag and push image
id: push
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ steps.tag_bump.outputs.new_tag }}
APP_NAME: ${{ inputs.image_name }}
run: |
docker load --input $GITHUB_WORKSPACE/container-image.tar
docker tag container:latest $ECR_REGISTRY/$APP_NAME:$IMAGE_TAG
docker push $ECR_REGISTRY/$APP_NAME:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$APP_NAME:$IMAGE_TAG" >> $GITHUB_OUTPUT
Loading