ci: fix release.yaml so v0.3.1+ auto-publishes a complete release
Some checks failed
ARM64 Build / Build generic ARM64 disk image (push) Failing after 3s
CI / Go Tests (push) Successful in 1m40s
CI / Shellcheck (push) Successful in 55s
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Successful in 1m16s
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Successful in 1m21s
Some checks failed
ARM64 Build / Build generic ARM64 disk image (push) Failing after 3s
CI / Go Tests (push) Successful in 1m40s
CI / Shellcheck (push) Successful in 55s
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Successful in 1m16s
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Successful in 1m21s
Three changes that should have happened pre-v0.3.0:
1. Add a build-disk-arm64 job that runs on the arm64-linux runner (Odroid),
building kernel + rootfs + disk-image then xz-compressing the .arm64.img.
The previous release.yaml shipped x86_64 only.
2. Replace softprops/action-gh-release@v2 with a direct curl against Gitea's
/api/v1/repos/<owner>/<repo>/releases endpoint. The softprops action
hard-codes api.github.com instead of honouring ${{ github.api_url }},
so on Gitea's act_runner it succeeds silently without creating a
release. The curl path uses the auto-populated ${{ secrets.GITHUB_TOKEN }}
for auth; doc note in ci-runners.md covers the GITEA_TOKEN fallback.
3. Downgrade actions/upload-artifact and actions/download-artifact from
@v4 to @v3 to match Gitea act_runner v1.0.x's compatibility — same fix
we applied to ci.yaml in 0c6e200.
Also compress the x86 disk image with xz before uploading (parity with
the arm64 path, saves ~95% on bandwidth), and emit SHA256SUMS over all
attached artifacts.
docs/ci-runners.md gains a "Workflows in this repo" table, a per-job
breakdown of the release pipeline, the rationale for direct-curl over
the marketplace action, and a "manually re-running a release" section
warning against force-updating published tags.
This commit fixes the workflow but does not retroactively rebuild v0.3.0.
v0.3.0's release page already has the manually-uploaded arm64 image and
SHA256SUMS; x86 users who want the v0.3.0 artifact build from source
(documented in the release body). v0.3.1 will be the first tag that
exercises the fixed workflow end-to-end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,19 @@
|
|||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
|
# Triggered by `git push origin vX.Y.Z`. Builds Go binaries (amd64+arm64),
|
||||||
|
# x86_64 ISO + disk image, ARM64 disk image, computes SHA256SUMS over all
|
||||||
|
# artifacts, and posts a Gitea release with everything attached via the
|
||||||
|
# Gitea API.
|
||||||
|
#
|
||||||
|
# Notes for future-you:
|
||||||
|
# - upload-artifact / download-artifact are pinned to @v3 because Gitea's
|
||||||
|
# act_runner v1.0.x doesn't fully implement v4 yet.
|
||||||
|
# - The release step uses curl against Gitea's own /api/v1/repos/.../releases
|
||||||
|
# instead of a third-party action (softprops/action-gh-release et al);
|
||||||
|
# act_runner doesn't reliably proxy GitHub.com-targeted actions.
|
||||||
|
# - The arm64 disk-image build runs on the Odroid self-hosted runner via
|
||||||
|
# the `arm64-linux` label. Docs in docs/ci-runners.md.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
@@ -11,19 +25,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.22'
|
go-version: '1.22'
|
||||||
|
|
||||||
- name: Test cloud-init
|
- name: Test cloud-init
|
||||||
run: cd cloud-init && go test ./... -count=1
|
run: cd cloud-init && go test ./... -count=1
|
||||||
|
|
||||||
- name: Test update agent
|
- name: Test update agent
|
||||||
run: cd update && go test ./... -count=1
|
run: cd update && go test ./... -count=1
|
||||||
|
|
||||||
build-binaries:
|
build-binaries:
|
||||||
name: Build Binaries
|
name: Build Binaries (${{ matrix.suffix }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: test
|
needs: test
|
||||||
strategy:
|
strategy:
|
||||||
@@ -37,129 +48,221 @@ jobs:
|
|||||||
suffix: linux-arm64
|
suffix: linux-arm64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.22'
|
go-version: '1.22'
|
||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
id: version
|
id: version
|
||||||
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build cloud-init
|
- name: Build cloud-init
|
||||||
run: |
|
run: |
|
||||||
CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \
|
CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \
|
||||||
go build -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \
|
go build -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \
|
||||||
-o kubesolo-cloudinit-${{ matrix.suffix }} ./cmd/
|
-o kubesolo-cloudinit-${{ matrix.suffix }} ./cmd/
|
||||||
working-directory: cloud-init
|
working-directory: cloud-init
|
||||||
|
|
||||||
- name: Build update agent
|
- name: Build update agent
|
||||||
run: |
|
run: |
|
||||||
CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \
|
CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \
|
||||||
go build -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \
|
go build -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \
|
||||||
-o kubesolo-update-${{ matrix.suffix }} .
|
-o kubesolo-update-${{ matrix.suffix }} .
|
||||||
working-directory: update
|
working-directory: update
|
||||||
|
|
||||||
- name: Upload binaries
|
- name: Upload binaries
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: binaries-${{ matrix.suffix }}
|
name: binaries-${{ matrix.suffix }}
|
||||||
path: |
|
path: |
|
||||||
cloud-init/kubesolo-cloudinit-${{ matrix.suffix }}
|
cloud-init/kubesolo-cloudinit-${{ matrix.suffix }}
|
||||||
update/kubesolo-update-${{ matrix.suffix }}
|
update/kubesolo-update-${{ matrix.suffix }}
|
||||||
|
|
||||||
build-iso:
|
build-iso-amd64:
|
||||||
name: Build ISO (amd64)
|
name: Build x86_64 ISO + disk image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build-binaries
|
needs: build-binaries
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.22'
|
go-version: '1.22'
|
||||||
|
|
||||||
- name: Install build deps
|
- name: Install build deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends \
|
sudo apt-get install -y --no-install-recommends \
|
||||||
cpio gzip genisoimage isolinux syslinux syslinux-common \
|
cpio gzip genisoimage isolinux syslinux syslinux-common \
|
||||||
syslinux-utils xorriso xz-utils wget squashfs-tools \
|
syslinux-utils xorriso xz-utils wget squashfs-tools \
|
||||||
dosfstools e2fsprogs fdisk parted bsdtar
|
dosfstools e2fsprogs fdisk parted libarchive-tools \
|
||||||
|
grub-common grub-efi-amd64-bin grub-pc-bin kpartx busybox-static
|
||||||
- name: Build ISO
|
- name: Build kernel + ISO + disk-image
|
||||||
run: make iso
|
run: |
|
||||||
|
make kernel
|
||||||
- name: Build disk image
|
make build-cloudinit build-update-agent
|
||||||
run: make disk-image
|
make rootfs initramfs
|
||||||
|
make iso
|
||||||
- name: Get version
|
make disk-image
|
||||||
id: version
|
- name: Compress disk image
|
||||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
# The raw .img is 4 GB sparse; xz takes it to ~50-300 MB depending
|
||||||
|
# on dictionary level. Use -6 (default) for memory safety on the
|
||||||
- name: Upload ISO
|
# GitHub-Actions-style runner.
|
||||||
uses: actions/upload-artifact@v4
|
run: |
|
||||||
|
xz -k -T0 --memlimit-compress=1500MiB -6 output/*.img
|
||||||
|
ls -lh output/
|
||||||
|
- name: Upload x86_64 artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: iso-amd64
|
name: image-amd64
|
||||||
path: output/*.iso
|
path: |
|
||||||
|
output/*.iso
|
||||||
|
output/*.img.xz
|
||||||
|
|
||||||
- name: Upload disk image
|
build-disk-arm64:
|
||||||
uses: actions/upload-artifact@v4
|
name: Build ARM64 disk image
|
||||||
|
runs-on: arm64-linux
|
||||||
|
needs: test
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Show host info
|
||||||
|
run: |
|
||||||
|
uname -a
|
||||||
|
nproc
|
||||||
|
free -h
|
||||||
|
df -h /
|
||||||
|
- name: Build kernel + rootfs + disk-image
|
||||||
|
# Runner runs as root via systemd; explicit sudo is harmless but
|
||||||
|
# documented as such in docs/ci-runners.md.
|
||||||
|
run: |
|
||||||
|
make kernel-arm64
|
||||||
|
make build-cross
|
||||||
|
make rootfs-arm64
|
||||||
|
make disk-image-arm64
|
||||||
|
- name: Compress disk image
|
||||||
|
run: |
|
||||||
|
xz -k -T0 --memlimit-compress=1500MiB -6 output/*.arm64.img
|
||||||
|
ls -lh output/
|
||||||
|
- name: Upload ARM64 artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: disk-image-amd64
|
name: image-arm64
|
||||||
path: output/*.img
|
path: output/*.arm64.img.xz
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Publish Gitea Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build-binaries, build-iso]
|
needs: [build-binaries, build-iso-amd64, build-disk-arm64]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
id: version
|
id: version
|
||||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
# `cat VERSION` would be stale on tag pushes (VERSION already bumped
|
||||||
|
# for the tag, but using ref_name is unambiguous).
|
||||||
|
run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
||||||
- name: Compute checksums
|
- name: Flatten artifacts + compute checksums
|
||||||
run: |
|
run: |
|
||||||
cd artifacts
|
mkdir -p release
|
||||||
find . -type f \( -name "*.iso" -o -name "*.img" -o -name "kubesolo-*" \) \
|
# Each upload-artifact wrote into artifacts/<name>/...
|
||||||
-exec sha256sum {} \; | sort > ../SHA256SUMS
|
find artifacts -type f \( \
|
||||||
cd ..
|
-name "*.iso" -o \
|
||||||
|
-name "*.img.xz" -o \
|
||||||
|
-name "kubesolo-*" \
|
||||||
|
\) -exec cp {} release/ \;
|
||||||
|
(cd release && sha256sum * | sort > SHA256SUMS)
|
||||||
|
ls -lh release/
|
||||||
|
cat release/SHA256SUMS
|
||||||
|
|
||||||
- name: Create release
|
- name: Install release tooling
|
||||||
uses: softprops/action-gh-release@v2
|
run: sudo apt-get update && sudo apt-get install -y jq curl
|
||||||
with:
|
|
||||||
name: KubeSolo OS v${{ steps.version.outputs.version }}
|
|
||||||
body: |
|
|
||||||
## KubeSolo OS v${{ steps.version.outputs.version }}
|
|
||||||
|
|
||||||
### Downloads
|
- name: Render release body
|
||||||
- **ISO** — Boot from CD/USB, ideal for testing
|
id: body
|
||||||
- **Disk Image** — Raw disk with A/B partitions + GRUB
|
run: |
|
||||||
- **Binaries** — Standalone cloud-init and update agent
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
|
# Strip the leading 'v' for cosmetic display in the body.
|
||||||
|
DISPLAY="${VERSION#v}"
|
||||||
|
cat > release-body.md <<EOF
|
||||||
|
See [docs/release-notes-${DISPLAY}.md](./docs/release-notes-${DISPLAY}.md)
|
||||||
|
and [CHANGELOG.md](./CHANGELOG.md) for the full release notes.
|
||||||
|
|
||||||
### Verify
|
### Downloads
|
||||||
```
|
|
||||||
sha256sum -c SHA256SUMS
|
|
||||||
```
|
|
||||||
|
|
||||||
### Quick Start
|
- \`kubesolo-os-${DISPLAY}.iso\` — bootable x86_64 ISO
|
||||||
```bash
|
- \`kubesolo-os-${DISPLAY}.img.xz\` — x86_64 raw disk image (A/B GPT, GRUB)
|
||||||
# Boot in QEMU
|
- \`kubesolo-os-${DISPLAY}.arm64.img.xz\` — ARM64 raw disk image (A/B GPT, UEFI)
|
||||||
qemu-system-x86_64 -m 1024 -smp 2 -enable-kvm \
|
- \`kubesolo-cloudinit-linux-{amd64,arm64}\` — standalone cloud-init parser
|
||||||
-cdrom kubesolo-os-${{ steps.version.outputs.version }}.iso \
|
- \`kubesolo-update-linux-{amd64,arm64}\` — standalone update agent
|
||||||
-nographic
|
- \`SHA256SUMS\` — checksums for every artifact above
|
||||||
```
|
|
||||||
files: |
|
### Verify
|
||||||
artifacts/**/*.iso
|
|
||||||
artifacts/**/*.img
|
\`\`\`
|
||||||
artifacts/**/kubesolo-*
|
sha256sum -c SHA256SUMS
|
||||||
SHA256SUMS
|
\`\`\`
|
||||||
draft: false
|
|
||||||
prerelease: false
|
### Quick start
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
# x86_64 in QEMU/KVM
|
||||||
|
xz -d kubesolo-os-${DISPLAY}.img.xz
|
||||||
|
qemu-system-x86_64 -m 2048 -smp 2 -enable-kvm \\
|
||||||
|
-drive file=kubesolo-os-${DISPLAY}.img,format=raw,if=virtio \\
|
||||||
|
-nographic
|
||||||
|
|
||||||
|
# ARM64 on Graviton/Ampere or under qemu-system-aarch64
|
||||||
|
xz -d kubesolo-os-${DISPLAY}.arm64.img.xz
|
||||||
|
dd if=kubesolo-os-${DISPLAY}.arm64.img of=/dev/sdX bs=4M status=progress
|
||||||
|
\`\`\`
|
||||||
|
EOF
|
||||||
|
cat release-body.md
|
||||||
|
|
||||||
|
- name: Create release via Gitea API
|
||||||
|
env:
|
||||||
|
# Gitea's act_runner auto-populates this with repo-write scope.
|
||||||
|
# If not, set a personal access token as a secret named GITEA_TOKEN
|
||||||
|
# on the org and swap the var name below.
|
||||||
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
TAG="${{ steps.version.outputs.version }}"
|
||||||
|
REPO_API="${{ github.api_url }}/repos/${{ github.repository }}"
|
||||||
|
|
||||||
|
# 1. Create the release. The API is GitHub-compatible at the
|
||||||
|
# request shape; the response includes the numeric release id we
|
||||||
|
# need for asset uploads.
|
||||||
|
PAYLOAD=$(jq -n \
|
||||||
|
--arg tag "$TAG" \
|
||||||
|
--arg name "KubeSolo OS $TAG" \
|
||||||
|
--rawfile body release-body.md \
|
||||||
|
'{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')
|
||||||
|
|
||||||
|
echo "==> Creating release for $TAG against $REPO_API"
|
||||||
|
CREATE_RESP=$(curl -fsSL -X POST \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$PAYLOAD" \
|
||||||
|
"$REPO_API/releases")
|
||||||
|
|
||||||
|
RELEASE_ID=$(echo "$CREATE_RESP" | jq -r '.id')
|
||||||
|
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
||||||
|
echo "ERROR: Could not extract release id from response:"
|
||||||
|
echo "$CREATE_RESP" | jq . || echo "$CREATE_RESP"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "==> Release id: $RELEASE_ID"
|
||||||
|
|
||||||
|
# 2. Upload each asset. asset?name= names the attachment; we use
|
||||||
|
# the basename so users see the same filename the build produced.
|
||||||
|
for f in release/*; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
name=$(basename "$f")
|
||||||
|
echo "==> Uploading $name ($(du -h "$f" | cut -f1))"
|
||||||
|
curl -fsSL -X POST \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-F "attachment=@$f" \
|
||||||
|
"$REPO_API/releases/$RELEASE_ID/assets?name=$name" >/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> Release published: $REPO_API/../releases/tag/$TAG"
|
||||||
|
|||||||
@@ -26,6 +26,63 @@ Generic ubuntu jobs that don't care about arch fall through to whichever runner
|
|||||||
them up first; on the Odroid they run in Docker via the `ubuntu-latest` /
|
them up first; on the Odroid they run in Docker via the `ubuntu-latest` /
|
||||||
`ubuntu-22.04` / `ubuntu-24.04` labels.
|
`ubuntu-22.04` / `ubuntu-24.04` labels.
|
||||||
|
|
||||||
|
## Workflows in this repo
|
||||||
|
|
||||||
|
| Workflow file | Trigger | Where it runs | What it produces |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `.gitea/workflows/ci.yaml` | push / PR to main | ubuntu-latest | Go tests, cross-arch binary build, shellcheck |
|
||||||
|
| `.gitea/workflows/build-arm64.yaml` | push to main, tags `v*`, manual | `arm64-linux` (Odroid) | ARM64 kernel + rootfs + disk image; uploads as workflow artifact only |
|
||||||
|
| `.gitea/workflows/release.yaml` | tags `v*` | mix: ubuntu-latest + `arm64-linux` | Full release: x86 ISO + disk, ARM64 disk, Go binaries, SHA256SUMS — posted to Gitea Releases via API |
|
||||||
|
|
||||||
|
### Release workflow specifics
|
||||||
|
|
||||||
|
`release.yaml` is what fires when you `git push origin vX.Y.Z`. The pipeline:
|
||||||
|
|
||||||
|
1. **test** — `go test` cloud-init + update modules (ubuntu-latest).
|
||||||
|
2. **build-binaries** — cross-compiles `kubesolo-cloudinit` and
|
||||||
|
`kubesolo-update` for linux-amd64 + linux-arm64 with the version baked
|
||||||
|
in via `-X main.version=…`.
|
||||||
|
3. **build-iso-amd64** — runs `make iso disk-image` on ubuntu-latest;
|
||||||
|
produces the x86_64 ISO and a `.img.xz` compressed disk image.
|
||||||
|
4. **build-disk-arm64** — runs the same flow on the Odroid (`arm64-linux`
|
||||||
|
label); produces `.arm64.img.xz`.
|
||||||
|
5. **release** — downloads everything, computes `SHA256SUMS`, calls
|
||||||
|
Gitea's `POST /api/v1/repos/<owner>/<repo>/releases` to create the
|
||||||
|
release, then `POST .../releases/<id>/assets?name=…` once per asset.
|
||||||
|
|
||||||
|
Authentication uses Gitea's built-in `${{ secrets.GITHUB_TOKEN }}` — the
|
||||||
|
runner auto-populates that secret with repo-write scope. If your runner
|
||||||
|
is configured without that automatic token (e.g. an older `act_runner`),
|
||||||
|
generate a personal access token with `repo:write` scope, add it as an
|
||||||
|
org secret named `GITEA_TOKEN`, and swap the `TOKEN: ${{ secrets.GITHUB_TOKEN }}`
|
||||||
|
line in `release.yaml` for `TOKEN: ${{ secrets.GITEA_TOKEN }}`.
|
||||||
|
|
||||||
|
### Why not the GitHub Marketplace release actions?
|
||||||
|
|
||||||
|
`release.yaml` used to call `softprops/action-gh-release@v2`. That action
|
||||||
|
hard-codes calls to `api.github.com` instead of using `${{ github.api_url }}`
|
||||||
|
(which Gitea sets to its own API). On Gitea's act_runner the action fails
|
||||||
|
silently — the job reports green but no release is created. We replaced
|
||||||
|
it with a direct `curl` so the behaviour is explicit and debuggable.
|
||||||
|
|
||||||
|
Similarly, `actions/upload-artifact@v4` and `@download-artifact@v4` are not
|
||||||
|
fully implemented by act_runner v1.0.x. Pin to `@v3` until upstream
|
||||||
|
support catches up.
|
||||||
|
|
||||||
|
### Manually re-running a release
|
||||||
|
|
||||||
|
Releases are immutable once published, but you can:
|
||||||
|
|
||||||
|
- **Delete and recreate the release** through the Gitea UI on the
|
||||||
|
`releases/tag/vX.Y.Z` page, then push the tag again (Gitea reuses the
|
||||||
|
existing tag), and re-trigger the workflow via the Actions UI.
|
||||||
|
- **Trigger the build-arm64 workflow manually** for a one-off arm64
|
||||||
|
artifact: Gitea UI → Actions → ARM64 Build → Run workflow.
|
||||||
|
|
||||||
|
Don't force-update a published tag — anyone who already fetched it (or
|
||||||
|
downloaded an asset) sees a checksum mismatch. Prefer cutting a new patch
|
||||||
|
release (vX.Y.Z+1) over rewriting a published one.
|
||||||
|
|
||||||
## Registering a new runner
|
## Registering a new runner
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|||||||
Reference in New Issue
Block a user