diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0b8809a..a72a62b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -183,8 +183,9 @@ jobs:
gh release create "v${version}" \
--title "${version}" \
--notes-file build/release-notes.md \
- --prerelease \
- build/OpenDeviceHub-${version}.dmg build/SHA256SUMS
+ --latest \
+ build/OpenDeviceHub-${version}.dmg build/OpenDeviceHub.dmg build/SHA256SUMS \
+ build/appcast.xml
env:
GH_TOKEN: ${{ github.token }}
diff --git a/README.md b/README.md
index 876a02c..5282716 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
-
+
@@ -30,7 +30,7 @@
## Install
-Download [OpenDeviceHub-0.1.0.dmg](https://github.com/Mastersam07/OpenDeviceHub/releases/download/v0.1.0/OpenDeviceHub-0.1.0.dmg),
+Download [OpenDeviceHub.dmg](https://github.com/Mastersam07/OpenDeviceHub/releases/latest/download/OpenDeviceHub.dmg),
drag OpenDeviceHub to Applications and launch it. Every version, with its checksums, is on
[Releases](https://github.com/Mastersam07/OpenDeviceHub/releases). The app is signed with a Developer ID certificate and
notarized, so there is no Gatekeeper warning, and it updates itself from the app menu.
diff --git a/RELEASING.md b/RELEASING.md
index 6718e83..3c3be9e 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -57,13 +57,14 @@ unsigned build that reaches a release page is worse than a run that stops.
short retention name so you can download and check them.
4. Install the dry run's DMG and use it. `stapler validate` on the app and on the DMG, and
`shasum -c SHA256SUMS` from a different directory.
-5. Run the workflow again with `publish` **true**. It creates the tag and a pre-release with the DMG
- and `SHA256SUMS`. Then point the README's download button and its Install link at the new DMG:
- they download it directly rather than opening the Releases page, and `releases/latest` skips
- pre-releases, so the link has to carry the version.
-6. **Only once that release page exists**, commit the generated `appcast.xml` to the feed
- repository. A feed pointing at a download that is not there yet breaks updates for everyone who
- reads it in the meantime.
+5. Run the workflow again with `publish` **true**. It creates the tag and a release marked as the
+ latest, carrying the DMG under its versioned name, the same DMG as `OpenDeviceHub.dmg`,
+ `SHA256SUMS` and the signed `appcast.xml`. The README's download button and its Install link fetch
+ `OpenDeviceHub.dmg` from the latest release, so they need no edit.
+6. **Only once that release page exists**, commit the release's `appcast.xml` to the feed
+ repository. Installed copies read the feed from there, never from the release, which is why the
+ feed URL can never move. A feed pointing at a download that is not there yet breaks updates for
+ everyone who reads it in the meantime.
7. Confirm an already installed older copy finds the update, verifies it and installs it, ending on
the new version. Do this before announcing anything: a broken updater cannot be fixed by a later
release.
diff --git a/scripts/release-notes.py b/scripts/release-notes.py
index 740bc93..70d5bbf 100755
--- a/scripts/release-notes.py
+++ b/scripts/release-notes.py
@@ -69,7 +69,7 @@ def main() -> int:
## Known gaps
-This is a pre-release. These are the ones worth knowing before you install it:
+These are the ones worth knowing before you install it:
{limitations}
diff --git a/scripts/sign-and-notarize.sh b/scripts/sign-and-notarize.sh
index 0ca294e..072b37a 100755
--- a/scripts/sign-and-notarize.sh
+++ b/scripts/sign-and-notarize.sh
@@ -36,6 +36,12 @@ echo
echo "== notarize and staple the disk image =="
"${repo_root}/scripts/notarize.sh" "${dmg}"
+echo
+echo "== the same disk image under a name that never changes =="
+# The README's download button fetches this name from the latest release, so it never needs editing.
+cp "${dmg}" "${repo_root}/build/OpenDeviceHub.dmg"
+echo "${repo_root}/build/OpenDeviceHub.dmg"
+
echo
echo "== checksums, from the stapled artifacts =="
"${repo_root}/scripts/checksums.sh"