Files
ctask/.gitea/workflows/release.yml
T
typebasedio bbc41646ee
Release / release (push) Successful in 27s
feat(release): add Gitea release-publishing pipeline
- Add scripts/build-release.sh: cross-compile linux+windows amd64 with
  ldflags injecting main.version and main.commit, write
  checksums-sha256.txt and release-manifest.json (full commit SHA).
- Add scripts/release-check.sh: local mirror of CI (test, vet, build,
  --version substring check); falls back to Windows artifact when run
  on a Windows host where the Linux binary can't exec.
- Wire main.version / main.commit -> cmd.SetVersionInfo. Default to
  "dev" / "" so local builds without ldflags still produce a
  sensible string. Output format: single line
  'ctask <version> (<short-sha>)' or 'ctask <version>' / 'ctask dev'.
- Add .gitea/workflows/release.yml: triggered on v* tags, runs-on
  ctask-release (golang:1.26-bookworm). Tag parsed from gitea.ref
  (not gitea.ref_name). Pure shell + Gitea API; no actions/checkout,
  no setup-go, no third-party release action. Installs jq at job
  start. RC tags are deletable+recreatable; final tags are immutable.
  Verify step downloads published assets, sha256sum -c's, and runs
  --version.
- notes.md: log Phase 0/2/3 + version-injection completion.
2026-05-20 15:19:59 -04:00

150 lines
5.5 KiB
YAML

# Gitea Actions release workflow for ctask.
#
# Triggered by pushing a tag matching v*. Builds release artifacts using the
# same scripts/build-release.sh that operators run locally, then creates a
# Gitea release via the API and uploads the four artifacts.
#
# Design notes:
# - Pure shell + Gitea API. No actions/checkout, no actions/setup-go, no
# softprops/action-gh-release or any third-party action.
# - Tag is parsed from `gitea.ref` (strip `refs/tags/` prefix). The plan
# pins this explicitly: do not depend on `gitea.ref_name`.
# - RC tags (matching `-rc`) are deletable: if a release for the tag
# already exists, it's deleted and recreated. Final tags are
# immutable — the workflow refuses to overwrite an existing release.
# - RC tags are marked `prerelease: true` on the Gitea release page.
# - Runner label `ctask-release` is provisioned by the shared
# vps-act-runner-01 host, backed by golang:1.26-bookworm. jq is not
# in that base image so it's installed at the top of the job.
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ctask-release
env:
TOKEN: ${{ secrets.RELEASE_TOKEN }}
API: https://git.typebased.dev/api/v1
REPO: typebasedio/ctask
steps:
- name: Install jq
run: |
set -euo pipefail
if ! command -v jq >/dev/null 2>&1; then
apt-get update
apt-get install -y --no-install-recommends jq
fi
jq --version
- name: Derive tag from gitea.ref
run: |
set -euo pipefail
TAG="${{ gitea.ref }}"
TAG="${TAG#refs/tags/}"
echo "TAG=${TAG}" >> "$GITHUB_ENV"
echo "Building release for tag: ${TAG}"
- name: Checkout source at tag
run: |
set -euo pipefail
git clone --depth 1 --branch "${TAG}" \
https://git.typebased.dev/typebasedio/ctask.git .
git rev-parse HEAD
- name: Run tests
run: |
set -euo pipefail
go test ./...
go vet ./...
- name: Build artifacts
run: bash scripts/build-release.sh "${TAG}"
- name: Create release and upload artifacts
run: |
set -euo pipefail
# If a release already exists for this tag, decide what to do:
# RC tags (anything containing '-rc') are deletable and
# recreatable. Final tags are immutable.
EXISTING=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token ${TOKEN}" \
"${API}/repos/${REPO}/releases/tags/${TAG}")
if [ "${EXISTING}" = "200" ]; then
if echo "${TAG}" | grep -q -- '-rc'; then
EXISTING_ID=$(curl -sfS \
-H "Authorization: token ${TOKEN}" \
"${API}/repos/${REPO}/releases/tags/${TAG}" | jq -r '.id')
curl -sfS -X DELETE \
-H "Authorization: token ${TOKEN}" \
"${API}/repos/${REPO}/releases/${EXISTING_ID}"
echo "Deleted existing RC release ${EXISTING_ID}"
else
echo "ERROR: Release ${TAG} already exists and is not an RC. Refusing to overwrite." >&2
exit 1
fi
fi
# Mark RC tags as prereleases on the Gitea release page.
if echo "${TAG}" | grep -q -- '-rc'; then
PRERELEASE=true
else
PRERELEASE=false
fi
BODY=$(jq -nc \
--arg tag "${TAG}" \
--argjson pre "${PRERELEASE}" \
'{tag_name:$tag, name:$tag, draft:false, prerelease:$pre}')
RELEASE_ID=$(curl -sfS -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
-d "${BODY}" \
"${API}/repos/${REPO}/releases" | jq -r '.id')
if [ -z "${RELEASE_ID}" ] || [ "${RELEASE_ID}" = "null" ]; then
echo "ERROR: failed to create release for ${TAG}" >&2
exit 1
fi
echo "Created release ${RELEASE_ID} for ${TAG}"
for file in \
dist/ctask-linux-amd64 \
dist/ctask-windows-amd64.exe \
dist/checksums-sha256.txt \
dist/release-manifest.json; do
filename=$(basename "${file}")
echo "Uploading ${filename}..."
curl -sfS -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary "@${file}" \
"${API}/repos/${REPO}/releases/${RELEASE_ID}/assets?name=${filename}" \
> /dev/null
done
echo "Uploaded 4 assets to release ${RELEASE_ID}"
- name: Verify published artifacts
run: |
set -euo pipefail
BASE="https://git.typebased.dev/typebasedio/ctask/releases/download"
rm -rf /tmp/verify
mkdir -p /tmp/verify
cd /tmp/verify
curl -fL "${BASE}/${TAG}/ctask-linux-amd64" -o ctask-linux-amd64
curl -fL "${BASE}/${TAG}/checksums-sha256.txt" -o checksums-sha256.txt
curl -fL "${BASE}/${TAG}/release-manifest.json" -o release-manifest.json
sha256sum -c checksums-sha256.txt --ignore-missing
jq -e . release-manifest.json > /dev/null
chmod +x ctask-linux-amd64
REPORTED="$(./ctask-linux-amd64 --version)"
echo "Published binary reports: ${REPORTED}"
echo "${REPORTED}" | grep -qF "${TAG}"
echo "Download verification passed for ${TAG}"