Skip to content

build: add development flow #19

build: add development flow

build: add development flow #19

Workflow file for this run

name: development
on:
pull_request:
push:
branches:
- '!main' # excludes main
- '!master' # excludes master
env:
TARGET_PLATFORMS: linux/amd64,linux/arm64/v8
jobs:
docker:
services:
registry:
image: registry:3
ports:
- 5000:5000
strategy:
fail-fast: true
matrix:
repository:
- 'localhost:5000'
python:
- '3.14'
- '3.13'
- '3.12'
- '3.11'
- '3.10'
- '3.9'
- '3.8'
alpine:
- '3.20'
- '3.21'
- '3.22'
os:
- 'ubuntu-latest'
exclude:
# No tag
- python: '3.8'
alpine: '3.21'
- python: '3.8'
alpine: '3.22'
- python: '3.14'
alpine: '3.20'
runs-on: ${{ matrix.os }}
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
-
id: image_env
run: |
. ./env.sh \
'${{ matrix.alpine }}' \
'${{ matrix.python }}' \
'${{ github.repository_owner }}' \
'${{ matrix.repository }}'
docker pull "${SOURCE_IMAGE}" || true
echo "IMAGE_HOME=$(mktemp -d)" >> "$GITHUB_OUTPUT"
echo ALPINE_VERSION="${ALPINE_VERSION}" >> "$GITHUB_OUTPUT"
echo PYTHON_VERSION="${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
echo SOURCE_IMAGE="${SOURCE_IMAGE}" >> "$GITHUB_OUTPUT"
echo IMAGE_TAG="${IMAGE_TAG}" >> "$GITHUB_OUTPUT"
echo IMAGE_BUILDROOT_TAG="${IMAGE_TAG}-buildroot" >> "$GITHUB_OUTPUT"
echo IMAGE_TAG_SAFE="$(echo "$IMAGE_TAG" | base64 -w 0 )" >> "$GITHUB_OUTPUT"
echo IMAGE_BUILDROOT_TAG_SAFE="$(echo "${IMAGE_TAG}-buildroot" | base64 -w 0 )" >> "$GITHUB_OUTPUT"
echo REPOSITORY="${REPOSITORY}" >> "$GITHUB_OUTPUT"
echo REPOSITORY_SAFE="$(echo "${REPOSITORY}" | base64 -w 0 )" >> "$GITHUB_OUTPUT"
echo BASE_IMAGE_DIGEST="$(digest_of "$SOURCE_IMAGE")" >> "$GITHUB_OUTPUT"
echo 'IMAGE_DESCRIPTION=${{ github.event.repository.description }}. See ${{ github.server_url }}/${{ github.repository }} for more info.' >> "$GITHUB_OUTPUT"
-
name: Create Buildroot
uses: docker/build-push-action@v6
id: buildroot
with:
push: true
platforms: ${{ env.TARGET_PLATFORMS }}
context: "."
file: Dockerfile.alpine
target: buildroot
cache-to: |
type=gha,mode=max
cache-from: |
type=gha
type=registry,ref=${{ steps.image_env.outputs.IMAGE_TAG }}-buildroot
type=registry,ref=${{ steps.image_env.outputs.SOURCE_IMAGE }}@${{ steps.image_env.outputs.BASE_IMAGE_DIGEST }}
build-args: |
ALPINE_VERSION=${{ steps.image_env.outputs.ALPINE_VERSION }}
BASE_IMAGE_DIGEST=${{ steps.image_env.outputs.BASE_IMAGE_DIGEST }}
PYTHON_VERSION=${{ steps.image_env.outputs.PYTHON_VERSION }}
SOURCE_IMAGE=${{ steps.image_env.outputs.SOURCE_IMAGE }}
BUILD_ROOT=/d
tags: "${{ steps.image_env.outputs.IMAGE_TAG }}-buildroot"
outputs: type=oci,dest=${{ steps.image_env.outputs.IMAGE_HOME }}/image-${{ steps.image_env.outputs.IMAGE_BUILDROOT_TAG_SAFE }}.tar
-
name: Create Image
id: runtime
uses: docker/build-push-action@v6
env:
SOURCE_DATE_EPOCH: 0
with:
push: true
context: "."
platforms: ${{ env.TARGET_PLATFORMS }}
file: Dockerfile.alpine
cache-to: |
type=gha,mode=max
cache-from: |
type=gha
type=registry,ref=${{ steps.image_env.outputs.IMAGE_TAG }}
type=registry,ref=${{ steps.image_env.outputs.IMAGE_TAG }}-buildroot
type=registry,ref=${{ steps.image_env.outputs.SOURCE_IMAGE }}@${{ steps.image_env.outputs.BASE_IMAGE_DIGEST }}
build-args: |
ALPINE_VERSION=${{ steps.image_env.outputs.ALPINE_VERSION }}
BASE_IMAGE_DIGEST=${{ steps.image_env.outputs.BASE_IMAGE_DIGEST }}
PYTHON_VERSION=${{ steps.image_env.outputs.PYTHON_VERSION }}
SOURCE_IMAGE=${{ steps.image_env.outputs.SOURCE_IMAGE }}
BUILD_ROOT=/d
tags: "${{ steps.image_env.outputs.IMAGE_TAG }}"
outputs: type=oci,dest=${{ steps.image_env.outputs.IMAGE_HOME }}/image-${{ steps.image_env.outputs.IMAGE_TAG_SAFE }}.tar
labels: ${{steps.image_env.outputs.IMAGE_LABELS}}
sbom: true
annotations: |
index,manifest:org.opencontainers.image.authors=distroless-python image developers <[email protected]>
index,manifest:org.opencontainers.image.source=https://github.com/autumnjolitz/distroless-python
index,manifest:org.opencontainers.image.title=distroless-python${{ steps.image_env.outputs.PYTHON_VERSION }}-alpine${{ steps.image_env.outputs.ALPINE_VERSION }}
index,manifest:org.opencontainers.image.description=${{ steps.image_env.outputs.IMAGE_DESCRIPTION }}
index,manifest:org.opencontainers.image.base.digest=${{ steps.image_env.outputs.BASE_IMAGE_DIGEST }}
index,manifest:org.opencontainers.image.base.name=${{ steps.image_env.outputs.SOURCE_IMAGE }}
index,manifest:distroless.python-version=${{ steps.image_env.outputs.PYTHON_VERSION }}
index,manifest:distroless.alpine-version=${{ steps.image_env.outputs.ALPINE_VERSION }}
index,manifest:distroless.base-image=alpine${{ steps.image_env.outputs.ALPINE_VERSION }}
-
name: examples/simple-flask
uses: docker/build-push-action@v6
with:
context: "examples/simple-flask"
platforms: ${{ env.TARGET_PLATFORMS }}
cache-from: |
type=gha
type=registry,ref=${{ steps.image_env.outputs.IMAGE_TAG }}
type=registry,ref=${{ steps.image_env.outputs.IMAGE_TAG }}-buildroot
type=registry,ref=${{ steps.image_env.outputs.SOURCE_IMAGE }}@${{ steps.image_env.outputs.BASE_IMAGE_DIGEST }}
build-args: |
SOURCE_IMAGE=${{ steps.image_env.outputs.IMAGE_TAG }}
tags: "${{ steps.image_env.outputs.IMAGE_TAG }}-example1-amd64"
outputs: type=oci,dest=${{ steps.image_env.outputs.IMAGE_HOME }}/example1-${{ steps.image_env.outputs.IMAGE_TAG_SAFE }}.tar
-
id: post_build
run: |
echo 'IMAGE_DIGEST=${{steps.runtime.outputs.digest}}' >> "GITHUB_OUTPUT"
echo 'IMAGE_BUILDROOT_DIGEST=${{steps.buildroot.outputs.digest}}' >> "GITHUB_OUTPUT"
echo '${{ steps.image_env.outputs.IMAGE_TAG }}@'"$IMAGE_DIGEST" | tee -a ${{ steps.image_env.outputs.IMAGE_HOME }}/manifest.txt
echo '${{ steps.image_env.outputs.IMAGE_BUILDROOT_TAG }}@'"$IMAGE_BUILDROOT_DIGEST" | tee -a ${{ steps.image_env.outputs.IMAGE_HOME }}/manifest.txt
ls ${{ steps.image_env.outputs.IMAGE_HOME }}
- name: upload build info
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
retention-days: 1
name: artifact-${{steps.image_env.outputs.REPOSITORY_SAFE}}-alpine${{steps.image_env.outputs.ALPINE_VERSION}}-python${{steps.image_env.outputs.PYTHON_VERSION}}
path: |
${{ steps.image_env.outputs.IMAGE_HOME }}/image-${{ steps.image_env.outputs.IMAGE_TAG_SAFE }}.tar
${{ steps.image_env.outputs.IMAGE_HOME }}/image-${{ steps.image_env.outputs.IMAGE_BUILDROOT_TAG_SAFE }}.tar
render-dockerhub-desc:
needs: [docker]
runs-on: "ubuntu-latest"
steps:
-
name: Checkout
uses: actions/checkout@v4
- uses: actions/setup-python@v6
with:
python-version: '3.12'
-
run: |
python -m pip install jinplate
-
name: Download all workflow run artifacts
uses: actions/download-artifact@v5
with:
pattern: artifact-*
path: dist-images
merge-multiple: true
-
id: looky
run: |
for filename in $(echo dist-images/image-*.tar)
do
IMAGE_URI="$(basename -s .tar $filename | sed 's/image-//g' | base64 -d)"
echo '{"url": "'"$IMAGE_URI"'", "tag": "'$(echo $IMAGE_URI | cut -d: -f2-)'", "registry": "'"$(echo $IMAGE_URI | cut -d/ -f1)"'"}'
done | >./values.json jq -s '. | {"images": .}'
cat ./values.json
-
name: Convert README.rst to markdown
uses: docker://pandoc/core:2.9
with:
args: >-
-s
--wrap=none
-t gfm
-o README.md
README.rst