Skip to content

docs: a user manual for every action (what it does, how to set it up, every input and output) #178

Description

@quantecon-services

Goal: every action has a user-manual chapter in docs/user, generated from its action.yml and checked in CI; docs/dev describes the project as it is; and the manual is published (#179).

Where we stand (verified 2026-09-28)

Next: PR 4 (#191), the cross-cutting chapters: getting started with migration, how the actions compose, containers, versioning and security, with the templates and container READMEs as signposts. #192, the docs/dev rewrites, can run alongside it.

Why

Someone adopting these actions has no single place that answers "which action do I use for this, how do I set it up, and what does it accept?".

  • docs/ is mostly developer material.
  • The user-facing reference is spread over the per-action READMEs. That is eight files of 177–308 lines, each structured differently. They drift from each action.yml: docs: reconcile action READMEs and templates with the shipped code #109 lists documented inputs that do not exist, inputs that exist but are missing, and a link to an action that was removed.
  • The docs are large and overlapping. PLAN item 10 counts roughly 4,900 doc lines for about 1,600 lines of action code, with four overlapping indexes.

What the manual covers

One chapter per action, all following the same template:

  • What it does, and when to use it. Also when not to: for example publish-gh-pages against deploy-cloudflare, and preview-netlify against preview-cloudflare.
  • Requirements: runner or container, Node, the permissions: block, secrets, and any one-time setup outside GitHub (the Netlify site, Pages settings, the Cloudflare Worker and Access checklist).
  • Inputs: name, required or not, default, and accepted values.
  • Outputs, and when each one is set.
  • Examples: a minimal workflow and a realistic one, each with its permissions: block (docs: reconcile action READMEs and templates with the shipped code #109 found examples that 403 without one).
  • Behaviour: what it checks, what fails the job, cache keys, and the artifacts it produces.
  • Troubleshooting.

That is eight chapters: setup-environment, build-lectures, build-jupyter-cache, restore-jupyter-cache, preview-netlify, preview-cloudflare, publish-gh-pages, and deploy-cloudflare (#163, #177).

Cross-cutting chapters:

  • Getting started: choosing actions for a lecture repo, the standard CI / cache / publish set in templates/, and migrating an existing repo.
  • How the actions compose: cache build → restore → build → preview or publish.
  • Containers: which image to use and what is in it (from docs/CONTAINER-GUIDE.md and the container READMEs).
  • Versioning: @v0 against exact pins, and how releases reach consumers.
  • Security: fork PRs, secrets, and why pull_request_target must not be used (fix(preview): surface deploy errors, pin CLIs, remove unsafe fork guidance #105).

Keeping it true

#109 is what hand-maintained tables turn into. The input and output tables are generated from each action.yml, with a CI check that fails when the manual no longer matches. Examples pass actionlint in CI and link to the templates/ rather than copying them. Details are in decision 5.

Decisions (2026-09-24)

1. Audience

QuantEcon lecture-repo maintainers, written so it does not rely on insider knowledge.

  • Every setup step is spelled out: no "ask X for the token", and nothing that exists only in a repo the reader may not be able to open.
  • The manual opens by saying the actions are built for QuantEcon lecture repos and are on 0.x. Outside use is fine but unsupported. There is no separate path for outside users.
  • The repo is public, so nothing in the manual carries account details. That includes the deploy-cloudflare Access checklist.

2. Format and home

GitHub-flavoured Markdown, read on GitHub, in two trees: docs/user (the manual) and docs/dev (developer docs). No built site for now.

Publishing to GitHub Pages with the standard QuantEcon docs theme is #179. That issue also records the test builds (Jupyter Book 1 and mystmd) behind this decision.

These writing rules keep #179 cheap:

  • no strikethrough;
  • ${{ … }} only inside backticks;
  • anything outside docs/, directories especially, linked by its absolute GitHub URL;
  • file names unique within docs/user.

GitHub alerts (> [!NOTE]) are allowed.

3. Per-action READMEs

Chapters live at docs/user/actions/<action>.md. Each <action>/README.md becomes a signpost.

  • The signpost holds only the action's name, its description: from action.yml, and links to the chapter and to the manual's index. It has no inputs and no examples.
  • Signposts are generated (decision 5).
  • Content that exists only in READMEs today moves into the chapters:
    • the Netlify and Cloudflare setup guides
    • the Cloudflare vs Netlify comparison
    • the publish-gh-pages migration notes
    • the deploy-cloudflare Access checklist

4. Existing docs

Rule for both trees: the docs describe the project as it is: how to use it (docs/user), and how it is designed and maintained (docs/dev). They do not catalogue history. That means no dated status blocks, no "corrected on" notes, no struck-through finished items and no resolved questions. History lives in CHANGELOG.md, in issues and PRs, and in git.

Today Goes to
docs/QUICK-REFERENCE.md Deleted. Content moves into the action chapters. Its one-screen action table becomes docs/user/README.md.
docs/MIGRATION-GUIDE.md Deleted. The general steps and rollback become a docs/user chapter, "Migrating an existing repo". The per-repo notes move to PLAN's rollout section, because they describe rollout state and go stale.
docs/CONTAINER-GUIDE.md, and the user-facing parts of containers/README.md, containers/quantecon/README.md and containers/quantecon-build/README.md A docs/user containers chapter. The container READMEs become signposts. Their Development, Automated Builds and Testing sections move to docs/dev. build-containers.yml gains '!containers/**/README.md' in paths:, so README edits stop rebuilding and pushing both :latest images. That is safe because the Dockerfiles copy only environment.yml. It is READMEs rather than all .md because the smoke-test fixture's pages are Markdown and must still trigger the build.
docs/ARCHITECTURE.md docs/dev, rewritten as the current design. Its user-facing "how the actions fit together" material feeds the composition chapter. "Open Questions (Resolved)", "Success Criteria", "Migration Path" and the stale performance targets go.
docs/GPU-AMI-SETUP.md docs/dev. How to run setup-environment on the AMI goes to that action's chapter. Whether the AMI build doc moves to QuantEcon/infrastructure is a separate question.
containers/VALIDATION.md docs/dev/CONTAINER-VALIDATION.md.
TESTING.md docs/dev, rewritten as how testing works now (harness, fixtures, canary). The dated status, phases, rollout plan and success metrics go.
PLAN.md docs/dev, trimmed to current priorities, consumers, rollout state and dependency policy.
docs/FUTURE-DEVELOPMENT.md Deleted. Ideas that are still live become issues.
PROJECT-OPTIMIZE-PREVIEWS.md Deleted. #92 and its sub-issues hold the work. Any current design reasoning moves to docs/dev.
docs/README.md Deleted. docs/user/README.md and docs/dev/README.md are the two indexes; GitHub shows each when its folder is opened.
templates/README.md Signpost. Its content moves to Getting started.
.github/copilot-instructions.md Deleted. Anything still useful moves to a general AGENTS.md at the root. It follows the same rule, and points at docs/dev rather than repeating it.
README.md, CHANGELOG.md, CONTRIBUTING.md, LICENSE Stay at the root. The README's Documentation section points at docs/user and docs/dev.
tests/README.md Stays.

Notes on the moves:

  • Moves use git mv, so history is kept.
  • Moving PLAN.md breaks existing links to blob/main/PLAN.md, because GitHub does not redirect moved files. That is accepted.
  • The harness gate's IGNORED list and its self-test name the moved root files. They are updated to the new paths, and AGENTS.md is added to the list.
  • This absorbs all of PLAN item 10.

5. Keeping it true

  1. action.yml is the single source for per-input and per-output facts. Its descriptions are written for readers, including accepted values and when each output is set. The generator copies them verbatim. Chapter prose covers behaviour, not per-input facts.
  2. Generated content. All of it is committed, between <!-- BEGIN GENERATED: … --> and <!-- END GENERATED --> markers:
    • each chapter's Inputs table (name, required, default, description) and Outputs table
    • each signpost README, in full
    • the action table in docs/user/README.md
  3. Generator. scripts/generate-docs.py, written in Python 3 with PyYAML. Its --check mode prints the diff and fails. PyYAML is pinned in a requirements file under Dependabot's pip ecosystem.
  4. Examples.
    • The realistic example is a link to the template that uses the action, not a copy.
    • The minimal example is a short, complete workflow with its permissions: block.
    • Checks:
      • actionlint runs on templates/*.yml and on every complete workflow in a yaml block in docs/user. It is installed as a pinned release with a checksum, because actionlint-py ships only an sdist.
      • Every quantecon/actions/<x>@… step in the docs and templates uses only inputs that exist in that action.yml, and supplies every required one.
      • Every complete example has a permissions: block.
  5. Where the checks run. In the harness gate job, beside the template pin-drift check from fix(actions): #107 correctness batch and #109 code items #173. A docs-only PR matches IGNORED and skips every other job. The gate also fails when an action directory has no chapter.

Running actionlint on .github/workflows/ is out of scope.

6. Sequencing

The sweep starts now that the open PRs are settled. #176 and #174 have merged, and #144 will not be merged.

7. Which version the manual describes

main. The manual's index and each chapter header say:

This describes main. For the version you pin, open the manual at that tag. Changes not yet released are under [Unreleased] in the CHANGELOG.

Automatically marking unreleased inputs can come later if the gap causes confusion. That would mean comparing against the latest release named in the CHANGELOG, not against v0, because moving v0 is only a tag push and would turn the next unrelated PR red.

Relationship to existing issues

Checklist

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions