Skip to content

Build and Push Docker Image #10

Build and Push Docker Image

Build and Push Docker Image #10

Workflow file for this run

# .github/workflows/docker-build.yml
name: Build and Push Docker Image
on:
push:
tags:
- 'v*'
release:
types: [published]
workflow_dispatch:
inputs:
tag_override:
description: 'Override tag (optional)'
required: false
type: string
force_build:
description: 'Force build even if repository is private'
required: false
type: boolean
default: false
build_strategy:
description: 'Build strategy'
required: false
type: choice
default: 'buildx-multi'
options:
- 'buildx-multi'
- 'buildx-single'
- 'legacy'
env:
REGISTRY: ghcr.io
jobs:
check-repository-visibility:
runs-on: ubuntu-latest
outputs:
is_public: ${{ steps.check.outputs.is_public }}
should_build: ${{ steps.check.outputs.should_build }}
steps:
- name: Check if repository is public
id: check
run: |
REPO_INFO=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}")
IS_PRIVATE=$(echo "$REPO_INFO" | jq -r '.private')
if [ "$IS_PRIVATE" = "false" ]; then
echo "is_public=true" >> $GITHUB_OUTPUT
echo "should_build=true" >> $GITHUB_OUTPUT
echo "Repository is public - proceeding with Docker build"
elif [ "${{ github.event.inputs.force_build }}" = "true" ]; then
echo "is_public=false" >> $GITHUB_OUTPUT
echo "should_build=true" >> $GITHUB_OUTPUT
echo "Repository is private but force_build is enabled - proceeding with Docker build"
else
echo "is_public=false" >> $GITHUB_OUTPUT
echo "should_build=false" >> $GITHUB_OUTPUT
echo "Repository is private - skipping Docker build"
fi
build-and-push:
needs: check-repository-visibility
if: needs.check-repository-visibility.outputs.should_build == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Convert repository name to lowercase
id: repo
run: echo "name=${GITHUB_REPOSITORY,,}" >> $GITHUB_OUTPUT
- name: Set up QEMU (for multi-platform builds)
if: github.event.inputs.build_strategy != 'legacy'
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
if: github.event.inputs.build_strategy != 'legacy'
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
network=host
buildkitd-flags: |
--allow-insecure-entitlement security.insecure
--allow-insecure-entitlement network.host
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}
labels: |
org.opencontainers.image.title=Changerawr
org.opencontainers.image.description=Ship, Change, Rawr 🦖 - Changelog management made cute and simple
org.opencontainers.image.vendor=Supernova3339
org.opencontainers.image.url=https://github.com/${{ github.repository }}
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.documentation=https://github.com/${{ github.repository }}#readme
- name: Determine final tags and build args
id: build_config
run: |
if [ -n "${{ github.event.inputs.tag_override }}" ]; then
echo "tags=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}:${{ github.event.inputs.tag_override }}" >> $GITHUB_OUTPUT
else
echo "tags=${{ steps.meta.outputs.tags }}" >> $GITHUB_OUTPUT
fi
# Set build args
echo "buildtime=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}" >> $GITHUB_OUTPUT
echo "version=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" >> $GITHUB_OUTPUT
echo "revision=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}" >> $GITHUB_OUTPUT
# Strategy 1: Multi-platform buildx (default)
- name: Build and push Docker image (Multi-platform)
if: github.event.inputs.build_strategy == 'buildx-multi' || github.event.inputs.build_strategy == ''
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.build_config.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILDTIME=${{ steps.build_config.outputs.buildtime }}
VERSION=${{ steps.build_config.outputs.version }}
REVISION=${{ steps.build_config.outputs.revision }}
provenance: false
sbom: false
# Strategy 2: Single platform buildx (fallback)
- name: Build and push Docker image (Single platform)
if: github.event.inputs.build_strategy == 'buildx-single'
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.build_config.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILDTIME=${{ steps.build_config.outputs.buildtime }}
VERSION=${{ steps.build_config.outputs.version }}
REVISION=${{ steps.build_config.outputs.revision }}
provenance: false
sbom: false
# Strategy 3: Legacy docker build (last resort)
- name: Build Docker image (Legacy)
if: github.event.inputs.build_strategy == 'legacy'
run: |
# Get the first tag for legacy build
FIRST_TAG=$(echo "${{ steps.build_config.outputs.tags }}" | head -n1)
docker build \
--build-arg BUILDTIME="${{ steps.build_config.outputs.buildtime }}" \
--build-arg VERSION="${{ steps.build_config.outputs.version }}" \
--build-arg REVISION="${{ steps.build_config.outputs.revision }}" \
--tag "$FIRST_TAG" \
--file ./Dockerfile \
.
- name: Push Docker image (Legacy)
if: github.event.inputs.build_strategy == 'legacy'
run: |
# Push all tags for legacy build
echo "${{ steps.build_config.outputs.tags }}" | while IFS= read -r tag; do
if [ -n "$tag" ]; then
echo "Pushing $tag"
docker push "$tag"
fi
done
- name: Generate image summary
run: |
echo "## Docker Image Built Successfully! 🦖" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.check-repository-visibility.outputs.is_public }}" = "false" ]; then
echo "⚠️ **Note:** Build was forced for private repository" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
fi
BUILD_STRATEGY="${{ github.event.inputs.build_strategy }}"
if [ -z "$BUILD_STRATEGY" ]; then
BUILD_STRATEGY="buildx-multi"
fi
echo "**Build Strategy:** $BUILD_STRATEGY" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.build_config.outputs.tags }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$BUILD_STRATEGY" = "legacy" ]; then
echo "**Platforms:** linux/amd64" >> $GITHUB_STEP_SUMMARY
elif [ "$BUILD_STRATEGY" = "buildx-single" ]; then
echo "**Platforms:** linux/amd64" >> $GITHUB_STEP_SUMMARY
else
echo "**Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Pull Command:**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "docker pull ${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}:latest" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
skip-build:
needs: check-repository-visibility
if: needs.check-repository-visibility.outputs.should_build == 'false'
runs-on: ubuntu-latest
steps:
- name: Skip build notification
run: |
echo "## Build Skipped 🔒" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Docker image build was skipped because this repository is private." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**To enable Docker builds:**" >> $GITHUB_STEP_SUMMARY
echo "1. Make the repository public, or" >> $GITHUB_STEP_SUMMARY
echo "2. Run workflow manually with 'Force build' option enabled, or" >> $GITHUB_STEP_SUMMARY
echo "3. Modify the workflow to allow private builds by default" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Repository:** \`${{ github.repository }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Trigger:** \`${{ github.event_name }}\`" >> $GITHUB_STEP_SUMMARY