Skip to content

Auto Build and Push #316

Auto Build and Push

Auto Build and Push #316

name: Auto Build and Push
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
env:
SOURCE_HOST: github.com
SOURCE_REPO_OWNER: kd2org
SOURCE_REPO_NAME: opodsync
IMAGE_REGISTRY: ghcr.io
IMAGE_NAME: opodsync
IMAGE_URI: ghcr.io/${{ github.repository_owner }}/opodsync # must match IMAGE_REGISTRY and IMAGE_NAME
BASE_IMAGE: php:8-alpine # must be the base image from the dockerfile
jobs:
compare:
runs-on: ubuntu-22.04
permissions:
contents: read
packages: read
outputs:
is_new_version: ${{ steps.compare_tags.outputs.is_greater_a }}
rc_source_tag: ${{ steps.compare_tags.outputs.rc_a }}
current_source_tag: ${{ steps.get_latest_source_tag.outputs.tag }}
new_image_tag: ${{ steps.get_new_image_tag.outputs.new_image_tag }}
new_image_tag_suffix: ${{ steps.get_new_image_tag.outputs.new_image_tag_suffix }}
is_new_base_image: ${{ steps.base_image_update_check.outputs.needs-updating }}
steps:
# Compare version tags
- name: Get latest program tag from source
id: get_latest_source_tag
uses: lhstrh/action-repo-semver@23839f38b149db8715f21dbd38e6dde122817222
with:
repo: ${{ env.SOURCE_REPO_OWNER }}/${{ env.SOURCE_REPO_NAME }}
- name: Get latest image tag from GHCR
id: get_latest_image_tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Prerequisite: Package in repo must exist
# 1. Fetch all tags for the GHCR package
# 2. Check if any tags were found
# 3. Strip everything before and after semver x.x.x and sort by semantic versioning
# 4. Output the latest tag
run: |
set -e
tags=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
--paginate \
"/user/packages/container/${IMAGE_NAME}/versions?per_page=100" --jq '.[].metadata.container.tags[]') || {
echo "Failed to fetch tags from GHCR API"
exit 1
}
if [ -z "$tags" ]; then
latest_tag="0.0.1"
else
latest_tag=$(echo "$tags" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+(_[0-9]+)?' | sort -V | tail -n 1)
fi
echo "Latest tag: $latest_tag"
echo "latest_tag_with_base_version=$latest_tag" >> "$GITHUB_OUTPUT"
echo "latest_tag_core=$(echo "$latest_tag" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')" >> "$GITHUB_OUTPUT"
- name: Compare version tags
id: compare_tags
uses: YunaBraska/semver-info-action@9878bfb06b973865ed1ccfce66402c159cf3fa48
with:
semver-a: ${{ steps.get_latest_source_tag.outputs.current }}
semver-b: ${{ steps.get_latest_image_tag.outputs.latest_tag_core }}
- name: Check for Base Image Update
id: base_image_update_check
uses: lucacome/docker-image-update-checker@a233de0585661c019fb71f9601328db37051cc66
with:
base-image: ${{ env.BASE_IMAGE }}
image: ${{ env.IMAGE_URI }}:latest
- name: Output new Image Tag
id: get_new_image_tag
env:
CURRENT_IMAGE_TAG: ${{ steps.get_latest_image_tag.outputs.latest_tag_with_base_version }}
CURRENT_SOURCE_TAG: ${{ steps.get_latest_source_tag.outputs.current }}
IS_NEW_SOURCE_TAG: ${{ steps.compare_tags.outputs.is_greater_a }}
NEW_SOURCE_TAG_RC: ${{ steps.compare_tags.outputs.rc_source_tag }}
IS_NEW_IMAGE_BASE: ${{ steps.base_image_update_check.outputs.needs-updating }}
run: |
# Decide which tag to use for the new image
if [[ "$IS_NEW_SOURCE_TAG" == "true" && "$NEW_SOURCE_TAG_RC" == "" ]]; then
new_image_tag="${CURRENT_SOURCE_TAG}"
new_base=1
elif [[ "$IS_NEW_IMAGE_BASE" == "true" ]]; then
# Increment the last number after '_' in the tag, or add '_1' if not present
if [[ "$CURRENT_IMAGE_TAG" =~ ^([0-9]+\.[0-9]+\.[0-9]+)(_([0-9]+))?$ ]]; then
version_core="${BASH_REMATCH[1]}"
if [[ -n "${BASH_REMATCH[3]}" ]]; then
new_base=$((BASH_REMATCH[3]+1))
new_image_tag="${version_core}"
else
new_base=1
new_image_tag="${version_core}"
fi
else
# If this is reached, many things have gone wrong in the pipeline
new_image_tag="${CURRENT_IMAGE_TAG}"
new_base=1
fi
else
# No update
new_image_tag="$CURRENT_IMAGE_TAG"
new_base=""
fi
echo "New image tag: $new_image_tag"
echo "new_image_tag=$new_image_tag" >> "$GITHUB_OUTPUT"
echo "New suffix: $new_base"
if [[ -n "$new_base" ]]; then
echo "new_image_tag_suffix=_${new_base}" >> "$GITHUB_OUTPUT"
else
echo "new_image_tag_suffix=" >> "$GITHUB_OUTPUT"
fi
# FIXME: Reusable workflow can't have an env variable evaluated before it is passed.
# https://github.com/orgs/community/discussions/26671
build-push-envs:
runs-on: ubuntu-22.04
needs: [compare]
if: (needs.compare.outputs.is_new_version == 'true' && needs.compare.outputs.rc_source_tag == '') || needs.compare.outputs.is_new_base_image == 'true'
outputs:
image_uri: ${{ steps.env-to-output.outputs.image_uri }}
image_registry: ${{ steps.env-to-output.outputs.image_registry }}
source_host: ${{ steps.env-to-output.outputs.source_host }}
source_repo_owner: ${{ steps.env-to-output.outputs.source_repo_owner }}
source_repo_name: ${{ steps.env-to-output.outputs.source_repo_name }}
steps:
- name: Prepare environment variables for reusable build push workflow.
id: env-to-output
shell: bash
run: |
vars="IMAGE_REGISTRY IMAGE_URI SOURCE_HOST SOURCE_REPO_OWNER SOURCE_REPO_NAME"
for var in $vars; do
echo "${var,,}=${!var}" >> $GITHUB_OUTPUT
done
build-push:
uses: ./.github/workflows/reusable-build-push.yml
permissions:
contents: read
packages: write
needs: [build-push-envs, compare]
if: (needs.compare.outputs.is_new_version == 'true' && needs.compare.outputs.rc_source_tag == '') || needs.compare.outputs.is_new_base_image == 'true'
with:
registry: ${{ needs.build-push-envs.outputs.image_registry }}
image_uri: ${{ needs.build-push-envs.outputs.image_uri }}
source_host: ${{ needs.build-push-envs.outputs.source_host }}
source_repo_owner: ${{ needs.build-push-envs.outputs.source_repo_owner }}
source_repo_name: ${{ needs.build-push-envs.outputs.source_repo_name }}
source_version_tag: ${{ needs.compare.outputs.current_source_tag }}
new_version_tag: ${{ needs.compare.outputs.new_image_tag }}
new_version_tag_suffix: ${{ needs.compare.outputs.new_image_tag_suffix }}
is_production: true
workflow-keepalive:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- uses: liskin/gh-workflow-keepalive@f72ff1a1336129f29bf0166c0fd0ca6cf1bcb38c