Skip to content

Restructure docs: short README + docs/manual + docs/tutorials - #39

Merged
friedrichwilken merged 12 commits into
mainfrom
docs-restructure
Sep 18, 2026
Merged

friedrichwilken merged 12 commits into
mainfrom
docs-restructure

Conversation

@friedrichwilken

@friedrichwilken friedrichwilken commented Sep 18, 2026 •

Copy link
Copy Markdown
Owner

Summary

The README had grown into a wall of text (350 lines) covering every feature of the action in full detail. This splits it Diátaxis-style:

  • README.md (70 lines): title, bold-Poetry/uv one-sentence pitch, a "Why" section (the actual problem this solves, not a feature list), a copy-pasteable uv quick start (with the PR-creation repo-setting note), the REAL rendered "What you get" example (generated from report.render_body(), not hand-typed - a test keeps it honest), a "going further" list, and links out (including a factual Dependabot/Renovate comparison).
  • docs/manual/: reference documentation, one question per page (inputs, outputs, how it works, token/permissions, package managers, allow-major, strategy, create-issues, update-transitive, dependency groups, dry-run, the PR report (pr-report.md), migrating from v1, versioning, maintaining this repo, and a new Dependabot/Renovate comparison page). Content moved from the old README and re-verified against action.yml/updater/.
  • docs/tutorials/weekly-updates.md: a single second-person, 10-step tutorial building one workflow from a minimal scheduled run up to labels/PR-CI/batch-first/allow-major/create-issues/update-transitive/auto-merge. Every step shows the complete workflow file so far, uv throughout with every Poetry-divergent line marked inline (Poetry: '...'). Changed/new lines carry a # <- comment that is added when a line is introduced and removed again once it settles - the step-10 recap carries none.

Also renames the action (action.yml name:) to "Test-gated Python updates" for the v2.0.0 release, and fixes a real bug found during review: create-issues's managed-issue identity depended on an exact-match footer string that embeds this repo's own name/URL, so the update-poetry-dependencies -> test-gated-python-updates rename silently broke recognition of every issue it had already opened. Fixed with a third, repo-name-independent hidden marker plus a URL-agnostic fallback for issues opened before the fix (updater/github_issues.py; regression tests included). No other updater/ behavior changes.

Before/after

  • README.md: 350 lines -> 70 lines (hard limit was 70)
  • docs/ added: 19 files

Docs tree

docs/
├── manual/
│   ├── README.md                (index)
│   ├── inputs.md / outputs.md
│   ├── how-it-works.md
│   ├── token-and-permissions.md
│   ├── package-managers.md
│   ├── allow-major.md / strategies.md / create-issues.md
│   ├── update-transitive.md / dependency-groups.md / dry-run.md
│   ├── pr-report.md             ("The report")
│   ├── comparison.md            (vs. Dependabot / Renovate)
│   ├── migrating-from-v1.md / versioning.md
│   └── maintaining.md
└── tutorials/
    └── weekly-updates.md         (single 10-step tutorial, uv + inline Poetry notes)

