Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The build workflow packages and uploads `SimStore.app.tar.bz2` and `release.json

Both publication workflows use the `simstore-releases` concurrency group with a multiple-run queue. Stable drafts can be retried, while an already published stable release cannot have its assets overwritten by the publisher. A delayed build cannot replace a newer nightly. The nightly's package and metadata are uploaded before its version index.

Release descriptions retain the Terminal installation command and the instruction against downloading the archive through a browser. The command uses the release's own tag, including stable tags. Nightly publishing refreshes the index in the same workflow; it does not depend on a second release event generated by `GITHUB_TOKEN`.
Release descriptions direct existing users to SimStore → Check for Updates… and provide a Terminal command for a first installation or manual reinstall. The command stays on one line, uses the release's own tag including stable tags, and removes the temporary archive after extraction. The description warns against downloading through a browser. Nightly publishing refreshes the index in the same workflow; it does not depend on a second release event generated by `GITHUB_TOKEN`.

To create a stable release, choose the next version and tag the tested main commit:

Expand Down
7 changes: 4 additions & 3 deletions scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,14 @@ def assemble_index(nightly: Release, stable: list[Release]) -> dict[str, object]

def release_notes(repo: str, tag: str) -> str:
command = (
'rm -rf /tmp/SimStore.app && '
f'curl -fL https://github.com/{repo}/releases/download/{tag}/{ARCHIVE} '
f'-o /tmp/{ARCHIVE} && rm -rf ~/Applications/SimStore.app && '
f'mkdir -p ~/Applications && tar -xjf /tmp/{ARCHIVE} -C ~/Applications'
f'mkdir -p ~/Applications && tar -xjf /tmp/{ARCHIVE} -C ~/Applications && '
f'rm -f /tmp/{ARCHIVE}'
)
return (
'Execute the command in Terminal to install this version:\n\n'
'If SimStore is already installed, choose SimStore → Check for Updates… in the app.\n\n'
'To install SimStore for the first time or reinstall it manually, run this command in Terminal:\n\n'
f'```sh\n{command}\n```\n\nDo NOT download by clicking the link below.\n'
)

Expand Down
17 changes: 11 additions & 6 deletions tests/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,17 @@ def test_invalid_release_fields_and_installation_instructions(self) -> None:
path = self.work / METADATA
write_json(path, {**valid, field: value})
Release.read(path)
notes = release_notes('example/simstore', '0.1.0')
command = notes.split('```sh\n')[1].split('\n```')[0]
self.assertNotIn('\n', command)
self.assertIn('/releases/download/0.1.0/SimStore.app.tar.bz2', command)
self.assertTrue(command.startswith('rm -rf /tmp/SimStore.app && curl'))
self.assertTrue(notes.endswith('Do NOT download by clicking the link below.\n'))
for tag in ('latest', '0.1.0'):
with self.subTest(tag=tag):
notes = release_notes('example/simstore', tag)
command = notes.split('```sh\n')[1].split('\n```')[0]
self.assertIn('SimStore → Check for Updates…', notes)
self.assertIn('first time or reinstall it manually', notes)
self.assertNotIn('\n', command)
self.assertIn(f'/releases/download/{tag}/{ARCHIVE}', command)
self.assertTrue(command.startswith('curl -fL '))
self.assertTrue(command.endswith(f'&& rm -f /tmp/{ARCHIVE}'))
self.assertTrue(notes.endswith('Do NOT download by clicking the link below.\n'))


if __name__ == '__main__':
Expand Down