diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 573e2f6..c30ff37 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,11 +106,31 @@ jobs: name: ${{ needs.build.outputs.title-id }} path: dist - - name: Publish a draft release + # Two ways a tag gets here, and both must work. + # + # tools/release.sh + git push - the tag arrives with no release, so + # create a draft for review. + # GitHub's "Draft a new release" - publishing in the web UI creates the + # tag AND the release together, so by + # the time this runs the release already + # exists. Creating it again would fail, + # and the ZIP would never be attached; + # upload into it instead and leave the + # notes the author wrote alone. + - name: Attach the build to its release env: GH_TOKEN: ${{ github.token }} ZIP: dist/${{ needs.build.outputs.title-id }}.zip run: | + if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + echo "release $GITHUB_REF_NAME already exists; uploading assets into it" + gh release upload "$GITHUB_REF_NAME" \ + "$ZIP" LICENSE THIRD_PARTY_NOTICES.md --clobber + gh release view "$GITHUB_REF_NAME" --json isDraft,assets \ + --jq '"draft=\(.isDraft) assets=\([.assets[].name]|join(","))"' + exit 0 + fi + previous=$(git describe --tags --abbrev=0 "$GITHUB_REF_NAME^" 2>/dev/null || true) { printf 'Unpack `%s` into `/data/homebrew/` on the console, then launch\n' "$(basename "$ZIP")" diff --git a/README.md b/README.md index c356d78..aaf4efd 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,13 @@ git push origin v1.1.0 CI then builds and opens a **draft** release with the ZIP attached. **Publish it** from the Releases page — a draft cannot be downloaded, so stores and users can't see it. +You can do it entirely in the browser instead: edit `sce_sys/param.json` to raise +`contentVersion`, commit it to `main`, then **Releases → Draft a new release**, type the +matching new tag (`v1.1.0`), and **Publish release**. That creates the tag and the release +together; CI then verifies the version and uploads the ZIP into the release you just made, +leaving your notes untouched. Either route works — the only rule is that the committed +`contentVersion` and the tag agree, and CI fails the release if they don't. + Why the order matters: a PS5 decides an installed copy is out of date by comparing `sce_sys/param.json`'s `contentVersion`, and [ps5-homebrew-catalog][catalog] reads that value from the **committed** `param.json` at the release tag. If the bump isn't in the commit the tag diff --git a/tests/test_tools.py b/tests/test_tools.py index da67da5..7e2b174 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -303,6 +303,12 @@ class ToolTests(unittest.TestCase): # stamping it at build time would leave the committed value behind. self.assertIn("tools/set-content-version.sh --check", workflow) self.assertIn("--draft", workflow) + # Publishing from GitHub's web UI creates the tag and the release + # together, so the release can already exist when this job runs. + # Creating it again fails and the ZIP is never attached; the workflow + # has to upload into the existing release instead. + self.assertIn("gh release view", workflow) + self.assertIn("gh release upload", workflow) # Pinned, not floating: this toolchain needs the Clang 18 image, which # only ubuntu-24.04 carries. Ignore comments, which explain the pin. code = "\n".join(