Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
166 changes: 166 additions & 0 deletions .github/workflows/openwiki-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# OpenWiki Update workflow
# Runs the OpenWiki documentation agent (langchain-ai/openwiki) on every push to
# `main` (plus a weekly backstop) to keep the agent-navigable `openwiki/` wiki
# current, then opens/refreshes a single rolling PR against `main`.
#
# LLM serving: Bedrock's OpenAI-compatible endpoint with GLM-5 (zai.glm-5) — the
# same serving stack as psd401/aistudio. No third-party LLM vendor; spend lands
# on the district AWS account. Verified in aistudio 2026-07-09 against
# bedrock-runtime.us-west-2.amazonaws.com. Do NOT switch to OPENWIKI_PROVIDER=
# anthropic + Claude on the Bedrock /anthropic path: openwiki's @langchain/
# anthropic layer unconditionally sends REQUEST-TOP-LEVEL cache_control
# (first-party auto-caching), which Bedrock's compat layer rejects with
# "cache_control: Extra inputs are not permitted" (block-level caching is fine,
# but openwiki exposes no knob).
#
# ⚠️ Scaffolder clobber warning: running `openwiki code --init` locally rewrites
# THIS FILE with openwiki's stock template (OpenRouter provider, unpinned
# install, no secret gate, add-paths spanning CLAUDE.md/AGENTS.md). Never accept
# that rewrite — restore this hardened version. In CI this is harmless: the
# create-pull-request `add-paths: openwiki` cap keeps any scaffold churn out of
# the rolling PR.
#
# Manual prerequisites (one-time, out of code):
# 1. Make `BEDROCK_API_KEY` available to this repository as either a repo
# secret or a selected-repository psd401 organization secret. It must be a
# LONG-TERM Bedrock API key (AWS console -> Bedrock -> API keys ->
# long-term; it is an IAM service-specific credential). Short-term keys
# expire in <=12h and will strand the schedule.
# 2. Enable Settings -> Actions -> General -> Workflow permissions ->
# "Allow GitHub Actions to create and approve pull requests".
# (The initial `openwiki/` tree is committed with this workflow; the
# `--update` runs below refresh it incrementally.)
#
# The scheduled PR is opened by the default GITHUB_TOKEN, so (by GitHub's
# anti-recursion rule) it does NOT trigger other push/PR workflows. That is
# intentional for a docs-only PR and saves review-bot cost.
name: OpenWiki Update

on:
workflow_dispatch:
push:
branches: [main]
schedule:
# UTC. 08:00 UTC = midnight PST. Weekly (Mon) backstop in case push-driven
# runs were skipped (e.g. the provider secret was temporarily absent).
- cron: "0 8 * * 1"

# One update at a time. A push landing mid-run queues exactly one follow-up
# (GitHub coalesces pending runs per group), which then covers every commit
# that arrived meanwhile. No cancel-in-progress: killing a mid-flight LLM run
# wastes its spend without saving anything. Self-trigger note: merging the
# rolling openwiki/update PR pushes to main and re-runs this workflow, but
# openwiki's no-op detection (git diff from the recorded gitHead) sees only
# openwiki/ paths changed and skips the LLM pass.
concurrency:
group: openwiki-update
cancel-in-progress: false

permissions:
contents: write
pull-requests: write

jobs:
update:
name: Regenerate OpenWiki
runs-on: ubuntu-latest
# Runaway guard: caps Actions minutes + LLM spend if a run hangs. Incremental
# `--update` runs are small; a full first-generation is done locally, not here.
timeout-minutes: 60

steps:
# Graceful gate: until the BEDROCK_API_KEY secret is configured, every main
# push would otherwise fail this workflow red. Skip cleanly instead — the
# remaining steps are conditioned on this.
- name: Check provider secret
id: gate
env:
BEDROCK_KEY: ${{ secrets.BEDROCK_API_KEY }}
run: |
if [ -z "$BEDROCK_KEY" ]; then
echo "BEDROCK_API_KEY not configured — skipping OpenWiki update (see workflow header for one-time setup)."
echo "configured=false" >> "$GITHUB_OUTPUT"
else
echo "configured=true" >> "$GITHUB_OUTPUT"
fi

