Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build Docker image and push to GHCR #230

Merged
merged 19 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/build-and-push-docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---

name: 🏗️

on: # yamllint disable-line rule:truthy
pull_request:
push:
branches: ["release/*", "unstable/*"]
workflow_dispatch:
inputs:
tag:
description: Docker image tag
br3ndonland marked this conversation as resolved.
Show resolved Hide resolved
required: true
type: string

jobs:
smoke-test:
uses: ./.github/workflows/reusable-smoke-test.yml
build-and-push:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
needs:
- smoke-test
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: |
DOCKER_TAG="${DOCKER_TAG/'/'/'-'}"
DOCKER_TAG_MAJOR=$(echo "$DOCKER_TAG" | cut -d '.' -f 1)
DOCKER_TAG_MAJOR_MINOR=$(echo "$DOCKER_TAG" | cut -d '.' -f 1-2)
IMAGE="ghcr.io/$GITHUB_REPOSITORY:${DOCKER_TAG}"
IMAGE_MAJOR="ghcr.io/$GITHUB_REPOSITORY:${DOCKER_TAG_MAJOR}"
IMAGE_MAJOR_MINOR="ghcr.io/$GITHUB_REPOSITORY:${DOCKER_TAG_MAJOR_MINOR}"
echo "IMAGE=$IMAGE" >>"$GITHUB_ENV"
echo "IMAGE_MAJOR=$IMAGE_MAJOR" >>"$GITHUB_ENV"
echo "IMAGE_MAJOR_MINOR=$IMAGE_MAJOR_MINOR" >>"$GITHUB_ENV"
docker build . \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--cache-from $IMAGE \
--tag $IMAGE
docker tag $IMAGE $IMAGE_MAJOR
docker tag $IMAGE $IMAGE_MAJOR_MINOR
env:
DOCKER_TAG: ${{ inputs.tag || github.ref_name }}
- name: Log in to GHCR
run: >-
echo ${{ secrets.GITHUB_TOKEN }} |
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
- name: Push Docker image to GHCR
run: |
docker push $IMAGE
docker push $IMAGE_MAJOR
docker push $IMAGE_MAJOR_MINOR
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---

name: 🧪
name: ♻️ 🧪

on: # yamllint disable-line rule:truthy
push:
pull_request:
workflow_call:

env:
devpi-password: abcd1234
Expand All @@ -27,7 +26,33 @@ env:
PYTEST_THEME_MODE

jobs:
fail-fast:

strategy:
matrix:
os: [macos-latest, windows-latest]

runs-on: ${{ matrix.os }}

timeout-minutes: 2

steps:
- name: Check out the action locally
uses: actions/checkout@v4
with:
path: test
- name: Fail-fast in unsupported environments
continue-on-error: true
id: fail-fast
uses: ./test
- name: Error if action did not fail-fast in unsupported environments
if: steps.fail-fast.outcome == 'success'
run: |
>&2 echo This action should fail-fast in unsupported environments.
exit 1

smoke-test:

runs-on: ubuntu-latest

services:
Expand Down
79 changes: 67 additions & 12 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,70 @@ 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:
br3ndonland marked this conversation as resolved.
Show resolved Hide resolved
- name: Fail-fast in unsupported environments
if: runner.os != 'Linux'
run: |
>&2 echo This action is only able to run under GNU/Linux environments
exit 1
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
shell: bash -eEuo pipefail {0}
- name: Reset path if needed
run: |
# Reset path if needed
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
# 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 || env.PR_REF || github.ref_name }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@br3ndonland when running in another repo, wouldn't github.ref_name point to that repo instead of ours? Is it safe to use this var as a fallback? Same question for github.event.pull_request. Is this to cover contributions to the action itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If another repo is using the marketplace action (uses: pypa/gh-action-pypi-publish), env.ACTION_REF will be set from github.action_ref.

If the action is being run on a PR to this repo, env.PR_REF will be set from github.event.pull_request.head.ref.

