From 783267be6946bcf454fcec01dd3ddf45c7830dbc Mon Sep 17 00:00:00 2001 From: Brendon Smith Date: Tue, 16 Apr 2024 03:02:03 -0400 Subject: [PATCH] Build Docker image and push to GHCR Up to this point, the project has been set up as a Docker action referencing the Dockerfile. The downside to using the Dockerfile for the action is that the Docker image must be built every time the action is used. This commit will set up the project to build the Docker image and push it to GitHub Container Registry (GHCR). This change will speed up user workflows every time the action is used because the workflows will simply pull the Docker image from GHCR instead of building again. Changes: - Add required metadata to Dockerfile - Build container image with GitHub Actions - Push container image to GHCR Docker actions support pulling in pre-built Docker images. The downside is that there's no way to specify the correct Docker tag because the GitHub Actions `image` and `uses:` keys don't accept any context. For example, if a user's workflow has `uses: pypa/gh-action-pypi-publish@release/v1.8`, then the action should pull in a Docker image built from the `release/v1.8` branch, something like `ghcr.io/pypa/gh-action-pypi-publish:release-v1.8` (Docker tags can't have `/`). The workaround is to switch the top-level `action.yml` to a composite action that then calls the Docker action, substituting the correct image name and tag. --- .../actions/run-docker-container/action.yml | 32 +++++++++ .../workflows/build-and-push-docker-image.yml | 29 ++++++++ .github/workflows/self-smoke-test-action.yml | 7 +- action.yml | 69 +++++++++++++++---- 4 files changed, 124 insertions(+), 13 deletions(-) create mode 100644 .github/actions/run-docker-container/action.yml create mode 100644 .github/workflows/build-and-push-docker-image.yml diff --git a/.github/actions/run-docker-container/action.yml b/.github/actions/run-docker-container/action.yml new file mode 100644 index 0000000..05a04b1 --- /dev/null +++ b/.github/actions/run-docker-container/action.yml @@ -0,0 +1,32 @@ +--- +name: ๐Ÿƒ +inputs: + user: + required: false + password: + required: false + repository-url: + required: false + packages-dir: + required: false + verify-metadata: + required: false + skip-existing: + required: false + verbose: + required: false + print-hash: + required: false +runs: + using: docker + image: {{image}} + args: + - ${{ inputs.user }} + - ${{ inputs.password }} + - ${{ inputs.repository-url }} + - ${{ inputs.packages-dir }} + - ${{ inputs.verify-metadata }} + - ${{ inputs.skip-existing }} + - ${{ inputs.verbose }} + - ${{ inputs.print-hash }} + - ${{ inputs.attestations }} diff --git a/.github/workflows/build-and-push-docker-image.yml b/.github/workflows/build-and-push-docker-image.yml new file mode 100644 index 0000000..cd3c731 --- /dev/null +++ b/.github/workflows/build-and-push-docker-image.yml @@ -0,0 +1,29 @@ +--- + +name: ๐Ÿ—๏ธ + +on: # yamllint disable-line rule:truthy + pull_request: + push: + branches: ["release/*", "unstable/*"] + tags: ["*"] + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build Docker image + run: | + IMAGE="ghcr.io/$GITHUB_REPOSITORY:${GITHUB_REF_NAME/'/'/'-'}" + echo "IMAGE=$IMAGE" >>"$GITHUB_ENV" + docker build . \ + --build-arg BUILDKIT_INLINE_CACHE=1 \ + --cache-from $IMAGE \ + --tag $IMAGE + - name: Push Docker image to GHCR + if: github.event_name != 'pull_request' + run: | + echo ${{ secrets.GITHUB_TOKEN }} | + docker login ghcr.io -u $GITHUB_ACTOR --password-stdin + docker push $IMAGE diff --git a/.github/workflows/self-smoke-test-action.yml b/.github/workflows/self-smoke-test-action.yml index b655019..0a88c1c 100644 --- a/.github/workflows/self-smoke-test-action.yml +++ b/.github/workflows/self-smoke-test-action.yml @@ -3,8 +3,10 @@ name: ๐Ÿงช on: # yamllint disable-line rule:truthy - push: pull_request: + workflow_run: + workflows: [๐Ÿ—๏ธ] + types: [completed] env: devpi-password: abcd1234 @@ -28,6 +30,9 @@ env: jobs: smoke-test: + if: >- + github.event_name == 'pull_request' || + github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest services: diff --git a/action.yml b/action.yml index f71598d..e67f9c2 100644 --- a/action.yml +++ b/action.yml @@ -91,15 +91,60 @@ branding: color: yellow icon: upload-cloud runs: - using: docker - image: Dockerfile - args: - - ${{ inputs.user }} - - ${{ inputs.password }} - - ${{ inputs.repository-url }} - - ${{ inputs.packages-dir }} - - ${{ inputs.verify-metadata }} - - ${{ inputs.skip-existing }} - - ${{ inputs.verbose }} - - ${{ inputs.print-hash }} - - ${{ inputs.attestations }} + using: composite + steps: + - name: Reset path if needed + run: | + # Reset path if needed + # https://github.com/pypa/gh-action-pypi-publish/issues/112 + if [[ $PATH != *"/usr/bin"* ]]; then + echo "\$PATH=$PATH. Resetting \$PATH for GitHub Actions." + PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + echo "PATH=$PATH" >>"$GITHUB_ENV" + echo "$PATH" >>"$GITHUB_PATH" + echo "\$PATH reset. \$PATH=$PATH" + fi + shell: bash + - name: Set repo and ref from which to run Docker container action + id: set-repo-and-ref + run: | + # Set repo and ref from which to run Docker container action + # to handle cases in which `github.action_` context is not set + # https://github.com/actions/runner/issues/2473 + REF=${{ env.ACTION_REF || github.ref_name }} + REPO=${{ env.ACTION_REPO || github.repository }} + echo "ref=$REF" >>"$GITHUB_OUTPUT" + echo "repo=$REPO" >>"$GITHUB_OUTPUT" + shell: bash + env: + ACTION_REF: ${{ github.action_ref }} + ACTION_REPO: ${{ github.action_repository }} + - name: Set Docker image name and tag + run: | + # Set Docker image name and tag + # if action run was triggered by a pull request to this repo, + # build image from Dockerfile because it has not been pushed to GHCR, + # else pull image from GHCR + if [[ $GITHUB_EVENT_NAME == "pull_request" ]] && + [[ $GITHUB_REPOSITORY == "pypa/gh-action-pypi-publish" ]]; then + IMAGE="../../../Dockerfile" + else + REF=${{ steps.set-repo-and-ref.outputs.ref }} + REPO=${{ steps.set-repo-and-ref.outputs.repo }} + IMAGE="docker://ghcr.io/$REPO:${REF/'/'/'-'}" + fi + FILE=".github/actions/run-docker-container/action.yml" + sed -i -e "s|{{image}}|$IMAGE|g" "$FILE" + shell: bash + - name: Run Docker container + uses: ./.github/actions/run-docker-container + with: + user: ${{ inputs.user }} + password: ${{ inputs.password }} + repository-url: ${{ inputs.repository-url || inputs.repository_url }} + packages-dir: ${{ inputs.packages-dir || inputs.packages_dir }} + verify-metadata: ${{ inputs.verify-metadata || inputs.verify_metadata }} + skip-existing: ${{ inputs.skip-existing || inputs.skip_existing }} + verbose: ${{ inputs.verbose }} + print-hash: ${{ inputs.print-hash || inputs.print_hash }} + attestations: ${{ inputs.attestations }}