release/: the newest stage's manufacturing files and documentation

A stage tag (v*) now builds, with kicad-cli, pandoc and pdflatex in the CI
image (.gitea/scripts/release-files.py):
- per board: Gerbers + Excellon drill zip (JLCPCB-compatible settings), BOM
  (grouped, DNP left out), pick and place, schematic and PCB PDFs, 3D renders;
- docs/*.md and docs/tex/*.tex as PDF, tag and commit in the footer;
- release/README.md with tag, commit, ERC/DRC result, files, SHA-256 and the
  stage's CHANGELOG section.
Every file name carries the tag. release-attach.py attaches the files plus a
zip of the whole folder to the tag's release (replacing assets of an earlier
run); for the newest stage tag (not older stages, not pre-releases) the job
commits them to release/ on main with [skip ci].

.gitignore: !/release/ after Release/ (Windows matches it case-insensitively);
.gitattributes: release/** -text so the SHA-256 match on every checkout.
TEMPLATE.md: "Release files" section, rules and CI updated.

Tested in git.b4l.co.th/b4l/kicad10_auto_node with harNES's board and docs:
v0.1 committed, v0.0 and v0.2-rc.1 left release/ alone, v0.2 tagged on an
older commit landed on top of a moved main; uploads byte-exact against a stub
of the Gitea release API.
This commit is contained in:
grabowski committed 2026-10-16 18:50:01 +07:00
1 parent 0e002be80c
commit 52a40c1c3e
11 files changed
+654 -53

No files matched your search

+57 -6
View File
@@ -20,7 +20,8 @@ description. Gitea puts the name into `README.md`, `CHANGELOG.md`,
project file is `hardware/<name>/<name>.kicad_pro`).
3. Commit and push. The KiBot workflow checks the board on every push.
4. Tag the first prototype `v0.1` when its boards are ordered, and link the
tag to the stage on the project's Prototypes tab in proplan.
tag to the stage on the project's Prototypes tab in proplan. CI then puts
the stage's manufacturing files and documentation into `release/`.
## Layout
@@ -28,6 +29,7 @@ description. Gitea puts the name into `README.md`, `CHANGELOG.md`,
|---|---|
| `proplan.toml` | the manifest proplan reads (below) |
| `README.md`, `CHANGELOG.md` | what the product is; one changelog section per stage (`## v0.2`) |
| `release/` | the newest stage's manufacturing files and documentation, written by CI (below) |
| `assets/product.png` | the product image |
| `hardware/<board>/` | one KiCad project per board |
| `hardware/lib/` | symbols, footprints and 3D models shared by the boards |
@@ -47,7 +49,9 @@ description. Gitea puts the name into `README.md`, `CHANGELOG.md`,
(48 V and 24 V, 2-board and 3-board) is its own folder under `hardware/` and
its own `[[boards]]` entry.
- Generated output (gerbers, BOMs, production zips, PDFs, plots) is built by CI
and attached to the release; it is not committed.
and attached to the release; it is not committed. The one exception is
`release/`, which CI fills at a stage tag: nothing goes there by hand, and
generated files go nowhere else.
- Vendor datasheets go to `docs/datasheets/`, not the repository root.
- Third-party code is a git submodule in `external/` and is not edited here.
- IDE build output and tool caches (`Debug/`, `__pycache__/`, `.claude/`,
@@ -98,9 +102,53 @@ For all three:
folder. The root `CHANGELOG.md` has one section per prototype stage and
lists the firmware and software versions that stage was built with.
- Firmware and software releases are made by hand in Gitea for now (push the
tag, then New Release); `release.yml` builds board outputs for `v*` tags
tag, then New Release); `release.yml` builds the release files for `v*` tags
only.
## Release files (`release/`)
`release/` always holds the newest prototype stage, ready to send to a
manufacturer or a customer: whoever needs the current boards or documents
takes them from there, without KiCad and without knowing the tags. CI writes
it (`.gitea/workflows/release.yml`, `.gitea/scripts/release-files.py`) when a
stage tag is pushed; nobody edits it.
| Path | What |
|---|---|
| `release/README.md` | tag, commit, date, KiCad version, ERC and DRC result per board, the file list with sizes and SHA-256, the stage's CHANGELOG section |
| `release/hardware/<board>/<board>-<tag>-gerbers.zip` | Gerbers (every copper layer, paste, silkscreen, mask, outline; Protel names, no X2) and Excellon drill files (mm, PTH and NPTH apart): what a PCB fab such as JLCPCB takes |
| `release/hardware/<board>/<board>-<tag>-bom.csv` | bill of materials grouped by value, footprint, manufacturer, MPN and LCSC; DNP parts left out |
| `release/hardware/<board>/<board>-<tag>-cpl.csv` | pick and place (KiCad position file, mm, both sides, DNP left out) |
| `release/hardware/<board>/<board>-<tag>-schematic.pdf`, `-pcb.pdf` | the schematic; the PCB with one page per copper, silkscreen and fab layer |
| `release/hardware/<board>/<board>-<tag>-top.png`, `-bottom.png` | 3D renders |
| `release/docs/<name>-<tag>.pdf` | every `docs/*.md` except `README.md` and `input.md` (pandoc), and every `docs/tex/*.tex` with a `\documentclass` (pdflatex); the footer carries product, tag, commit and date |
- Boards are the `[[boards]]` of `proplan.toml` (or `hardware/*/*.kicad_pro`
when it names none), so a repository that adopted the layout without moving
folders gets its release files too.
- The tag is in every file name: a file sent to a fab or forwarded by mail
still says which stage it is.
- The same files, plus one zip of the whole folder, are attached to the tag's
release, so older stages stay one click away. `release/` follows the newest
stage tag only: a tag of an older stage or a pre-release (`v0.3-rc.1`) gets
its release attachments but leaves `release/` as it is.
- ERC and DRC errors do not stop the release (the tag records what was
ordered), but they are printed in `release/README.md` and as warnings on the
workflow run. Check the KiBot run before tagging.
- A document that does not build is listed in `release/README.md` as not
built; characters pdflatex cannot print (emoji) come out as `?` and are
named there.
- The commit says `[skip ci]` and `release/` is outside every workflow's
paths, so it starts no other workflow. `.gitattributes` keeps the files
byte for byte (`release/** -text`), so the SHA-256 match on Windows too.
- Locally, from the repository root, in the CI image (Docker):
`docker run --rm -v "$PWD:/w" -w /w git.b4l.co.th/b4l/kicad10_auto_node:latest python3 .gitea/scripts/release-files.py v0.1 --out build/release`
writes the same files to `build/` (ignored by git).
Not in it (yet): firmware binaries (firmware has its own tags), STEP models
(`mech/`), JLCPCB-specific BOM/CPL with rotation corrections (harNES's
`jlcpcb-files.py` does that per push).
## proplan.toml
proplan reads this file and the image it names, nothing else of the
@@ -204,9 +252,12 @@ external = "external"
ERC and DRC and builds schematic PDF, gerbers, drill files, pick and place
and BOM for every board (`hardware/*/*.kicad_pro`); the outputs are kept as a
workflow artifact.
- `.gitea/workflows/release.yml`: on a tag `v*`, the same outputs are zipped
per board and attached to the tag's release (created when missing). The
Actions token must be allowed to write releases. Firmware and software tags
- `.gitea/workflows/release.yml`: on a tag `v*`, builds the release files
(above) with kicad-cli, pandoc and pdflatex, attaches them to the tag's
release (created when missing, with the stage's CHANGELOG section) and, for
the newest stage, commits them to `release/` on main. The Actions token must
be allowed to write releases and to push to main (if main is protected, its
push rules must let the Actions bot through). Firmware and software tags
(`firmware/...`, `software/...`) do not start it.
- `.gitea/workflows/docgen.yml`: with a `docs/input.md` (typecad-docgen front
matter, as in PowerModule), builds the fabrication document of the first