Skip to content

Merge pull request #15 from BICEP-Pump/feature/ghcrio #16

Merge pull request #15 from BICEP-Pump/feature/ghcrio

Merge pull request #15 from BICEP-Pump/feature/ghcrio #16

Workflow file for this run

name: Build and Push to GHCR
on:
pull_request:
branches: [ dev, main ]
types: [ closed ]
push:
branches: [ dev, main ]
workflow_dispatch:
inputs:
target_branch:
description: Branch to rebuild and publish to GHCR
required: true
default: main
type: choice
options:
- main
- dev
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
# Run for merged PRs, direct pushes to tracked branches, or manual dispatch.
if: (github.event_name == 'pull_request' && github.event.pull_request.merged == true) || github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.target_branch || github.ref }}
fetch-depth: 0 # Needed to read branch history and push VERSION updates
- name: Lowercase IMAGE_NAME
id: lowercase_image
run: |
echo "IMAGE_NAME_LOWER=${GITHUB_REPOSITORY,,}" >> $GITHUB_OUTPUT
- name: Calculate New Version
id: versioning
shell: bash
run: |
set -euo pipefail
normalize_version() {
local version="${1#v}"
version="${version%-dev}"
version="${version%%-*}"
IFS='.' read -r -a parts <<< "$version"
while [[ "${#parts[@]}" -lt 3 ]]; do
parts+=(0)
done
printf '%s.%s.%s\n' "${parts[0]}" "${parts[1]}" "${parts[2]}"
}
version_tag() {
printf 'v%s\n' "$(normalize_version "$1")"
}
dev_version_tag() {
printf '%s-dev\n' "$(version_tag "$1")"
}
bump_version() {
local current="$1"
local part="$2"
local normalized
local major
local minor
local patch
normalized="$(normalize_version "$current")"
IFS='.' read -r major minor patch <<< "$normalized"
case "$part" in
major)
((major += 1))
minor=0
patch=0
;;
minor)
((minor += 1))
patch=0
;;
patch)
((patch += 1))
;;
*)
echo "Unsupported bump type: $part" >&2
exit 1
;;
esac
printf '%s.%s.%s\n' "$major" "$minor" "$patch"
}
read_version() {
tr -d '[:space:]' < "$1"
}
read_version_from_ref() {
local ref="$1"
git show "${ref}:VERSION" | tr -d '[:space:]'
}
get_bump_type() {
local branch="$1"
case "$branch" in
release/*|major/*)
echo "major"
;;
feature/*|feat/*|minor/*)
echo "minor"
;;
hotfix/*|fix/*|bugfix/*|patch/*)
echo "patch"
;;
*)
echo "patch"
;;
esac
}
resolve_branch_version() {
local branch="$1"
local current="$2"
local explicit_version=""
if [[ "$branch" =~ ^release/v?([0-9]+(\.[0-9]+){0,2})$ ]]; then
explicit_version="${BASH_REMATCH[1]}"
normalize_version "$explicit_version"
return 0
fi
bump_version "$current" "$(get_bump_type "$branch")"
}
CURRENT_VER="$(normalize_version "$(read_version VERSION)")"
NEW_VER="$CURRENT_VER"
DOCKER_TAG="$(version_tag "$CURRENT_VER")"
TARGET_BRANCH="${{ github.event.inputs.target_branch || github.ref_name }}"
PUSH_BRANCH="$TARGET_BRANCH"
SHOULD_COMMIT_VERSION="false"
TAG_LATEST="false"
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
BASE_BRANCH="${{ github.event.pull_request.base.ref }}"
SOURCE_BRANCH="${{ github.event.pull_request.head.ref }}"
SOURCE_SHA="${{ github.event.pull_request.head.sha }}"
PUSH_BRANCH="$BASE_BRANCH"
SHOULD_COMMIT_VERSION="true"
if [[ "$BASE_BRANCH" == "dev" ]]; then
NEW_VER="$(resolve_branch_version "$SOURCE_BRANCH" "$CURRENT_VER")"
DOCKER_TAG="$(dev_version_tag "$NEW_VER")"
elif [[ "$BASE_BRANCH" == "main" ]]; then
if [[ "$SOURCE_BRANCH" == "dev" ]]; then
if git cat-file -e "${SOURCE_SHA}:VERSION" 2>/dev/null; then
NEW_VER="$(normalize_version "$(read_version_from_ref "$SOURCE_SHA")")"
fi
else
NEW_VER="$(resolve_branch_version "$SOURCE_BRANCH" "$CURRENT_VER")"
fi
DOCKER_TAG="$(version_tag "$NEW_VER")"
TAG_LATEST="true"
else
echo "Unsupported pull request target branch: $BASE_BRANCH" >&2
exit 1
fi
elif [[ "$TARGET_BRANCH" == "dev" ]]; then
DOCKER_TAG="$(dev_version_tag "$CURRENT_VER")"
else
DOCKER_TAG="$(version_tag "$CURRENT_VER")"
if [[ "$TARGET_BRANCH" == "main" ]]; then
TAG_LATEST="true"
fi
fi
echo "NEW_VERSION=${NEW_VER}" >> "$GITHUB_OUTPUT"
echo "DOCKER_TAG=${DOCKER_TAG}" >> "$GITHUB_OUTPUT"
echo "PUSH_BRANCH=${PUSH_BRANCH}" >> "$GITHUB_OUTPUT"
echo "SHOULD_COMMIT_VERSION=${SHOULD_COMMIT_VERSION}" >> "$GITHUB_OUTPUT"
echo "TAG_LATEST=${TAG_LATEST}" >> "$GITHUB_OUTPUT"
- name: Apply VERSION file
shell: bash
run: |
echo "${{ steps.versioning.outputs.NEW_VERSION }}" > VERSION
- name: Commit VERSION file
if: steps.versioning.outputs.SHOULD_COMMIT_VERSION == 'true'
shell: bash
run: |
set -euo pipefail
if git diff --quiet -- VERSION; then
exit 0
fi
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add VERSION
git commit -m "Bump version to ${{ steps.versioning.outputs.NEW_VERSION }} [skip ci]"
git push origin HEAD:${{ steps.versioning.outputs.PUSH_BRANCH }}
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare Docker tags
id: tags
shell: bash
run: |
IMAGE_REF="${{ env.REGISTRY }}/${{ steps.lowercase_image.outputs.IMAGE_NAME_LOWER }}"
{
echo "value<<EOF"
echo "${IMAGE_REF}:${{ steps.versioning.outputs.DOCKER_TAG }}"
if [[ "${{ steps.versioning.outputs.TAG_LATEST }}" == "true" ]]; then
echo "${IMAGE_REF}:latest"
fi
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.tags.outputs.value }}
labels: |
org.opencontainers.image.version=${{ steps.versioning.outputs.DOCKER_TAG }}