Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
12f1bd9
Add documentation proposal automation design and plan
dhruv8sh Oct 1, 2026
f70ce72
Propose documentation updates after code merges to main
dhruv8sh Oct 1, 2026
f22e366
Isolate documentation proposal builds from publication credentials
dhruv8sh Oct 3, 2026
ae8d9c5
Merge branch 'main' into feat/docs-proposal-automation
prk-Jr Oct 5, 2026
e26af27
Keep maintainer commits on proposal branches across retries
dhruv8sh Oct 7, 2026
8ce9d08
Stop allowing Copilot to run git grep
dhruv8sh Oct 7, 2026
d0710fe
Drop the npm cache from jobs that run untrusted content
dhruv8sh Oct 7, 2026
5c3fd10
Bound documentation proposal jobs with timeouts
dhruv8sh Oct 7, 2026
17a0938
Neutralize mentions in the proposal rationale
dhruv8sh Oct 7, 2026
f9f47ee
Refuse proposal retries that inspect a different range
dhruv8sh Oct 7, 2026
947cf4c
Document the proposal scripts CI gate and first-run prerequisites
dhruv8sh Oct 7, 2026
2304a9a
Fill the proposal work directory into Copilot prompts
dhruv8sh Oct 7, 2026
b3e3b22
Merge remote-tracking branch 'origin/main' into feat/docs-proposal-au…
dhruv8sh Oct 7, 2026
0bc4bf7
Guard empty-rerun branch deletion with a lease
dhruv8sh Oct 7, 2026
a7ad11d
Harden documentation proposals against forks, symlinks, and live rati…
dhruv8sh Oct 9, 2026
5e54ade
Merge remote-tracking branch 'origin/main' into feat/docs-proposal-au…
dhruv8sh Oct 10, 2026
a40b319
Merge branch 'main' into feat/docs-proposal-automation
prk-Jr Oct 12, 2026
c3a33e6
Merge branch 'main' into feat/docs-proposal-automation
aram356 Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ jobs:
id: node-version
run: echo "node-version=$(grep '^nodejs ' .tool-versions | awk '{print $2}')" >> $GITHUB_OUTPUT

# No dependency cache: the docs-proposal workflow runs generated content
# on the main ref, where it could save a poisoned entry under this key.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low: Untrusted code in propose/validate runs on the main ref, so it can still poison other main-scoped caches (rust-cache and npm in test.yml/format.yml, restored by every PR). Those have read-only tokens and no secrets, so the impact is CI integrity only today. A future privileged workflow that adds a cache would be exposed, though. Consider a note in docs-proposal.yml or the design doc saying privileged workflows must not restore caches.

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.node-version.outputs.node-version }}
cache: "npm"
cache-dependency-path: docs/package-lock.json

- name: Setup Pages
uses: actions/configure-pages@v4
Expand Down
187 changes: 187 additions & 0 deletions .github/workflows/docs-proposal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
name: Documentation proposal

# Proposes documentation edits with Copilot CLI after code merges to main and
# opens one reviewable pull request per merge. See
# docs/superpowers/specs/2026-10-01-docs-proposal-automation-design.md.
on:
push:
branches: [main]
paths:
- "crates/**"
- "trusted-server.example.toml"
- "edgezero.toml"
- "fastly.toml"
- ".cargo/config.toml"
- "scripts/**"
- "!scripts/docs-proposal/**"
workflow_dispatch:
inputs:
sha:
description: Full SHA of a commit on main to propose documentation for
required: true
type: string
base:
description: >-
Full SHA of main before the push that added the commit, when that
push added several commits; defaults to the commit's first parent
required: false
type: string

permissions: {}

# Sequential merges are proposed one at a time, in order. The default queue
# keeps only one pending run and cancels older ones, so keep them all. Every
# job has a timeout so a hung run cannot hold the queue for hours.
concurrency:
group: docs-proposal
cancel-in-progress: false
Comment thread
dhruv8sh marked this conversation as resolved.
queue: max

# Each job runs the proposal scripts from the workflow's own revision in
# `tools/` against a checkout of the merge commit in `source/`, so retrying a
# merge that predates this tooling, or a later fix to it, still works. A push
# that adds several commits is inspected from the previous main head; a manual
# retry of such a push needs that head as its `base` input.
env:
MERGE_SHA: ${{ inputs.sha || github.sha }}
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || inputs.base }}

jobs:
# Copilot runs here with a read-only token; it cannot push or open PRs.
# Copilot can write files that later steps execute, so treat this job as
# untrusted: it uses no dependency cache that later runs would restore.
propose:
runs-on: ubuntu-latest
Comment thread
dhruv8sh marked this conversation as resolved.
timeout-minutes: 30
permissions:
contents: read
copilot-requests: write
steps:
- name: Checkout tools
uses: actions/checkout@v4
with:
ref: ${{ github.workflow_sha }}
path: tools
persist-credentials: false

