Skip to content

Refactor Docker image build process in create_packages.yml #1700

Refactor Docker image build process in create_packages.yml

Refactor Docker image build process in create_packages.yml #1700

---
name: Create packages
on:
push:
tags:
- "v*" # Trigger on version tags
branches:
- "main"
- "master"
- "develop"
- "production"
- "test-prod"
paths-ignore:
- "**.md"
- "docs/**"
- ".gitignore"
- "LICENSE"
jobs:
changes:
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
main: ${{ steps.filter.outputs.main }}
r-api: ${{ steps.filter.outputs.r-api }}
steps:
- uses: actions/checkout@v3
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
frontend:
- 'frontend/**'
- '.docker/frontend'
main:
- 'app/**'
- '.docker/main'
r-api:
- 'R/**'
- '.docker/r-api'
build:
needs: changes
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Update tags.json version
uses: jossef/[email protected]
with:
file: frontend/src/tags.json
field: gitBranch
value: ${{github.ref_name}}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_PAT }}
- name: Prepare .docker files
run: |
for p in .docker/*.default ; do
mv "$p" "${p%.default}"
done
# Pull existing images for layer caching
- name: Pull existing images
run: |
# Sanitize branch name for docker tags
branch="${{ github.ref_name }}"
safe_branch="${branch//\//-}" # Replace / with -
for image in herdbook_r-api herdbook_main herdbook_frontend; do
docker pull "ghcr.io/nbisweden/$image:latest" || true
docker pull "ghcr.io/nbisweden/$image:$safe_branch" || true
done
# Build images using docker compose
- name: Build images
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
run: |
# Only build on production branch, tags will just retag existing images
if [[ "${{ github.ref_name }}" == "production" ]]; then
docker compose build --no-cache --build-arg BUILDKIT_INLINE_CACHE=1 herdbook-frontend main
elif [[ "${{ github.ref_type }}" != "tag" ]]; then
# For other branches (except tags), only build changed images and their dependents
if [[ "${{ needs.changes.outputs.frontend }}" == "true" ]]; then
docker compose build --build-arg BUILDKIT_INLINE_CACHE=1 herdbook-frontend main
elif [[ "${{ needs.changes.outputs.main }}" == "true" ]]; then
docker compose build --build-arg BUILDKIT_INLINE_CACHE=1 main
fi
if [[ "${{ needs.changes.outputs.r-api }}" == "true" ]]; then
docker compose build --build-arg BUILDKIT_INLINE_CACHE=1 r-api
fi
fi
# Push images
- name: Push images
run: |
# Sanitize branch name for docker tags
branch="${{ github.ref_name }}"
safe_branch="${branch//\//-}" # Replace / with -
# Function to push an image if it was built or if we're tagging
push_if_built() {
local image="$1"
local is_tag="${2:-false}"
# For tags, try to pull the production image first
if [[ "$is_tag" == "true" ]]; then
docker pull "ghcr.io/nbisweden/$image:production" || return 1
docker tag "ghcr.io/nbisweden/$image:production" "$image:latest"
fi
if docker image inspect "$image:latest" >/dev/null 2>&1; then
docker tag "$image:latest" "ghcr.io/nbisweden/$image:$safe_branch"
docker push "ghcr.io/nbisweden/$image:$safe_branch"
if [[ "${{ github.ref_type }}" == "tag" || "$branch" == "main" || "$branch" == "master" || "$branch" == "develop" || "$branch" == "production" || "$branch" == "test-prod" ]]; then
docker tag "$image:latest" "ghcr.io/nbisweden/$image:latest"
docker push "ghcr.io/nbisweden/$image:latest"
fi
fi
}
# For tags, retag production images. For production, push built images
if [[ "${{ github.ref_type }}" == "tag" ]]; then
push_if_built "herdbook_frontend" true
push_if_built "herdbook_main" true
elif [[ "${{ github.ref_name }}" == "production" ]]; then
push_if_built "herdbook_frontend"
push_if_built "herdbook_main"
else
# For other branches, push only the images that were built
if [[ "${{ needs.changes.outputs.frontend }}" == "true" ]]; then
push_if_built "herdbook_frontend"
fi
if [[ "${{ needs.changes.outputs.main }}" == "true" || "${{ needs.changes.outputs.frontend }}" == "true" ]]; then
push_if_built "herdbook_main"
fi
if [[ "${{ needs.changes.outputs.r-api }}" == "true" ]]; then
push_if_built "herdbook_r-api"
fi
fi