Skip to content

Build and Push Release Docker Image #53

Build and Push Release Docker Image

Build and Push Release Docker Image #53

name: Build and Push Release Docker Image
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version (e.g. 1.0.0)'
required: true
default: ''
trigger_app_release:
description: 'Trigger app release simultaneously'
type: boolean
default: true
set_latest:
description: 'Set Docker image as latest tag'
type: boolean
default: true
permissions:
contents: write
packages: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
update-version:
name: Update Project Version
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set Git User
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "[email protected]"
- name: Get Version
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.version }}" != "" ]]; then
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
else
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
fi
echo "Trigger app version release: ${{ env.VERSION }}"
echo "Version value: ${{ env.VERSION }}"
- name: Update package.json Version
run: |
# Get current version from package.json
CURRENT_VERSION=$(jq -r '.version' package.json)
# Only update if versions are different
if [ "$CURRENT_VERSION" != "${{ env.VERSION }}" ]; then
# Update version using jq
jq '.version = "${{ env.VERSION }}"' package.json > package.json.tmp
mv package.json.tmp package.json
# Commit changes
git add package.json
git commit -m "chore: Update version to ${{ env.VERSION }}"
git pull --rebase origin ${GITHUB_REF}
git push origin HEAD:${GITHUB_REF}
else
echo "Version ${{ env.VERSION }} already set in package.json, skipping update"
fi
build:
needs: update-version
strategy:
matrix:
include:
- platform: linux/amd64
os: ubuntu-latest
- platform: linux/arm64
os: ubuntu-24.04-arm
runs-on: ${{ matrix.os }}
name: Build ${{ matrix.platform }} Image
permissions:
contents: read
packages: write
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.version }}" != "" ]]; then
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
else
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
fi
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Pull latest changes
run: |
git pull origin ${{ github.ref_name }}
- name: Verify package.json version
run: |
PACKAGE_VERSION=$(jq -r '.version' package.json)
echo "Package.json version: $PACKAGE_VERSION"
echo "Expected version: ${{ env.VERSION }}"
if [ "$PACKAGE_VERSION" != "${{ env.VERSION }}" ]; then
echo "::error::Package.json version ($PACKAGE_VERSION) does not match expected version (${{ env.VERSION }})"
exit 1
fi
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
blinkospace/blinko
ghcr.io/blinkospace/blinko
tags: |
type=raw,value=${{ env.VERSION }}
flavor: |
latest=${{ github.event_name != 'workflow_dispatch' || github.event.inputs.set_latest == 'true' }}
labels: |
org.opencontainers.image.version=${{ env.VERSION }}
org.opencontainers.image.created=${{ env.BUILD_DATE }}
- name: Build and export
id: build
uses: docker/build-push-action@v5
with:
platforms: ${{ matrix.platform }}
context: ./
file: dockerfile
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=${{ github.workflow }}-${{ matrix.platform }}
cache-to: type=gha,scope=${{ github.workflow }}-${{ matrix.platform }},mode=max
outputs: type=image,name=blinkospace/blinko,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
rm -rf /tmp/digests
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: digest-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Merge and Push Multi-Architecture Image
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Pull latest changes
run: |
git pull origin ${{ github.ref_name }}
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digest-*
merge-multiple: true
- name: Extract version
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.version }}" != "" ]]; then
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
else
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
fi
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
blinkospace/blinko
ghcr.io/blinkospace/blinko
tags: |
type=raw,value=${{ env.VERSION }}
flavor: |
latest=${{ github.event_name != 'workflow_dispatch' || github.event.inputs.set_latest == 'true' }}
labels: |
org.opencontainers.image.version=${{ env.VERSION }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'blinkospace/blinko@sha256:%s ' *)
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON" | sed 's/blinkospace\/blinko/ghcr.io\/blinkospace\/blinko/g') \
$(printf 'blinkospace/blinko@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect blinkospace/blinko:${{ env.VERSION }}
docker buildx imagetools inspect ghcr.io/blinkospace/blinko:${{ env.VERSION }}
trigger-app-release:
name: Trigger App Build Release
needs: update-version
# Only run when manually triggered and app release trigger option selected
if: github.event_name == 'workflow_dispatch' && github.event.inputs.trigger_app_release == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Get Version
run: |
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
else
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
fi
echo "Trigger app version release: ${{ env.VERSION }}"
- name: Trigger App Release Workflow
id: dispatch
uses: peter-evans/repository-dispatch@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
event-type: trigger-app-release
client-payload: |
{
"tag": "${{ env.VERSION }}",
"version": "${{ env.VERSION }}",
"sha": "${{ github.sha }}"
}
continue-on-error: true
- name: Check Dispatch Result
if: steps.dispatch.outcome == 'failure'
run: |
echo "::warning::Failed to trigger app release workflow. This might be due to permission issues."
echo "::warning::Please ensure the GITHUB_TOKEN has 'workflow' permission enabled in repository settings."
echo "::warning::Alternatively, you can manually trigger the app-release workflow with version: ${{ env.VERSION }}"