3 Commits
Author SHA1 Message Date
wayfinderak 9ddab5f1fa feat(delivery): publish immutable source images and declare release
Build and Push Container / docker (pull_request) Failing after 5s
2026-09-11 08:53:23 +00:00
wayfinderak 8502885a9d Cancel superseded pull request validation without cancelling releases 2026-09-11 08:47:07 +00:00
wayfinderak 20c1efb8a3 Scope documentation CI and isolate delivery job resources 2026-09-11 08:10:38 +00:00
4 changed files with 86 additions and 6 deletions
+5
View File
@@ -0,0 +1,5 @@
# Service release contract
Butler resolves this repository's protected source revision to verified immutable images. The platform updates only image references in the existing production Compose file and restarts only the already running application services. It preserves current environment, storage, routes, and provider configuration. It retains previous application images and restores them if readiness fails.
Migration and maintenance images are pinned when declared, but this release operation does not run database migrations or maintenance jobs. A release requiring a schema change needs the corresponding explicit platform migration first. No homelab image-pin commit is required for an ordinary compatible application release.
+12
View File
@@ -0,0 +1,12 @@
{
"version": 1,
"deployment": "prepbot-release",
"environment": "production",
"images": {
"prepbot_release_prepbot_image": {
"name": "prepbot",
"tag": "sha-{revision}"
}
},
"revision_variable": "prepbot_release_revision"
}
+30 -6
View File
@@ -3,30 +3,50 @@ name: Build and Push Container
on:
push:
branches:
- master
- main
- main
tags:
- v*
workflow_dispatch:
- v*
workflow_dispatch: null
pull_request:
branches:
- main
env:
REGISTRY: gitea.wayfinderak.com
IMAGE_NAME: wayfinderak/prepbot
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number
|| github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
docker:
runs-on: ubuntu-latest
runs-on: butler-ci
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Select relevant delivery work
id: delivery
env:
DELIVERY_EVENT: ${{ github.event_name }}
DELIVERY_REF: ${{ github.ref }}
DELIVERY_SHA: ${{ github.sha }}
DELIVERY_BASE: ${{ github.event.pull_request.base.sha || github.event.before }}
run: |
cd .
bash scripts/ci-select.sh
- name: Set up QEMU
if: ${{ steps.delivery.outputs.run == 'true' }}
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: ${{ steps.delivery.outputs.run == 'true' }}
uses: docker/setup-buildx-action@v3
- name: Log in to Gitea registry
if: ${{ (steps.delivery.outputs.run == 'true') && github.event_name != 'pull_request' }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
@@ -34,11 +54,13 @@ jobs:
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Prepare image tags
if: ${{ steps.delivery.outputs.run == 'true' }}
id: prep
shell: bash
run: |
short_sha="${GITHUB_SHA::7}"
tags="${REGISTRY}/${IMAGE_NAME}:sha-${short_sha}"
tags+=$'\n'"${REGISTRY}/${IMAGE_NAME}:sha-${GITHUB_SHA}"
if [[ "${GITHUB_REF_TYPE}" == "branch" && ("${GITHUB_REF_NAME}" == "master" || "${GITHUB_REF_NAME}" == "main") ]]; then
tags+=$'\n'"${REGISTRY}/${IMAGE_NAME}:latest"
@@ -56,9 +78,11 @@ jobs:
} >> "$GITHUB_OUTPUT"
- name: Build and push image
if: ${{ steps.delivery.outputs.run == 'true' }}
uses: docker/build-push-action@v6
with:
context: .
push: true
push: ${{ github.event_name != 'pull_request' }}
platforms: linux/amd64,linux/arm64
tags: ${{ steps.prep.outputs.tags }}
labels: org.opencontainers.image.revision=${{ github.sha }}
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Keep required jobs alive; only skip reviewed non-runtime documentation paths.
set -euo pipefail
base="${DELIVERY_BASE:-}"
head="$(git rev-parse HEAD)"
run=true
if [[ "${DELIVERY_REF:-}" != refs/tags/* && "$head" == "${DELIVERY_SHA:-}" && "${DELIVERY_EVENT:-}" =~ ^(push|pull_request)$ && "$base" =~ ^[0-9a-f]{40}$ && "$base" != 0000000000000000000000000000000000000000 ]]; then
if ! git cat-file -e "$base^{commit}" 2>/dev/null; then
if [[ -n "${DELIVERY_FETCH_TOKEN:-}" ]]; then
git -c "http.extraHeader=Authorization: token ${DELIVERY_FETCH_TOKEN}" fetch --quiet --depth=1 origin "$base" >/dev/null 2>&1 || true
else
git fetch --quiet --depth=1 origin "$base" >/dev/null 2>&1 || true
fi
fi
if git cat-file -e "$base^{commit}" 2>/dev/null; then
paths="$(mktemp)"
trap 'rm -f -- "$paths"' EXIT
# Snapshot comparison is conservative when main advanced during a PR.
# Both rename sides remain visible, including names containing newlines.
if git diff --no-renames --name-only -z "$base" "$head" > "$paths"; then
run=false
while IFS= read -r -d '' path; do
case "$path" in
README.md|CHANGELOG.md|LICENSE|LICENSE.md) ;;
*) run=true; break ;;
esac
done < "$paths"
fi
fi
fi
if [[ "$run" == false ]]; then
echo 'Only reviewed non-runtime documentation changed; build and validation are not applicable.'
else
echo 'Runtime, unknown inputs, or unavailable event history: run required validation.'
fi
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
echo "run=$run" >> "$GITHUB_OUTPUT"
fi
printf '%s\n' "$run"