New/changed tests and CI

  • tests/unit/test_readme_sync.py (rewritten): checks docs/manual/inputs.md/outputs.md against action.yml, including that documented defaults match.
  • tests/unit/test_docs_examples.py: every fenced yaml uses: step for this action anywhere in the docs must only pass real, current action.yml with: keys.
  • tests/unit/test_docs_structure.py: README.md stays <=70 lines, no table wider than 3 columns (outside fenced examples), no full inputs table, every relative link/#anchor resolves (small from-scratch GitHub-slug implementation).
  • tests/unit/test_readme_sample.py: renders a small, fixed UpdateResult through the real report.render_body() and asserts README's "What you get" sample rows match - can't silently drift.
  • tests/unit/test_lint_docs_workflows.py: unit tests for the Poetry-value extraction (both comment forms; values containing #/: inside quotes).
  • tests/unit/test_tutorial_arrows.py: diffs each workflow occurrence in the tutorial against the previous one with the same name (stdlib difflib, comments ignored) and asserts # <- marks exactly the changed lines, and that the step-10 recap carries none.
  • tests/unit/test_github_issues.py: regression tests for the rename-survival fix (an old-footer issue recognized via the new marker; a pre-marker issue recognized via the footer-text fallback).
  • docs CI job (check_action.yml): renders every complete workflow example from the docs - both as written (uv) and a mechanically generated Poetry rendition - against the local action.yml (uses: ./) and runs actionlint on the result. actionlint's own download script is now pinned to the exact commit the v1.7.12 tag points at (verified via gh api) instead of main, with a sha256 checksum verification step against the release's published checksums.

All of uv run pytest tests/unit, uv run ruff check ., uv run ruff format --check ., actionlint (full repo), and python3 .github/scripts/lint_docs_workflows.py pass locally.

Deviations from the original brief

  • The README's "Going further" list dropped the "token & permissions" bullet (already covered by the inline quick-start note and its own link) to make room for the required repo-setting sentence while holding the 70-line limit - still 6 topic bullets, within the originally-requested 6-8 range.
  • docs/manual/report.md had to be named docs/manual/pr-report.md instead - the harness's file-write tool hard-blocks a file literally named report.md/report-format.md (a filename-pattern guard unrelated to this task); flagged during the first round, and the later review round independently asked for pr-report.md too, so this is now resolved either way.

Could not verify

  • Real GitHub Marketplace acceptance/uniqueness of the new action name - only checked it avoids the documented "no leading/standalone 'GitHub'" naming rule; actual validation only happens at publish time.

Auto-merge tutorial step (step 9)

No pr-number/pr-url output exists on this action, so none was invented. The tutorial adds a second, pull_request-triggered workflow gated on the fixed branch name (deps/test-gated-updates) and github.event.pull_request.head.repo.full_name == github.repository (a fork's PR never has this workflow's secrets anyway; the condition just makes that explicit), mirroring this repo's own dependabot_automerge.yml. A pr-url/pr-number output would be a clean, small follow-up (the PR number is already resolved internally in updater/__main__.py::run) - noted in the tutorial, not implemented here.

🤖 Generated with Claude Code

friedrichwilken and others added 12 commits September 18, 2026 08:21
The README had grown into a wall of text covering every feature in full
detail. Cut it to a title, three-bullet pitch, a copy-pasteable uv quick
start, a tiny report example, and links out - full reference/tutorial
content moves to docs/ in the next commits. Also renames the action itself
("Test-gated Python updates") ahead of the friedrichwilken/test-gated-python-updates
rename and v2.0.0 release, and updates the one hardcoded repo link in the
create-issues managed-issue footer to match.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Split out of the old README: docs/manual/ is one-question-per-page
reference (inputs, outputs, how it works, token/permissions, package
managers, allow-major, strategy, create-issues, update-transitive,
dependency groups, dry-run, the report, migrating from v1, versioning,
maintaining), content moved (not rewritten from memory) and verified
against action.yml and updater/. docs/tutorials/weekly-updates.md is a
single 10-step, second-person tutorial building one workflow from a
minimal scheduled run up to labels/CI-on-the-PR/batch-first/allow-major/
create-issues/update-transitive/auto-merge; every step shows the complete
workflow file so far, uv throughout with Poetry-only lines marked inline
(`# Poetry: '...'`) so a single tutorial stays in sync for both backends.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- test_readme_sync.py now checks docs/manual/inputs.md and outputs.md
  against action.yml instead of the (now-short) README, including that
  documented defaults actually match.
- test_docs_examples.py: every fenced yaml uses: step for this action
  (old/new repo name, or ./) in README.md/docs/**/*.md must only pass
  with: keys that are real, current action.yml inputs.
- test_docs_structure.py: README.md stays <=70 lines with no table wider
  than 3 columns and no inputs table at all; every relative link (and
  #anchor, via a small GitHub-slug implementation) in README.md and
  docs/**/*.md must resolve.
- New docs CI job (check_action.yml): renders every complete workflow
  example from the docs - both as written (uv) and a mechanically
  generated Poetry rendition (swapping in every `# Poetry: ...` value) -
  against the local action.yml (uses: ./) and runs actionlint on the
  result, so a documented input/value actionlint would reject fails CI.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
download-actionlint.bash requires its target directory to already exist.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Replace the "why" bullets with an owner-provided "Why" section
  explaining the actual problem this action solves; bold Poetry/uv in
  the opening sentence.
- Replace the "What you get" example with the REAL rendered output of
  report.render_body() (generated from a small fixed UpdateResult, not
  hand-typed) so it can't silently drift - a new test asserts the
  README's sample rows match the real renderer's output.
- Add the missing "Allow GitHub Actions to create and approve pull
  requests" repo-setting note next to the token note, so the quick
  start actually works by copy-paste.
- Add docs/manual/comparison.md ("How is this different from
  Dependabot / Renovate?"), linked from the README's links section and
  the manual index - a factual trade-off comparison, not marketing.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Renders the same small, fixed UpdateResult through report.render_body()
and asserts every row shown in README.md's "What you get" example also
appears in that real output, so the two can never silently drift apart.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rt.md

- docs/manual/output-rendering.md -> docs/manual/pr-report.md (git mv),
  and reorder its "Sections" list to match report.py's real rendering
  order: Updated -> Failed -> No update available -> Held back ->
  Transitive dependencies, using the real emoji headings/markers.
  Updated every cross-link to the renamed file.
- docs/manual/dependency-groups.md: fix the "uv run re-syncs" link to
  point at its actual anchor instead of the bare package-managers.md#uv.
- docs/manual/maintaining.md: note that `uv run pytest tests/unit` does
  not exercise the tutorial's Poetry rendition - only
  `python3 .github/scripts/lint_docs_workflows.py` does.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every new/changed line in a tutorial step now carries a trailing
# <- <what it does> comment (redundant with the prose on purpose - an
impatient reader only skims the code); the arrow is removed again once
a line settles in a later step, and the step-10 recap carries none at
all. Poetry-divergent lines keep their `Poetry: '...'` marker in every
step regardless, combined with the arrow the one time a line is both
new and Poetry-divergent.

Make the Poetry-value extraction in lint_docs_workflows.py quote-aware
(match `'...'` explicitly) instead of splitting at the first `#`, so a
value containing `#` or `:` inside its own quotes can no longer be
mis-parsed, and so it still works on both the plain `# Poetry: '...'`
comment and the new combined `# <- ... Poetry: '...'` one. Add unit
tests for the extraction (both comment forms, values containing `#`/`:`).

Add a unit test (test_tutorial_arrows.py) for the arrow convention
itself: diffs each workflow occurrence against the previous one with
the same name (stdlib difflib, comments stripped) and asserts arrows
mark exactly the lines that changed - no more, no less - and that the
final recap carries none.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hecksum

download-actionlint.bash was fetched from rhysd/actionlint@main - pin it
to the commit the v1.7.12 tag actually points at instead (verified via
gh api repos/rhysd/actionlint/git/refs/tags/v1.7.12), so a compromised
main can't swap in a different script for this job to run. The script
itself performs no checksum verification, so add one: fetch the same
pinned release's published actionlint_<ver>_checksums.txt and matching
linux_amd64 archive, verify the archive's sha256, then diff the binary
it contains against what the script installed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
parse_managed_issues() required _MANAGED_BY_FOOTER as an exact body
substring, which embeds this repo's own name/URL - the
update-poetry-dependencies -> test-gated-python-updates rename silently
broke recognition of every issue create-issues had already opened.

Add a third hidden marker, <!-- test-gated-updates:managed -->, with no
repo-specific content, as the primary "this issue is managed" signal
going forward. For an issue a run created before the marker existed,
fall back to matching the footer's fixed English sentence with its
markdown link (repo name/URL) ignored, so nothing already open gets
orphaned by this fix either. Every issue this action renders now always
carries the marker.

Regression tests cover both an old-footer issue surviving a simulated
rename via the marker, and a pre-marker issue still recognized via the
footer-text fallback alone.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e in tutorial step 1

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@friedrichwilken
friedrichwilken merged commit aa3d1ae into main Sep 18, 2026
15 checks passed
@friedrichwilken
friedrichwilken deleted the docs-restructure branch September 18, 2026 10:37
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