All checks were successful
Build Cronicle image / build (push) Successful in 43s
119 lines
4.8 KiB
YAML
119 lines
4.8 KiB
YAML
name: Build Cronicle image
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
# Nightly upstream check. 13:00 UTC / 6AM Pacific, deliberately offset from
|
|
# aws-zig's 12:30 nightly because the runner has capacity: 1.
|
|
schedule:
|
|
- cron: '0 13 * * *'
|
|
push:
|
|
branches:
|
|
- master
|
|
|
|
env:
|
|
# Hardcoded rather than derived from ${{ github.repository }}: the packaging
|
|
# repo is cronicle-docker, but the image it produces is plain Cronicle.
|
|
IMAGE: git.lerch.org/lobo/cronicle
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
image: ghcr.io/catthehacker/ubuntu:act-22.04
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
|
|
# Upstream publishes a GitHub Release per tag, so releases/latest is the
|
|
# authoritative "newest stable" pointer. Cronicle is marked
|
|
# "private": true in package.json, so npm is not an option -- the
|
|
# Dockerfile builds from the release tarball.
|
|
#
|
|
# NOTE: every `run:` block here is POSIX sh. The runner executes these
|
|
# with dash, which has no `set -o pipefail`. Rather than depend on shell
|
|
# selection, the fetch and the parse are separate statements: under
|
|
# `set -e`, an assignment from a failing command substitution aborts, so
|
|
# `curl -f` failing is caught without needing pipefail.
|
|
- name: Resolve latest upstream Cronicle version
|
|
id: upstream
|
|
run: |
|
|
set -eu
|
|
release_json="$(curl -fsSL https://api.github.com/repos/jhuckaby/Cronicle/releases/latest)"
|
|
version="$(printf '%s' "$release_json" | jq -r '.tag_name // empty' | sed 's/^v//')"
|
|
if [ -z "$version" ]; then
|
|
echo "Could not resolve upstream Cronicle version" >&2
|
|
exit 1
|
|
fi
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
echo "Upstream latest release: v$version"
|
|
|
|
- name: Compute image tags
|
|
id: tags
|
|
run: |
|
|
set -eu
|
|
shortsha="$(git rev-parse --short HEAD)"
|
|
echo "shortsha=$shortsha" >> "$GITHUB_OUTPUT"
|
|
echo "immutable=${{ steps.upstream.outputs.version }}-$shortsha" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Login to Gitea
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: git.lerch.org
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.PACKAGE_PUSH }}
|
|
|
|
# Set up before the existence check below, which uses buildx.
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
# The immutable tag encodes BOTH the upstream version and the packaging
|
|
# commit, so this single check covers both reasons to rebuild: a new
|
|
# Cronicle release, or a change to this repo. Nightly runs that find
|
|
# nothing new become a no-op with no state file to maintain.
|
|
#
|
|
# `buildx imagetools inspect` rather than `docker manifest inspect`:
|
|
# Forgejo's registry serves OCI media types
|
|
# (application/vnd.oci.image.manifest.v1+json) and authenticates via the
|
|
# Bearer token flow. imagetools handles both natively, whereas
|
|
# `docker manifest inspect` fails outright on OCI manifests with older
|
|
# docker CLIs ("unsupported manifest media type and no default
|
|
# available"). imagetools reuses the credentials login-action just wrote.
|
|
- name: Skip if this exact image was already built
|
|
id: check
|
|
run: |
|
|
set -u
|
|
tag="${IMAGE}:${{ steps.tags.outputs.immutable }}"
|
|
if docker buildx imagetools inspect "$tag" >/dev/null 2>&1; then
|
|
echo "exists=true" >> "$GITHUB_OUTPUT"
|
|
echo "$tag is already published; nothing to do."
|
|
else
|
|
echo "exists=false" >> "$GITHUB_OUTPUT"
|
|
echo "$tag not found; building."
|
|
fi
|
|
|
|
# Three tags: one immutable (what deployments should pin), two moving.
|
|
- name: Build and push
|
|
if: steps.check.outputs.exists == 'false'
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
push: true
|
|
build-args: |
|
|
CRONICLE_VERSION=${{ steps.upstream.outputs.version }}
|
|
tags: |
|
|
${{ env.IMAGE }}:${{ steps.tags.outputs.immutable }}
|
|
${{ env.IMAGE }}:${{ steps.upstream.outputs.version }}
|
|
${{ env.IMAGE }}:latest
|
|
|
|
# Only ping when a build was actually attempted -- a nightly "nothing to
|
|
# do" notification 365 times a year is noise. Uses != 'true' rather than
|
|
# == 'false' so that a failure *before* the check step still notifies.
|
|
- name: Notify
|
|
uses: https://git.lerch.org/lobo/action-notify-ntfy@v2
|
|
if: always() && steps.check.outputs.exists != 'true'
|
|
with:
|
|
host: ${{ secrets.NTFY_HOST }}
|
|
topic: ${{ secrets.NTFY_TOPIC }}
|
|
status: ${{ job.status }}
|
|
user: ${{ secrets.NTFY_USER }}
|
|
password: ${{ secrets.NTFY_PASSWORD }}
|