If the action is being run from a push, release, or other event in this repo, github.ref_name will be used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. Thanks for clarifying. So I'll need to be careful in the release process to make an image before tagging…

REPO=${{ env.ACTION_REPO || env.PR_REPO || github.repository }}
REPO_ID=${{ env.PR_REPO_ID || github.repository_id }}
echo "ref=$REF" >>"$GITHUB_OUTPUT"
echo "repo=$REPO" >>"$GITHUB_OUTPUT"
echo "repo-id=$REPO_ID" >>"$GITHUB_OUTPUT"
shell: bash
env:
ACTION_REF: ${{ github.action_ref }}
ACTION_REPO: ${{ github.action_repository }}
PR_REF: ${{ github.event.pull_request.head.ref }}
PR_REPO: ${{ github.event.pull_request.head.repo.full_name }}
PR_REPO_ID: ${{ github.event.pull_request.base.repo.id }}
- name: Check out action repo
uses: actions/checkout@v4
br3ndonland marked this conversation as resolved.
Show resolved Hide resolved
with:
path: action-repo
ref: ${{ steps.set-repo-and-ref.outputs.ref }}
repository: ${{ steps.set-repo-and-ref.outputs.repo }}
- name: Create Docker container action
run: |
# Create Docker container action
python create-docker-action.py
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
br3ndonland marked this conversation as resolved.
Show resolved Hide resolved
env:
REF: ${{ steps.set-repo-and-ref.outputs.ref }}
REPO: ${{ steps.set-repo-and-ref.outputs.repo }}
REPO_ID: ${{ steps.set-repo-and-ref.outputs.repo-id }}
shell: bash
working-directory: action-repo
- name: Run Docker container
uses: ./action-repo/.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 }}
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
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 }}
75 changes: 75 additions & 0 deletions create-docker-action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import json
import os
import pathlib

DESCRIPTION = 'description'
REQUIRED = 'required'

REF = os.environ['REF']
REPO = os.environ['REPO']
REPO_ID = os.environ['REPO_ID']
REPO_ID_GH_ACTION = '178055147'


def set_image(ref: str, repo: str, repo_id: str) -> str:
if repo_id == REPO_ID_GH_ACTION:
return '../../../Dockerfile'
docker_ref = ref.replace('/', '-')
return f'docker://ghcr.io/{repo}:{docker_ref}'


image = set_image(REF, REPO, REPO_ID)

action = {
'name': '🏃',
DESCRIPTION: (
'Run Docker container to upload Python distribution packages to PyPI'
),
'inputs': {
webknjaz marked this conversation as resolved.
Show resolved Hide resolved
'user': {DESCRIPTION: 'PyPI user', REQUIRED: False},
'password': {
DESCRIPTION: 'Password for your PyPI user or an access token',
REQUIRED: False,
},
'repository-url': {
DESCRIPTION: 'The repository URL to use',
REQUIRED: False,
},
'packages-dir': {
DESCRIPTION: 'The target directory for distribution',
REQUIRED: False,
},
'verify-metadata': {
DESCRIPTION: 'Check metadata before uploading',
REQUIRED: False,
},
'skip-existing': {
DESCRIPTION: (
'Do not fail if a Python package distribution'
' exists in the target package index'
),
REQUIRED: False,
},
'verbose': {DESCRIPTION: 'Show verbose output.', REQUIRED: False},
'print-hash': {
DESCRIPTION: 'Show hash values of files to be uploaded',
REQUIRED: False,
},
'attestations': {
DESCRIPTION: (
'[EXPERIMENTAL]'
' Enable experimental support for PEP 740 attestations.'
' Only works with PyPI and TestPyPI via Trusted Publishing.'
),
REQUIRED: False,
},
},
'runs': {
'using': 'docker',
'image': image,
},
}

action_path = pathlib.Path('.github/actions/run-docker-container/action.yml')
action_path.parent.mkdir(parents=True, exist_ok=True)
action_path.write_text(json.dumps(action, ensure_ascii=False), encoding='utf-8')
Loading