Skip to content
Merged
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
56 changes: 56 additions & 0 deletions .github/scripts/check-release-notes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python3
"""Render the release notes header the way the workflow does, and check it.

The v0.1.0 notes shipped with an empty ```bash block in them. It came from
editing the heredoc by string substitution — inserting a closing fence, some
prose and an opening fence directly above a closing fence that was already
there. Nothing rendered the result before it was published.

Markdown has no compiler, so this is the compiler: unbalanced fences and empty
code blocks are the two failures that survive review by looking fine in a diff.
"""

import pathlib
import sys

WORKFLOW = pathlib.Path(".github/workflows/release.yml")
START = "cat > header.md <<'EOF'\n"
END = "\n EOF\n"


def main() -> int:
text = WORKFLOW.read_text()
if START not in text or END not in text:
print(f"{WORKFLOW}: no release-notes heredoc to check")
return 1

body = text.split(START, 1)[1].split(END, 1)[0]
# The heredoc is indented ten spaces inside the YAML.
header = "\n".join(
line[10:] if line.startswith(" " * 10) else line for line in body.split("\n")
)
header = header.replace("OWNER", "example").replace("TAG", "v0.0.0")

lines = header.split("\n")
fences = [n for n, line in enumerate(lines) if line.strip().startswith("```")]

problems = []
if len(fences) % 2:
problems.append(f"{len(fences)} code fences — unbalanced, so one block never closes")

for opened, closed in zip(fences[0::2], fences[1::2]):
if not [line for line in lines[opened + 1 : closed] if line.strip()]:
problems.append(f"empty code block at lines {opened + 1}-{closed + 1}")

if problems:
print("release notes would render wrong:")
for problem in problems:
print(f" {problem}")
return 1

print(f"release notes: {len(fences) // 2} code blocks, all balanced and non-empty")
return 0


if __name__ == "__main__":
sys.exit(main())
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ jobs:
fi
echo "README and CI agree on $WANT"

# The v0.1.0 notes shipped with an empty ```bash block, from editing the
# heredoc by string substitution and never rendering the result.
# Markdown has no compiler; this is the compiler.
- name: The release notes would render
run: python3 .github/scripts/check-release-notes.py

- name: Host tests
run: cargo test -p oxinit-unit -p oxinit-graph -p oxinit-service -p oxinit-cgroup -p oxinit-user -p oxinit-ipc -p oxinit-log -p oxinit-timer

Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ jobs:
`ghcr.io/OWNER/oxinit:demo` tracks `main` if you would rather have the
latest.

```bash
```

### Install

Download the tarball for your architecture below, check it, and put
Expand Down
25 changes: 25 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,31 @@ and runs.
The lesson is the same one the bug taught, applied to the fix: the reason to
run the command is that reasoning about what it will do is not the same thing.

### v0.1.0, and an empty code block in its notes

The release workflow worked on its first run: both architectures' tarballs with
checksums, the versioned image, and notes generated from the merged pull
requests. Verified by downloading what was published rather than trusting what
was built — both checksums match, and the binaries out of both tarballs report
`0.1.0` under emulation.

The notes shipped with an empty ```` ```bash ```` block in them, reported by
the first person to read them.

It came from editing the heredoc that writes those notes by string
substitution: the insertion ended with an opening fence directly above a
closing fence that was already there. The diff looked fine. Nothing rendered
the result, and Markdown has no compiler to complain.

So CI has one now. `.github/scripts/check-release-notes.py` renders the header
the way the workflow does and fails on unbalanced fences or empty blocks —
which are exactly the two mistakes that survive review by looking correct in a
diff. The published v0.1.0 notes were edited in place.

Third time in this project that the failure was *editing text without looking
at the output*, and the second time it reached somebody. It is worth naming as
a pattern rather than as three separate slips.

## Not doing, and why

These were on the list. They are coming off it with a reason rather than
Expand Down
Loading