packaging: bare backticks — a heredoc's backslash isn't the JSON's
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m5s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m16s
Desktop (Tauri) / Update manifest (push) Successful in 4s

Run 2981 built everything and then died posting the release: HTTP 422,
"invalid escape sequence \`". The body's other backticks are written \` because
they sit in an UNQUOTED heredoc, where that backslash is the shell's and is gone
before any JSON exists. Copying the idiom into a single-quoted variable changed
what it meant — single quotes already stop substitution, so the backslash
survived into the body as an escape JSON has no rule for.

bash -n passes either way; it checks syntax, not what a string becomes. So parse
the assembled body for every branch it can take instead, and write down the
recipe next to the one for formatting Rust.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKsUY9Z45KQd34V956hZ9Q
This commit is contained in:
2026-07-27 23:10:42 -04:00
co-authored by Claude Opus 5
parent 8b6dfab3a7
commit 13e48672c0
2 changed files with 19 additions and 1 deletions
+14
View File
@@ -183,3 +183,17 @@ bash -n desktop/packaging/publish-release.sh
Where a script resolves URLs from the Forgejo API, exercise the resolution Where a script resolves URLs from the Forgejo API, exercise the resolution
against the live instance (plain `curl` reads, no install) rather than trusting against the live instance (plain `curl` reads, no install) rather than trusting
the regex by eye. Both channel paths in `install.sh` were verified that way. the regex by eye. Both channel paths in `install.sh` were verified that way.
**Hand-assembled JSON: parse it before you push it.** `publish-release.sh` builds
its request bodies as shell strings, and quoting context decides what survives
into the JSON — a `` \` `` inside an unquoted heredoc loses its backslash to the
shell, the same `` \` `` inside a single-quoted variable does not, and reaches
Forgejo as an illegal escape (HTTP 422, one wasted build). `sh -n` cannot see
this. Extract the body block and parse it for every branch it can take:
```
sed -n '/^# The install command printed/,/^JSON$/p' desktop/packaging/publish-release.sh > /tmp/body.sh
echo ')' >> /tmp/body.sh
bash -c 'GITHUB_SERVER_URL=https://git.fabledsword.com GITHUB_REPOSITORY=o/r \
TAG=dev RELEASE_PRERELEASE=true; . /tmp/body.sh; printf "%s" "$BODY" | python3 -m json.tool >/dev/null'
```
+5 -1
View File
@@ -100,7 +100,11 @@ first_id() { grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE
# wonders why the version they were sent isn't what they got. # wonders why the version they were sent isn't what they got.
if [ "$TAG" = "dev" ]; then if [ "$TAG" = "dev" ]; then
INSTALL_TAIL='sh -s -- --channel dev' INSTALL_TAIL='sh -s -- --channel dev'
CHANNEL_NOTE='\n\nThis is the rolling **dev** channel: republished on every green push to \`dev\`, and pruned to the current build.' # Backticks BARE, not `\``. The heredoc below is unquoted, so there the backslash
# is the shell's — it suppresses command substitution and never reaches the JSON.
# Here single quotes already do that job, so a backslash would survive into the
# body as `\``, which is not a legal JSON escape: Forgejo answers 422.
CHANNEL_NOTE='\n\nThis is the rolling **dev** channel: republished on every green push to `dev`, and pruned to the current build.'
else else
INSTALL_TAIL='sh' INSTALL_TAIL='sh'
CHANNEL_NOTE='' CHANNEL_NOTE=''