ci: publish devnotes independently of releases#536
Conversation
Adds a GitHub Actions workflow that rebuilds the `latest` docs alias when devnotes change on main, so blog posts go live without cutting a package release.
Code Review: PR #536 — ci: publish devnotes independently of releasesSummaryThis PR adds a new GitHub Actions workflow ( The approach is sound and the motivation is clear — blog posts shouldn't be gated on package releases. The workflow closely mirrors the existing Findings1. [High] Actions must be SHA-pinned — supply-chain hardening regressionFile: The new workflow uses unpinned tag references for third-party actions: uses: actions/checkout@v6
uses: astral-sh/setup-uv@v7
uses: actions/download-artifact@v7All other workflows in this repo were updated in PR #517 (commit uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7Why it matters: Tag-based references are mutable. A compromised upstream action tag could inject malicious code into the CI pipeline. SHA pinning ensures reproducibility and integrity. Dependabot is configured to keep these SHAs up to date. Suggested fix: Replace the three 2. [Medium] Missing top-level
|
Greptile SummaryAdds a dedicated
|
| Filename | Overview |
|---|---|
| .github/workflows/publish-devnotes.yml | New workflow that decouples devnotes publishing from releases; reads last deployed state from gh-pages to reconstruct the docs source, overlays new devnotes, downloads cached notebooks, and redeploys — all action refs are SHA-pinned and permissions are minimal. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([Push to main\ndocs/devnotes/**\nor workflow_dispatch]) --> B[Checkout repo\nfetch-depth: 0]
B --> C[git fetch gh-pages\nparse DEPLOY_MSG\nextract SOURCE_SHA + VERSION]
C --> D{Parse OK?}
D -- No --> E([exit 1])
D -- Yes --> F[git checkout SOURCE_SHA\ngit checkout github.sha -- docs/devnotes/]
F --> G[uv sync --group docs\nat SOURCE_SHA state]
G --> H[gh run list build-docs.yml\ndownload notebooks artifact]
H --> I{Run found?}
I -- No --> J([exit 1])
I -- Yes --> K[git config bot identity]
K --> L[mike deploy --push\n--update-aliases VERSION latest]
L --> M([gh-pages updated\nlatest alias points to new devnotes])
Reviews (4): Last reviewed commit: "Merge branch 'main' into andreatgretel/c..." | Re-trigger Greptile
Address Greptile review findings: - Pin checkout, setup-uv, and download-artifact to commit SHAs matching the pattern from #517 - Add top-level permissions: {} to restrict default token scope
Instead of building the full site from main (which could include unreleased docs), checkout the commit that latest was last built from (tracked in gh-pages commit messages) and overlay only docs/devnotes/ from main. Download notebooks from the last successful build-docs run instead of rebuilding them.
The gh run list/download calls need actions:read on GITHUB_TOKEN,
which is denied by the top-level permissions: {} block.
Code Review: PR #536 — ci: publish devnotes independently of releasesSummaryThis PR adds a new GitHub Actions workflow ( The approach: parse the Changed files: 1 added ( Findings1. [Medium] Fragile dependency on mike's internal commit message formatFile: The workflow parses the SOURCE_SHA=$(echo "$DEPLOY_MSG" | sed -n 's/^Deployed \([0-9a-f]*\) to .*/\1/p')
VERSION=$(echo "$DEPLOY_MSG" | sed -n 's/^Deployed [0-9a-f]* to \([^ ]*\) .*/\1/p')This relies on mike's internal commit message format: Suggestions (pick one):
2. [Medium] Expression interpolation of parsed values in shell contextFile: run: |
git checkout ${{ env.SOURCE_SHA }}
git checkout ${{ github.sha }} -- docs/devnotes/
...
run: uv run mike deploy --push --update-aliases ${{ env.VERSION }} latest
# Safer: let the shell expand the quoted variable
run: git checkout "$SOURCE_SHA"
...
run: uv run mike deploy --push --update-aliases "$VERSION" latestNote: The same pattern exists in 3. [Medium] Artifact retention window riskFile: The workflow downloads notebooks from the last successful Suggestion: Add a more descriptive error that mentions artifact retention, or consider storing built notebooks as a release asset or on 4. [Low] PR description does not match implementationThe PR body states the workflow "Reuses 5. [Low] Short SHA from mike may become ambiguousMike records Positive observations
VerdictApprove with suggestions. This is a well-structured workflow that solves a real operational pain point — blog posts should not be blocked on package releases. The overlay approach is clever and efficient. The primary concern is the fragile coupling to mike's internal commit message format (Finding 1). Since this workflow runs automatically on every devnotes merge, a mike upgrade that changes the format would silently break publishing. Using mike's The expression interpolation issue (Finding 2) is low-risk but trivially fixable and worth addressing for defense-in-depth. The artifact retention issue (Finding 3) is an edge case but could cause confusing failures during periods of low release frequency. None of these issues are blocking — the workflow is correct and safe as-is for the current mike version. They are hardening improvements to make the workflow more durable over time. |
📋 Summary
Decouples devnotes (blog) publishing from package releases. Currently, new blog posts only go live when
build-docs.ymlruns on a release event. This adds a dedicated workflow that rebuilds thelatestdocs alias whenever devnotes change onmain, so posts are live within minutes of merging - without affecting the rest of the published docs.🔗 Related Issue
N/A
🔄 Changes
✨ Added
publish-devnotes.ymlworkflow triggered on pushes tomainwhendocs/devnotes/**changes (also supports manualworkflow_dispatch)🔧 Changed
🔍 Attention Areas
publish-devnotes.yml— The workflow parses mike'sgh-pagescommit message (Deployed <sha> to <version> ...) to determine the source commit and version of the last deployment. It then checks out that commit, overlays onlydocs/devnotes/frommain, and downloads pre-built notebooks from the last successfulbuild-docs.ymlrun. This ensures non-devnotes docs remain at the last intentionally deployed state.🧪 Testing
make testpasses — N/A, no testable logic (CI workflow only)mainand verify the workflow triggerslatestdocs show the new postworkflow_dispatchand verify it succeedsbuild-docs.ymlrelease flow still works✅ Checklist
Description updated with AI