Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions .github/workflows/action-image-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,36 @@ jobs:
fi

chan_tag_version="${chan_upstream_version//+/-}"

# An app's stable channels all share one package — ubuntu publishes
# noble, jammy and focal as `ubuntu:` — so when every one of them
# writes the floating `:rolling` tag it is last-build-wins, and
# `ubuntu:rolling` flips between OS releases behind consumers' backs
# (it silently went 24.04 -> 20.04 on 2026-08-12). A stable channel
# now owns `:rolling` only when it claims it with "rolling": true, or
# when it is the app's only stable channel. Non-stable channels each
# get their own `${app}-${channel}` package, so they cannot collide.
#
# Moving ownership between channels needs a manual rebuild of the new
# owner ("Release: Manual", app + channel, push=true). image-rebuild
# deliberately ignores apps/**/metadata.json — the build writes
# publishedVersion back into it, so triggering on it would loop — and
# the scheduled fetch only builds on a version change, so a
# metadata-only ownership commit leaves `:rolling` on the old owner's
# image until the new owner next builds.
chan_stable_total=$(jq '[.channels[] | select(.stable == true)] | length' ./apps/${{ matrix.image.app }}/metadata.json)
chan_rolling_total=$(jq '[.channels[] | select(.stable == true and .rolling == true)] | length' ./apps/${{ matrix.image.app }}/metadata.json)
chan_rolling=$(jq --raw-output '.rolling // false' <<< "${chan_config}")

if [[ "${chan_stable}" == true ]]; then
if (( chan_stable_total > 1 )) && (( chan_rolling_total != 1 )); then
echo "::error::${{ matrix.image.app }} has ${chan_stable_total} stable channels but ${chan_rolling_total} marked \"rolling\": true — exactly one must own the floating :rolling tag"
exit 1
fi
echo "::set-output name=chan_tag_testing::${{ matrix.image.app }}:testingz"
echo "::set-output name=chan_tag_rolling::${{ matrix.image.app }}:rolling"
if (( chan_stable_total == 1 )) || [[ "${chan_rolling}" == true ]]; then
echo "::set-output name=chan_tag_rolling::${{ matrix.image.app }}:rolling"
fi
echo "::set-output name=chan_tag_version::${{ matrix.image.app }}:${chan_tag_version}"
else
echo "::set-output name=chan_tag_testing::${{ matrix.image.app }}-${{ matrix.image.channel }}:testingz"
Expand Down Expand Up @@ -517,9 +544,11 @@ jobs:
platforms: ${{ steps.vars.outputs.chan_platforms }}
file: ${{ steps.vars.outputs.chan_dockerfile }}
push: ${{ inputs.pushImages == 'true' }}
# chan_tag_rolling is unset for a stable channel that doesn't own the
# floating tag; build-push-action skips the resulting empty line.
tags: |-
ghcr.io/${{ github.repository_owner }}/${{ steps.vars.outputs.chan_tag_rolling }}
ghcr.io/${{ github.repository_owner }}/${{ steps.vars.outputs.chan_tag_version }}
${{ steps.vars.outputs.chan_tag_rolling && format('ghcr.io/{0}/{1}', github.repository_owner, steps.vars.outputs.chan_tag_rolling) || '' }}
cache-from: type=gha
cache-to: type=gha,mode=max

Expand Down
2 changes: 1 addition & 1 deletion apps/kavita/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG VERSION

FROM jvmilazz0/kavita:nightly-${VERSION} as upstream
FROM ghcr.io/elfhosted/ubuntu:rolling@sha256:dd5112a70dbae5ae5c53126969b9168c7ef2141576938272f7bff8d194be4823
FROM ghcr.io/elfhosted/ubuntu:noble-20260730.1@sha256:7d06c5e6e4f39b2d7b88a0a439207bfd6d7c31474c75ad8969f621cabddcd96a

# for initial install
USER root
Expand Down
2 changes: 1 addition & 1 deletion apps/ombi/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/elfhosted/ubuntu:rolling@sha256:dd5112a70dbae5ae5c53126969b9168c7ef2141576938272f7bff8d194be4823
FROM ghcr.io/elfhosted/ubuntu:noble-20260730.1@sha256:7d06c5e6e4f39b2d7b88a0a439207bfd6d7c31474c75ad8969f621cabddcd96a

ARG TARGETPLATFORM
ARG BUILDPLATFORM
Expand Down
2 changes: 1 addition & 1 deletion apps/openbooks/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG VERSION
FROM ghcr.io/evan-buss/openbooks:${VERSION} as upstream
FROM ghcr.io/elfhosted/ubuntu:rolling@sha256:dd5112a70dbae5ae5c53126969b9168c7ef2141576938272f7bff8d194be4823
FROM ghcr.io/elfhosted/ubuntu:noble-20260730.1@sha256:7d06c5e6e4f39b2d7b88a0a439207bfd6d7c31474c75ad8969f621cabddcd96a

# default to ephemeral storage
ENV DATA_DIR=/config
Expand Down
2 changes: 1 addition & 1 deletion apps/plextraktsync/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/elfhosted/ubuntu:rolling@sha256:dd5112a70dbae5ae5c53126969b9168c7ef2141576938272f7bff8d194be4823
FROM ghcr.io/elfhosted/ubuntu:noble-20260730.1@sha256:7d06c5e6e4f39b2d7b88a0a439207bfd6d7c31474c75ad8969f621cabddcd96a

RUN apt-get -y update && apt-get -y install curl tmux pipx python3.8-venv

Expand Down
2 changes: 1 addition & 1 deletion apps/resilio-sync/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/elfhosted/ubuntu:rolling@sha256:dd5112a70dbae5ae5c53126969b9168c7ef2141576938272f7bff8d194be4823
FROM ghcr.io/elfhosted/ubuntu:noble-20260730.1@sha256:7d06c5e6e4f39b2d7b88a0a439207bfd6d7c31474c75ad8969f621cabddcd96a

# set version label
ARG BUILD_DATE
Expand Down
1 change: 1 addition & 0 deletions apps/ubuntu/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"linux/arm64"
],
"stable": true,
"rolling": true,
"tests": {
"enabled": false,
"type": "cli"
Expand Down
2 changes: 1 addition & 1 deletion apps/wireguard/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/elfhosted/ubuntu:rolling@sha256:dd5112a70dbae5ae5c53126969b9168c7ef2141576938272f7bff8d194be4823
FROM ghcr.io/elfhosted/ubuntu:noble-20260730.1@sha256:7d06c5e6e4f39b2d7b88a0a439207bfd6d7c31474c75ad8969f621cabddcd96a

ARG VERSION
USER root
Expand Down
4 changes: 4 additions & 0 deletions metadata.rules.cue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
name: #NonEmptyString
platforms: [...#AcceptedPlatforms]
stable: bool
// Stable channels of one app share a package, so only one of them may own
// the floating `:rolling` tag. Required when an app has more than one
// stable channel; implicit (and unnecessary) when it has exactly one.
rolling?: bool
tests: {
enabled: bool
type?: =~"^(cli|web)$"
Expand Down