Self-destructing hotfixes with updatecli

lois.postu.la · 2026-09-30 · by Long Nguyen ·generic

Self-destructing hotfixes with updatecli

Table of Contents

podman 5.8.7 broke every `uses:` step on our Forgejo runners (podman#29805). The hotfix moved the runners to Docker. We also added two updatecli policies: one to propose reverting the hotfix, and one to remove both policies afterwards.

We already use updatecli to keep dependencies up to date. Its sources, conditions, targets and PR actions work for this too: read the installed version, check upstream, then propose a git revert.

When to revert #

The policies run daily:

1. Read podman’s version from the nixpkgs locked in our nix repo. 2. If it is newer than 5.8.7 and the upstream issue is closed, open a PR reverting the Docker workaround. 3. When the cleanup policy detects that the workaround is gone, open a PR deleting both policies and their workflow entries.

The version comes from our pinned nixpkgs, because an upstream release alone would not change what our runners use:

command: nix eval --raw --impure --expr '(builtins.getFlake (toString ./.)).inputs.nixpkgs.legacyPackages.x86_64-linux.podman.version'

These are the revert conditions, with the repository wiring omitted:

upstream-closed:
  kind: json
  disablesourceinput: true
  spec:
    file: https://api.github.com/repos/podman-container-tools/podman/issues/29805
    key: state
    value: closed
fixed:
  kind: shell
  sourceid: podman
  spec:
    command: sh -c '[ "$(printf "%s\n" 5.8.7 "$1" | sort -V | tail -n1)" != 5.8.7 ]' --
workaround-present:
  kind: file
  disablesourceinput: true
  spec:
    file: modules/forgejo-runner.nix
    matchpattern: 'virtualisation\.docker'

A newer version and a closed issue are enough to ask for a review, but they do not prove that our package contains the fix. The PR body asks the reviewer to check the release notes for the buildah copier change before merging, then re-run an `ubuntu-latest` job using `actions/checkout` after deployment.

Reverting and cleaning up #

The revert target runs this shell command in the nix repo:

sh -c '
  set -- $(git log -1 -F --grep="(#255)" --format="%H %P")
  [ $# -gt 0 ] || { echo "o27/nix#255 is not on the branch" >&2; exit 2; }
  commit=$1; mainline=""
  [ $# -gt 2 ] && mainline="-m 1"
  [ "$DRY_RUN" = true ] && { echo "would revert $commit"; exit 0; }
  git revert --no-commit $mainline "$commit" || { git revert --abort; exit 2; }
  git diff --cached --quiet && exit 1
  exit 0
'

It finds the hotfix by the `(#255)` marker in its commit message. Reverting that commit also removes the comments explaining the workaround. Both shell targets check `DRY_RUN`, so PR checks report the proposed changes without applying them.

The cleanup policy checks the nix repo for two things: the hotfix’s commit message is in the history, and `modules/forgejo-runner.nix` no longer contains `virtualisation.docker`. Checking only for Docker’s absence would also pass before the hotfix merged.

That is our proxy for a merged revert; it does not inspect the revert PR’s status. The cleanup target then opens a PR in the gitops repo, deleting both policy files and removing their entries from the updatecli workflow.

Full updatecli policies

These use our existing `nix_ci` values and credentials from the environment.

forgejo-runner-podman.yaml

# Temporary: o27/nix#255 moved the Forgejo runners to Docker because podman 5.8.7

cannot copy actions into /var/run/act (podman#29805). This proposes reverting

that PR once the pinned nixpkgs carries a newer podman;

forgejo-runner-podman-cleanup.yaml then deletes both policies.

name: Revert the Forgejo runner Docker workaround {{ if .nix_ci.enabled }} scms: nix: kind: gitea spec: url: '{{ .nix_ci.url }}' owner: '{{ .nix_ci.owner }}' repository: '{{ .nix_ci.repository }}' branch: '{{ .nix_ci.branch }}' token: '{{ requiredEnv "GITEA_TOKEN" }}' user: '{{ requiredEnv "UPDATECLI_GIT_USER" }}' email: '{{ requiredEnv "UPDATECLI_GIT_EMAIL" }}' gpg: signingkey: {{ requiredEnv "UPDATECLI_GPG_PRIVATE_KEY" | quote }} passphrase: {{ env "UPDATECLI_GPG_PASSPHRASE" | quote }} commitmessage: type: revert scope: forgejo-runner hidecredit: true footers: 'Signed-off-by: {{ requiredEnv "UPDATECLI_GIT_USER" }} <{{ requiredEnv "UPDATECLI_GIT_EMAIL" }}>' {{ end }}

sources: podman: name: podman version in the nixpkgs pinned by o27/nix kind: shell {{ if .nix_ci.enabled }} scmid: nix {{ end }} spec: command: nix eval --raw --impure --expr '(builtins.getFlake (toString ./.)).inputs.nixpkgs.legacyPackages.x86_64-linux.podman.version' environments: - name: PATH - name: HOME

conditions: # A newer podman alone does not prove the buildah copier change was relaxed. upstream-closed: name: podman#29805 is closed kind: json disablesourceinput: true spec: file: https://api.github.com/repos/podman-container-tools/podman/issues/29805 key: state value: closed fixed: name: the pinned podman is newer than 5.8.7 kind: shell sourceid: podman spec: command: sh -c '[ "$(printf "%s\n" 5.8.7 "$1" | sort -V | tail -n1)" != 5.8.7 ]' -- environments: - name: PATH # Without it the revert would be proposed again, and fail, once it has merged. workaround-present: name: o27/nix still runs the runners on Docker kind: file disablesourceinput: true {{ if .nix_ci.enabled }} scmid: nix {{ end }} spec: file: modules/forgejo-runner.nix matchpattern: 'virtualisation\.docker'

targets: revert: name: revert o27/nix#255 kind: shell disablesourceinput: true {{ if .nix_ci.enabled }} scmid: nix {{ end }} spec: # Reverting the merge rather than editing the module also drops the comments that justified the workaround. # updatecli runs this under DRY_RUN=true in diff mode, so it only reports there. command: | sh -c ' set -- $(git log -1 -F --grep="(#255)" --format="%H %P") [ $# -gt 0 ] || { echo "o27/nix#255 is not on the branch" >&2; exit 2; } commit=$1; mainline="" [ $# -gt 2 ] && mainline="-m 1" [ "$DRY_RUN" = true ] && { echo "would revert $commit"; exit 0; } git revert --no-commit $mainline "$commit" || { git revert --abort; exit 2; } git diff --cached --quiet && exit 1 exit 0 ' environments: - name: PATH - name: HOME changedif: kind: exitcode spec: warning: 0 success: 1 failure: 2 {{ if .nix_ci.enabled }} actions: nix: kind: gitea/pullrequest scmid: nix title: 'revert(forgejo-runner): go back to podman {{ source "podman" }}' spec: url: '{{ .nix_ci.url }}' owner: '{{ .nix_ci.owner }}' repository: '{{ .nix_ci.repository }}' body: | Reverts o27/nix#255. The pinned nixpkgs now carries podman {{ source "podman" }}, newer than the 5.8.7 that broke action copies into /var/run/act (podman#29805).

A newer version is not proof of the fix: check the podman release notes for the buildah copier change before merging. After the deploy, re-run an ubuntu-latest job that uses actions/checkout.

Once this merges, forgejo-runner-podman-cleanup.yaml in o27/gitops opens the PR that deletes both policies. {{ end }}

forgejo-runner-podman-cleanup.yaml

# Temporary: deletes itself and forgejo-runner-podman.yaml once o27/nix has

reverted the #255 Docker workaround.

name: Remove the Forgejo runner podman policies {{ if .nix_ci.enabled }} scms: nix: kind: gitea spec: url: '{{ .nix_ci.url }}' owner: '{{ .nix_ci.owner }}' repository: '{{ .nix_ci.repository }}' branch: '{{ .nix_ci.branch }}' token: '{{ requiredEnv "GITEA_TOKEN" }}' gitops: kind: gitea spec: url: '{{ .nix_ci.url }}' owner: '{{ .nix_ci.owner }}' repository: gitops branch: main token: '{{ requiredEnv "GITEA_TOKEN" }}' user: '{{ requiredEnv "UPDATECLI_GIT_USER" }}' email: '{{ requiredEnv "UPDATECLI_GIT_EMAIL" }}' gpg: signingkey: {{ requiredEnv "UPDATECLI_GPG_PRIVATE_KEY" | quote }} passphrase: {{ env "UPDATECLI_GPG_PASSPHRASE" | quote }} commitmessage: type: chore scope: updatecli hidecredit: true footers: 'Signed-off-by: {{ requiredEnv "UPDATECLI_GIT_USER" }} <{{ requiredEnv "UPDATECLI_GIT_EMAIL" }}>' {{ end }}

conditions: # "Workaround gone" alone is also true before #255 merges, which would delete the policies before they ran. reverted: name: o27/nix merged PR 255 and no longer runs the runners on Docker kind: shell disablesourceinput: true {{ if .nix_ci.enabled }} scmid: nix {{ end }} spec: command: sh -c 'git log -1 -F --grep="(#255)" --format=%H | grep -q . && ! grep -q "virtualisation\.docker" modules/forgejo-runner.nix' environments: - name: PATH

targets: remove: name: delete both policies and their workflow entries kind: shell disablesourceinput: true {{ if .nix_ci.enabled }} scmid: gitops {{ end }} spec: command: | sh -c ' [ -e updatecli/nix-ci.d/forgejo-runner-podman.yaml ] || exit 1 [ "$DRY_RUN" = true ] && { echo "would delete the forgejo-runner-podman policies"; exit 0; } git rm -q updatecli/nix-ci.d/forgejo-runner-podman.yaml updatecli/nix-ci.d/forgejo-runner-podman-cleanup.yaml || exit 2 sed -i "/nix-ci\.d\/forgejo-runner-podman/d" .forgejo/workflows/updatecli.yaml || exit 2 exit 0 ' environments: - name: PATH changedif: kind: exitcode spec: warning: 0 success: 1 failure: 2 {{ if .nix_ci.enabled }} actions: gitops: kind: gitea/pullrequest scmid: gitops title: 'chore(updatecli): remove the Forgejo runner podman policies' spec: url: '{{ .nix_ci.url }}' owner: '{{ .nix_ci.owner }}' repository: gitops body: | o27/nix has merged the revert of #255, so the runners are back on podman and these two policies have nothing left to do. {{ end }}

lois.postu.la · 1 images · 21 links

Comments (0)

No comments yet