Skip to content

Commit da53abb

Browse files
committed
fkclaude: bring the docs up to date with what was actually submitted
The review runbook still said "nothing has been pushed yet" and explained how to open the PRs. They are open, so it now leads with their state - four PRs against oltaco, two changes prepared and deliberately held back, and the separate MeshCore PR - and the submission section records how it was done rather than how it would be. Two things from that section are worth having written down. gh is not installed system-wide; a portable copy sits at D:\FkDev\GHcli and authenticates from the Git Credential Manager token. And gh pr edit fails on that token because it goes through GraphQL, which wants read:org even to change a body - the REST path works with the plain repo scope. Adds fcl_HowTo_release_and_ci.md for the release machinery, all of it established by running it on the fork: the workflow builds on release creation only, so pull requests get no CI at all upstream; the tag name lands in all 42 asset names, in INFO_UF2.TXT and in the BLE firmware revision string; the workflow is taken from the tagged commit rather than the default branch, so CI changes can be tested without touching master; and a fork's default_workflow_permissions is read, which lets every board build and then fails the upload with "Resource not accessible by integration". Also records the mistake that cannot be undone: #NN in a commit message on a fork creates a permanent referenced event on the upstream PR, showing the commit subject. Two internal commits leaked working notes into oltaco#47 and oltaco#50 that way. Rewriting the messages stops new ones; the existing events stay, and the orphaned commits remain fetchable by SHA.
1 parent b75c3f3 commit da53abb

3 files changed

Lines changed: 143 additions & 23 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Releases and CI - how the automation actually behaves
2+
3+
Everything here was established by running it, on `fkallay1/Adafruit_nRF52_Bootloader_OTAFIX`
4+
(2026-07-28/29). Nothing was tried against `oltaco`.
5+
6+
## What builds, and when
7+
8+
`.github/workflows/githubci.yml` builds **on release creation only**:
9+
10+
```yaml
11+
on:
12+
# pull_request:
13+
# push:
14+
release:
15+
types: [created]
16+
```
17+
18+
`push` and `pull_request` are commented out, which has one consequence worth knowing before you
19+
send anything upstream: **pull requests get no CI at all there.** No maintainer sees a green
20+
check on our PRs, so the measured results written into the PR bodies are the only evidence
21+
offered.
22+
23+
On a release it generates the board matrix from `src/boards/*` (14 boards today), builds each on
24+
a GitHub-hosted `ubuntu-latest` runner with ARM GCC 12.3.Rel1 - nothing runs locally - and
25+
attaches three files per board: `<board>_bootloader-*.zip`, `*.hex`, and
26+
`update-<board>_bootloader-*_nosd.uf2`. 14 x 3 = the 42 assets each upstream release has.
27+
28+
## Cutting a release
29+
30+
```sh
31+
GH=/d/FkDev/GHcli/bin/gh.exe
32+
export GH_TOKEN=$(printf "protocol=https\nhost=github.com\n\n" | git credential fill | sed -n 's/^password=//p')
33+
"$GH" release create <tag> -R fkallay1/Adafruit_nRF52_Bootloader_OTAFIX \
34+
--target <branch> --title "<tag>" --notes "..."
35+
```
36+
37+
Four things that will bite:
38+
39+
**The tag names the artifacts.** The version comes from `git describe`, so it lands in all 42
40+
asset names *and* in `INFO_UF2.TXT` on the device *and* in `BLEDIS_FW_VERSION` (the Firmware
41+
Revision in the BLE Device Information Service). Tag the exact commit you mean - anywhere else
42+
and you get `-<n>-g<sha>` glued into every filename. Do not invent a version number: follow the
43+
upstream scheme, e.g. `0.9.2-OTAFIX2.2-BP1.3-dfu-recovery-v1`, which says what it is without
44+
claiming to be 0.9.3.
45+
46+
**Releases are repo-level, their content is per-commit.** One list of releases for the repo, but
47+
each is pinned to a tag, and that tag can sit on any branch. Building a release from a feature
48+
branch is normal.
49+
50+
**The workflow comes from the tagged commit, not from the default branch.** Measured: `master`
51+
pinned `checkout@v4` while the tagged branch pinned `@v7`, and `@v7` is what ran. So CI changes
52+
can be tested without touching `master`.
53+
54+
**`default_workflow_permissions` must be `write`.** A fork defaults to `read`, and then every
55+
board builds fine and the last step dies with `Resource not accessible by integration` - which
56+
reads like a code failure and is not:
57+
58+
```sh
59+
"$GH" api repos/OWNER/REPO/actions/permissions/workflow --method PUT -f default_workflow_permissions=write
60+
```
61+
62+
Also: `release: types: [created]` does not reliably fire when you publish a saved **draft**.
63+
Create the release directly, not draft-then-publish.
64+
65+
## The Node deprecation
66+
67+
Every job used to carry `Node 20 is deprecated ... forced to run on Node.js 24`. That is a
68+
warning, not an error - the run is green and the assets appear. But when the fallback is
69+
withdrawn, as it was for Node 12 and 16, the steps will not start, and with `pull_request`
70+
disabled the first sign would be a release producing nothing.
71+
72+
The actions were three majors behind, and the Node version does **not** track the major:
73+
74+
| action | was | Node | now | Node |
75+
|---|---|---|---|---|
76+
| `actions/checkout` | v4 | node20 | v7 | node24 |
77+
| `actions/upload-artifact` | v4 | node20 | v7 | node24 (v5 is *still* node20 - v6 is the first that helps) |
78+
| `softprops/action-gh-release` | v1 | **node16** | v3 | node24 |
79+
80+
Bumped on `feature/serial-dfu-auto-recovery` and verified by a release: 14 boards, 42 assets, and
81+
the annotation gone from every job. The same four-line change is staged for upstream as
82+
`feature/ci-node24-actions` - see `fkclaude/docs/upstream-prs/ci-node24-actions.*`.

