Skip to content

fix: accept any single-root docs.zip, not only html/ - #55

Merged
coretl merged 1 commit into
mainfrom
fix/accept-any-single-root-in-docs-zip
Jul 29, 2026
Merged

fix: accept any single-root docs.zip, not only html/#55
coretl merged 1 commit into
mainfrom
fix/accept-any-single-root-in-docs-zip

Conversation

@coretl

@coretl coretl commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Releases whose docs.zip is not rooted at html/ were silently dropped from the reconstructed site.

The bug

publish.yml's extract keyed on the zip containing an html/ directory:

unzip -q "$f" 'html/*' -d "$tmp" 2>/dev/null && [ -d "$tmp/html" ]

Release assets are durable and long-lived, and a repo migrating from python-copier-template's _release.yml carries releases rooted at the tag name instead:

mv html $GITHUB_REF_NAME
zip -r docs.zip $GITHUB_REF_NAME

Those releases hit the || branch and were skipped. Only the default branch is guarded (--required "$DEFAULT"), so the deploy stayed green while every pre-migration version vanished from the switcher — as seen on this blueapi run. The assets cannot be re-cut: these repos have immutable releases.

The fix

Loosen the contract on the read side only. A docs.zip must unzip to exactly one top-level directory, whose contents become site/<version-name>; the directory's name is ignored. Zero entries, several entries, or files loose at the zip root are malformed → still warn + skip rather than guess. docs.yml is unchanged and still packs html/.

Test fixture

v0.23.1rc1 is a throwaway prerelease whose docs.zip is rooted at v0.23.1rc1/, reproducing the layout above. It is marked prerelease + non-latest, and isPrerelease is tag-name based (/\d(a|b|rc)/i), so it is excluded from preferred/stable and cannot hijack the root redirect.

  • Before (unfixed code on main, run 30462749601): green, but ! v0.23.1rc1: no html/ root in zip — skipping.
  • After: this PR's own publish should extract it and list v0.23.1rc1 in switcher.json.

Also verified locally against generated fixture zips: html/ root, tag-name root, no explicit dir entries, dir name with a space → all extract; files loose at root, two top-level dirs, single root file, dir + .DS_Store, empty zip, non-zip → all warn + skip.

Note: the release job on the v0.23.1rc1 tag is red by design — gh release upload --clobber hit Cannot delete asset from an immutable release, which is what preserved the hand-made fixture asset.

🤖 Generated with Claude Code

publish.yml's extract keyed on the zip containing an `html/` directory
(`unzip -q "$f" 'html/*'`). Release assets are durable and long-lived, and
a repo migrating from python-copier-template's `_release.yml` carries
releases whose docs.zip is rooted at the TAG NAME instead:

    mv html $GITHUB_REF_NAME
    zip -r docs.zip $GITHUB_REF_NAME

Those releases were silently dropped from the reconstructed site — the
extract warned and skipped, and only the default branch is guarded, so the
deploy stayed green while every pre-migration version vanished from the
switcher. The assets cannot be re-cut on a repo with immutable releases.

Loosen the contract on the read side: a docs.zip must unzip to exactly one
top-level directory, whose CONTENTS become site/<version-name>; the
directory's NAME is ignored. Zero entries, several entries, or files loose
at the zip root are malformed and still warn + skip rather than guess.
docs.yml is unchanged and still packs html/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coretl
coretl merged commit 98d45da into main Jul 29, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant