Merge pull request #15 from BICEP-Pump/feature/ghcrio #16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 }} |