77 workflow_dispatch :
88 inputs :
99 tag_name :
10- description : " Release tag (stable: v1.0.0, beta: v1.0.0-beta.1)."
10+ description : " Release tag (stable: v1.0.0-beta or v1.0.0 , beta: v1.0.0-beta.1)."
1111 required : false
1212 type : string
1313 checkout_ref :
@@ -125,6 +125,10 @@ jobs:
125125 echo "Existing tag ${TAG} points to ${TAG_SHA}, not requested commit ${CHECKOUT_SHA}." >&2
126126 exit 1
127127 fi
128+ if [[ "${UPLOAD}" == "true" && -z "${TAG_SHA}" ]]; then
129+ echo "Publishing requires existing tag ${TAG} at ${CHECKOUT_SHA}. Push the tag before dispatching." >&2
130+ exit 1
131+ fi
128132 CHECKOUT_REF="${CHECKOUT_SHA}"
129133
130134 echo "version=$VERSION" >> "$GITHUB_OUTPUT"
@@ -144,8 +148,8 @@ jobs:
144148 NODE_OPTIONS : --max-old-space-size=6144
145149 OPENBITFUN_ENABLE_UPDATER_ARTIFACTS : ${{ needs.prepare.outputs.upload_to_release }}
146150 OPENBITFUN_RELEASE_CHANNEL : ${{ needs.prepare.outputs.release_channel }}
147- TAURI_UPDATER_ENDPOINT : ${{ github.repository != 'GCWing/OpenBitFun' && needs.prepare.outputs.release_channel == 'beta' && format('https://github.com/{0}/releases/download/channel-beta/latest.json', github.repository) || '' }}
148- TAURI_UPDATER_FALLBACK_ENDPOINT : ${{ github.repository != 'GCWing/OpenBitFun' && needs.prepare.outputs.release_channel == 'beta' && format('https://github.com/{0}/releases/download/channel-beta/latest.json', github.repository) || '' }}
151+ TAURI_UPDATER_ENDPOINT : ${{ github.repository != 'GCWing/OpenBitFun' && ( needs.prepare.outputs.release_channel == 'beta' && format('https://github.com/{0}/releases/download/channel-v1- beta/latest-v1 .json', github.repository) || format('https://github.com/{0}/releases/latest/download/latest-v1.json', github.repository) ) || '' }}
152+ TAURI_UPDATER_FALLBACK_ENDPOINT : ${{ github.repository != 'GCWing/OpenBitFun' && ( needs.prepare.outputs.release_channel == 'beta' && format('https://github.com/{0}/releases/download/channel-v1- beta/latest-v1 .json', github.repository) || format('https://github.com/{0}/releases/latest/download/latest-v1.json', github.repository) ) || '' }}
149153 TAURI_UPDATER_PUBKEY : ${{ secrets.TAURI_UPDATER_PUBKEY }}
150154 # Same trust root, compiled into the Desktop binary so one-click relay
151155 # deploy can verify the signed checksum locally and hand the remote host
@@ -623,13 +627,13 @@ jobs:
623627 --version "${{ needs.prepare.outputs.version }}" \
624628 --tag "${{ needs.prepare.outputs.release_tag }}" \
625629 --repo "${{ github.repository }}" \
626- --out release-updater-assets/latest.json \
630+ --out release-updater-assets/latest-v1 .json \
627631 --required-platforms "${REQUIRED_UPDATER_PLATFORMS}"
628632
629633 - name : Verify updater manifest
630634 run : |
631635 node scripts/verify-tauri-latest-json.mjs \
632- --manifest release-updater-assets/latest.json \
636+ --manifest release-updater-assets/latest-v1 .json \
633637 --version "${{ needs.prepare.outputs.version }}" \
634638 --required-platforms "${REQUIRED_UPDATER_PLATFORMS}" \
635639 --required-manual-platforms "windows-x86_64"
@@ -641,7 +645,7 @@ jobs:
641645 --version "${{ needs.prepare.outputs.version }}" \
642646 --tag "${{ needs.prepare.outputs.release_tag }}" \
643647 --repo "${{ github.repository }}" \
644- --out linux-release-assets/linux-binaries.json
648+ --out linux-release-assets/linux-binaries-v1 .json
645649
646650 # The Tauri bundler signs the five updater artifacts during `tauri build`,
647651 # but the installers people download by hand from the release page — dmg,
@@ -698,25 +702,76 @@ jobs:
698702 linux-release-assets/openbitfun-relay-server-*.tar.gz.sha256 \
699703 linux-release-assets/*.tar.gz.sig \
700704 linux-release-assets/*.tar.gz.sha256.sig \
701- linux-release-assets/linux-binaries.json \
705+ linux-release-assets/linux-binaries-v1 .json \
702706 relay-image-assets/relay-image.json \
703707 relay-image-assets/relay-image.json.sig
704708
709+ # Old Desktop and CLI clients follow GitHub Latest. Keep their feeds on
710+ # the final 0.2 release; only versioned manifests may advertise 1.x.
711+ - name : Preserve legacy update feeds
712+ if : needs.prepare.outputs.release_channel == 'stable'
713+ shell : bash
714+ run : |
715+ set -euo pipefail
716+ for manifest in latest.json linux-binaries.json; do
717+ curl -fsSL --retry 5 --retry-delay 3 \
718+ "https://github.com/GCWing/OpenBitFun/releases/download/v0.2.19/${manifest}" \
719+ -o "release-upload-assets/${manifest}"
720+ jq -e '.version == "0.2.19"' "release-upload-assets/${manifest}" >/dev/null
721+ done
722+
705723 - name : Upload to release
706- uses : softprops/action-gh-release@v3
707- with :
708- tag_name : ${{ needs.prepare.outputs.release_tag }}
709- target_commitish : ${{ needs.prepare.outputs.checkout_ref }}
710- prerelease : ${{ needs.prepare.outputs.release_channel == 'beta' }}
711- name : ${{ needs.prepare.outputs.release_channel == 'beta' && format('OpenBitFun {0} Beta', needs.prepare.outputs.version) || format('OpenBitFun {0}', needs.prepare.outputs.version) }}
712- generate_release_notes : true
713- files : release-upload-assets/*
714- fail_on_unmatched_files : true
724+ shell : bash
725+ env :
726+ GH_TOKEN : ${{ github.token }}
727+ RELEASE_TAG : ${{ needs.prepare.outputs.release_tag }}
728+ RELEASE_VERSION : ${{ needs.prepare.outputs.version }}
729+ RELEASE_PRERELEASE : ${{ needs.prepare.outputs.release_channel == 'beta' }}
730+ RELEASE_LATEST : ${{ needs.prepare.outputs.release_channel == 'stable' }}
731+ run : |
732+ set -euo pipefail
733+ # The immutable tag was checked before building. Do not send
734+ # target_commitish: GitHub can require workflows:write even when the
735+ # tag already exists. action-gh-release also resends the stored value.
736+ status="$(curl -sS --retry 5 --retry-delay 3 \
737+ --output release-state.json --write-out '%{http_code}' \
738+ -H "Authorization: Bearer ${GH_TOKEN}" \
739+ -H 'Accept: application/vnd.github+json' \
740+ "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}")"
741+ case "${status}" in
742+ 200) ;;
743+ 404)
744+ gh release create "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" \
745+ --verify-tag --draft --title "OpenBitFun ${RELEASE_VERSION}" \
746+ --generate-notes
747+ ;;
748+ *)
749+ echo "Could not inspect release (GitHub API returned ${status})." >&2
750+ exit 1
751+ ;;
752+ esac
753+ gh release upload "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" \
754+ --clobber release-upload-assets/*
755+ gh release edit "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" \
756+ --title "OpenBitFun ${RELEASE_VERSION}" --draft=false \
757+ --prerelease="${RELEASE_PRERELEASE}" --latest="${RELEASE_LATEST}"
758+
759+ - name : Verify published legacy update feeds
760+ if : needs.prepare.outputs.release_channel == 'stable'
761+ shell : bash
762+ run : |
763+ set -euo pipefail
764+ for manifest in latest.json linux-binaries.json; do
765+ curl -fsSL --retry 5 --retry-delay 3 \
766+ "https://github.com/${{ github.repository }}/releases/download/${{ needs.prepare.outputs.release_tag }}/${manifest}" \
767+ -o "legacy-${manifest}"
768+ cmp "release-upload-assets/${manifest}" "legacy-${manifest}"
769+ done
715770
716771 - name : Verify published updater manifest
717772 run : |
718773 curl -fsSL --retry 5 --retry-delay 3 \
719- "https://github.com/${{ github.repository }}/releases/download/${{ needs.prepare.outputs.release_tag }}/latest.json" \
774+ "https://github.com/${{ github.repository }}/releases/download/${{ needs.prepare.outputs.release_tag }}/latest-v1 .json" \
720775 -o latest.published.json
721776 node scripts/verify-tauri-latest-json.mjs \
722777 --manifest latest.published.json \
@@ -728,7 +783,7 @@ jobs:
728783 - name : Verify published Linux binaries manifest
729784 run : |
730785 curl -fsSL --retry 5 --retry-delay 3 \
731- "https://github.com/${{ github.repository }}/releases/download/${{ needs.prepare.outputs.release_tag }}/linux-binaries.json" \
786+ "https://github.com/${{ github.repository }}/releases/download/${{ needs.prepare.outputs.release_tag }}/linux-binaries-v1 .json" \
732787 -o linux-binaries.published.json
733788 test "$(jq -r '.version' linux-binaries.published.json)" = "${{ needs.prepare.outputs.version }}"
734789 jq -e '.platforms | has("linux-x86_64") and has("linux-aarch64")' linux-binaries.published.json >/dev/null
@@ -773,12 +828,12 @@ jobs:
773828 -H "Authorization: Bearer ${GH_TOKEN}" \
774829 -H 'Accept: application/vnd.github+json' \
775830 -H 'X-GitHub-Api-Version: 2022-11-28' \
776- "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/channel-beta")"
831+ "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/channel-v1- beta")"
777832 case "${channel_status}" in
778833 200)
779834 echo "channel_exists=true" >>"$GITHUB_OUTPUT"
780835 curl -fsSL --retry 5 --retry-delay 3 \
781- "https://github.com/${GITHUB_REPOSITORY}/releases/download/channel-beta/latest.json" \
836+ "https://github.com/${GITHUB_REPOSITORY}/releases/download/channel-v1- beta/latest-v1 .json" \
782837 -o current.beta.json
783838 ;;
784839 404)
@@ -790,7 +845,7 @@ jobs:
790845 fi
791846 ;;
792847 *)
793- echo "Could not inspect channel-beta release (GitHub API returned ${channel_status})." >&2
848+ echo "Could not inspect channel-v1- beta release (GitHub API returned ${channel_status})." >&2
794849 exit 1
795850 ;;
796851 esac
@@ -811,26 +866,26 @@ jobs:
811866 run : |
812867 set -euo pipefail
813868 if [[ "${CHANNEL_EXISTS}" != "true" ]]; then
814- gh release create channel-beta \
869+ gh release create channel-v1- beta \
815870 --repo "${GITHUB_REPOSITORY}" \
816871 --target "${CHECKOUT_REF}" \
817872 --prerelease \
818873 --title "OpenBitFun Beta Update Channel" \
819874 --notes "Mutable updater pointer. Installable beta releases use immutable version tags."
820875 fi
821876 mkdir -p beta-channel
822- cp latest.published.json beta-channel/latest.json
823- gh release upload channel-beta beta-channel/latest.json \
877+ cp latest.published.json beta-channel/latest-v1 .json
878+ gh release upload channel-v1- beta beta-channel/latest-v1 .json \
824879 --repo "${GITHUB_REPOSITORY}" \
825880 --clobber
826881 # A successful HTTP response can still contain the previous CDN object.
827882 # Retry content validation as well as transport failures after replacement.
828883 for attempt in {1..12}; do
829884 if curl -fsSL --max-time 30 \
830- "https://github.com/${GITHUB_REPOSITORY}/releases/download/channel-beta/latest.json" \
831- -o channel-beta.published.json && \
885+ "https://github.com/${GITHUB_REPOSITORY}/releases/download/channel-v1- beta/latest-v1 .json" \
886+ -o channel-v1- beta.published.json && \
832887 jq -e --arg version "${CANDIDATE_VERSION}" \
833- '.version == $version' channel-beta.published.json >/dev/null; then
888+ '.version == $version' channel-v1- beta.published.json >/dev/null; then
834889 echo "Beta channel manifest verified: ${CANDIDATE_VERSION}"
835890 exit 0
836891 fi
0 commit comments