Skip to content

Commit

Permalink
ci: add CI/CD workflows (#5)
Browse files Browse the repository at this point in the history
* ci: add CI/CD workflows

* ci: add PHP 8 example

* ci: merge lint and build jobs

* ci: add CD workflow

* ci: test the CD workflow

* ci: remove `release-type`

* ci: test mono-repo releases

* ci: add multiple release-please PRs

* ci: revert release matrix

* ci: always build Docker images on release

* ci: remove `if` to run the rest of CD

* ci: tweak logic when CD workflows run

* ci: limit file patterns in orchestrator

* ci: trigger CI

* ci: remove `files` and include everything

* ci: update registry and signer key id

* ci: fix OIDC role

* ci: fix orchestrator

* ci: trigger CI

* ci: remove debug lines

* ci: add README instructions

* ci: test `files_ignore` new pattern

* ci: update `files_ignore` pattern

* ci: remove branch CD label
  • Loading branch information
JoshuaLicense authored Apr 15, 2024
1 parent 640fcc4 commit 14904eb
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 0 deletions.
75 changes: 75 additions & 0 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: CD

on:
push:
branches:
- main

permissions:
contents: read

jobs:
release-please:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
tag_name: ${{ steps.release.outputs.tag_name }}
release_created: ${{ steps.release.outputs.release_created }}
steps:
- uses: google-github-actions/release-please-action@v4
id: release
with:
release-type: simple
target-branch: ${{ github.ref_name }}

orchestrator:
name: Orchestrator
runs-on: ubuntu-latest
needs:
- release-please
outputs:
changed-directories: ${{ steps.changed-directories.outputs.all_changed_and_modified_files_count > 0 && steps.changed-directories.outputs.all_changed_files || null }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: tj-actions/changed-files@v44
id: changed-directories
with:
files_ignore: |
.github/**
README.md
CHANGELOG.md
.editorconfig
.gitignore
dir_names: true

docker:
name: Docker
if: ${{ needs.release-please.outputs.release_created || needs.orchestrator.outputs.changed-directories }}
concurrency:
group: docker-${{ matrix.base }}
needs:
- release-please
- orchestrator
strategy:
fail-fast: false
matrix:
base:
- php/7.4/fpm-nginx
- php/8.0/fpm-nginx
exclude:
- base: ${{ needs.release-please.outputs.release_created || contains(needs.orchestrator.outputs.changed-directories, 'php/7.4/fpm-nginx') && 'ignored' || 'php/7.4/fpm-nginx' }}
- base: ${{ needs.release-please.outputs.release_created || contains(needs.orchestrator.outputs.changed-directories, 'php/8.0/fpm-nginx') && 'ignored' || 'php/8.0/fpm-nginx' }}
uses: ./.github/workflows/docker.yaml
with:
version: ${{ needs.release-please.outputs.release_created && needs.release-please.outputs.tag_name || github.sha}}
local-path: ${{ matrix.base }}
repository: ${{ matrix.base }}
push: true
permissions:
contents: read
id-token: write
51 changes: 51 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
pull_request:

permissions:
contents: read

jobs:
orchestrator:
name: Orchestrator
runs-on: ubuntu-latest
outputs:
changed-directories: ${{ steps.changed-directories.outputs.all_changed_and_modified_files_count > 0 && steps.changed-directories.outputs.all_changed_files || null }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: tj-actions/changed-files@v44
id: changed-directories
with:
files_ignore: |
.github/**
README.md
CHANGELOG.md
.editorconfig
.gitignore
dir_names: true

docker:
name: Docker
if: ${{ needs.orchestrator.outputs.changed-directories }}
needs:
- orchestrator
strategy:
fail-fast: false
matrix:
base:
- php/7.4/fpm-nginx
- php/8.0/fpm-nginx
exclude:
- base: ${{ contains(needs.orchestrator.outputs.changed-directories, 'php/7.4/fpm-nginx') && 'ignored' || 'php/7.4/fpm-nginx' }}
- base: ${{ contains(needs.orchestrator.outputs.changed-directories, 'php/8.0/fpm-nginx') && 'ignored' || 'php/8.0/fpm-nginx' }}
uses: ./.github/workflows/docker.yaml
with:
version: ${{ github.event.pull_request.head.sha }}
local-path: ${{ matrix.base }}
repository: ${{ matrix.base }}
permissions:
contents: read
id-token: write
117 changes: 117 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Docker

on:
workflow_call:
inputs:
ref:
type: string
required: false
repository:
type: string
required: true
local-path:
type: string
required: true
version:
type: string
required: true
push:
type: boolean
default: false
is-release:
type: boolean
default: false

env:
AWS_OIDC_ROLE: ${{ inputs.push && vars.TF_OIDC_ROLE || vars.TF_OIDC_READONLY_ROLE }}
ECR_REGISTRY: 245185850403.dkr.ecr.eu-west-1.amazonaws.com
AWS_REGION: eu-west-1

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || null }}
sparse-checkout: ${{ inputs.local-path }}

- uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: ${{ inputs.local-path }}/Dockerfile

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

- name: Extract mutable Docker metadata
id: mutable-meta
uses: docker/metadata-action@v5
with:
images: ${{ env.ECR_REGISTRY }}/${{ inputs.repository }}
tags: |
type=raw,value=latest
type=semver,enable=${{ inputs.is-release }},pattern={{major}}.{{minor}},value=${{ inputs.version }}
type=semver,enable=${{ inputs.is-release }},pattern={{major}},value=${{ inputs.version }}
- name: Extract all Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.ECR_REGISTRY }}/${{ inputs.repository }}
tags: |
type=raw,value=latest
type=semver,enable=${{ inputs.is-release }},pattern={{major}}.{{minor}},value=${{ inputs.version }}
type=semver,enable=${{ inputs.is-release }},pattern={{major}},value=${{ inputs.version }}
type=semver,enable=${{ inputs.is-release }},pattern={{version}},value=${{ inputs.version }}
- name: Configure AWS credentials
if: ${{ inputs.push }}
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_OIDC_ROLE }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to ECR
if: ${{ inputs.push }}
uses: docker/login-action@v3
with:
registry: ${{ env.ECR_REGISTRY }}

- name: Untag mutable tags
if: ${{ inputs.push && steps.mutable-meta.outputs.tags }}
env:
MUTABLE_TAGS: ${{ steps.mutable-meta.outputs.tags }}
REPOSITORY: ${{ inputs.repository }}
run: |
for tag in $MUTABLE_TAGS; do
aws ecr batch-delete-image --repository-name $REPOSITORY --image-ids imageTag=$tag
done
- name: Build ${{ inputs.push && 'and push ' || '' }}Docker image
id: build-and-push
uses: docker/build-push-action@v5
with:
context: ${{ inputs.local-path }}
platforms: linux/amd64,linux/arm64
push: ${{ inputs.push }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Setup Notation CLI
if: ${{ inputs.push }}
uses: notaryproject/notation-action/setup@v1
with:
version: "1.1.0"

- name: Sign artefact
if: ${{ inputs.push }}
uses: notaryproject/notation-action/sign@v1
with:
plugin_name: com.amazonaws.signer.notation.plugin
plugin_url: https://d2hvyiie56hcat.cloudfront.net/linux/amd64/plugin/latest/notation-aws-signer-plugin.zip
plugin_checksum: cccfe8fdcdf853d83fd57ffc80524eddda75ad7ae9d9a257b087007230ec02f9
key_id: arn:aws:signer:eu-west-1:245185850403:/signing-profiles/base_image_signer20240410115736478500000001
target_artifact_reference: ${{ env.ECR_REGISTRY }}/${{ inputs.repository }}@${{ steps.build-and-push.outputs.digest }}
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
# DVSA Base Images
Docker Images for use in DVSA projects

## Adding a new base image

1. Create a new directory in the root of this repository with the name of the image you want to create. The convention is usually [language]/[version]/[flavour] e.g. `node/12/alpine`, `php/8.3/fpm-nginx` etc.

2. Create a `Dockerfile` in the directory you just created. This file should contain the instructions for building the image.

3. Update the `docker` job in `ci.yaml` and `cd.yaml` and update the matrix to add your new image. This ensures the image is build & pushed if it has changed (or during a new release).
```yaml
strategy:
fail-fast: false
matrix:
base:
# ...
- node/20/alpine
exclude:
# ...
- base: ${{ needs.release-please.outputs.release_created || contains(needs.orchestrator.outputs.changed-directories, 'node/20/alpine') && 'ignored' || 'node/20/alpine' }}
```

0 comments on commit 14904eb

Please sign in to comment.