Caching TechDocs Builds in CI
TechDocs rebuilds every docs site from source on each push, and on a monorepo with hundreds of docs that turns into minutes of CI burned re-rendering pages that never changed. Caching the build — keying on content hashes and reusing prior output — cuts that to seconds for the unchanged majority. This how-to sets up content-addressed caching for TechDocs in CI. It extends TechDocs & Documentation Pipelines within Developer Portal Architecture & Frameworks.
Prerequisites
- A working TechDocs pipeline that builds docs in CI and publishes to external storage (S3, GCS, or Azure Blob).
- CI with a cache mechanism — GitHub Actions cache, GitLab cache, or a shared artifact store.
- Docs sources under version control so content hashes are stable and computable.
- The
techdocs-cliavailable in the CI image.
Exact Configuration
-
Compute a content hash per docs directory and use it as the cache key.
# Requires git, sha256sum # Hash only the docs sources for one component DOCS_HASH=$(git ls-files docs mkdocs.yml | xargs sha256sum | sha256sum | cut -c1-16) echo "techdocs-${DOCS_HASH}" -
Restore-or-build in CI. Skip the build when the cache holds output for this hash.
# .github/workflows/techdocs.yml # Requires actions/cache >= v4 - uses: actions/cache@v4 id: techdocs-cache with: path: site/ key: techdocs-${{ hashFiles('docs/**', 'mkdocs.yml') }} - name: Build TechDocs if: steps.techdocs-cache.outputs.cache-hit != 'true' run: techdocs-cli generate --no-docker -
Publish either way so the storage bucket always has the current output, cache hit or miss.
# Requires techdocs-cli techdocs-cli publish --publisher-type awsS3 \ --storage-name "$DOCS_BUCKET" --entity default/component/payments
Validation
# Requires CI logs / timing
# 1. An unchanged docs push hits the cache
# Push with no docs change; confirm the build step is skipped
grep -q "Cache restored" ci.log && echo "cache hit on unchanged docs"
# Expected: cache hit on unchanged docs
# 2. A docs change misses the cache and rebuilds
# Edit one page; confirm the build ran
grep -q "Building documentation" ci.log && echo "rebuilt on change"
# Expected: rebuilt on change
# 3. Published output matches the current sources
techdocs-cli publish --dry-run --entity default/component/payments
# Expected: uploads reflect the latest content
Edge Cases & Troubleshooting
| Symptom | Root Cause | Resolution |
|---|---|---|
| Stale docs served after an edit | Hash omits a changed input | Include every source in the hash: docs/**, mkdocs.yml, theme |
| Cache never hits | Key includes volatile data (timestamps, commit SHA) | Key only on content, not on run metadata |
| Cache hits but storage stale | Publish gated behind the cache-miss branch | Always publish, regardless of cache outcome |
| Cache grows unbounded | No eviction of old hashes | Rely on the CI cache’s LRU eviction; scope keys per component |
| Shared macros change nothing | Included partials not hashed | Add shared includes to the hashed input set |
Frequently Asked Questions
Should I cache the build output or the rendered site?
Cache the rendered site/ output keyed on the source hash. The expensive step is rendering markdown to HTML, so caching the result of that step is where the time is saved. Caching intermediate build state is fiddlier and buys less, because the render still has to run.
Does per-component caching help a monorepo?
Enormously. Scope the cache key per component so editing one team’s docs invalidates only that component, leaving the other hundreds as cache hits. A single site-wide key would rebuild everything on any change, which defeats the purpose on a large monorepo.