Skip to content

Docs Deploy

Reusable workflow for building and deploying VitePress sites to Cloudflare Pages. Includes content hash gating to skip unnecessary deploys when documentation sources have not changed.

Publication policy

Use this workflow only for content approved for publication. When the site contains sensitive operational guides, Cloudflare Pages publication must be protected by an authentication layer before exposure.

Trigger

yaml
on:
  workflow_call:

Called via uses: from the repository's documentation deploy workflow.

Inputs

InputTypeDefaultRequiredDescription
docs-pathstring--YesPath to the VitePress docs directory (e.g. docs-site/, docs/)
project-namestring--YesCloudflare Pages project name (e.g. my-project-docs)
deploy-urlstring--YesURL to check the current deployed hash against (e.g. https://my-project-docs.pages.dev)
node-versionstring'22'NoNode.js version
build-commandstring'npm run docs:build'NoBuild command to run inside docs-path
forcebooleanfalseNoForce deploy ignoring content hash

Secrets

SecretDescription
CLOUDFLARE_API_TOKENCloudflare API token with Pages deploy scope
CLOUDFLARE_ACCOUNT_IDCloudflare account ID

Permissions

yaml
permissions:
  contents: read
  deployments: write

Job: deploy

Runs on ubuntu-latest:

  1. Checkout the code.
  2. Compute content hash — calculates SHA-256 of all .md, .ts, and .json files in the docs directory (excluding node_modules, dist, and cache).
  3. Compare with deployed hash — requests <deploy-url>/.content-hash and compares:
    • If force: true: deploys regardless.
    • If hashes differ: deploys.
    • If hashes match: skips deploy.
  4. Setup Node.js with npm cache.
  5. Install and buildnpm ci + configured build command.
  6. Write content hash — saves the hash to .vitepress/dist/.content-hash for future comparisons.
  7. Deploy to Cloudflare Pages — via cloudflare/wrangler-action@v3.

Content Hash Gating

The content hash mechanism prevents redundant deploys:

Calculate SHA-256 of sources (.md, .ts, .json)


Fetch deployed hash from <url>/.content-hash

         ┌──────┴──────┐
         │             │
      Different      Same
         │             │
         ▼             ▼
      Deploy       Skip deploy

The .content-hash file is saved at the deploy root and serves as a reference for the next run.

Usage example

yaml
# .github/workflows/docs.yml
name: Deploy Docs

on:
  push:
    branches: [main]
    paths:
      - 'docs-site/**'

jobs:
  deploy:
    uses: middag-io/.github-private/.github/workflows/docs-deploy.yml@workflows-v1
    with:
      docs-path: docs-site/
      project-name: my-project-docs
      deploy-url: https://my-project-docs.pages.dev
    secrets: inherit

Force deploy

yaml
jobs:
  deploy:
    uses: middag-io/.github-private/.github/workflows/docs-deploy.yml@workflows-v1
    with:
      docs-path: docs-site/
      project-name: my-project-docs
      deploy-url: https://my-project-docs.pages.dev
      force: true
    secrets: inherit

MIDDAG Tecnologia