surrealpatch/.github/workflows/reusable_docker.yml

370 lines
13 KiB
YAML
Raw Normal View History

on:
workflow_call:
inputs:
git-ref:
required: true
type: string
description: "The github ref to checkout for building the Docker images."
tag-prefix:
required: true
type: string
description: "The prefix of the Docker image tag. i.e. 'nightly' for 'surrealdb/surrealdb:nightly-dev' or 'surrealdb/surrealdb:nightly-fdb'."
build:
required: false
type: boolean
default: true
description: "Build the Docker images."
push:
required: false
type: boolean
default: false
description: "Publish the Docker images."
latest:
required: false
type: boolean
default: false
description: "Update the latest tag of the Docker image."
secrets:
DOCKER_USER:
required: false
DOCKER_PASS:
required: false
AWS_CI_ACCESS_KEY_ID:
required: false
AWS_CI_SECRET_ACCESS_KEY:
required: false
defaults:
run:
shell: bash
jobs:
prepare:
name: Prepare steps
runs-on: ubuntu-latest
outputs:
with-ecr: ${{ steps.aws-credentials.outputs.with-ecr }}
tag-prefix: ${{ steps.tag-prefix.outputs.tag-prefix }}
build-matrix: ${{ steps.set-matrix.outputs.build-matrix }}
push-matrix: ${{ steps.set-matrix.outputs.push-matrix }}
steps:
- name: Check if AWS credentials are set
id: aws-credentials
run: |
if [[ "${{ secrets.AWS_CI_ACCESS_KEY_ID }}" == "" ]]; then
echo "###"
echo "### AWS credentials are not set. Will skip any AWS ECR action."
echo "###"
echo "with-ecr=false" >> $GITHUB_OUTPUT
else
echo "with-ecr=true" >> $GITHUB_OUTPUT
fi
- name: Sanitize tag name
id: tag-prefix
run: |
echo "tag-prefix=$(echo '${{ inputs.tag-prefix }}' | sed 's/[^a-zA-Z0-9_.-]/-/g' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
# Define matrix here so we don't need to search for it when making changes
- name: Set matrix
id: set-matrix
env:
BUILD_MATRIX: |
include:
########
# Binary image
########
- name: Binary image
dockerfile: Dockerfile.binary
platform: amd64
runner: ["self-hosted", "amd64", "builder"]
tag: amd64-${{ steps.tag-prefix.outputs.tag-prefix }}-binary
########################################
# Base images
########################################
# Prod AMD64 image
- &base_image
name: Base image
dockerfile: Dockerfile
build-target: prod
platform: amd64
runner: ["self-hosted", "amd64", "builder"]
tag: amd64-${{ steps.tag-prefix.outputs.tag-prefix }}
# Prod ARM64 image
- <<: *base_image
platform: arm64
runner: ["self-hosted", "arm64", "builder"]
tag: arm64-${{ steps.tag-prefix.outputs.tag-prefix }}
# Dev AMD64 image
- <<: *base_image
build-target: dev
tag: amd64-${{ steps.tag-prefix.outputs.tag-prefix }}-dev
# Dev ARM64 image
- <<: *base_image
build-target: dev
platform: arm64
runner: ["self-hosted", "arm64", "builder"]
tag: arm64-${{ steps.tag-prefix.outputs.tag-prefix }}-dev
########################################
# FoundationDB images (FDB client library is only available for amd64)
########################################
# Prod AMD64 image
- &fdb_image
name: FDB image
dockerfile: Dockerfile.fdb
build-target: prod
platform: amd64
runner: ["self-hosted", "amd64", "builder"]
tag: amd64-${{ steps.tag-prefix.outputs.tag-prefix }}-fdb
# Dev AMD64 image
- <<: *fdb_image
build-target: dev
tag: amd64-${{ steps.tag-prefix.outputs.tag-prefix }}-fdb-dev
PUSH_MATRIX: |
include:
########################################
# Base images
########################################
# Prod images
- &base_image
platforms: linux/amd64,linux/arm64
tag: ${{ steps.tag-prefix.outputs.tag-prefix }}
tag-latest: latest
# Dev images
- <<: *base_image
platforms: linux/amd64,linux/arm64
tag: ${{ steps.tag-prefix.outputs.tag-prefix }}-dev
tag-latest: latest-dev
# TODO: Decide whether or not we want a dedicated image for FoundationDB
# ########################################
# # FoundationDB images (FDB client library is only available for amd64)
# ########################################
# # Prod images
# - &fdb_image
# platforms: linux/amd64
# tag: ${{ steps.tag-prefix.outputs.tag-prefix }}-fdb
# tag-latest: latest-fdb
# # Dev images
# - <<: *fdb_image
# tag: ${{ steps.tag-prefix.outputs.tag-prefix }}-fdb-dev
# tag-latest: latest-fdb-dev
run: |
echo '${{ env.BUILD_MATRIX }}' > build-matrix.yaml
echo "build-matrix=$(yq -o json -I=0 build-matrix.yaml)" >> $GITHUB_OUTPUT
echo '${{ env.PUSH_MATRIX }}' > push-matrix.yaml
echo "push-matrix=$(yq -o json -I=0 push-matrix.yaml)" >> $GITHUB_OUTPUT
build:
name: Build ${{ matrix.name }} (${{ matrix.build-target || 'default' }}, ${{ matrix.platform }})
runs-on: ${{ matrix.runner }}
needs: prepare
if: ${{ inputs.build }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare.outputs.build-matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.git-ref }}
- name: Checkout docker
uses: actions/checkout@v4
with:
path: _docker
# Replace docker files. It allows us to test new Dockerfiles with workflow_dispatch and a custom git ref.
# When triggered by a push or a schedule, this git ref will be the same as 'inputs.git-ref'
- name: Replace docker files
env:
GH_TOKEN: ${{ github.token }}
run: |
rm -rf docker .dockerignore
mv _docker/docker .
mv _docker/.dockerignore .
rm -rf _docker
- name: Cleanup
if: ${{ always() }}
run: |
set -x
set +e # Don't fail, do what we can
docker system prune -f
docker image prune -a -f
docker image ls
docker ps -a
df -h
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- name: Build and export to Docker.
uses: docker/build-push-action@v5
id: build
with:
context: .
load: true
platforms: linux/${{ matrix.platform }}
file: docker/${{ matrix.dockerfile }}
target: ${{ matrix.build-target }}
tags: surrealdb-ci:${{ matrix.tag }}-${{ github.run_id }}
# Start the docker image as server and wait until it is ready
- name: Test the Docker image
run: |
docker run --net=host --rm ${{ steps.build.outputs.imageid }} start 2>&1 >surreal.log &
retries=5
until docker run --net=host --rm ${{ steps.build.outputs.imageid }} is-ready; do
retries=$((retries-1))
if [[ $retries -eq 0 ]]; then
echo "###"
echo "### The container is not ready after 5 seconds!"
echo "###"
cat surreal.log
echo "###"
echo "### ERROR: The docker image is not valid. Aborting."
echo "###"
exit 1
fi
sleep 1
done
- name: Configure AWS credentials
if: ${{ needs.prepare.outputs.with-ecr == 'true' }}
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_CI_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
if: ${{ needs.prepare.outputs.with-ecr == 'true' }}
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Push individual images to CI registry.
if: ${{ needs.prepare.outputs.with-ecr == 'true' }}
run: |
docker tag ${{ steps.build.outputs.imageid }} ${{ steps.login-ecr.outputs.registry }}/surrealdb-ci:${{ matrix.tag }}-${{ github.run_id }}
docker push ${{ steps.login-ecr.outputs.registry }}/surrealdb-ci:${{ matrix.tag }}-${{ github.run_id }}
- name: Cleanup
if: ${{ always() }}
run: |
set -x
set +e # Don't fail, do what we can
docker system prune -f
docker image rm ${{ steps.build.outputs.imageid }}
docker image rm ${{ steps.login-ecr.outputs.registry }}/surrealdb-ci:${{ matrix.tag }}-${{ github.run_id }}
docker system prune -f
docker image ls
docker ps -a
df -h
# Push a multi-arch manifest to the CI registry
push-all-to-ecr-ci:
name: Push ${{ matrix.tag }} to CI registry
runs-on: ubuntu-latest
needs: [prepare, build]
if: ${{ inputs.build && needs.prepare.outputs.with-ecr == 'true' }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare.outputs.push-matrix) }}
steps:
# Checkout the workflow code, we don't need the code to build SurrealDB, that's why we don't checkout "input.git-ref" here
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_CI_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Push multi-arch Docker manifest to CI registry
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile.multi-arch
platforms: ${{ matrix.platforms }}
push: true
tags: ${{ steps.login-ecr.outputs.registry }}/surrealdb-ci:${{ matrix.tag }}
build-args: |
IMAGE_REPO=${{ steps.login-ecr.outputs.registry }}/surrealdb-ci
TAG=${{ matrix.tag }}-${{ github.run_id }}
# Push a multi-arch manifest to DockerHub
push-all-to-dockerhub:
name: Push ${{ matrix.tag }} to DockerHub
runs-on: ubuntu-latest
needs: [prepare]
if: ${{ inputs.push }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare.outputs.push-matrix) }}
steps:
# Checkout the workflow code, we don't need the code to build SurrealDB, that's why we don't checkout "input.git-ref" here
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_CI_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_CI_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Configure DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
- name: Push multi-arch Docker manifest to DockerHub
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile.multi-arch
platforms: ${{ matrix.platforms }}
push: true
tags: surrealdb/surrealdb:${{ matrix.tag }}
build-args: |
IMAGE_REPO=${{ steps.login-ecr.outputs.registry }}/surrealdb-ci
TAG=${{ matrix.tag }}-${{ github.run_id }}
- name: Tag multi-arch Docker manifest as latest
uses: docker/build-push-action@v5
if: ${{ inputs.latest }}
with:
context: .
file: ./docker/Dockerfile.multi-arch
platforms: ${{ matrix.platforms }}
push: true
tags: surrealdb/surrealdb:${{ matrix.tag-latest }}
build-args: |
IMAGE_REPO=${{ steps.login-ecr.outputs.registry }}/surrealdb-ci
TAG=${{ matrix.tag }}-${{ github.run_id }}