The old server name and the account the repositories live under were still scattered through comments, doc prose and one line of dashboard copy. None of those readings told anyone anything: neither name is what anything is called now, and a comment that explains a value in terms of a name nobody uses explains nothing. Values are untouched, and that distinction is the whole rule. The legacy backup type string, the pre-rename UserDefaults key, the pre-rename host in the User-Agent allowlist and the registry namespaces are all things somebody else already stored; rewriting one breaks an install rather than tidying it. So the sentences changed and the strings did not, and AGENTS.md now lists exactly which hits a sweep is supposed to keep finding. The feed's blocklist grows the second name, so a future message cannot put it back on a page anyone can load. Its fixtures name both on purpose: that test is the proof the feed never publishes them, and it cannot show that without saying them once. Also states the thing that had been left implicit: FTStore Admin is the dashboard and the console app together, so an operator-facing control that lands in only one of them is half-built.
91 lines
3.7 KiB
YAML
91 lines
3.7 KiB
YAML
name: Web Delete Release
|
|
# Deletes a FTStore Admin (web/) release, images included. Only the `web-v*`
|
|
# namespace: this refuses `v*` and `manager-v*` outright rather than trusting
|
|
# the confirmation field, because a hand-typed tag is the one input that can
|
|
# take out the release an installed app is currently resolving updates from.
|
|
#
|
|
# The two app namespaces are not left to pile up — `stable-release.yml` retires
|
|
# their older releases itself, keeping the newest and trimming the AltStore
|
|
# version history to match. That path knows which release it just published;
|
|
# this one only knows what someone typed.
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "Release tag to delete (e.g. web-v0.1)"
|
|
required: true
|
|
type: string
|
|
confirm:
|
|
description: "Type the tag again to confirm deletion"
|
|
required: true
|
|
type: string
|
|
|
|
jobs:
|
|
delete:
|
|
name: Delete Release & Tag
|
|
runs-on: [self-hosted, linux, x64]
|
|
permissions:
|
|
contents: write
|
|
packages: write
|
|
steps:
|
|
- name: Confirm deletion
|
|
run: |
|
|
if [ "${{ inputs.tag }}" != "${{ inputs.confirm }}" ]; then
|
|
echo "::error::Confirmation does not match. You entered '${{ inputs.confirm }}' but expected '${{ inputs.tag }}'"
|
|
exit 1
|
|
fi
|
|
if [[ ! "${{ inputs.tag }}" =~ ^web-v ]]; then
|
|
echo "::error::This workflow only deletes web-v* releases. '${{ inputs.tag }}' is not one — the app's v* releases are not deletable from here."
|
|
exit 1
|
|
fi
|
|
|
|
- name: Delete GitHub Release
|
|
continue-on-error: true
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
gh release delete "${{ inputs.tag }}" --repo "${{ github.repository }}" --yes --cleanup-tag && \
|
|
echo "Deleted release and tag: ${{ inputs.tag }}" || \
|
|
echo "No release found for ${{ inputs.tag }}, skipping"
|
|
|
|
- name: Delete orphan tag
|
|
continue-on-error: true
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
git ls-remote --tags "https://github.com/${{ github.repository }}" "${{ inputs.tag }}" | grep -q . && \
|
|
gh api --method DELETE "repos/${{ github.repository }}/git/refs/tags/${{ inputs.tag }}" && \
|
|
echo "Deleted orphan tag: ${{ inputs.tag }}" || \
|
|
echo "No tag found for ${{ inputs.tag }}, skipping"
|
|
|
|
- name: Delete Docker images
|
|
continue-on-error: true
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
TAG="${{ inputs.tag }}"
|
|
# web-release.yml pushes `vX.Y` — the git tag minus the namespace.
|
|
# `X.Y` is what the pre-rename semver rule produced; still matched so
|
|
# images from before the rename can be cleaned up too.
|
|
VERSION="${TAG#web-}"
|
|
BARE="${VERSION#v}"
|
|
OWNER="${{ github.repository_owner }}"
|
|
|
|
for IMAGE in ftstore-admin-app ftstore-admin-worker; do
|
|
# Find the image version ID
|
|
VERSION_ID=$(gh api \
|
|
"orgs/${OWNER}/packages/container/${IMAGE}/versions" \
|
|
--jq ".[] | select(.metadata.container.tags | index(\"${VERSION}\") or index(\"${BARE}\")) | .id" 2>/dev/null || true)
|
|
|
|
if [ -n "$VERSION_ID" ]; then
|
|
gh api --method DELETE \
|
|
"orgs/${OWNER}/packages/container/${IMAGE}/versions/${VERSION_ID}" 2>/dev/null || \
|
|
gh api --method DELETE \
|
|
"users/${OWNER}/packages/container/${IMAGE}/versions/${VERSION_ID}" 2>/dev/null || true
|
|
echo "Deleted ${IMAGE}:${VERSION}"
|
|
else
|
|
echo "No image found for ${IMAGE}:${VERSION}"
|
|
fi
|
|
done
|