Skip to content
Thally
Log inGet started
Guide

Updated · 13 min read

CI documentation updates: generate, check, and review code changes

Set up CI documentation updates with a tested reference generator, a GitHub Actions check, scoped cross-repository handoffs, and human review before release.

By Published Updated Sources verified

A client timeout changes from ten seconds to twenty. The product tests pass, but the configuration reference still says ten. A continuous integration (CI) job can catch that mismatch before merge if the reference comes from the same maintained source. The quickstart that explains when to override the timeout needs a different check: someone has to understand what changed for the reader.

CI documentation updates work best when you separate generation, validation, and editorial review. This guide builds a small reference check you can reproduce locally, then explains how to extend that process to separate documentation repositories and reviewed proposals. It is for engineers maintaining Git-based product documentation. The runnable example uses synthetic configuration data, Node.js 24, and no external packages or credentials.

What CI can and cannot do for docs

Choose the output you want before choosing the trigger.

JobSourceUseful outputWhat still needs review
Generate reference materialMaintained schema, types, or command definitionsReproducible reference filesWhether the source describes the released product
Check documentationDocs, examples, links, and build configurationA failing check with a specific problemWhether passing instructions solve the reader's task
Remind an authorChanged public-surface pathsOne actionable reminderWhich pages the behavior affects
Propose prose updatesA product change and applicable docsA reviewable diff with supporting evidenceAccuracy, missing pages, and release timing

A successful build proves that the site can build. It does not establish that a tutorial teaches the right behavior. Keep both checks in the process. Our guide to keeping docs in sync with code covers the broader ownership and review work.

Two engineers compare a source sheet with an open documentation guide beside a whiteboard labelled Generate, Check, and Review.
Generating a reference and reviewing a guide answer different questions. Keep the product source and the reader's instructions visible together.

Step 1: regenerate what comes from a spec

Start in a disposable directory or a branch in a test repository. Run the commands from that directory throughout this example. Create directories for a source file and generator:

mkdir -p config scripts

Save this synthetic configuration as config/defaults.json. In a real project, use the schema or definitions the product actually consumes. A second hand-maintained copy would create another place for drift.

{
  "timeoutMs": 10000,
  "maxRetries": 3
}

Save the following as scripts/generate-reference.mjs. It accepts nonnegative integer defaults with alphanumeric setting names and writes a sorted Markdown table. The --check mode compares the expected bytes with the saved file without changing it.

import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"

const defaults = JSON.parse(readFileSync("config/defaults.json", "utf8"))
const keys = Object.keys(defaults).sort()
for (const key of keys) {
  if (!/^[A-Za-z][A-Za-z0-9]*$/.test(key) ||
      !Number.isSafeInteger(defaults[key]) || defaults[key] < 0) {
    throw new Error(`Invalid default: ${key}`)
  }
}
const rows = keys.map(key => `| ${key} | ${defaults[key]} |`)
const output = [
  "# Client defaults", "", "| Setting | Default |",
  "| --- | --- |", ...rows, ""
].join("\n")
const destination = "docs/generated/defaults.md"

if (process.argv.includes("--check")) {
  if (!existsSync(destination) || readFileSync(destination, "utf8") !== output) {
    console.error("Reference is stale or missing. Run the generator.")
    process.exitCode = 1
  } else {
    console.log("Reference is current.")
  }
} else {
  mkdirSync("docs/generated", { recursive: true })
  writeFileSync(destination, output)
  console.log(`Wrote ${destination}`)
}

Generate and check the reference:

node scripts/generate-reference.mjs
node scripts/generate-reference.mjs --check

The first command writes docs/generated/defaults.md. The second prints Reference is current. and exits successfully. Commit the source, script, and generated file together. Edit the source when a default changes, then regenerate. Manual edits to this generated page will fail the byte comparison.

For an OpenAPI reference, substitute your pinned generator and maintained API description. Include referenced files in its inputs. Keep generated output separate from authored explanation so the generator cannot overwrite a writer's guide.

Step 2: prove the check catches a stale reference

