Skip to content

v2.0.0b3 — Full IPv6 support #4

v2.0.0b3 — Full IPv6 support

v2.0.0b3 — Full IPv6 support #4

Workflow file for this run

name: Publish Docker Image
# Triggers:
#
# - release: published
# Full tag set (:VERSION, :major.minor, :major, :latest) - the
# canonical "ship a new version" path. Same trigger as
# python-publish.yml, so one release ships PyPI + Docker together.
#
# - workflow_dispatch
# Manual trigger. Two modes depending on inputs:
#
# - With `version` input (e.g. `--field version=2.0.0b2`):
# Publishes the full tag set (:VERSION, :major.minor, :major,
# :latest) using the supplied version string. Builds whatever
# code is at the dispatched ref. Use this for retroactive
# publishes when the release event didn't fire docker-publish
# (e.g. workflow file added after the release was created),
# or to force-republish a specific version.
#
# - Without `version` input:
# Publishes :manual-<timestamp> only. Useful for smoke-testing
# the workflow on master HEAD without affecting any version tags.
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g. 2.0.0b2). Leave empty for a smoke-test build tagged :manual-<timestamp>."
required: false
default: ""
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # required to push to ghcr.io
steps:
- name: Check out source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# ref omitted: uses GITHUB_REF, which for both `release` events
# and `workflow_dispatch` is the ref that triggered the workflow.
# Multi-arch builds need QEMU for cross-compilation under buildx.
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
# Buildx is the modern docker builder; supports multi-platform output.
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
# Docker Hub login. Token must be a Hub access token (NOT a password)
# scoped to the proxybroker2 repository for least-privilege.
- name: Log in to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# GHCR login + push are temporarily disabled. Tracking #206.
# Reason: the GHCR package `ghcr.io/bluet/proxybroker2` doesn't
# exist yet, and `permissions: packages: write` + the OCI source
# label (added in PR #205) aren't sufficient to bootstrap a
# brand-new package from a workflow's GITHUB_TOKEN - the first
# push gets 403 Forbidden. Pre-creating the package once via the
# GHCR web UI (or pushing once with a maintainer PAT scoped to
# write:packages) unblocks subsequent workflow pushes.
# Re-enable by uncommenting the two GHCR-related blocks below
# AND restoring `ghcr.io/bluet/proxybroker2` in the `images:`
# list of the metadata-action step.
#
# - name: Log in to GitHub Container Registry
# uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
# with:
# registry: ghcr.io
# username: ${{ github.actor }}
# password: ${{ secrets.GITHUB_TOKEN }}
# Compute version components for manual workflow_dispatch with version input.
# Strips any leading 'v', then derives major / major.minor by removing
# PEP 440 prerelease/post suffixes (a / b / rc / .dev / .post). Only runs
# when version input is non-empty.
- name: Compute version components (manual dispatch)
id: ver
if: github.event_name == 'workflow_dispatch' && inputs.version != ''
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
version="${INPUT_VERSION#v}"
# Strip prerelease/post suffix to get bare M.N.P
base=$(echo "$version" | sed -E 's/(a|b|rc|\.dev|\.post)[0-9]+.*$//')
major="${base%%.*}"
major_minor=$(echo "$base" | cut -d. -f1-2)
{
echo "version=$version"
echo "major=$major"
echo "major_minor=$major_minor"
} >> "$GITHUB_OUTPUT"
# Tag strategy:
#
# `:VERSION` (e.g. `:2.0.0b2`) - exact version pin.
# Uses type=pep440 (NOT type=semver) because this project
# versions in PEP 440 form (`2.0.0b2`), not SemVer
# (`2.0.0-beta.2`). PyPI mandates PEP 440 - we follow.
#
# `:major.minor` / `:major` / `:latest` - floating aliases.
# Advanced on every release event AND on workflow_dispatch
# with version input. Type=match is used for release events
# (regex on git tag) because metadata-action's pep440/semver
# parsers deliberately hold floating aliases back for
# prereleases - we want them to advance for prereleases too:
# this project has been in beta for a year, and locking
# floating tags to stable releases would freeze them on
# `v2.0.0b1` (May 2025) until 2.0.0 ships.
#
# `:manual-<timestamp>` - per-build tag for workflow_dispatch
# without a version input. Smoke-test builds.
#
# `flavor: latest=false` disables metadata-action's automatic
# `:latest` for the highest stable version. We control `:latest`
# explicitly above so it only fires when we explicitly say so.
#
# Acknowledged side-effect: if a future patch is released for an
# OLDER version line (e.g. 1.5.1 after 2.0.0), floating tags would
# advance backward. Not maintaining old version lines today;
# restore `flavor: latest=auto` if that ever changes.
- name: Extract image metadata (tags, labels)
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: |
bluet/proxybroker2
flavor: |
latest=false
tags: |
type=pep440,pattern={{version}},enable=${{ github.event_name == 'release' }}
type=match,pattern=v(\d+\.\d+),group=1,enable=${{ github.event_name == 'release' }}
type=match,pattern=v(\d+),group=1,enable=${{ github.event_name == 'release' }}
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
type=raw,value=${{ steps.ver.outputs.version }},enable=${{ steps.ver.outputs.version != '' }}
type=raw,value=${{ steps.ver.outputs.major_minor }},enable=${{ steps.ver.outputs.major_minor != '' }}
type=raw,value=${{ steps.ver.outputs.major }},enable=${{ steps.ver.outputs.major != '' }}
type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' && inputs.version != '' }}
type=raw,value=manual-{{date 'YYYYMMDDHHmmss'}},enable=${{ github.event_name == 'workflow_dispatch' && inputs.version == '' }}
# Build once, push to both registries. cache-from/to use the GitHub
# Actions cache backend so a second run on the same code reuses
# layers and finishes in seconds instead of minutes.
- name: Build and push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max