Auto Build and Push #316
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: 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 |