Change timeoutMs to 20000 in the JSON file, leaving the generated Markdown untouched. Run the check again:

node scripts/generate-reference.mjs --check

It prints Reference is stale or missing. Run the generator. and exits with status 1. Regenerate, inspect the diff, and rerun the check. It now passes with a twenty-second default in the reference.

This is the boundary of the example. The script checks the generated file only. It will not find a sentence in a quickstart that promises a ten-second timeout, infer which product release uses the new value, or test the timeout implementation. Add those checks separately. Remove the disposable directory when you finish, or keep the files on your test branch.

Step 3: gate the docs build

In the test repository, save this workflow as .github/workflows/docs-reference.yml. It checks every pull request and pushes to main. Change that branch name if your default branch differs.

name: Docs reference
on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  reference:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
        with:
          persist-credentials: false
      - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
        with:
          node-version: "24"
          package-manager-cache: false
      - name: Check generated reference
        run: node scripts/generate-reference.mjs --check

The actions are pinned to full commit revisions verified on October 21, 2026. Review updates through your dependency process. Consult the checkout and setup-node documentation for runner requirements, particularly on self-hosted runners.

The local script and its failure cases were executed with Node.js 24.1.0. This workflow's configuration was checked against GitHub's documentation, but the sample was not executed on a hosted Actions runner. After adding it to your test repository, open a PR with a stale reference, observe the failure, then regenerate and push the fix. Confirm the check passes on the new revision before making it required.

There is deliberately no workflow-level path filter. GitHub documents that checks can remain pending when a workflow is skipped by branch or path filters. A required check that never starts can block an unrelated change. For this small generator, running on every PR keeps the result straightforward.

For a real docs site, add its production build, link checks, and executable example tests to this validation stage using the project's locked dependencies. If you use a merge queue, configure and verify the appropriate merge_group trigger too. The sample does not include merge-queue coverage.

Step 4: remind authors when a public surface changes without docs

Generation covers facts that have a maintained source. For the rest, ask the author what changed for users. A new timeout default might affect the quickstart, retry guidance, migration notes, and older supported versions differently.

A reminder can inspect API descriptions, exported SDK interfaces, CLI definitions, or configuration paths. Make it one updatable comment or a label with an owner, rather than a new comment on every commit. Give the author a way to explain why no docs change is needed. A path match is a signal to review, not proof that a page is wrong.

Keep the validation workflow read-only. Fork PRs normally lack repository secrets and have a read-only token. Put any privileged reminder or writing step behind a separately reviewed trust boundary. Do not switch to pull_request_target and execute the contributor's code to obtain write access. Follow GitHub's guidance on untrusted checkouts and script injection. When a script consumes PR text, pass it through an environment variable or structured input instead of interpolating it into shell code.

Step 5: tell the docs repository a change merged

When product code and docs live separately, pass a specific revision to the documentation workflow. A notification does not grant the receiver permission to read a private source repository.

GitHub's repository_dispatch event is one option. The receiving workflow must exist on the docs repository's default branch. A fine-grained token used to create the dispatch needs Contents: write on that destination repository. The source repository's normal GITHUB_TOKEN does not automatically grant access to another private repository.

Design the handoff before adding a remote writing job:

  1. Record the source repository, merged PR, immutable product revision, intended release, and destination branch.
  2. Give the receiver separate, scoped access to fetch any private product evidence it needs. Keep credentials out of the event payload.
  3. Validate the allowed source repository and revision. Treat payload strings as data, never commands to execute or arbitrary checkout instructions.
  4. Reuse an existing proposal for the same source revision and destination. Make a retry safe when a notification is delivered twice.
  5. Record whether processing completed, found no update, failed, or was skipped. Link the result to the source change.

A GitHub App can provide scoped installation tokens when the workflow needs permissions beyond its normal token. Review GitHub's authentication guidance. This section describes a handoff design, not a tested cross-repository dispatch implementation.

Let a docs agent draft the pull request

