also looking at this
fix(release): one publisher, and a red run when the DMG is missing
#58
3 files
+93
-36
| @@ -5,38 +5,72 @@ on: | ||
| 5 | 5 | tags: |
| 6 | 6 | - 'v*' |
| 7 | 7 | |
| 8 | # Read only. This workflow publishes nothing: `buddy uplink:release` on a Mac | |
| 9 | # is the only publisher, because the DMG has to be signed with a Developer ID | |
| 10 | # and notarized by Apple, and no ubuntu runner can do that. | |
| 11 | # | |
| 12 | # It used to run `stacksjs/action-releaser`, which created a release for the | |
| 13 | # same tag and attached nothing. Whichever finished last decided what the | |
| 14 | # release page said, and a tag pushed without the manual step still produced | |
| 15 | # the release GitHub then calls `latest`, so every download 404'd with nothing | |
| 16 | # failing anywhere to say so (#32). | |
| 8 | 17 | permissions: |
| 9 | contents: write | |
| 18 | contents: read | |
| 10 | 19 | |
| 11 | 20 | jobs: |
| 12 | release: | |
| 21 | dmg-attached: | |
| 22 | name: The release has a DMG | |
| 13 | 23 | runs-on: ubuntu-latest |
| 14 | 24 | |
| 15 | 25 | steps: |
| 16 | - name: Checkout Code | |
| 17 | uses: actions/checkout@v6 | |
| 18 | with: | |
| 19 | # The changelog is generated from commits since the previous tag, so | |
| 20 | # the full history has to be present. | |
| 21 | fetch-depth: 0 | |
| 22 | ||
| 23 | - name: Setup Pantry | |
| 24 | uses: pantry-pm/pantry/packages/action@fa35547da630b14beda5b26a2625490864d5c963 # v0.11.60 | |
| 25 | with: | |
| 26 | install: 'false' | |
| 27 | ||
| 28 | - name: Use Cached node_modules | |
| 29 | uses: actions/cache@v5 | |
| 30 | with: | |
| 31 | path: node_modules | |
| 32 | key: node-modules-${{ hashFiles('**/bun.lock') }} | |
| 33 | restore-keys: | | |
| 34 | node-modules- | |
| 35 | ||
| 36 | - name: Install Dependencies | |
| 37 | run: bun install | |
| 38 | ||
| 39 | - name: Create GitHub Release | |
| 40 | uses: stacksjs/action-releaser@v1.2.9 | |
| 26 | # `gh release create` makes the tag and the release, then uploads about | |
| 27 | # 35 MB, so this run starts while the upload is still going. Polling is | |
| 28 | # the point: checking once would race the publisher that is working | |
| 29 | # correctly. | |
| 30 | - name: Wait for Uplink.dmg to be attached | |
| 41 | 31 | env: |
| 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| 32 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| 33 | TAG: ${{ github.ref_name }} | |
| 34 | REPO: ${{ github.repository }} | |
| 35 | run: | | |
| 36 | set -uo pipefail | |
| 37 | for attempt in $(seq 1 30); do | |
| 38 | release=$(gh release view "$TAG" --repo "$REPO" --json isDraft,assets 2>/dev/null) || release='' | |
| 39 | ||
| 40 | if [ -n "$release" ]; then | |
| 41 | # A draft never becomes `latest`, so it cannot 404 a download. | |
| 42 | if [ "$(echo "$release" | jq -r '.isDraft')" = 'true' ]; then | |
| 43 | echo "$TAG is a draft. Nothing points at it yet, so there is nothing to check." | |
| 44 | exit 0 | |
| 45 | fi | |
| 46 | if echo "$release" | jq -e '.assets[] | select(.name == "Uplink.dmg")' >/dev/null; then | |
| 47 | echo "$TAG has Uplink.dmg. releases/latest/download/Uplink.dmg resolves." | |
| 48 | exit 0 | |
| 49 | fi | |
| 50 | fi | |
| 51 | ||
| 52 | echo "attempt $attempt/30: no Uplink.dmg on $TAG yet, waiting 20s" | |
| 53 | sleep 20 | |
| 54 | done | |
| 55 | ||
| 56 | cat <<EOF | |
| 57 | ::error::$TAG has no Uplink.dmg after 10 minutes. | |
| 58 | ||
| 59 | Every download link in the project goes through | |
| 60 | releases/latest/download/Uplink.dmg: the README button and the three | |
| 61 | on the homepage. A published release without that asset moves | |
| 62 | 'latest' and 404s all of them. | |
| 63 | ||
| 64 | This usually means the tag was pushed without running the publisher. | |
| 65 | Only 'buddy uplink:release' on a Mac can attach the DMG, because it | |
| 66 | signs with a Developer ID and notarizes with Apple. | |
| 67 | ||
| 68 | Either attach the asset to the existing release: | |
| 69 | ||
| 70 | gh release upload $TAG storage/framework/desktop-dmg/Uplink.dmg | |
| 71 | ||
| 72 | or take the tag back so 'latest' stops pointing at it: | |
| 73 | ||
| 74 | gh release delete $TAG --cleanup-tag | |
| 75 | EOF | |
| 76 | exit 1 | |