- name: Check out repository
if: steps.gate.outputs.configured == 'true'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
# Generate from, and propose against, the same branch. create-pull-request
# builds the PR branch from the checked-out HEAD, so pin `ref` to the PR
# base (`main`): scheduled runs use the default branch and a manual dispatch
# can be launched from any ref, but this PR always targets `main`. Without
# this, a dispatch from another ref would open a PR full of that ref's delta
# rather than just the regenerated wiki.
ref: main
# Full history: openwiki --update reads the previous run's gitHead from
# openwiki/.last-update.json and runs `git diff <gitHead>..HEAD` for its
# no-op detection and changed-paths summary. With the default depth-1 clone
# that SHA is absent after the first merged update PR, degrading every
# later run's diff to a fatal git error.
fetch-depth: 0
# Harden: do not leave the GITHUB_TOKEN in .git/config while the OpenWiki
# agent runs arbitrary LLM-driven code with filesystem access. The
# create-pull-request step below authenticates via its own `token` input
# (defaults to github.token), so persisted checkout credentials aren't needed.
persist-credentials: false

- name: Set up Node.js
if: steps.gate.outputs.configured == 'true'
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"

- name: Install OpenWiki
if: steps.gate.outputs.configured == 'true'
# Version-pinned: this job runs on a schedule with a provider secret, so we
# do not auto-adopt an unreviewed OpenWiki release. Bump deliberately.
# 0.2.0 emits Open Knowledge Format (OKF v0.1) pages — YAML front matter
# with a required `type` and reserved per-directory index.md. The one-time
# full OKF regeneration of openwiki/ is generated locally alongside this
# pin; these --update runs maintain it incrementally.
#
# Transitive deps stay caret-ranged (global install has no lockfile). We do
# NOT pass --ignore-scripts: OpenWiki depends directly on
# @langchain/langgraph-checkpoint-sqlite -> better-sqlite3, whose install
# script builds a required native binding. Residual supply-chain risk is
# bounded by the job-scoped GITHUB_TOKEN, human-reviewed PR, and
# `add-paths: openwiki` cap.
run: npm install --global openwiki@0.2.0

- name: Run OpenWiki
if: steps.gate.outputs.configured == 'true'
# `code` mode is explicit (0.1.0 made the CLI general-purpose).
run: openwiki code --update --print
env:
OPENWIKI_PROVIDER: openai-compatible
OPENWIKI_MODEL_ID: zai.glm-5
OPENAI_COMPATIBLE_BASE_URL: https://bedrock-runtime.us-west-2.amazonaws.com/openai/v1
OPENAI_COMPATIBLE_API_KEY: ${{ secrets.BEDROCK_API_KEY }}
# 0.2.0 added anonymous CLI telemetry. District policy: no third-party
# usage phone-home from CI. DO_NOT_TRACK also covers future telemetry libs.
OPENWIKI_TELEMETRY_DISABLED: "1"
DO_NOT_TRACK: "1"
# Optional LangSmith tracing — enable only if a LANGSMITH_API_KEY secret exists:
# LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
# LANGCHAIN_PROJECT: openwiki
# LANGCHAIN_TRACING_V2: "true"

- name: Create OpenWiki update pull request
if: steps.gate.outputs.configured == 'true'
# Third-party action — SHA-pinned. v8+ declares node24, ahead of GitHub's
# 2026 removal of the node20 action runtime from hosted runners.
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
base: main
add-paths: openwiki
branch: openwiki/update
commit-message: "docs: update OpenWiki"
title: "docs: update OpenWiki"
body: |
Automated OpenWiki documentation update.
Generated by the scheduled OpenWiki workflow (`.github/workflows/openwiki-update.yml`).

Scoped to `openwiki/` only — the hand-curated `CLAUDE.md` is untouched.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,4 @@ tmp/
.opencode/package-lock.json
branding/
deploy/cert.p12
.openwiki/
Loading