diff --git a/.github/workflows/distro-release-sync.yml b/.github/workflows/distro-release-sync.yml index 5e4d674..a9b7ae6 100644 --- a/.github/workflows/distro-release-sync.yml +++ b/.github/workflows/distro-release-sync.yml @@ -111,7 +111,7 @@ jobs: for f in /tmp/from-main/*; do if [ -f "$f" ]; then bn=$(basename "$f") - if should_skip_merge_from_github "$bn"; then + if should_skip_existing_launcher_artifact "$bn"; then echo "Skipping GitHub release asset (CI launcher or excluded): $bn" continue fi diff --git a/.github/workflows/gitea-release-sync.yml b/.github/workflows/gitea-release-sync.yml index 68e40b1..b47aeae 100644 --- a/.github/workflows/gitea-release-sync.yml +++ b/.github/workflows/gitea-release-sync.yml @@ -1,27 +1,27 @@ -# Primary path for player-facing binaries: every *published* GitHub Release on this repo -# is mirrored to your self-hosted Gitea (same tag). No public GitHub distro repo. +# Player-facing binaries live on self-hosted Gitea releases (same tag as this run). +# This workflow builds the Electron launcher (Windows + Linux) and uploads it together with +# whatever attachments already exist on that Gitea release (patches, Wow exe, …). It does **not** +# copy from GitHub releases anymore — create/publish the release on Gitea first, then run CI. # # Triggers: -# - release: published / released → GitHub “Release” (not a raw git tag alone). -# - workflow_dispatch → Actions → this workflow → “Run workflow” (enter tag). +# - release: published / released → GitHub “Release” (optional hook; tag must match Gitea). +# - workflow_dispatch → Actions → this workflow → “Run workflow” (enter tag = Gitea release tag). # # Troubleshooting: “Re-run failed jobs” on an OLD run replays the *original* workflow -# YAML (e.g. still runs `npm run pack:win` without --publish never). After changing this -# file on default branch, start a *new* run via “Run workflow”, not Re-run on a pre-fix run. +# YAML. After changing this file on default branch, start a *new* run via “Run workflow”. # -# Important: pushing only a git tag does NOT run this — you must create/publish a -# Release on github.com (Releases → Draft/new release → Publish). The workflow -# definition must exist on the repo DEFAULT branch (GitHub runs it from there). +# Important: the Gitea release for the chosen tag must already exist with non-launcher assets +# if you expect them on the final upload (CI rewrites all attachments on that release). # # Steps: Windows (NSIS+portable) + Linux (AppImage) in parallel, launcher from DEFAULT BRANCH -# overlay on tag checkout → merge with GitHub release assets → upload all to Gitea. +# overlay on tag checkout → download existing Gitea attachments → merge CI launcher → upload to Gitea. # # Secrets: GITEA_BASE_URL, GITEA_TOKEN, GITEA_OWNER, GITEA_REPO # Optional variable: GITEA_TARGET_REF (see tools/fractured-launcher-electron/README.md) # # Job guard: edit `if:` if github.repository is not HighSocietyRaiding/Fractured. -name: Sync release to Gitea +name: Gitea release — attach launcher builds on: release: @@ -29,7 +29,7 @@ on: workflow_dispatch: inputs: tag: - description: 'Git tag only (e.g. v0.7.11-paragon-foo). NOT the release title — open the release and copy the tag next to the title.' + description: 'Gitea release tag (e.g. v0.7.11-paragon-foo). Must match an existing Gitea release on GITEA_OWNER/GITEA_REPO.' required: true type: string @@ -64,7 +64,7 @@ jobs: exit 1 fi if printf '%s' "$TAG" | grep -q '[[:space:]]'; then - echo '::error::Tag contains whitespace — that is usually the **release title**, not the tag. On GitHub → Releases → open the release → copy the **tag** (short ref like v0.7.11-…), not the long title line.' + echo '::error::Tag contains whitespace — use the exact Gitea tag (e.g. v0.7.11-…), not the release title.' exit 1 fi fi @@ -202,33 +202,19 @@ jobs: name: electron-dist-linux path: /tmp/electron-linux - - name: Merge GitHub release assets + Electron build - env: - GH_TOKEN: ${{ github.token }} + - name: Merge Gitea release assets + Electron build run: | set -euo pipefail - . tools/fractured-launcher-electron/scripts/release-sync-filters.sh TAG="${{ needs.meta.outputs.tag }}" mkdir -p combined - mkdir -p /tmp/from-main - if gh release download "$TAG" -R "${{ github.repository }}" -D /tmp/from-main 2>/tmp/dl.err; then - shopt -s nullglob - for f in /tmp/from-main/*; do - if [ -f "$f" ]; then - bn=$(basename "$f") - if should_skip_merge_from_github "$bn"; then - echo "Skipping GitHub release asset (CI launcher or excluded): $bn" - continue - fi - cp -f "$f" combined/ - fi - done - echo "Merged assets from ${{ github.repository }} release $TAG" - else - echo "GitHub release download note (continuing with launcher only):" - cat /tmp/dl.err || true - fi + mkdir -p /tmp/from-gitea + bash tools/fractured-launcher-electron/scripts/download-release-from-gitea.sh /tmp/from-gitea "$TAG" shopt -s nullglob + for f in /tmp/from-gitea/*; do + if [ -f "$f" ]; then + cp -f "$f" combined/ + fi + done for f in /tmp/electron-win/* /tmp/electron-linux/*; do if [ -f "$f" ]; then cp -f "$f" combined/ diff --git a/scripts/vps-update-server.sh b/scripts/vps-update-server.sh index 760ccf3..668878e 100755 --- a/scripts/vps-update-server.sh +++ b/scripts/vps-update-server.sh @@ -22,9 +22,16 @@ # bash scripts/vps-update-server.sh --dry-run # bash scripts/vps-update-server.sh --run-after 'custom command here' # +# Canonical Fractured source (Gitea): https://git.hisora.dev/HighSocietyRaiding/Fractured.git +# If this clone still has github.com/HighSocietyRaiding/Fractured on the pull remote, the script +# rewrites that remote URL to Gitea before pulling (override with FRACTURED_GITEA_ORIGIN_URL; +# disable with FRACTURED_SKIP_ORIGIN_MIGRATION=1). +# # Environment: -# FRACTURED_GIT_REMOTE — remote name (default: origin) -# FRACTURED_POST_UPDATE_CMD — shell command run after compile (used by bare --run-after) +# FRACTURED_GIT_REMOTE — remote name (default: origin) +# FRACTURED_GITEA_ORIGIN_URL — URL used when auto-migrating off GitHub (default: Gitea HTTPS above) +# FRACTURED_SKIP_ORIGIN_MIGRATION — set to 1 to never rewrite remote URLs +# FRACTURED_POST_UPDATE_CMD — shell command run after compile (used by bare --run-after) set -euo pipefail @@ -40,6 +47,7 @@ DO_RESTART=0 INSTALL_PREFIX="" POST_UPDATE_CMD="${FRACTURED_POST_UPDATE_CMD:-}" GIT_REMOTE="${FRACTURED_GIT_REMOTE:-origin}" +FRACTURED_GITEA_ORIGIN_URL="${FRACTURED_GITEA_ORIGIN_URL:-https://git.hisora.dev/HighSocietyRaiding/Fractured.git}" usage() { cat <<'EOF' @@ -59,8 +67,10 @@ Options: If CMD is omitted, uses FRACTURED_POST_UPDATE_CMD. Environment: - FRACTURED_GIT_REMOTE Git remote (default: origin). - FRACTURED_POST_UPDATE_CMD Used with bare --run-after. + FRACTURED_GIT_REMOTE Git remote name (default: origin). + FRACTURED_GITEA_ORIGIN_URL Target URL when auto-migrating from GitHub Fractured remote. + FRACTURED_SKIP_ORIGIN_MIGRATION Set to 1 to skip GitHub → Gitea remote rewrite. + FRACTURED_POST_UPDATE_CMD Used with bare --run-after. EOF } @@ -178,12 +188,27 @@ current_branch() { git symbolic-ref -q --short HEAD || git rev-parse --short HEAD } +# Old VPS clones may still have origin → github.com/HighSocietyRaiding/Fractured; repoint to Gitea. +ensure_fractured_origin_on_gitea() { + if [[ "${FRACTURED_SKIP_ORIGIN_MIGRATION:-0}" == "1" ]]; then + return 0 + fi + local url + url="$(git remote get-url "$GIT_REMOTE" 2>/dev/null || true)" + [[ -z "$url" ]] && return 0 + if [[ "$url" =~ github\.com[:/]HighSocietyRaiding/Fractured ]]; then + echo "==> $GIT_REMOTE still points at GitHub Fractured; switching to Gitea: $FRACTURED_GITEA_ORIGIN_URL" + run git remote set-url "$GIT_REMOTE" "$FRACTURED_GITEA_ORIGIN_URL" + fi +} + if [[ "$NO_PULL" -eq 0 ]]; then ref="$(current_branch)" if [[ "$ref" == "HEAD" ]]; then echo "error: detached HEAD; checkout a branch or use --no-pull." >&2 exit 1 fi + ensure_fractured_origin_on_gitea echo "==> git pull $GIT_REMOTE $ref" run git pull "$GIT_REMOTE" "$ref" else diff --git a/tools/fractured-launcher-electron/README.md b/tools/fractured-launcher-electron/README.md index f7ac00c..bc5e9d5 100644 --- a/tools/fractured-launcher-electron/README.md +++ b/tools/fractured-launcher-electron/README.md @@ -43,7 +43,7 @@ npm install npm run pack:linux ``` -Produces **`dist/Fractured-Launcher-${version}-Linux-x86_64.AppImage`**. Same **`lib/baked-gitea-channel.js`** and **`default-launcher.json`** as Windows; run on **Linux** (or use **Fractured launcher CI** / **Sync release to Gitea**, which upload this file to Gitea with the Windows installers). +Produces **`dist/Fractured-Launcher-${version}-Linux-x86_64.AppImage`**. Same **`lib/baked-gitea-channel.js`** and **`default-launcher.json`** as Windows; run on **Linux** (or use **Fractured launcher CI** / **Gitea release — attach launcher builds**, which upload this file to Gitea with the Windows installers). **Quick local test (avoids tag snapshot / CI):** - **Linux:** from repo root, **`bash tools/fractured-launcher-electron/scripts/manual-pack-linux.sh`** → **`dist/*.AppImage`**. @@ -66,7 +66,7 @@ Produces **`dist/Fractured-Launcher-${version}-Linux-x86_64.AppImage`**. Same ** ### Where launcher updates are hosted -**`npm run publish:win`** runs **`electron-builder` with `--publish never`** — artifacts stay in **`dist/`**; CI uploads them to Gitea when you **publish a GitHub release**. For ad-hoc uploads, use **`scripts/upload-release-to-gitea.sh`**. For launcher auto-update, prefer: +**`npm run publish:win`** runs **`electron-builder` with `--publish never`** — artifacts stay in **`dist/`**; CI uploads them to Gitea when you run **Gitea release — attach launcher builds** (see below). For ad-hoc uploads, use **`scripts/upload-release-to-gitea.sh`**. For launcher auto-update, prefer: - Set **`update_feed_url`** (or **`LAUNCHER_UPDATE_URL`**) to a **generic** HTTPS base URL where **`latest.yml`** and the installer files are hosted (often the same Gitea release attachment URLs pattern your reverse proxy exposes), **or** - Keep publishing to a GitHub release only for **`latest.yml`** + installers if you accept that small metadata/binary channel there. @@ -78,17 +78,18 @@ Produces **`dist/Fractured-Launcher-${version}-Linux-x86_64.AppImage`**. Same ** ### Publishing a new launcher version 1. Bump **`version`** in `package.json` on `main` (or your release branch) and merge. -2. Create a **GitHub release** (tag + attach patches / `Wow.exe` if needed) and click **Publish** — **Sync release to Gitea** builds **Windows + Linux** launcher artifacts and mirrors everything to Gitea. -3. Local check: **`npm run pack:win`** (on Windows) or **`npm run pack:linux`** / **`scripts/manual-pack-linux.sh`**, then **`scripts/upload-release-to-gitea.sh`** with the same **`GITEA_*`** env vars as CI if you need a manual upload. +2. Create/publish the **Gitea** release for that tag (attach patches / `Wow.exe`, **`patch-manifest.json`**, etc.). +3. Run **GitHub Actions → Gitea release — attach launcher builds** (or publish a **GitHub** release with the same tag if you still use that trigger) so CI builds **Windows + Linux** launchers and re-uploads **all** release files to Gitea (see workflow header). +4. Local check: **`npm run pack:win`** (on Windows) or **`npm run pack:linux`** / **`scripts/manual-pack-linux.sh`**, then **`scripts/upload-release-to-gitea.sh`** with the same **`GITEA_*`** env vars as CI if you need a manual upload. -## Sync to Gitea (patches + launcher binaries) +## Gitea release + launcher (patches + binaries) -CI workflow **Sync release to Gitea** (`.github/workflows/gitea-release-sync.yml`) runs on **every published GitHub release** on this repo: +CI workflow **Gitea release — attach launcher builds** (`.github/workflows/gitea-release-sync.yml`) attaches CI-built launcher binaries to the **Gitea** release that already exists for the chosen tag: -1. Triggers on **release published** on **`HighSocietyRaiding/Fractured`** (or **workflow_dispatch** with a tag). +1. Triggers on **release published** on **`HighSocietyRaiding/Fractured`** (optional) or **workflow_dispatch** with a tag (the tag must match a **Gitea** release on **`GITEA_OWNER` / `GITEA_REPO`**). 2. Builds **Windows** (NSIS + portable) and **Linux** (AppImage) in parallel, each using **`tools/fractured-launcher-electron` from the default branch** (overlaid onto the tag checkout), so older release tags never ship a launcher missing new **`lib/*.js`** files. -3. Downloads **all assets** attached to that **GitHub** release (MPQs, patched `Wow.exe`, etc.). -4. Merges with the built launcher artifacts and uploads to a **Gitea release** with the **same tag** (existing attachments on that Gitea release are replaced). **Launcher installers** attached on GitHub (**`Fractured-Launcher*`**, case-insensitive) are **not** merged — the **CI build from the default branch** is the only source of launcher binaries, so an old installer on the GitHub release cannot “stick” on Gitea next to a newer build. **`*.blockmap`** and **`builder-debug.yml`** are omitted from the merge and from Gitea uploads. +3. Downloads **existing attachments** from that **Gitea** release (MPQs, patched `Wow.exe`, etc.). +4. Merges with the built launcher artifacts and **replaces** all attachments on the same Gitea release (the upload script clears prior attachments, then posts the merged set). **Launcher installers** already on Gitea (**`Fractured-Launcher*`**, case-insensitive) are **not** re-downloaded — the **CI build from the default branch** is the only source of launcher binaries. **`*.blockmap`** and **`builder-debug.yml`** are omitted from the merge and from Gitea uploads. **GitHub Actions secrets** (repository → Settings → Secrets and variables → Actions): @@ -99,7 +100,7 @@ CI workflow **Sync release to Gitea** (`.github/workflows/gitea-release-sync.yml | **`GITEA_OWNER`** | Organization or username on Gitea | | **`GITEA_REPO`** | Repository name — must already have **at least one commit** (Gitea returns HTTP 422 “repo is empty” for zero-commit repos; push e.g. a README on **`main`** or set **`GITEA_TARGET_REF`** to your default branch) | -**Optional variable** (Settings → Variables): **`GITEA_TARGET_REF`** — default branch/commitish used **only when the workflow must create a new Gitea release** and Gitea needs `target_commitish` (defaults to **`main`** in the upload script if unset). +**Optional variable** (Settings → Variables): **`GITEA_TARGET_REF`** — default branch/commitish used **only when the upload script must create a new Gitea release** (no release for that tag yet) and Gitea needs `target_commitish` (defaults to **`main`** in the upload script if unset). Prefer creating the release on Gitea **before** CI so patches ship in the same run. **Player `launcher.json`:** packaged builds should already include **`gitea.base_url` / `owner` / `repo`** from the bake step above. Players only need to set **`GITEA_TOKEN`** (or your **`token_env`**) if the Gitea repo is **private**. To point at another instance, edit **`gitea`** in **`launcher.json`**: @@ -126,28 +127,29 @@ bash tools/fractured-launcher-electron/scripts/gitea-replace-launcher-only.sh \ That script deletes only **`Fractured-Launcher*`**, **`latest.yml`** (only if you supply a new **`latest.yml`** in **`dist/`**), **`latest-linux.yml`** (only if supplied), **`*.blockmap`**, and **`builder-debug.yml`** on the release, then uploads the new files — **Wow.exe**, MPQs, and **`patch-manifest.json`** are left alone. If you only built Linux locally, merge **Windows CI `dist/`** files into the same folder first so **`latest.yml`** is not removed without a replacement. Use release tag **`latest`** if that is what **`release_tag`** points at. -### Sync did not run / Gitea unchanged — checklist +### Launcher attach did not run / Gitea unchanged — checklist -1. **Git tag ≠ GitHub Release** — Only **Releases** (published on the GitHub **Releases** page) trigger this workflow. If your teammate only **`git push --tags`**, create a **Release** from that tag and click **Publish** (or run **Actions → Sync release to Gitea → Run workflow** and enter the tag). -2. **Manual run: tag vs title** — **Run workflow** must receive the **git tag** (e.g. `v0.7.11-paragon-…`), copied from the release page’s tag badge. Pasting the **release title** (long line with spaces/parentheses) breaks `git fetch` with `invalid refspec`. -3. **Draft release** — Must click **Publish release**; drafts do not mirror. -4. **Workflow on default branch** — GitHub runs `release` workflows from the **default branch** (e.g. `main`). Ensure `.github/workflows/gitea-release-sync.yml` is merged there. -5. **Repo name guard** — Jobs use `if: github.repository == 'HighSocietyRaiding/Fractured'`. Forks or renames must change that line or runs are skipped (GitHub Actions only; canonical clone is Gitea). -6. **Secrets** — **`GITEA_BASE_URL`**, **`GITEA_TOKEN`**, **`GITEA_OWNER`**, **`GITEA_REPO`** must be set under **Settings → Secrets and variables → Actions**. A failed “Upload to Gitea” step usually prints which is missing. -7. **Actions tab** — Open the latest **Sync release to Gitea** run; a red **build-electron** (old tag without `package-lock.json`, etc.) or **Upload to Gitea** step shows the real error. -8. **HTTP 422 `repo is empty`** — The Gitea repo has **no commits** yet. Push any initial commit (e.g. **Add README** in the Gitea web UI, or `git push` to **`main`**). Optionally set **`GITEA_TARGET_REF`** to match your real default branch if it is not **`main`**. From this repo you can run **`scripts/bootstrap-gitea-repo.sh`** (see script header for `GITEA_*` env or pass the HTTPS/SSH clone URL as the first argument). -9. **`sync Wow.exe: fetch failed`** — Often **HTTPS/TLS** to Gitea; use **`http://…`** in **`lib/baked-gitea-channel.js`** if you only serve plain HTTP, or fix certs / **`NODE_EXTRA_CA_CERTS`**. Ensure **`Wow-patched.exe`** exists on the release (**`release_tag`**: `latest` vs pinned). Errors include the failing URL when possible. -10. **Wine + Windows portable** — If the folder picker returns **`/home/...`**, the launcher maps it to **`Z:\home\...`** (Wine’s Unix root). **`Wow.exe`** is matched case-insensitively for Linux-backed folders. Re-save the WoW folder after upgrading if validation still fails. -11. **`EBUSY` / file locked on Windows** — The client (or antivirus) may keep **`.MPQ`** files open. The launcher **retries** for a short window and downloads the new file **before** replacing the old one; if sync still fails, **exit WoW** (and any tool previewing that folder) and run **Download updates** again. -12. **`.bak-*` clutter** — When **Download updates** finishes without error, the launcher removes matching **`*.bak-YYYYMMDD-HHmmss`** files from earlier runs (same pattern it uses when replacing files). Failed syncs do not delete backups. -13. **Gitea still shows an old launcher version** — The sync workflow overlays **`tools/fractured-launcher-electron` from the default branch**, so **`package.json`** there defines the built version. Ensure launcher changes are **merged to `main`** before publishing the GitHub release (or re-run **Actions → Sync release to Gitea** after merging). Previously, **Fractured-Launcher\*** files **attached on the GitHub release** were merged too, which could leave **two** installer versions on Gitea; those assets are now skipped in favor of CI-only builds. -14. **Migrating `baked-gitea-channel.js` to a new host** — Publish **`gitea-replace-launcher-only.sh`** (see **Manual upload** above) on the **old** Gitea **`latest`** release so auto-update still works until clients move to the new URL. +1. **Gitea release missing** — The workflow downloads from **Gitea** first. Create/publish a release on **`GITEA_OWNER` / `GITEA_REPO`** with the **same tag** before running CI (or rely on upload script to create an empty release — you still need **`GITEA_TARGET_REF`** if the repo default branch is not **`main`**). +2. **GitHub-only tag** — If you use the **release published** trigger on GitHub, the tag must still exist as a **Gitea** release with your patch assets. Otherwise use **Actions → Gitea release — attach launcher builds → Run workflow** after the Gitea release exists. +3. **Manual run: tag vs title** — **Run workflow** must receive the **git tag** (e.g. `v0.7.11-paragon-…`), not the long human-readable release title (spaces break the tag). +4. **Draft release** — On Gitea, publish the release; drafts may not be visible to the API the same way — use a published release. +5. **Workflow on default branch** — GitHub runs `release` workflows from the **default branch** (e.g. `main`). Ensure `.github/workflows/gitea-release-sync.yml` is merged there. +6. **Repo name guard** — Jobs use `if: github.repository == 'HighSocietyRaiding/Fractured'`. Forks or renames must change that line or runs are skipped (GitHub Actions only; canonical clone is Gitea). +7. **Secrets** — **`GITEA_BASE_URL`**, **`GITEA_TOKEN`**, **`GITEA_OWNER`**, **`GITEA_REPO`** must be set under **Settings → Secrets and variables → Actions**. A failed “Upload to Gitea” step usually prints which is missing. +8. **Actions tab** — Open the latest **Gitea release — attach launcher builds** run; a red **build-electron** (old tag without `package-lock.json`, etc.), **Merge Gitea release assets**, or **Upload to Gitea** step shows the real error. +9. **HTTP 422 `repo is empty`** — The Gitea repo has **no commits** yet. Push any initial commit (e.g. **Add README** in the Gitea web UI, or `git push` to **`main`**). Optionally set **`GITEA_TARGET_REF`** to match your real default branch if it is not **`main`**. From this repo you can run **`scripts/bootstrap-gitea-repo.sh`** (see script header for `GITEA_*` env or pass the HTTPS/SSH clone URL as the first argument). +10. **`sync Wow.exe: fetch failed`** — Often **HTTPS/TLS** to Gitea; use **`http://…`** in **`lib/baked-gitea-channel.js`** if you only serve plain HTTP, or fix certs / **`NODE_EXTRA_CA_CERTS`**. Ensure **`Wow-patched.exe`** exists on the release (**`release_tag`**: `latest` vs pinned). Errors include the failing URL when possible. +11. **Wine + Windows portable** — If the folder picker returns **`/home/...`**, the launcher maps it to **`Z:\home\...`** (Wine’s Unix root). **`Wow.exe`** is matched case-insensitively for Linux-backed folders. Re-save the WoW folder after upgrading if validation still fails. +12. **`EBUSY` / file locked on Windows** — The client (or antivirus) may keep **`.MPQ`** files open. The launcher **retries** for a short window and downloads the new file **before** replacing the old one; if sync still fails, **exit WoW** (and any tool previewing that folder) and run **Download updates** again. +13. **`.bak-*` clutter** — When **Download updates** finishes without error, the launcher removes matching **`*.bak-YYYYMMDD-HHmmss`** files from earlier runs (same pattern it uses when replacing files). Failed syncs do not delete backups. +14. **Gitea still shows an old launcher version** — The workflow overlays **`tools/fractured-launcher-electron` from the default branch**, so **`package.json`** there defines the built version. Ensure launcher changes are **merged to `main`** before attaching to the release (or re-run **Actions → Gitea release — attach launcher builds** after merging). **Fractured-Launcher\*** files already on Gitea are skipped when re-downloading so CI is the only launcher source. +15. **Migrating `baked-gitea-channel.js` to a new host** — Publish **`gitea-replace-launcher-only.sh`** (see **Manual upload** above) on the **old** Gitea **`latest`** release so auto-update still works until clients move to the new URL. ### Private Gitea token for players Do **not** embed a shared admin PAT in a shipped `launcher.json`. Prefer read-only tokens scoped to one repo, short-lived tokens, or a small auth service that redirects to signed URLs. -**Release asset names** must match **`files[].source`** when **`from_release`**: true. Use **`release_tag`**: `"latest"` or a pinned tag matching both GitHub and Gitea. +**Release asset names** must match **`files[].source`** when **`from_release`**: true. Use **`release_tag`**: `"latest"` or a pinned tag matching your Gitea releases. ## Patch versions (same filenames, different bytes) @@ -166,13 +168,13 @@ cd /path/to/staging node tools/fractured-launcher-electron/scripts/generate-patch-manifest.js v0.9.0-client Wow-patched.exe > patch-manifest.json ``` -Attach **`patch-manifest.json`** together with the MPQ/exe to the GitHub release (CI sync copies it to Gitea with everything else). +Attach **`patch-manifest.json`** together with the MPQ/exe to the **Gitea** release (same files CI merges before upload). ## CI Workflow **Fractured launcher CI** (`.github/workflows/fractured-launcher-ci.yml`) runs on pushes/PRs under `tools/fractured-launcher-electron/`: **Windows** (`npm run pack:win`) and **Linux** (`npm run pack:linux`) jobs, each **`electron-builder … --publish never`**. **Actions → Fractured launcher CI → Run workflow** runs it manually. -**Sync release to Gitea** (`.github/workflows/gitea-release-sync.yml`) uses the same pack commands. If you see `GH_TOKEN` / `GitHubPublisher` errors in logs, the job is almost certainly an old **Re-run failed jobs** — open **Actions → Sync release to Gitea → Run workflow**, enter the tag, and start a **new** run instead. +**Gitea release — attach launcher builds** (`.github/workflows/gitea-release-sync.yml`) uses the same pack commands. If you see stale behaviour after a workflow edit, start a **new** run (**Actions → Gitea release — attach launcher builds → Run workflow**) instead of **Re-run failed jobs** on an old run. ## Config diff --git a/tools/fractured-launcher-electron/scripts/bootstrap-gitea-repo.sh b/tools/fractured-launcher-electron/scripts/bootstrap-gitea-repo.sh index 4852a10..f462e3c 100755 --- a/tools/fractured-launcher-electron/scripts/bootstrap-gitea-repo.sh +++ b/tools/fractured-launcher-electron/scripts/bootstrap-gitea-repo.sh @@ -36,7 +36,7 @@ git checkout -q -b "$BRANCH" cat >README.md <<'EOF' # Fractured release mirror -Release assets (launcher builds, patches, `patch-manifest.json`, etc.) are uploaded here by **GitHub Actions** (“Sync release to Gitea”) from the main Fractured repository. +Release assets (launcher builds, patches, `patch-manifest.json`, etc.) are uploaded here by **GitHub Actions** (**Gitea release — attach launcher builds**) from the main Fractured repository. This initial commit exists because **Gitea requires at least one commit** in the repository before releases can be created. EOF diff --git a/tools/fractured-launcher-electron/scripts/download-release-from-gitea.sh b/tools/fractured-launcher-electron/scripts/download-release-from-gitea.sh new file mode 100644 index 0000000..b9b8bf3 --- /dev/null +++ b/tools/fractured-launcher-electron/scripts/download-release-from-gitea.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# Download attachments from an existing Gitea release (same tag as CI). Skips filenames that +# the launcher CI rebuilds (see release-sync-filters.sh) so Electron artifacts can replace them. +# +# Usage: +# export GITEA_BASE_URL=https://git.example.com +# export GITEA_TOKEN=gta_... +# export GITEA_OWNER=myorg +# export GITEA_REPO=Fractured +# ./download-release-from-gitea.sh /tmp/gitea-assets v1.0.0 +# +set -euo pipefail + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=release-sync-filters.sh +. "$SCRIPT_DIR/release-sync-filters.sh" + +OUTDIR="${1:?first arg: output directory}" +TAG="${2:?second arg: release tag (e.g. v1.0.0)}" + +: "${GITEA_BASE_URL:?Set GITEA_BASE_URL (no trailing slash required)}" +: "${GITEA_TOKEN:?Set GITEA_TOKEN}" +: "${GITEA_OWNER:?Set GITEA_OWNER}" +: "${GITEA_REPO:?Set GITEA_REPO}" + +BASE="${GITEA_BASE_URL%/}" +API="$BASE/api/v1" +AUTH_JSON=(-H "Authorization: token ${GITEA_TOKEN}" -H "Accept: application/json") + +mkdir -p "$OUTDIR" + +TAG_ENC=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$TAG") +REL_JSON=$(mktemp) +trap 'rm -f "$REL_JSON"' EXIT + +code=$(curl -sS -o "$REL_JSON" -w "%{http_code}" "${AUTH_JSON[@]}" \ + "$API/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/tags/${TAG_ENC}") + +if [ "$code" != "200" ]; then + echo "Gitea GET release by tag \"$TAG\" failed HTTP $code — create/publish that release on Gitea first, then run this workflow." >&2 + cat "$REL_JSON" >&2 + exit 1 +fi + +count=0 +while IFS= read -r obj; do + [ -z "$obj" ] && continue + name=$(jq -r '.name // empty' <<<"$obj") + url=$(jq -r '(.browser_download_url // .download_url // empty)' <<<"$obj") + [ -z "$name" ] || [ "$name" = "null" ] && continue + [ -z "$url" ] || [ "$url" = "null" ] && continue + if should_skip_existing_launcher_artifact "$name"; then + echo "Skipping existing launcher artifact (CI replaces): $name" + continue + fi + if [[ "$url" != http://* && "$url" != https://* ]]; then + if [[ "$url" != /* ]]; then + echo "Unexpected attachment URL for $name: $url" >&2 + exit 1 + fi + url="${BASE}${url}" + fi + echo "Downloading $name …" + curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" -o "$OUTDIR/$name" "$url" + count=$((count + 1)) +done < <(jq -c '(.attachments // .assets // [])[]' "$REL_JSON") + +echo "Downloaded $count non-launcher attachment(s) from Gitea release $TAG." diff --git a/tools/fractured-launcher-electron/scripts/release-sync-filters.sh b/tools/fractured-launcher-electron/scripts/release-sync-filters.sh index a06c159..e234734 100644 --- a/tools/fractured-launcher-electron/scripts/release-sync-filters.sh +++ b/tools/fractured-launcher-electron/scripts/release-sync-filters.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash -# Shared filters for GitHub → Gitea / distro release merges and Gitea uploads. +# Shared filters for release merges (GitHub/Gitea sources) and Gitea uploads. # shellcheck shell=bash -# Skip when copying assets from `gh release download` into combined/: CI-built launcher is authoritative. -should_skip_merge_from_github() { +# Skip when copying existing release assets into combined/: CI-built launcher wins on collision. +should_skip_existing_launcher_artifact() { local l l=$(printf '%s' "${1##*/}" | tr '[:upper:]' '[:lower:]') case "$l" in @@ -14,6 +14,11 @@ should_skip_merge_from_github() { return 1 } +# Legacy name (GitHub release download step); same rules as Gitea merge. +should_skip_merge_from_github() { + should_skip_existing_launcher_artifact "$@" +} + # Skip when POSTing attachments to Gitea (belt-and-suspenders if something slips into combined/). should_skip_gitea_upload() { local l diff --git a/tools/fractured-launcher-electron/scripts/upload-release-to-gitea.sh b/tools/fractured-launcher-electron/scripts/upload-release-to-gitea.sh index 59123e2..4f9944c 100644 --- a/tools/fractured-launcher-electron/scripts/upload-release-to-gitea.sh +++ b/tools/fractured-launcher-electron/scripts/upload-release-to-gitea.sh @@ -41,7 +41,7 @@ elif [ "$code" = "404" ]; then body=$(jq -n \ --arg tag "$TAG" \ --arg name "Fractured $TAG" \ - --arg body "Synced from GitHub Actions (Fractured)." \ + --arg body "Fractured $TAG (CI)." \ --arg target "$TARGET" \ '{tag_name:$tag,name:$name,body:$body,draft:false,prerelease:false,target_commitish:$target}') code=$(curl -sS -o "$REL_JSON" -w "%{http_code}" -X POST "${AUTH_H[@]}" \