To move from a notification to proposed wording, an author or tool needs to inspect the product change and the affected passages. Include the old claim, the relevant source change, the applicable version, and the reason for each edit. A model-generated diff still needs the same build, link, example, and editorial checks as a human contribution.

Thally Track provides this workflow for connected GitHub sources and documentation destinations. You select repositories, branches, and optional watched paths. Its triggers include trusted same-repository, non-draft PR updates, merged changes, and scheduled branch comparisons. Each destination has its own run result. Track opens ready-for-review PRs and never merges them.

Track requires Cloud access, including trial access, and shared workspace AI Credits. It is separate from the MIT publishing engine and self-managed authoring tools. Connected Knowledge surfaces retain their own checks, previews, and publishing workflows. This does not imply a direct integration with every hosted help center.

Keep your existing CI gates when adding Track. It supplies proposals, while your repository's review and release process decides what reaches readers. For other approaches, see our documentation automation software comparison.

Hand-drawn workflow: a pull request feeds generation and checking. A failed check leads to Fix and Rerun. The passing route goes through a reviewer and a Release Ready gate before publishing.
A conceptual review and release process. A passing check leads to review, then a release decision. The sample workflow implements the reference check only.

Putting it together

Before calling an update complete, inspect the run and the rendered page on the exact documentation revision under review.

SituationWhat to inspectNext action
Generated reference is stale or missingSource, generator version, and expected diffRegenerate and commit the output, then rerun
A check stays pendingTrigger filters, approvals, and branch requirementsConfirm the intended workflow actually started
No docs proposal appearsRun status, accessible sources, watched paths, and destinationSeparate completed no-change from failed or skipped work
An automated PR has no passing validationIts latest revision and actual check runsResolve approval or trigger requirements, then verify the result
A product change is merged but unreleasedRelease state and the docs version being editedHold current-version publication until the behavior is available
An older supported release keeps the old defaultVersion-specific guide and referencePreserve the accurate older instructions

For the timeout example, completion means the generated table says twenty seconds, the current quickstart gives correct override advice, older versions retain their own defaults, and the preview renders those instructions correctly. If publication introduces an error, restore the last accurate documentation revision, correct the source or proposed edit, and rerun the same checks before releasing again.

Start with one generated reference and one known stale case. Once those results are dependable, add the prose review and cross-repository handoff your team needs. If you are evaluating Thally, inspect the read-only Track preview, then follow the setup guide for approved sources and destinations. The preview does not open PRs.

Sources and verification

Reviewed October 21, 2026. GitHub behavior follows the linked workflow syntax, event, security, authentication, and REST references. Thally claims follow its public Track and Knowledge surfaces guides. We build Thally. The local generation example uses synthetic data and is not a product benchmark. Hosted Actions execution, a cross-repository dispatch, and a private Track run were not performed. See our editorial policy.

Published under the Thally editorial policy. Technical conformance is defined in the agent-readiness methodology.

Frequently asked questions

How do CI documentation updates work?
Use CI to generate reference files from maintained sources and check that committed output matches. Add build, link, and example checks. Changes to guides need separate review of the product behavior, affected passages, and release version.
How do I trigger a docs build when my API spec changes?
Run your pinned reference generator against the maintained API description and its referenced files, then build and validate the docs. A required workflow needs a result on every relevant PR. Workflow-level path filters can leave skipped checks pending.
How does a product repository notify a separate docs repository?
A repository_dispatch event can notify a workflow on the docs repository's default branch. A fine-grained dispatch token needs Contents write permission there. The receiver also needs separate access to any private product evidence. A notification alone does not grant that access.
Should CI block merges when docs are missing?
Block on specific failures such as stale generated output or a broken build. A public-surface path match alone is a review signal. Let the author explain why no docs update is needed, and require editorial review for changed instructions.
Does a passing documentation check mean the docs are accurate?
It establishes only what the check measures. The example validates generated reference bytes. It does not find outdated prose, test the product implementation, or establish release readiness. Review those separately before publishing.

Build docs that stay close to your product.

Create a managed site, or use the open-source engine to run Thally yourself.