- 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.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# 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}"
|
||||
Reference in New Issue
Block a user