diff --git a/.github/scripts/common.py b/.github/scripts/common.py new file mode 100644 index 000000000..3913c91cd --- /dev/null +++ b/.github/scripts/common.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + + +def get_image_tag( + repo_name: str, + pkg_name: str, + pkg_version: str, +) -> str: + """ + Returns a string representing the normal image for a given package + """ + return f"ghcr.io/{repo_name}/builder/{pkg_name}:{pkg_version}" + + +def get_cache_image_tag( + repo_name: str, + pkg_name: str, + pkg_version: str, + branch_name: str, +) -> str: + """ + Returns a string representing the expected image cache tag for a given package + + Registry type caching is utilized for the builder images, to allow fast + rebuilds, generally almost instant for the same version + """ + return f"ghcr.io/{repo_name}/builder/cache/{pkg_name}:{pkg_version}" diff --git a/docker-builders/get-build-json.py b/.github/scripts/get-build-json.py similarity index 86% rename from docker-builders/get-build-json.py rename to .github/scripts/get-build-json.py index 4b96ac8d7..42c37d695 100755 --- a/docker-builders/get-build-json.py +++ b/.github/scripts/get-build-json.py @@ -20,13 +20,8 @@ import os from pathlib import Path from typing import Final - -def _get_image_tag( - repo_name: str, - pkg_name: str, - pkg_version: str, -) -> str: - return f"ghcr.io/{repo_name}/builder/{pkg_name}:{pkg_version}" +from common import get_cache_image_tag +from common import get_image_tag def _main(): @@ -49,7 +44,9 @@ def _main(): args: Final = parser.parse_args() + # Read from environment variables set by GitHub Actions repo_name: Final[str] = os.environ["GITHUB_REPOSITORY"] + branch_name: Final[str] = os.environ["GITHUB_REF_NAME"] # Default output values version = None @@ -58,7 +55,7 @@ def _main(): if args.package == "frontend": # Version is just the branch or tag name - version = os.environ["GITHUB_REF_NAME"] + version = branch_name elif args.package in pipfile_data["default"]: # Read the version from Pipfile.lock pkg_data = pipfile_data["default"][args.package] @@ -88,7 +85,13 @@ def _main(): "name": args.package, "version": version, "git_tag": git_tag, - "image_tag": _get_image_tag(repo_name, args.package, version), + "image_tag": get_image_tag(repo_name, args.package, version), + "cache_tag": get_cache_image_tag( + repo_name, + args.package, + version, + branch_name, + ), } # Add anything special a package may need diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34bcf21a2..9973f0eec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,15 +75,11 @@ jobs: uses: actions/setup-python@v3 with: python-version: "3.9" - - - name: Make script executable - run: | - chmod +x ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py - name: Setup qpdf image id: qpdf-setup run: | - build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py qpdf) + build_json=$(python ${GITHUB_WORKSPACE}/.github/scripts/get-build-json.py qpdf) echo ${build_json} @@ -92,7 +88,7 @@ jobs: name: Setup psycopg2 image id: psycopg2-setup run: | - build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py psycopg2) + build_json=$(python ${GITHUB_WORKSPACE}/.github/scripts/get-build-json.py psycopg2) echo ${build_json} @@ -101,7 +97,7 @@ jobs: name: Setup pikepdf image id: pikepdf-setup run: | - build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py pikepdf) + build_json=$(python ${GITHUB_WORKSPACE}/.github/scripts/get-build-json.py pikepdf) echo ${build_json} @@ -110,7 +106,7 @@ jobs: name: Setup jbig2enc image id: jbig2enc-setup run: | - build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py jbig2enc) + build_json=$(python ${GITHUB_WORKSPACE}/.github/scripts/get-build-json.py jbig2enc) echo ${build_json} @@ -119,7 +115,7 @@ jobs: name: Setup frontend image id: frontend-setup run: | - build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py frontend) + build_json=$(python ${GITHUB_WORKSPACE}/.github/scripts/get-build-json.py frontend) echo ${build_json} @@ -198,15 +194,6 @@ jobs: - name: Checkout uses: actions/checkout@v3 - with: - fetch-depth: 2 - - - name: Get changed frontend files - id: changed-files-specific - uses: tj-actions/changed-files@v18.1 - with: - files: | - src-ui/** - name: Login to Github Container Registry uses: docker/login-action@v1 @@ -214,33 +201,15 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - - name: Determine if build needed - id: build-skip-check - # Skip building the frontend if the tag exists and no src-ui files changed - run: | - if ! docker manifest inspect ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }} &> /dev/null ; then - echo "Build required, no existing image" - echo ::set-output name=frontend-build-needed::true - elif ${{ steps.changed-files-specific.outputs.any_changed }} == 'true' ; then - echo "Build required, src-ui changes" - echo ::set-output name=frontend-build-needed::true - else - echo "No build required" - echo ::set-output name=frontend-build-needed::false - fi - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - if: ${{ steps.build-skip-check.outputs.frontend-build-needed == 'true' }} - name: Set up QEMU uses: docker/setup-qemu-action@v1 - if: ${{ steps.build-skip-check.outputs.frontend-build-needed == 'true' }} - name: Compile frontend uses: docker/build-push-action@v2 - if: ${{ steps.build-skip-check.outputs.frontend-build-needed == 'true' }} with: context: . file: ./docker-builders/Dockerfile.frontend @@ -250,8 +219,8 @@ jobs: # But the platform is set to the runner's native for speedup platforms: linux/amd64 push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).cache_tag }} + cache-to: type=registry,mode=max,ref=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).cache_tag }} - name: Export frontend artifact from docker run: | diff --git a/.github/workflows/reusable-ci-backend.yml b/.github/workflows/reusable-ci-backend.yml index 28092fcb1..7e5cafb99 100644 --- a/.github/workflows/reusable-ci-backend.yml +++ b/.github/workflows/reusable-ci-backend.yml @@ -87,7 +87,7 @@ jobs: - name: Get changed files id: changed-files-specific - uses: tj-actions/changed-files@v18.1 + uses: tj-actions/changed-files@v18.7 with: files: | src/** diff --git a/.github/workflows/reusable-workflow-builder.yml b/.github/workflows/reusable-workflow-builder.yml index 543cd3d79..3741ad67b 100644 --- a/.github/workflows/reusable-workflow-builder.yml +++ b/.github/workflows/reusable-workflow-builder.yml @@ -23,6 +23,9 @@ jobs: name: Build ${{ fromJSON(inputs.build-json).name }} @ ${{ fromJSON(inputs.build-json).version }} runs-on: ubuntu-latest steps: + - + name: Checkout + uses: actions/checkout@v3 - name: Login to Github Container Registry uses: docker/login-action@v1 @@ -30,33 +33,15 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - - name: Determine if build needed - id: build-skip-check - run: | - if ! docker manifest inspect ${{ fromJSON(inputs.build-json).image_tag }} &> /dev/null ; then - echo "Building, no image exists with this version" - echo ::set-output name=image-exists::false - else - echo "Not building, image exists with this version" - echo ::set-output name=image-exists::true - fi - - - name: Checkout - uses: actions/checkout@v3 - if: ${{ steps.build-skip-check.outputs.image-exists == 'false' }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - if: ${{ steps.build-skip-check.outputs.image-exists == 'false' }} - name: Set up QEMU uses: docker/setup-qemu-action@v1 - if: ${{ steps.build-skip-check.outputs.image-exists == 'false' }} - name: Build ${{ fromJSON(inputs.build-json).name }} uses: docker/build-push-action@v2 - if: ${{ steps.build-skip-check.outputs.image-exists == 'false' }} with: context: . file: ${{ inputs.dockerfile }} @@ -64,5 +49,5 @@ jobs: platforms: linux/amd64,linux/arm64,linux/arm/v7 build-args: ${{ inputs.build-args }} push: true - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=${{ fromJSON(inputs.build-json).cache_tag }} + cache-to: type=registry,mode=max,ref=${{ fromJSON(inputs.build-json).cache_tag }}