Skip to content

Commit 295b067

Browse files
committed
docs: correct release runbook in MAINTAINING.md
mix publisho only commits and tags; it does not push. Drop the claim that it pushes and add an explicit push step that triggers the NIF release workflow. release-nif.yml now auto-publishes the draft release once both NIF cells build, so remove the obsolete manual `gh release edit --draft=false` promotion step. Renumber the remaining steps and demote the end-to-end verify to a recommended post-publish check.
1 parent 165148b commit 295b067

2 files changed

Lines changed: 61 additions & 42 deletions

File tree

MAINTAINING.md

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ default `aot`) through `config/config.exs` and stash the atom as
5050
## Cutting a release
5151

5252
Consumers verify each NIF tarball against the checksum pinned in
53-
`native_checksums.txt`, which ships in the hex package. Publishing is two
54-
commands (step 4): `mix emily.publish` regenerates that file from the
55-
freshly-built release artifacts, then `mix hex.publish` publishes — so
56-
there is nothing to update or commit by hand (the file is git-ignored and
57-
can't go stale).
53+
`native_checksums.txt`, which ships in the hex package. The publish step
54+
itself is two commands (steps 4–5): `mix emily.publish` regenerates that
55+
file from the built release artifacts, then `mix hex.publish` publishes —
56+
so there is nothing to update or commit by hand (the file is git-ignored
57+
and can't go stale).
5858

5959
### 1. Land changes on `main`
6060

@@ -68,8 +68,16 @@ mix publisho patch # or minor / major
6868
```
6969

7070
Bumps `@version`, rolls `RELEASE.md` into `CHANGELOG.md` under a
71-
dated `## <v>` heading, commits `Version <v>`, tags bare semver (no
72-
`v` prefix), and pushes both the commit and the tag.
71+
dated `## <v>` heading, commits `Version <v>`, and creates an annotated
72+
bare-semver tag (no `v` prefix). It does **not** push — that's the next
73+
step.
74+
75+
### 3. Push the commit and the tag
76+
77+
```sh
78+
git push # the `Version <v>` commit
79+
git push origin <v> # the tag — this is what fires the release workflow
80+
```
7381

7482
The tag push fires `.github/workflows/release-nif.yml`, which fans
7583
out `{variant × target}`:
@@ -89,9 +97,46 @@ sidecar (informational — consumers verify against the pinned
8997
`https://github.com/ausimian/emily/releases/tag/<v>` — the URL the
9098
consumer's `compile.emily_nif` step fetches from.
9199

92-
### 3. Verify end-to-end
100+
Once both cells finish, the workflow's `publish-release` job flips the
101+
release out of draft **automatically** (`gh release edit <v> --draft=false`),
102+
so its assets become public with no manual step. That job is gated to the
103+
tag-push path, so a manual `workflow_dispatch` rebuild leaves the release
104+
untouched — see *Rebuilding without retagging*.
105+
106+
### 4. Pin the checksums
107+
108+
Once the workflow has finished and the release is public:
93109

94-
In a throwaway project:
110+
```sh
111+
mix emily.publish # alias for `mix emily.checksums`
112+
```
113+
114+
Downloads each tarball from the now-public release and records its SHA256
115+
into `native_checksums.txt`. It does **not** trust the `.sha256` sidecars —
116+
it hashes the bytes itself. If the release isn't public yet, the download
117+
404s and the task aborts before writing anything.
118+
119+
### 5. Publish to Hex
120+
121+
```sh
122+
mix hex.publish # publishes the package (incl. native_checksums.txt) + docs
123+
```
124+
125+
Packages `native_checksums.txt` — so it's covered by Hex's package hash in
126+
the consumer's `mix.lock`, a trust root independent of the mutable GitHub
127+
release — and publishes the package + docs.
128+
129+
Steps 4 and 5 are two separate commands on purpose — they can't be folded
130+
into one alias. Mix only loads the Hex archive for the task *named on the
131+
command line*, so a `hex.publish` step chained inside an alias (whose CLI
132+
name is `emily.publish`) fails with `** (Mix) The task "hex.publish" could
133+
not be found`. Running `mix hex.publish` directly is what loads Hex.
134+
`hex.publish` keeps its `:docs` `preferred_env`, so it publishes docs as
135+
well as the package.
136+
137+
### 6. Verify end-to-end (recommended)
138+
139+
After publishing, in a throwaway project:
95140

96141
```sh
97142
mix new /tmp/emily-verify && cd /tmp/emily-verify
@@ -106,39 +151,9 @@ iex -S mix
106151
downloads the tarball, verifies, validates entries, extracts. A
107152
variant-mismatched consumer (`config :emily, variant: :jit`) should
108153
download the JIT tarball instead — worth spot-checking both lanes on
109-
the first release of a bump. (The pin only ever exists in the
110-
*published* package — `native_checksums.txt` is git-ignored and
111-
generated during `mix hex.publish` — so run this end-to-end verify
112-
against the published package, i.e. after step 4.)
113-
114-
### 4. Promote the draft and publish
115-
116-
Promote the release so its assets are public, then publish:
117-
118-
```sh
119-
gh release edit <v> --repo ausimian/emily --draft=false # assets go public
120-
mix emily.publish # regenerate native_checksums.txt
121-
mix hex.publish # publish package + docs
122-
```
123-
124-
`mix emily.publish` runs `mix emily.checksums`: it downloads each tarball
125-
from the (now-public) release and records its SHA256 into
126-
`native_checksums.txt`. Then `mix hex.publish` packages that file and
127-
publishes the package + docs.
128-
129-
These are two separate commands on purpose — they can't be folded into one
130-
alias. Mix only loads the Hex archive for the task *named on the command
131-
line*, so a `hex.publish` step chained inside an alias (whose CLI name is
132-
`emily.publish`) fails with `** (Mix) The task "hex.publish" could not be
133-
found`. Running `mix hex.publish` directly is what loads Hex. `hex.publish`
134-
keeps its `:docs` `preferred_env`, so it publishes docs as well as the
135-
package.
136-
137-
So the consumer verifies downloads against a trust root that lives in the
138-
immutable Hex package, not the mutable GitHub release — with no file to
139-
maintain and nothing to commit. The file is git-ignored and regenerated on
140-
every publish, so it can't go stale. If the draft isn't public yet,
141-
`mix emily.checksums` 404s and aborts before you publish.
154+
the first release of a bump. The checksum pin only exists in the
155+
*published* package, so this must run against the published package,
156+
i.e. after step 5.
142157

143158
### Rebuilding without retagging
144159

RELEASE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@
88
- The benchmark report's environment block now records the Emily
99
version the numbers were produced on (0.7.0) and drops a misleading
1010
run timestamp.
11+
- The `MAINTAINING.md` release runbook is corrected: `mix publisho` is
12+
no longer described as pushing (it only commits and tags), and the
13+
obsolete manual draft-promotion step is dropped — `release-nif.yml`
14+
now publishes the release automatically once the NIFs are built.

0 commit comments

Comments
 (0)