Added check_image_version job that verifies if Docker image already exists in registry using docker manifest inspect. This prevents redundant builds while handling registry cleanup scenarios. Also added explanatory comments above all jobs. Key changes: - New check_image_version job runs in parallel with check_version - Uses docker manifest inspect for lightweight image existence check - Build now uses OR logic: version changed OR image missing OR PR - Both check jobs run independently for faster parallel execution - Added comments explaining each job's purpose and build conditions Build logic: - Builds when version changed (new release) - Builds when image missing from registry (handles cleanup) - Always builds PRs (validation requirement) - Skips only when version unchanged AND image exists Benefits: - Comprehensive checking of both git history and registry state - Handles registry cleanup without manual intervention - Clear documentation of workflow logic - Parallel job execution for faster workflow runs Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
150 lines
5.9 KiB
YAML
150 lines
5.9 KiB
YAML
name: Build and Push Docker Image
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
- main
|
|
pull_request:
|
|
branches:
|
|
- master
|
|
- main
|
|
|
|
jobs:
|
|
# Detects version changes in package.json compared to previous commit
|
|
# Outputs the current version and whether it changed from the last commit
|
|
# This is used to determine if a new release/build is needed
|
|
check_version:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
version_changed: ${{ steps.version-check.outputs.version_changed }}
|
|
version: ${{ steps.version-check.outputs.version }}
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Check if version changed
|
|
id: version-check
|
|
run: |
|
|
# Get current version
|
|
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
echo "Current version: $CURRENT_VERSION"
|
|
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
|
|
# Check if HEAD~1 exists (handle first commit)
|
|
if ! git rev-parse HEAD~1 &>/dev/null; then
|
|
echo "First commit detected, running workflow"
|
|
echo "version_changed=true" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
fi
|
|
|
|
# Check if package.json exists in previous commit
|
|
if ! git show HEAD~1:package.json &>/dev/null; then
|
|
echo "package.json doesn't exist in previous commit"
|
|
echo "version_changed=true" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
fi
|
|
|
|
# Extract previous version using grep/sed (safer than node for old file)
|
|
PREVIOUS_VERSION=$(git show HEAD~1:package.json | grep '"version"' | head -1 | sed -E 's/.*"version"\s*:\s*"([^"]+)".*/\1/')
|
|
echo "Previous version: $PREVIOUS_VERSION"
|
|
|
|
# Compare versions
|
|
if [ "$CURRENT_VERSION" != "$PREVIOUS_VERSION" ]; then
|
|
echo "Version changed: $PREVIOUS_VERSION -> $CURRENT_VERSION"
|
|
echo "version_changed=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Version unchanged: $CURRENT_VERSION"
|
|
echo "version_changed=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
# Verifies if Docker image with current version already exists in registry
|
|
# This prevents rebuilding the same version but allows pulls and version changes
|
|
# to always trigger new builds. Uses lightweight manifest inspect (no download)
|
|
check_image_version:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
image_exists: ${{ steps.manifest-check.outputs.image_exists }}
|
|
version: ${{ steps.version-read.outputs.version }}
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Read version from package.json
|
|
id: version-read
|
|
run: |
|
|
VERSION=$(node -p "require('./package.json').version")
|
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
echo "Checking for image version: $VERSION"
|
|
|
|
- name: Login to Registry
|
|
run: |
|
|
echo "${{ secrets.PROFILE_REGISTRY_TOKEN }}" | docker login registry.budakova.org -u "${{ vars.PROFILE_REGISTRY_USERNAME }}" --password-stdin
|
|
|
|
- name: Check if image exists in registry
|
|
id: manifest-check
|
|
run: |
|
|
VERSION=${{ steps.version-read.outputs.version }}
|
|
IMAGE="registry.budakova.org/knee-cola/gitea-actions-demo-project:${VERSION}"
|
|
|
|
echo "Checking manifest for image: $IMAGE"
|
|
|
|
if docker manifest inspect "$IMAGE" &>/dev/null; then
|
|
echo "Image exists in registry"
|
|
echo "image_exists=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Image does not exist in registry"
|
|
echo "image_exists=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Summary
|
|
run: |
|
|
echo "Version: ${{ steps.version-read.outputs.version }}"
|
|
echo "Image exists: ${{ steps.manifest-check.outputs.image_exists }}"
|
|
|
|
# Builds and pushes Docker image to registry if conditions are met:
|
|
# - Version changed in package.json, OR
|
|
# - Image with current version doesn't exist in registry, OR
|
|
# - This is a pull request (always validate PRs)
|
|
# This ensures releases are built, missing images are created, and PRs are tested
|
|
build:
|
|
needs: [check_version, check_image_version]
|
|
if: |
|
|
needs.check_version.outputs.version_changed == 'true' ||
|
|
needs.check_image_version.outputs.image_exists == 'false' ||
|
|
github.event_name == 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Registry
|
|
# Gitea automatically provides these secrets:
|
|
# - `vars.REGISTRY_USERNAME` - defined as action variable in **repo settings**
|
|
# - `secrets.REGISTRY_TOKEN` - defined as action secret in **repo settings**
|
|
# created in user settings as personal access token with `write:packages` scope
|
|
# - `vars.PROFILE_REGISTRY_USERNAME` - defined as action variable in **profile settings**
|
|
# - `secrets.PROFILE_REGISTRY_TOKEN` - defined as action secret in **profile settings**
|
|
# created in user settings as personal access token with `write:packages` scope
|
|
run: |
|
|
echo "${{ secrets.PROFILE_REGISTRY_TOKEN }}" | docker login registry.budakova.org -u "${{ vars.PROFILE_REGISTRY_USERNAME }}" --password-stdin
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
push: true
|
|
tags: |
|
|
registry.budakova.org/knee-cola/gitea-actions-demo-project:${{ needs.check_version.outputs.version }}
|
|
registry.budakova.org/knee-cola/gitea-actions-demo-project:latest
|
|
cache-from: type=registry,ref=registry.budakova.org/knee-cola/gitea-actions-demo-project:buildcache
|
|
cache-to: type=registry,ref=registry.budakova.org/knee-cola/gitea-actions-demo-project:buildcache,mode=max
|