From 98d699d8444a695d6db2ec2af62aa393bb369358 Mon Sep 17 00:00:00 2001 From: thanhnv Date: Wed, 8 Jul 2026 16:06:28 +0900 Subject: [PATCH] ci(release): auto-publish split bundles to Gitea package registry on version tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .gitea/workflows/release.yml — on push tag v*: assert tag==VERSION, run the governance gate (must be green), build core/devkit/platform-preview/all-in-one-demo (enterprise skipped/refused), then PUT each .tar.gz (+.sha256) to the Gitea generic package registry using ${{ secrets.GITEA_TOKEN }}. Portable via GITHUB_SERVER_URL/OWNER. Guide updated with the one-time secret setup + release flow. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/release.yml | 78 +++++++++++++++++++++++++++ docs/packaging/GITEA_PACKAGE_GUIDE.md | 30 +++++++++-- 2 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..1dfd466 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,78 @@ +# CASAN release — build split bundles + publish to the Gitea package registry. +# Triggers on a version tag (vX.Y.Z). Verifies the gate, builds core/devkit/platform/ +# all-in-one-demo, and uploads each artifact to the Gitea generic package registry. +# Enterprise (Level 4) is intentionally skipped (package-release.sh refuses it). +# +# Requires repo/org secret: GITEA_TOKEN (scope: write:package). +name: CASAN Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ci-runner + timeout-minutes: 60 + env: + CASAN_CI_RUN_FRONTEND: "0" + CASAN_CI_RUN_BACKEND: "0" + CASAN_CI_RUN_INFRA_LAB: "0" + CASAN_CI_STEP_TIMEOUT_SEC: "1200" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Toolchain + run: | + set -euo pipefail + command -v python3 >/dev/null || { apt-get update && apt-get install -y python3; } + command -v curl >/dev/null || { apt-get update && apt-get install -y curl; } + python3 --version + + - name: Tag must match VERSION + run: | + set -euo pipefail + TAG="${GITHUB_REF_NAME#v}" + FILE_VER="$(cat VERSION)" + echo "tag=$TAG version-file=$FILE_VER" + [ "$TAG" = "$FILE_VER" ] || { echo "::error::tag v$TAG != VERSION $FILE_VER — bump VERSION before tagging"; exit 1; } + + - name: Verify governance gate (must be green to release) + run: bash packages/casan-harness/scripts/bash/ci-harness-gate.sh + + - name: Build split bundles + run: | + set -euo pipefail + for b in core devkit platform all-in-one-demo; do + scripts/package-release.sh "$b" + done + # enterprise is future → refused on purpose; do not fail the release + scripts/package-release.sh enterprise || echo "enterprise skipped (future, expected)" + ls -lh dist/ + + - name: Publish bundles to Gitea package registry + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + set -euo pipefail + [ -n "${GITEA_TOKEN:-}" ] || { echo "::error::secret GITEA_TOKEN not set (scope write:package)"; exit 1; } + BASE="${GITHUB_SERVER_URL:-http://localhost:3000}" + OWNER="${GITHUB_REPOSITORY_OWNER:-admin}" + V="$(cat VERSION)" + publish() { # + local f="$1" name="$2" ver="$3" + echo "→ $BASE/api/packages/$OWNER/generic/$name/$ver/$(basename "$f")" + curl -fsSL -X PUT -H "Authorization: token $GITEA_TOKEN" \ + --upload-file "$f" \ + "$BASE/api/packages/$OWNER/generic/$name/$ver/$(basename "$f")" + curl -fsSL -X PUT -H "Authorization: token $GITEA_TOKEN" \ + --upload-file "$f.sha256" \ + "$BASE/api/packages/$OWNER/generic/$name/$ver/$(basename "$f").sha256" + } + publish "dist/casan-core-v$V.tar.gz" casan-core "$V" + publish "dist/casan-devkit-v$V.tar.gz" casan-devkit "$V" + publish "dist/casan-platform-preview-v$V.tar.gz" casan-platform "$V-preview" + publish "dist/casan-all-in-one-demo-v$V.tar.gz" casan-all-in-one-demo "$V" + echo "Published core, devkit, platform(preview), all-in-one-demo to $BASE (owner=$OWNER, v=$V)." diff --git a/docs/packaging/GITEA_PACKAGE_GUIDE.md b/docs/packaging/GITEA_PACKAGE_GUIDE.md index 7b3fa3b..1b61cb8 100644 --- a/docs/packaging/GITEA_PACKAGE_GUIDE.md +++ b/docs/packaging/GITEA_PACKAGE_GUIDE.md @@ -67,7 +67,29 @@ curl -fsSL -XPOST -H "Authorization: token $GITEA_TOKEN" \ `platform` as `-preview`, `all-in-one-demo` for demos. Never publish `enterprise`. - Keep `VERSION` and `packages/casan-harness/level5/harness-package.json` version in lockstep. -## Automating in CI -Add a release job to `.gitea/workflows/` that runs after the gate, calls -`scripts/package-release.sh`, and does the `curl` uploads with `${{ secrets.GITEA_TOKEN }}`. -Keep it gated on tags (`on: push: tags: ['v*']`) so ordinary pushes don't publish. +## Automated release (recommended — already wired) +`.gitea/workflows/release.yml` does all of the above automatically on a version tag. You +never hand a token to anyone — it lives in a CI secret. + +**One-time setup** +1. Create a token: Gitea → *Settings → Applications → Generate New Token*, scope + `write:package` (+ `write:repository` if you also want release attachments). +2. Add it as a secret: repo (or org) → *Settings → Actions → Secrets* → name `GITEA_TOKEN`. + +**Cut a release** +```bash +# bump the version everywhere first +echo 1.0.1 > VERSION # must match the tag +# (also bump packages/casan-harness/level5/harness-package.json "version") +git commit -am "release v1.0.1" +git tag -a v1.0.1 -m "CASAN v1.0.1" +git push origin main --follow-tags +``` +On the tag push the workflow: checks `tag == VERSION` → runs the governance gate (must be +green) → builds `core`/`devkit`/`platform-preview`/`all-in-one-demo` (enterprise skipped) → +`curl` PUTs each `.tar.gz` (+ `.sha256`) to `.../api/packages//generic/...`. Bundles +appear under the repo's **Packages** tab. `GITHUB_SERVER_URL` / `GITHUB_REPOSITORY_OWNER` +are provided by Gitea Actions, so the workflow is portable across Gitea hosts. + +## Manual one-off (if you don't want to tag) +Use the `curl` snippets in §2/§3 above with a local `GITEA_TOKEN`.