- name: Checkout merge commit
uses: actions/checkout@v4
with:
ref: ${{ env.MERGE_SHA }}
Comment thread
dhruv8sh marked this conversation as resolved.
path: source
fetch-depth: 0
persist-credentials: false

- name: Retrieve Node.js version
id: node-version
run: echo "node-version=$(grep '^nodejs ' tools/.tool-versions | awk '{print $2}')" >> "$GITHUB_OUTPUT"

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.node-version.outputs.node-version }}

- name: Install Copilot CLI
run: npm install -g @github/copilot@1.0.90

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low: Only the top-level package is pinned; npm install -g resolves its transitive dependencies freshly on every run, in a job holding a token. Optional: install from a committed lockfile (e.g. a tiny package.json + package-lock.json with npm ci).


- name: Propose documentation edits
working-directory: source
env:
GITHUB_TOKEN: ${{ github.token }}
run: ../tools/scripts/docs-proposal/propose.sh "$MERGE_SHA" .docs-proposal "$BASE_SHA"

- name: Upload proposal
uses: actions/upload-artifact@v4
with:
name: docs-proposal
path: source/.docs-proposal/
include-hidden-files: true
if-no-files-found: error

# VitePress executes Vue in Markdown during the build, so the docs gates run
# here with no write token, persisted credentials, or dependency cache.
validate:
needs: propose
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- name: Checkout tools
uses: actions/checkout@v4
with:
ref: ${{ github.workflow_sha }}
path: tools
persist-credentials: false

- name: Checkout merge commit
uses: actions/checkout@v4
with:
ref: ${{ env.MERGE_SHA }}
path: source
fetch-depth: 0
persist-credentials: false

- name: Retrieve Node.js version
id: node-version
run: echo "node-version=$(grep '^nodejs ' tools/.tool-versions | awk '{print $2}')" >> "$GITHUB_OUTPUT"

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.node-version.outputs.node-version }}

- name: Download proposal
uses: actions/download-artifact@v4
with:
name: docs-proposal
path: source/.docs-proposal

- name: Validate proposal
working-directory: source
run: ../tools/scripts/docs-proposal/validate.sh "$MERGE_SHA" .docs-proposal

# Copilot does not run here, and neither does any proposal content: this job
# re-checks the path allowlist on a fresh checkout and publishes the patch.
publish:
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout tools
uses: actions/checkout@v4
with:
ref: ${{ github.workflow_sha }}
path: tools
persist-credentials: false

- name: Checkout merge commit
uses: actions/checkout@v4
with:
ref: ${{ env.MERGE_SHA }}
path: source
fetch-depth: 0

- name: Retrieve Node.js version
id: node-version
run: echo "node-version=$(grep '^nodejs ' tools/.tool-versions | awk '{print $2}')" >> "$GITHUB_OUTPUT"

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.node-version.outputs.node-version }}

- name: Download proposal
uses: actions/download-artifact@v4
with:
name: docs-proposal
path: source/.docs-proposal

- name: Publish proposal pull request
working-directory: source
env:
GH_TOKEN: ${{ github.token }}
run: ../tools/scripts/docs-proposal/publish.sh "$MERGE_SHA" .docs-proposal
25 changes: 25 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,28 @@ jobs:

- name: Build with VitePress (fails on dead links)
run: npm run build

docs-proposal-scripts:
name: docs-proposal scripts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Retrieve Node.js version
id: node-version
run: echo "node-version=$(grep '^nodejs ' .tool-versions | awk '{print $2}')" >> $GITHUB_OUTPUT
shell: bash

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ steps.node-version.outputs.node-version }}

- name: Run shellcheck
run: shellcheck scripts/docs-proposal/*.sh

- name: Test hunk review builder
run: node --test scripts/docs-proposal/hunks.test.mjs

- name: Test proposal scripts
run: scripts/docs-proposal/test.sh
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@ src/*.html
# leftover local build artifacts (node_modules, target, dist) that remain on disk.
/crates/js/
/crates/integration-tests/

# Documentation proposal workflow scratch space
/.docs-proposal/
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ Every PR must pass:
7. Docs format (`cd docs && npm run format`)
8. Markdown format outside `docs/` (requires `cd docs && npm ci` first): `docs/node_modules/.bin/prettier --config docs/.prettierrc --check "*.md" ".claude/**/*.md" ".github/**/*.md" "crates/**/*.md" "scripts/**/*.md" "tinybird/**/*.md"`; fix with `--write` in place of `--check`
9. Native core build-digest test and lint (`cargo test -p trusted-server-core --test template_build_digest` and `cargo clippy -p trusted-server-core --test template_build_digest -- -D warnings`)
10. Documentation proposal scripts: `shellcheck scripts/docs-proposal/*.sh && node --test scripts/docs-proposal/hunks.test.mjs && scripts/docs-proposal/test.sh`

---

Expand Down
Loading
Loading