CI: leave :latest to the newest series once 27.1 ships (release/2026) #240
No files matched your search
@@ -37,8 +37,10 @@
|
||||
# fixes through pull requests into it, and is tagged there, so production
|
||||
# can get a fix without everything that has landed on main since.
|
||||
#
|
||||
# :latest moves with every published tag: tags are cut by the weekly release
|
||||
# (or by hand for a real release); there are no prerelease tags here.
|
||||
# :latest moves with a published tag while 2026.x is the newest series. Once
|
||||
# a final release numbered by series exists (v27.1, v27.1.3), a 2026.x
|
||||
# security release from release/2026 leaves :latest where it is (the version
|
||||
# job's `latest` output).
|
||||
#
|
||||
# The push logs in with PACKAGE_TOKEN (jcoffey-dev, write:package): the job's
|
||||
# own token is refused by the container registry.
|
||||
@@ -64,6 +66,7 @@ jobs:
|
||||
image: python:3.13-slim@sha256:8d9d0b8bcf6506481eae4907c18f5e3e7902e629f5f6d684f9e7c32e85e3ddf0 # 3.13-slim
|
||||
outputs:
|
||||
version: ${{ steps.v.outputs.version }}
|
||||
latest: ${{ steps.latest.outputs.latest }}
|
||||
steps:
|
||||
# Full history: the ancestry check cannot be answered from a shallow
|
||||
# clone. The checkout also fetches every branch as origin/*.
|
||||
@@ -95,6 +98,22 @@ jobs:
|
||||
echo "$TAG is on $on"
|
||||
echo "version=$V" >> "$GITHUB_OUTPUT"
|
||||
echo "version $V"
|
||||
# inbuxa: :latest belongs to the newest series; see the top of this file
|
||||
- id: latest
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
python3 - <<'EOF'
|
||||
import json, os, re, urllib.request
|
||||
url = (f"{os.environ['CI_SERVER_INTERNAL']}/api/v1/repos/{os.environ['GITHUB_REPOSITORY']}"
|
||||
"/releases?draft=false&pre-release=false&limit=50")
|
||||
req = urllib.request.Request(url, headers={"Authorization": f"token {os.environ['TOKEN']}"})
|
||||
newer = [r["tag_name"] for r in json.load(urllib.request.urlopen(req))
|
||||
if re.match(r"v[0-9]{1,3}\.", r["tag_name"])]
|
||||
print(f"{newer[0]} is out: :latest stays on its series" if newer else "no series release yet: :latest moves")
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a") as out:
|
||||
out.write(f"latest={'false' if newer else 'true'}\n")
|
||||
EOF
|
||||
|
||||
publish-amd64:
|
||||
if: ${{ vars.BUILD_ON != 'github' }}
|
||||
@@ -150,6 +169,7 @@ jobs:
|
||||
REGISTRY: ${{ vars.REGISTRY }}
|
||||
IMAGE: ${{ vars.REGISTRY }}/${{ github.repository }}
|
||||
VERSION: ${{ needs.version.outputs.version }}
|
||||
LATEST: ${{ needs.version.outputs.latest }}
|
||||
PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
|
||||
steps:
|
||||
- uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec
|
||||
@@ -165,9 +185,11 @@ jobs:
|
||||
--provenance=false --sbom=false \
|
||||
--tag "$IMAGE:$VERSION-arm64" \
|
||||
--push .
|
||||
if [ "$LATEST" = true ]; then latest="--tag $IMAGE:latest"; else latest=""; fi
|
||||
# $latest unquoted on purpose: empty, or two words
|
||||
docker buildx imagetools create \
|
||||
--tag "$IMAGE:$VERSION" \
|
||||
--tag "$IMAGE:latest" \
|
||||
$latest \
|
||||
"$IMAGE:$VERSION-amd64" "$IMAGE:$VERSION-arm64"
|
||||
docker buildx imagetools inspect "$IMAGE:$VERSION"
|
||||
- if: always()
|
||||
@@ -222,6 +244,7 @@ jobs:
|
||||
env:
|
||||
TAG: ${{ github.ref_name }}
|
||||
VERSION: ${{ needs.version.outputs.version }}
|
||||
LATEST: ${{ needs.version.outputs.latest }}
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
REGISTRY: ${{ vars.REGISTRY }}
|
||||
@@ -237,9 +260,11 @@ jobs:
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code != 404: raise
|
||||
image = f"{os.environ['REGISTRY']}/{os.environ['REPO']}:{version}"
|
||||
body = (f"Container image: `{image}` (linux/amd64, linux/arm64); also `:latest`. "
|
||||
"amd64 is published first; arm64 is added to the same tag when its build "
|
||||
"finishes, and `:latest` moves then.\n\n"
|
||||
latest = os.environ["LATEST"] == "true"
|
||||
body = (f"Container image: `{image}` (linux/amd64, linux/arm64)"
|
||||
+ ("; also `:latest`. " if latest else ". `:latest` stays on the newer series. ")
|
||||
+ "amd64 is published first; arm64 is added to the same tag when its build finishes"
|
||||
+ (", and `:latest` moves then.\n\n" if latest else ".\n\n")
|
||||
"Binaries for a host install are attached: `inbuxa-linux-amd64.tar.gz` and "
|
||||
"`inbuxa-linux-arm64.tar.gz`, with `SHA256SUMS`. Each is the binary out of this "
|
||||
"release's image for that architecture, so it is the same build. The image "
|
||||
|
||||
@@ -176,6 +176,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.v.outputs.version }}
|
||||
latest: ${{ steps.latest.outputs.latest }}
|
||||
steps:
|
||||
# Full history, and every branch as origin/*: the ancestry check cannot
|
||||
# be answered from a shallow clone.
|
||||
@@ -205,6 +206,26 @@ jobs:
|
||||
[ -n "$on" ] || { echo "$TAG is not on main or a release/* branch" >&2; exit 1; }
|
||||
echo "$TAG is on $on"
|
||||
echo "version=$V" >> "$GITHUB_OUTPUT"
|
||||
# inbuxa: :latest belongs to the newest series. Until 27.1 ships it is
|
||||
# 2026.x's; once a final release numbered by series exists (v27.1,
|
||||
# v27.1.3), a 2026.x security release from this branch leaves :latest,
|
||||
# GHCR's :latest and the GitHub "latest release" where they are. The
|
||||
# check fails rather than guess: a wrong :latest is worse than a re-run.
|
||||
- id: latest
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
newer="$(curl -fsS --retry 5 --retry-all-errors --retry-delay 10 -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_URL/api/v1/repos/$GITHUB_REPOSITORY/releases?draft=false&pre-release=false&limit=50" |
|
||||
jq -r '[.[].tag_name | select(test("^v[0-9]{1,3}\\."))] | first // ""')"
|
||||
if [ -n "$newer" ]; then
|
||||
echo "$newer is out: :latest stays on its series"
|
||||
echo "latest=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "no series release yet: :latest moves"
|
||||
echo "latest=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Each architecture on its own native runner, side by side. The Dockerfile
|
||||
# cross-compiles from the build platform, and on the self-hosted runners one
|
||||
@@ -273,6 +294,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.version.outputs.version }}
|
||||
LATEST: ${{ needs.version.outputs.latest }}
|
||||
steps:
|
||||
- run: echo "IMAGE=${{ vars.REGISTRY }}/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"
|
||||
- uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0
|
||||
@@ -282,9 +304,9 @@ jobs:
|
||||
username: jcoffey-dev
|
||||
password: ${{ secrets.GITEA_TOKEN }}
|
||||
- run: |
|
||||
docker buildx imagetools create \
|
||||
--tag "$IMAGE:$VERSION" \
|
||||
--tag "$IMAGE:latest" \
|
||||
tags=(--tag "$IMAGE:$VERSION")
|
||||
[ "$LATEST" = true ] && tags+=(--tag "$IMAGE:latest")
|
||||
docker buildx imagetools create "${tags[@]}" \
|
||||
"$IMAGE:$VERSION-amd64" "$IMAGE:$VERSION-arm64"
|
||||
docker buildx imagetools inspect "$IMAGE:$VERSION"
|
||||
# Gitea keeps a container package on its owner; linking it shows it on
|
||||
@@ -308,6 +330,7 @@ jobs:
|
||||
- env:
|
||||
TAG: ${{ github.ref_name }}
|
||||
VERSION: ${{ needs.version.outputs.version }}
|
||||
LATEST: ${{ needs.version.outputs.latest }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
REGISTRY: ${{ vars.REGISTRY }}
|
||||
run: |
|
||||
@@ -317,7 +340,9 @@ jobs:
|
||||
if [ "$code" = 200 ]; then echo "$TAG already has a release"; exit 0; fi
|
||||
[ "$code" = 404 ] || { echo "looking up the release for $TAG answered $code" >&2; exit 1; }
|
||||
image="$REGISTRY/${GITHUB_REPOSITORY,,}:$VERSION"
|
||||
body="Container image: \`$image\` (linux/amd64, linux/arm64); also \`:latest\`.
|
||||
also="; also \`:latest\`."
|
||||
[ "$LATEST" = true ] || also=". \`:latest\` stays on the newer series."
|
||||
body="Container image: \`$image\` (linux/amd64, linux/arm64)$also
|
||||
|
||||
Binaries for a host install are attached: \`inbuxa-linux-amd64.tar.gz\` and \`inbuxa-linux-arm64.tar.gz\`, with \`SHA256SUMS\`. Each is the binary out of this release's image for that architecture, so it is the same build. The image grants it \`cap_net_bind_service\`; a host install has to grant that itself (\`setcap\`, or \`AmbientCapabilities\` in the unit) to bind port 25."
|
||||
jq -n --arg tag "$TAG" --arg name "INBUXA $VERSION" --arg body "$body" \
|
||||
@@ -398,13 +423,16 @@ jobs:
|
||||
- env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.version.outputs.version }}
|
||||
LATEST: ${{ needs.version.outputs.latest }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
src="${{ vars.REGISTRY }}/${GITHUB_REPOSITORY,,}"
|
||||
dst="ghcr.io/${GITHUB_REPOSITORY,,}"
|
||||
tag="$TAG"
|
||||
echo "$GH_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin
|
||||
docker buildx imagetools create -t "$dst:$tag" -t "$dst:latest" "$src:$tag"
|
||||
tags=(-t "$dst:$tag")
|
||||
[ "$LATEST" = true ] && tags+=(-t "$dst:latest")
|
||||
docker buildx imagetools create "${tags[@]}" "$src:$tag"
|
||||
want="$(docker buildx imagetools inspect "$src:$tag" --format '{{json .Manifest.Digest}}')"
|
||||
got="$(docker buildx imagetools inspect "$dst:$tag" --format '{{json .Manifest.Digest}}')"
|
||||
echo "registry $src:$tag = $want"
|
||||
@@ -420,7 +448,7 @@ jobs:
|
||||
# rewritten to Gitea links: on GitHub a bare #16 is some other PR.
|
||||
github-release:
|
||||
if: ${{ vars.BUILD_ON == 'github' && github.ref_type == 'tag' }}
|
||||
needs: [binaries]
|
||||
needs: [version, binaries]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -428,6 +456,7 @@ jobs:
|
||||
GITEA_URL: ${{ vars.GITEA_URL }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
LATEST: ${{ needs.version.outputs.latest }}
|
||||
steps:
|
||||
- run: |
|
||||
set -euo pipefail
|
||||
@@ -454,7 +483,9 @@ jobs:
|
||||
curl -fsSL -o "files/$name" "$url"; files+=("files/$name")
|
||||
done < <(jq -r '.assets[]? | [.name, .browser_download_url] | @tsv' rel.json)
|
||||
title="$(jq -r '.name // ""' rel.json)"; [ -n "$title" ] || title="$TAG"
|
||||
if [ "$(jq -r .prerelease rel.json)" = true ]; then kind=--prerelease; else kind=--latest; fi
|
||||
if [ "$(jq -r .prerelease rel.json)" = true ]; then kind=--prerelease
|
||||
elif [ "$LATEST" = true ]; then kind=--latest
|
||||
else kind=--latest=false; fi
|
||||
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --verify-tag --title "$title" \
|
||||
--notes-file notes.md "$kind" "${files[@]}"
|
||||
echo "created the GitHub release for $TAG with ${#files[@]} file(s)"
|
||||
|
||||
Reference in new issue
Block a user