mirror of
https://github.com/coder/coder.git
synced 2026-09-23 05:43:53 +08:00
27ed052d86b5c8a630ccaff45ca39632da2c419c
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8853f5535a |
fix(.github/workflows): raise docs indexer POST timeout to 300s (#27095)
## Problem The `algolia-and-isr` job's "POST to coder.com docs indexer" step aborts at `curl --max-time 120`. A whole-branch docs reindex fetches and extracts a few hundred pages server-side and runs longer than two minutes, so curl gives up before the handler responds: ``` curl: (28) Operation timed out after 120000 milliseconds ``` The step never receives the handler's result even though the server is still processing, so a legitimate reindex is reported as a failure. ## Fix Raise `--max-time` on that POST from `120` to `300`, matching the indexer's server-side function budget so curl waits for the response instead of aborting mid-reindex. - Only the Algolia indexer POST is changed. - The `vercel-rebuild` deploy-hook curl is left at `120` (it returns immediately). - No behavior change beyond the timeout. Validated with `actionlint`. <details> <summary>Rationale & decision log</summary> - The indexer handler performs an **atomic whole-branch reindex**: fetch the manifest, fetch + extract every navigable page, then replace the index slice. On a large ref that is a few hundred pages at concurrency 8, which comfortably exceeds the old 120s curl budget. - `300s` aligns curl with the handler's own server-side function ceiling, so the workflow observes the real response (or a real error) instead of a false client-side timeout. - The deploy-hook POST in `vercel-rebuild` only fires a webhook and returns immediately, so its timeout is intentionally left unchanged. - If 300s later proves tight, the next levers are raising server-side extract concurrency (bounded by upstream raw-content rate limits) or moving the whole-branch reindex to an async job. Out of scope here. </details> --- > Opened as a **draft** by Coder Agents on behalf of @nickvigilante. |
||
|
|
182bdc871a |
docs: scaffold docs/.style for the prose style guide (#25466)
Adds a private contributor-tooling directory at `docs/.style/` that will host the canonical prose style guide and the custom Vale rules used to enforce it. The directory's contents do not deploy to `coder.com/docs`. This PR is the scaffold only. The Vale configuration, the rule set, and the per-rule style-guide sections all land in follow-up PRs. ## What changes - New `docs/.style/` directory with: - `README.md` explaining the convention - `style-guide.md` as a table-of-contents scaffold - `styles/Coder/README.md` placeholder so Git tracks the empty Vale rules dir - `.github/workflows/deploy-docs.yaml`: skip the workflow on `.style`-only pushes, and exclude `.style` paths from the surgical-reindex git diff on mixed commits. Defense-in-depth on top of the manifest-driven coder.com routing. - `.github/.linkspector.yml`: add `docs/.style` to `excludedDirs` - `AGENTS.md` and `.claude/docs/DOCS_STYLE_GUIDE.md`: cross-link to the new style guide for agents ## Verification - `make pre-commit-light` clean (`fmt/markdown`, `lint/markdown`, `lint/typos`, `lint/emdash`, `lint/actions/actionlint`, `lint/shellcheck`). - `markdown-table-formatter --check` and `markdownlint-cli2` both process the new files (existing globs are `find docs -name '*.md'`). - `actionlint` clean on the modified workflow. - coder.com exclusion works because route discovery and Algolia indexing are manifest-driven; this directory is not in `docs/manifest.json`. The workflow changes are defense in depth. <details> <summary>Implementation plan and decision log</summary> ### Decisions - **Location**: `docs/.style/` (leading dot, mirrors `.github/`, `.vscode/`, `.claude/`). Vale's `StylesPath` will be `docs/.style/styles/`; `.vale.ini` lands at repo root in a follow-up. - **Existing public page `docs/about/contributing/documentation.md`**: untouched in this PR. Nick's separate information-architecture rework will redirect it to GitHub at the right time. - **Placeholder for empty `styles/Coder/`**: real `README.md`, not `.gitkeep`. Discoverable on GitHub, lints with the existing tooling, lists the planned starter rules. - **CONTRIBUTING.md**: not touched. It's a 2-line redirect to `coder.com/docs/CONTRIBUTING`; bloating it would defeat the redirect. - **`.claude/docs/DOCS_STYLE_GUIDE.md`**: kept as the structure/research companion. A blockquote at the top points at the new canonical prose guide. ### coder.com exclusion mechanism (verified by inspection) Direct inspection of `coder/coder.com`: - Route discovery in [`src/utils/docs/docs.ts`](https://github.com/coder/coder.com/blob/master/src/utils/docs/docs.ts) iterates `routes` from `docs/manifest.json`. Files not in the manifest never become routes. - The Algolia surgical indexer at [`src/utils/algoliaDocs/surgical.ts`](https://github.com/coder/coder.com/blob/master/src/utils/algoliaDocs/surgical.ts) explicitly skips paths not in the manifest, incrementing `pathsSkipped`. Net result: not adding anything from `docs/.style/` to `manifest.json` is the only thing that has to be true for the exclusion to work. The `deploy-docs.yaml` tweaks are defense in depth. ### deploy-docs.yaml changes (pre-mortem) 1. Trigger path negation `!docs/.style/**` skips the workflow on `.style`-only pushes. GitHub Actions only suppresses when every changed file matches a negation, so mixed commits still trigger. 2. The git-diff pathspec `:(exclude)docs/.style/**` drops `.style` paths from the surgical-reindex payload on mixed commits. Risks considered: - **Test contract**: `.github/workflows/test-deploy-docs-diff.sh` only exercises the downstream awk parser, not the git-diff invocation. The exclusion happens at git-diff time; the parser sees the same `<status>\0<path>\0` format. No test change needed. - **First push to a brand-new branch**: the workflow falls back to whole-branch reindex when `BEFORE_SHA` is all zeros. Whole-branch reindex re-extracts records from the manifest, which still excludes `.style` files because they are not in the manifest. - **Workflow-dispatch**: takes the whole-branch path; same reasoning. Safe. ### Why a real README in `styles/Coder/` instead of `.gitkeep` It explains intent, lists the upcoming rules, and lints with the existing tooling. The cost is one extra Markdown file; the upside is that a contributor browsing GitHub sees the plan without clicking around. </details> --- *Filed via [Coder Agents](https://coder.com/docs/ai-coder/agents) on Nick's behalf.* Linear: DOCS-180 |
||
|
|
fb24110933 |
feat(.github/workflows): trigger docs reindex on release.published (DOCS-327) (#26070)
Closes [DOCS-327](https://linear.app/codercom/issue/DOCS-327/trigger-docs-reindex-on-codercoder-releasepublished). ## What Add `release: { types: [published] }` to `.github/workflows/deploy-docs.yaml` so that publishing a stable `vX.Y.Z` GitHub Release on this repo auto-dispatches the docs-sync handler against the corresponding `release/X.Y` branch. The existing `push` and `workflow_dispatch` triggers are unchanged. The `Compute action and ref` step gains a release-event branch that: - Skips prereleases (`github.event.release.prerelease == true`) with a workflow notice. - Matches the tag against `^v([0-9]+)\.([0-9]+)\.[0-9]+$` and translates `v2.35.0` to `release/2.35`. - Falls through with a notice and `exit 0` for any tag that doesn't match the plain semver shape (`v2.35`, `v2.35.0-rc.1`, etc.). Downstream validation, HMAC body construction, and the POST step are unchanged. The POST step gains an `if: steps.input.outputs.action != ''` guard so the two `exit 0` paths skip the POST instead of sending empty `action`/`ref` to the production handler. A new `.github/workflows/test-deploy-docs-release.sh` exercises the release-event bash against the 11 event scenarios in the table below plus 3 regex boundary cases, mirroring the existing `test-deploy-docs-diff.sh` pattern. ## Why Today, every mainline rollover requires a human to dispatch this workflow manually with `action=index, ref=release/X.Y`. We just hit this rotation friction on [DOCS-324](https://linear.app/codercom/issue/DOCS-324/rotate-algolia-indexer-allowlist-for-v234-launch-add-release234-drop) (v2.34 launch) and the resulting empty-search-results incident on `/docs/@v2.34.x/...`. `release.published` is the right cue: it fires exactly when a version becomes user-visible, not when its release branch is cut weeks earlier with possibly-incomplete docs. ## Coupling (important) This change is **intentionally inert until coder.com's `INDEXED_REFS_BY_CORPUS` allowlist becomes self-rotating** (filed under [DOCS-210](https://linear.app/codercom/issue/DOCS-210/automated-docs-index-lifecycle-management)). Until that lands, the handler still rejects new minors with `{action: "skipped", reason: "...not in INDEXED_REFS_BY_CORPUS"}` and this workflow logs the skip. Pre-wiring lets both halves land roughly in parallel so the next release cut after both ship is automatic. Reviewers: feel free to merge this independently. There is no downside to the wiring being live before the allowlist half ships; worst case, every release-publish event creates a no-op workflow run. ## Behavior trace (the cases the bash handles) <details> <summary>11 event scenarios I walked through by hand</summary> | Event | Tag | prerelease | Result | |---|---|---|---| | push to main | n/a | n/a | `index`, `ref=main` (existing) | | push to release/2.34 | n/a | n/a | `index`, `ref=release/2.34` (existing) | | workflow_dispatch index release/2.34 | n/a | n/a | `index`, `ref=release/2.34` (existing) | | workflow_dispatch delete release/2.31 | n/a | n/a | `delete`, `ref=release/2.31` (existing) | | release.published | `v2.35.0` | `false` | `index`, `ref=release/2.35` (new) | | release.published | `v2.35.0-rc.1` | `true` | notice + `exit 0` (new) | | release.published | `v2.35.0-rc.1` | `false` | notice + `exit 0`, regex miss (new) | | release.published | `v2.35` | `false` | notice + `exit 0`, regex miss (new) | | release.published | `release-2.35` | `false` | notice + `exit 0`, regex miss (new) | | release.published | `v0.0.0` | `false` | `index`, `ref=release/0.0` then handler rejects via allowlist (defense in depth) | | release.published | `` (empty) | unset | notice with `<unknown>` + `exit 0` | </details> ## Safety - The handler's allowlist gate still applies; this PR can only cause `{action: "skipped"}` responses until DOCS-210's allowlist-derivation lands. No risk of indexing an unintended ref. - The workflow's existing input validation (`case "$REF" in main|release/*)`) rejects any translation output that isn't `release/<int>.<int>`. Defense in depth in case the regex ever loosens by accident. - [DOCS-121](https://linear.app/codercom/issue/DOCS-121/post-mortem-docs-search-outage-2026-05-12-pr-25049-merge-wiped-docs) self-trigger risk is not present here: the new trigger is `release.published`, not push-on-paths. Workflow file edits cannot induce a release event. - `concurrency: { group: deploy-docs-${{ github.ref }} }` already exists. Release events have `github.ref=refs/tags/vX.Y.Z`, distinct from push events on the same release branch. A theoretical race resolves through the handler's atomic deleteBy+saveObjects. - The POST step now has an `if:` guard that skips downstream calls when the Compute step exits early without writing outputs. Closes the empty-env-var failure mode that coder-agents-review CRF-1 flagged. ## Verification - `actionlint .github/workflows/deploy-docs.yaml` clean. - `make pre-commit-light` clean: `fmt/shfmt`, `fmt/markdown`, `lint/actions/actionlint`, `lint/shellcheck`, `lint/markdown`, `lint/emdash`, `lint/typos`, etc. - `.github/workflows/test-deploy-docs-release.sh`: 14 cases pass (11 scenario table + 3 regex boundary cases). - Bash logic hand-traced through 11 event scenarios (table above). ## Out of scope - Build-time allowlist derivation in coder.com (DOCS-210a, will be filed/PR'd as a sibling change). - Webhook-driven cleanup of aged-out refs ([DOCS-210](https://linear.app/codercom/issue/DOCS-210) parent). - code-server release lifecycle (different repo, code-server's docs corpus stays at `main`). --- _Coder Agents on behalf of @nickvigilante._ |
||
|
|
81b6132e02 |
fix(.github/workflows/deploy-docs.yaml): drop self-trigger from paths (#25285)
Edits to `.github/workflows/deploy-docs.yaml` previously self-triggered the workflow on push to `main` and `release/*` because the file was listed in its own `paths:`. On 2026-05-12, this caused merge of #25049 to fire a production reindex with no `docs/**` changes, which entered the empty-`paths_json` whole-branch path in the Algolia handler and wiped the `docs` index (see DOCS-121). This change removes `.github/workflows/deploy-docs.yaml` from `paths:` so the workflow only runs against real docs content. Reindexes from a workflow edit alone now require `workflow_dispatch`, which already accepts a `ref` input and an `action` choice of `index` or `delete`. The other safety net (a workflow-level `paths_json=[]` guard in `algolia-and-isr`) is tracked separately in DOCS-122. Refs DOCS-121, DOCS-122, DOCS-124. --- _Coder Agents on behalf of @nickvigilante._ |
||
|
|
36d52ba504 |
feat(.github/workflows): trigger Algolia, ISR, and Vercel deploy on docs/** changes (#25049)
Folds the Algolia/ISR sync trigger and surgical-reindex path computation
into the existing `deploy-docs.yaml` workflow so a single `docs/**` push
fires every update path the docs site needs.
One preflight job feeds two parallel sibling jobs:
- **`changes`** (preflight): diffs `github.event.before` against
`github.sha` to compute `manifest_changed` and `paths_json` (a JSON
array of `{path, status}` objects derived from `git diff --name-status
-z`, capped at 50 entries). The mapping is `A → added`, `M/T →
modified`, `D → deleted`, `R<n> → renamed` (indexed by the new path).
Falls back to whole-branch (emits `paths_json: "[]"`) on
`workflow_dispatch`, the first push to a new branch, fetch failure,
manifest changes (route restructuring would orphan records), or >50
markdown files.
- **`algolia-and-isr`** (always, parallel with `vercel-rebuild`):
HMAC-signed POST to `coder.com/api/algolia-docs-sync` with the
`paths_json` array as part of the body. Refreshes the Algolia `docs`
slice for the `(corpus, ref)` pair and ISR-revalidates every navigable
route the handler touched. Markdown-only edits surface in seconds with
no full rebuild. The step summary line `Mode: \`surgical\` (N path(s))`
lets operators verify which path ran without scrolling through the curl
output.
- **`vercel-rebuild`** (parallel with `algolia-and-isr`, only when
`docs/manifest.json` changed): fires the existing Vercel deploy hook for
a full build. Manifest changes can register or remove routes that
Next.js's `getStaticPaths` only re-evaluates on a full build, so
ISR-per-existing-path is not enough.
Trigger expanded from "main + manifest.json" to "main and `release/*` +
any `docs/**`" so release-branch docs edits also flow through the same
pipeline. The Vercel rebuild path stays gated on manifest changes
regardless of branch.
The pure shell + curl + openssl + jq + awk pipeline is preserved
verbatim. Zero Algolia or Node dependencies in CI.
## Why one workflow instead of two
The original split (a standalone Algolia workflow + the existing
`deploy-docs.yaml`) would have run twice per manifest push, with two
parallel concurrency groups, two GitHub Actions step summaries, and two
ways to forget to add a secret. Folding into one file makes the trigger
story symmetrical: "docs change → all docs surfaces refresh," with the
rebuild path being a strict superset of the ISR path, and the surgical
path strictly cheaper than whole-branch when computable.
## Pre-merge testing
The companion handler PR (coder/coder.com#741) supports an
`ALGOLIA_DOCS_INDEX` env-var override, scoped to `docs_smoke` on the
Vercel preview deploy, so this workflow can be exercised end-to-end
against a disposable index without touching production records. The
smoke harness at `~/audit/smoke/run.sh` (workspace-only) signs and posts
the same body shape this workflow does, so it covers the same crypto
path. To exercise the workflow itself, push a docs-only commit to a
throwaway branch and watch the step summary; the `algolia-and-isr` job
will print the resolved mode.
## Prerequisites before this can do anything useful
1. `secrets.ALGOLIA_DOCS_SYNC_SECRET` must be added as an Actions secret
on this repo. The same value goes on `coder.com`'s Vercel env. The
workflow logs a clear error and aborts with no network call if the
secret is missing.
2. The handler at coder/coder.com#741 must be merged and deployed.
Without it, the POST will 404.
3. `secrets.DEPLOY_DOCS_VERCEL_WEBHOOK` is already in place from the
existing `deploy-docs.yaml`; this PR does not change its usage.
## Demo, validation, and design
- Front-end-only fixes (modal layout, scroll-shadow, rank-order
preservation): coder/coder.com#749 ships these against production today,
independent of this PR.
- Companion handler PR on `coder.com`: coder/coder.com#741. Includes the
surgical-mode plumbing this workflow's `paths_json` output drives.
- Full design lives in the workspace at
`~/plans/algolia-search-revamp.md`. Key sections:
- §6.0–6.2: why the indexer lives in `coder.com`, not here.
- §6.7: per-version add/remove mechanics.
- §6.8: ISR revalidate rationale and same-time refresh.
- §6.9: surgical per-page reindex (workflow + handler + planning rules).
---
This PR was generated by Coder Agents.
|
||
|
|
e738ff5299 |
ci: remove dylib build pipeline (#22592)
## Summary The macOS `.dylib` is only used by Coder Desktop macOS v0.7.2 or older. v0.7.2 was released in August 2025. v0.8.0 of Coder Desktop macOS, also released in August 2025, uses a signed Coder slim binary from the deployment instead. It's unlikely customers will be using Coder Desktop macOS v0.7.2 and the next release of Coder simultaneously, so I think we can safely remove this process, given it slows down CI & release processes. ## Changes - **Makefile**: Remove `DYLIB_ARCHES`, `CODER_DYLIBS` variables and `build/coder-dylib` target - **scripts/build_go.sh**: Remove `--dylib` flag and all dylib-specific logic (c-shared buildmode, CGO, plist embedding, vpn/dylib entrypoint) - **scripts/sign_darwin.sh**: Remove dylib-specific comment - **CI (ci.yaml)**: Remove `build-dylib` job, artifact download/insert steps, and `build-dylib` dependency from `build` job - **Release (release.yaml)**: Remove `build-dylib` job, artifact download/insert steps, and `build-dylib` dependency from `release` job - **vpn/dylib/**: Delete entire directory (`lib.go` + `info.plist.tmpl`) - **vpn/router.go, vpn/dns.go**: Clean up comments referencing dylib The slim and fat binary builds are completely unaffected — the dylib was an independent build target with its own CI job. _Generated by mux but reviewed by a human_ |
||
|
|
ef2e408c0c |
chore: add GitHub Action to build+deploy coder.com whenever docs paths change (#22283)
## problem Fixes an issue where updates to docs resulted in docs links returning HTTP 404, sometimes taking 4-12 hours before returning HTTP 200 (OK). coder.com is deployed to Vercel from a separate Next.js repo, which has no knowledge of when docs pages in this repo get updated. ### examples (non-exhaustive) PR | 404 description ---|--- #19625 | URL for https://coder.com/docs/install/offline was updated to https://coder.com/docs/install/airgap, but the latter returned 404 for 3 hr 56 min after the PR was merged #21434 | URLs https://coder.com/docs/ai-coder/nsjail and https://coder.com/docs/ai-coder/landjail were added, but both paths 404ed for 1 hr 30 min after the PR was merged. Note that these paths have changed since then--don't be alarmed if clicking those links returns 404s while reviewing this PR #21708 | URL https://coder.com/docs/ai-coder/boundary/agent-boundary was added, but it returned 404 for 1 hr 19 min after the PR was merged ## solution All 3 PRs listed above modify manifest.json. This file is fetched during coder.com's `getStaticPaths` for docs pages, defining which docs URLs get statically generated at build time. In the latter 2 cases, the 404s were resolved by manually triggering a redeploy of coder.com in the Vercel dashboard. The new CI workflow in this PR automatically triggers a Vercel deploy hook ([see docs](https://vercel.com/docs/deploy-hooks#triggering-a-deploy-hook)) with a POST request that runs whenever commits are pushed to main that modify manifest.json. The deploy hook initiates a new build+deploy of the coder.com Next.js app, which reruns `getStaticPaths`, updating docs pages' URLs. **Note:** I have not tested this workflow yet. I will verify that it works after this PR is merged. I confirmed in a local terminal that the webhook URL does successfully initiate a new Vercel build. I also tested with a malformed URL and received error JSON output, so if the action fails for some reason, we should see error output in the workflow logs ([example](https://github.com/coder/coder/actions/runs/22361453442/job/64722503802)). |