Skip to content

Fix runs-on image for build_arm64 #11

Fix runs-on image for build_arm64

Fix runs-on image for build_arm64 #11

name: Continuous Deployment (Docker multi-arch)
on:
push:
branches: [ main, add-ci-cd ]
tags: ['v*', 'v*.*', 'v*.*.*']
pull_request:
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ${{ github.repository_owner }}/pyigmap
SERVICES_CSV: fastp
permissions:
contents: read
packages: write
id-token: write
jobs:
matrix:
name: Prepare services matrix
runs-on: ubuntu-24.04
outputs:
services: ${{ steps.mkjson.outputs.services }}
steps:
- name: Expand SERVICES_CSV -> JSON
id: mkjson
run: |
IFS=',' read -ra arr <<< "${SERVICES_CSV}"
printf '{"service":[%s]}\n' "$(printf '"%s",' "${arr[@]}" | sed 's/,$//')" > services.json
echo "services=$(cat services.json)" >> "$GITHUB_OUTPUT"
precheck:
name: Precheck version existence
needs: matrix
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix.outputs.services) }}
outputs:
skip: ${{ steps.out.outputs.skip }}
version: ${{ steps.out.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Parse version from pyproject.toml
id: get_ver
run: |
set -euo pipefail
FILE="./bin/${{ matrix.service }}/pyproject.toml"
VERSION=""
if [[ -f "$FILE" ]]; then
VERSION=$(awk '
/^\[project\]/ { in_proj=1; next }
in_proj && $0 ~ /^version[[:space:]]*=/ {
match($0, /"([^"]+)"/, m); if (m[1]!="") { print m[1]; exit }
}' "$FILE" || true)
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Detected version: ${VERSION:-<empty>}"
- name: Login to GHCR
if: steps.get_ver.outputs.version != ''
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Check tag existence in GHCR
id: exist
run: |
set -euo pipefail
if [[ -z "${{ steps.get_ver.outputs.version }}" ]]; then
echo "exists=false" >> "$GITHUB_OUTPUT"
exit 0
fi
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.service }}:${{ steps.get_ver.outputs.version }}"
if docker buildx imagetools inspect "${IMAGE}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
echo "Checked ${IMAGE}: exists=${{ steps.exist.outputs.exists }}"
- name: Expose outputs
id: out
run: |
SKIP=$([[ "${{ steps.exist.outputs.exists }}" == "true" ]] && echo true || echo false)
echo "skip=$SKIP" >> "$GITHUB_OUTPUT"
echo "version=${{ steps.get_ver.outputs.version }}" >> "$GITHUB_OUTPUT"
build_amd64:
name: Build & push (amd64)
needs: [matrix, precheck]
if: needs.precheck.outputs.skip != 'true'
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix.outputs.services) }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata (amd64 tags) — без branch tag
id: meta_amd
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.service }}
tags: |
type=raw,value=${{ needs.precheck.outputs.version }},enable=${{ needs.precheck.outputs.version != '' }}
type=sha
type=semver,pattern={{version}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
flavor: |
suffix=-amd64
- name: Build & push image (amd64)
uses: docker/build-push-action@v6
with:
context: ./bin/${{ matrix.service }}
file: ./bin/${{ matrix.service }}/Dockerfile
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta_amd.outputs.tags }}
labels: ${{ steps.meta_amd.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
sbom: false
build_arm64:
name: Build & push (arm64)
needs: [matrix, precheck]
if: needs.precheck.outputs.skip != 'true'
runs-on: ubuntu-24.04-arm
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix.outputs.services) }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata (arm64 tags)
id: meta_arm
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.service }}
tags: |
type=raw,value=${{ needs.precheck.outputs.version }},enable=${{ needs.precheck.outputs.version != '' }}
type=sha
type=semver,pattern={{version}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
flavor: |
suffix=-arm64
- name: Build & push image (arm64)
uses: docker/build-push-action@v6
with:
context: ./bin/${{ matrix.service }}
file: ./bin/${{ matrix.service }}/Dockerfile
platforms: linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta_arm.outputs.tags }}
labels: ${{ steps.meta_arm.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
sbom: false
manifest:
name: Assemble multi-arch manifest
needs: [matrix, precheck, build_amd64, build_arm64]
if: github.event_name != 'pull_request' && needs.precheck.outputs.skip != 'true'
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix.outputs.services) }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata (final tags)
id: meta_final
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.service }}
tags: |
type=raw,value=${{ needs.precheck.outputs.version }},enable=${{ needs.precheck.outputs.version != '' }}
type=sha
type=semver,pattern={{version}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
- name: Create multi-arch manifest using buildx imagetools
env:
TAGS: ${{ steps.meta_final.outputs.tags }}
run: |
set -euo pipefail
echo "$TAGS" | tr ' ' '\n' | while read -r TARGET; do
[ -z "$TARGET" ] && continue
BASE="${TARGET%:*}"
TAG="${TARGET##*:}"
AMD="${BASE}:${TAG}-amd64"
ARM="${BASE}:${TAG}-arm64"
echo "Creating manifest ${TARGET} from:"
echo " - ${AMD}"
echo " - ${ARM}"
docker buildx imagetools create \
--tag "${TARGET}" \
"${AMD}" \
"${ARM}"
docker buildx imagetools inspect "${TARGET}"
done