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.
This commit is contained in:
Brendon Smith 2024-04-16 03:02:03 -04:00
parent fb13cb3069
commit 783267be69
No known key found for this signature in database
4 changed files with 124 additions and 13 deletions

View file

@ -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 }}

View file

@ -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

View file

@ -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:

View file

@ -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 }}