fkclaude/fcl_HowTo_review_upstream_prs.md

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1-
# How to review the four upstream PRs before they are sent
1+
# The upstream submissions - what is out there, and how to follow up
22

3-
Everything for the review is in **`fkclaude/docs/upstream-prs/`** - one `.diff` (the code) and
4-
one `.msg.md` (the commit message, which is also the PR description) per PR. Nothing has been
5-
pushed yet; the branches exist only locally.
3+
**Submitted 2026-07-28.** The four bootloader PRs are open against `oltaco`, and two further
4+
changes are prepared but deliberately not sent. Current state:
5+
6+
| what | where | status |
7+
|---|---|---|
8+
| recover serial/USB DFU after a failed flash | [oltaco #47](https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX/pull/47) | open, `mergeable=clean` |
9+
| reboot when a started transfer goes silent | [oltaco #48](https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX/pull/48) | open, `mergeable=clean` |
10+
| accept a new session after an interrupted transfer | [oltaco #49](https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX/pull/49) | open, `mergeable=clean` |
11+
| serial reboot command (`DFU_REBOOT_PACKET`) | [oltaco #50](https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX/pull/50) | open, `mergeable=clean` |
12+
| CI onto Node 24 actions | branch `feature/ci-node24-actions` | **prepared, not sent** |
13+
| touch 2400 for UF2 mode | `adafruit/Adafruit_TinyUSB_Arduino`, branch in the scratchpad | **prepared, not sent** |
14+
| serial CLI lockup (a separate project) | [meshcore-dev #2978](https://github.com/meshcore-dev/MeshCore/pull/2978) | open since 2026-07-18, nudged |
15+
16+
Each PR cross-references the other three in order of importance, and #47/#48 are linked to
17+
upstream issues #40 and #41 with `Related to` - deliberately not `Fixes`, since neither issue is
18+
fully answered. Comments explaining what is and is not covered are posted under both issues.
19+
20+
Everything for reading them is in **`fkclaude/docs/upstream-prs/`** - one `.diff` (the code) and
21+
one `.msg.md` (the commit message, which is also the PR description) per change.
622

723
Related: `fkclaude/fcl_readme_dfu_recovery.md` (what the changes do), `fkclaude/scripts/README.md`
824
(the test rig), `fkclaude/docs/2026-07-28-dfu-recovery-investigation.md` (how it was diagnosed,
@@ -143,30 +159,50 @@ transiently (the PR 2 stall timeout is the backstop), and the nRF52832 path is c
143159
this fork - no board here selects a non-nRF52840 MCU - so PR 2's effect on it is argued
144160
arithmetically, not measured.
145161

146-
## Step 5 - when you approve, this is what gets run
162+
## Step 5 - how these were submitted, and how to follow up
147163

148-
Nothing below has been run yet.
164+
`gh` is **not installed system-wide**; a portable copy lives at `D:\FkDev\GHcli\bin\gh.exe`
165+
(v2.96.0, plain zip, no installer). It authenticates from the Git Credential Manager token:
149166

150167
```sh
151-
for b in dfu-recover-on-usb dfu-stall-timeout dfu-retry-after-abort dfu-serial-reboot-command; do
152-
git push -u origin feature/$b
153-
done
154-
155-
gh pr create --repo oltaco/Adafruit_nRF52_Bootloader_OTAFIX --base dev \
168+
GH=/d/FkDev/GHcli/bin/gh.exe
169+
export GH_TOKEN=$(printf "protocol=https\nhost=github.com\n\n" | git credential fill | sed -n 's/^password=//p')
170+
"$GH" pr create -R oltaco/Adafruit_nRF52_Bootloader_OTAFIX --base dev \
156171
--head fkallay1:feature/dfu-recover-on-usb \
157-
--title "dfu: recover serial/USB DFU automatically after a failed flash" \
158-
--body-file fkclaude/docs/upstream-prs/dfu-recover-on-usb.msg.md
172+
--title "$(git log -1 --format=%s feature/dfu-recover-on-usb)" \
173+
--body-file fkclaude/docs/upstream-prs/dfu-recover-on-usb.body
159174
```
160175

161-
...and the same for the other three. Two notes on the `gh` calls:
176+
Two things that cost time and are worth keeping:
162177

163-
- `--body-file` would include the subject line as the first line of the body. Strip it, or pass
164-
`--title` and a body file without the first two lines.
165-
- Open PR 1 first and reference it from the others, so the maintainer sees the intended reading
166-
order.
178+
- The body must not repeat the title. Split the commit message: `--format=%s` for the title,
179+
`--format=%b` for the body.
180+
- **`gh pr edit` fails on this token** - it goes through GraphQL, which demands the `read:org`
181+
scope even to change a body. The REST path works with the plain `repo` scope:
182+
`gh api repos/OWNER/REPO/pulls/N --method PATCH --input payload.json`.
167183

168-
## If you want a change
184+
To push a change to an open PR, commit on the branch and push normally - the PR follows the
185+
branch. The branches are regenerated from pristine `upstream/dev` by a script rather than
186+
edited in place, so a wording or code change means rebuilding that one branch; the other three
187+
keep their SHAs.
188+
189+
## A mistake worth not repeating
190+
191+
**Never write `#NN` in a commit message on a branch pushed to this fork.** The fork is in
192+
`oltaco`'s fork network, so GitHub turns every `#NN` in a pushed commit into a `referenced`
193+
event on that upstream PR, with the commit subject on display. Two internal `fkclaude:` commits
194+
mentioning `#47` and `#50` therefore leaked working notes into the timelines of PR #47 and #50.
195+
196+
It cannot be undone. Rewriting the messages and force-pushing stops *new* references, but the
197+
events already recorded stay - GitHub keeps them after the commit becomes unreachable, the
198+
orphaned commit is still fetchable by SHA so the link still opens it, and the REST API has no
199+
endpoint to delete a timeline event. Only GitHub Support can purge that.
200+
201+
Write `PR 50`, not `#50`. Check before pushing:
202+
203+
```sh
204+
git log --format=%B origin/master..HEAD | grep -oE '#[0-9]+'
205+
```
169206

170-
Say which PR and what should differ. The branches are regenerated from pristine `upstream/dev`
171-
by a script rather than edited in place, so a wording or code change means rebuilding that one
172-
branch - the other three keep their SHAs.
207+
File *content* is safe - a `#NN` inside a committed document creates nothing. Only commit
208+
messages, PR/issue bodies and comments autolink.

fkclaude/fcl_readme_dfu_recovery.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
What our bootloader changes do, how the device behaves after them, and how to flash them.
44

5-
- Reviewing/submitting the upstream PRs: `fkclaude/fcl_HowTo_review_upstream_prs.md`
5+
- State of the upstream submissions, and how to follow up: `fkclaude/fcl_HowTo_review_upstream_prs.md`
6+
- Releases and CI, and the traps in both: `fkclaude/fcl_HowTo_release_and_ci.md`
67
- Script reference for the test rig: `fkclaude/scripts/README.md`
8+
- Testing on a board with no debugger: `fkclaude/docs/2026-07-28-xiao-no-debugger-testing.md`
79
- How it was diagnosed, including the dead ends: `fkclaude/docs/2026-07-28-dfu-recovery-investigation.md`
810
- Original design brief: `esp32-s3_USBIP/fkclaude/docs/2026-07-27-bootloader-dfu-recovery-design.md`
911

0 commit comments

Comments
 (0)