This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
Commit 7e30d0b
ci(site): deploy the docs from a GitHub Actions workflow every 6 hours, and turn Vercel's Git-triggered builds off (objectui#12178) (#12182)
Refs: #12178 · stacked on #12179
## Why
Almost all of the maintainer's Vercel bill was "Build CPU Minutes" for
the `objectui` project (Root Directory `apps/site`, served at
objectui.org). Vercel built once for every commit pushed to `main`, and
started a preview build for every other branch (`claude/*`,
`gh-readonly-queue/*`, `changeset-release/*`, ...) that the dashboard's
Ignored Build Step then cancelled. Every production build since
2026-09-06 failed (#12178: 2023 failed production builds, about 9,400
build-minutes, the site frozen). This repository is public, so
`ubuntu-latest` minutes are free. The maintainer decided that the docs
deploy **only from `main`**, on **free compute**, **every 6 hours**.
## What
- **New `.github/workflows/docs-deploy.yml`**
- Triggers: `schedule`, cron `43 5,11,17,23 * * *` (every 6 hours), and
`workflow_dispatch`. Nothing else: no `push` trigger and no `paths`
list.
- Why that cron: `grep -rn 'cron:' .github/workflows/` shows hours
0/6/12/18, 1/7/13/19 and 2/8/14/20 each already carry another 6-hourly
job. 5/11/17/23 meet only one daily patrol, at 05:23. Minute 43 is off
the top of the hour and clear of the merge-queue patrol's :37 and :52. A
comment in the file records this.
- `concurrency: { group: docs-deploy-production, cancel-in-progress:
true }`. A later run builds a tip that contains the earlier run's
commits, so cancelling the earlier run loses nothing.
- Steps, all run from the **repository root**: `vercel pull --yes
--environment=production`, then `vercel build --prod`, then `vercel
deploy --prebuilt --prod`, with the CLI pinned (`VERCEL_CLI_VERSION`,
60.1.3). The project's Root Directory is `apps/site`, so `vercel build`
builds in `apps/site`, reads `apps/site/vercel.json` and writes
`./.vercel/output`, and `vercel deploy --prebuilt` uploads that
directory. I checked this against the pinned CLI's source: the build's
work path is the cwd joined with the project's `rootDirectory`, and the
prebuilt output dir is the cwd's `.vercel/output`. Running from inside
`apps/site` would apply the Root Directory twice.
- `VERCEL_ORG_ID` (`team_06nvlGKZCkwhzdXmRdxeCNnB`) and
`VERCEL_PROJECT_ID` (`prj_v1rXIczaI7YGmXmseQCLFUFOFxTB`) are inlined.
They are identifiers, not secrets.
- `VERCEL_TOKEN` is passed only to the `pull` and `deploy` steps.
`vercel build` needs no token (it is in the CLI's no-token command
list), and it runs `pnpm i` plus the whole workspace build, which
includes every dependency's install scripts, so it never sees the token.
- **Which way it fails:** the first step runs before checkout. If
`VERCEL_TOKEN` is missing, it stops with `::error title=VERCEL_TOKEN is
missing::...` and `exit 1`. If the ref is not `refs/heads/main`, it
stops with `::error title=Docs deploy runs from main only::...`. A
failed build or a failed upload is a red step. **Nothing turns into a
skipped green.**
- **`apps/site/vercel.json`** gains `"git": { "deploymentEnabled": false
}`. That is Vercel's documented switch for turning off Git-triggered
deployments on every branch, and I validated the file against
`https://openapi.vercel.sh/vercel.json`. Once this is merged, Vercel
builds nothing on push, and this workflow is the only way to production.
The `installCommand` (`pnpm i`) and the fixed `buildCommand` come from
#12179.
- **`content/docs/guide/ci-cd-pipeline.md`**: a `Docs Deploy
(docs-deploy.yml)` section, a Workflow Inventory row and a
`VERCEL_TOKEN` secrets row.
**`scripts/__tests__/ci-cd-pipeline-doc.test.ts`**: one declared entry.
The section names `turbo run build`, which the job really runs but
through `vercel build` and `vercel.json`, not in a `run:` step, so the
command-parity sweep cannot see it.
## Secret: already in place
`VERCEL_TOKEN` exists as an **organization** secret of `objectstack-ai`
(`gh api repos/objectstack-ai/objectui/actions/organization-secrets`
lists it, updated 2026-10-12T03:10:52Z), and this repository can see it.
`secrets.VERCEL_TOKEN` resolves org secrets the same way, so nothing has
to be configured before merging. The dry run below used it.
## Order with #12179
This branch contains #12179's commit. #12179 creates
`apps/site/vercel.json`, and this PR adds the `git` block to it.
- If #12179 merges first (it can merge as soon as it is green), merge
`origin/main` into this branch. The only conflict will be add/add on
`apps/site/vercel.json`. Resolve it by taking **this branch's** version,
which is #12179's file plus the `git` block.
- Alternatively, merge this PR alone (it carries #12179's change).
#12179 is then redundant and can be shut without merging.
## Evidence
- **Build-only dry run of this exact workflow on GitHub Actions**: run
38200568488, success, 5m08s. It ran from a temporary commit that added a
`pull_request` trigger and skipped the deploy step. That commit is
reverted on this branch, and the final tree is byte-identical to the
reviewed commit. In that run: `Vercel CLI 60.1.3 (Node.js 22.23.3)`,
`vercel pull` downloaded the production settings into
`./.vercel/project.json`, `vercel build` ran `Running "install" command:
pnpm i` and `Running "cd ../.. && pnpm turbo run build
--filter=@object-ui/site"`, turbo reported `Tasks: 30 successful, 30
total` (including `@object-ui/example-schema-catalog:build`, the package
whose absence breaks the Vercel build in #12178), Next generated 559 of
559 static pages, then `Created all serverless functions`, then `Build
Completed in .vercel/output`. `builds.json` shows `@vercel/next` with
this file's `installCommand` and `buildCommand`.
- **Not yet exercised: the `vercel deploy --prebuilt --prod` upload.**
The first real run after merge is that test.
- actionlint 1.7.12 reports nothing (shellcheck was not installed
locally, so the `run:` scripts were not shell-linted). The YAML parses.
A local run of the 88 `scripts/__tests__` files that read workflows or
the CI/CD page passed, except one test whose timeout was not caused by
this change: `check-i18n-dead-keys`, real-tree leg, 15 s, on a machine
at load 4. CI is the judge.
## After merge
1. Publish once and verify: `gh workflow run docs-deploy.yml --repo
objectstack-ai/objectui --ref main`, then watch the run. On green, the
step summary prints the deployment URL, and objectui.org should show
current content. #12179's build fix is part of this branch, so that run
is expected to be green. If it is red, #12178 has the diagnosis of the
build failure this replaces. The run is free either way.
2. From then on, the docs refresh **at most every 6 hours** (05:43,
11:43, 17:43 and 23:43 UTC). To publish immediately, use **Run
workflow** on the workflow's Actions page (or the `gh workflow run` line
above).
3. Shut #12178 by hand once a production deployment is READY. Neither PR
carries a closing keyword.
Side effects worth knowing:
- The `Vercel` commit status stops appearing on PRs and commits once
branches contain this `vercel.json`. `scripts/dependabot-merge-gate.mjs`
does not read statuses, so nothing waits on it.
- Branches created before this merge do not contain
`git.deploymentEnabled: false`, so Vercel will still start a preview for
them until they pick up `main`. The dashboard's Ignored Build Step still
cancels those, so leave it in place for now.
- The dashboard build and install commands are overridden by
`vercel.json` and no longer matter.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>1 parent 35a2b59 commit 7e30d0b
4 files changed
Lines changed: 184 additions & 0 deletions
File tree
- .github/workflows
- apps/site
- content/docs/guide
- scripts/__tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
| 59 | + | |
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
| |||
2654 | 2655 | | |
2655 | 2656 | | |
2656 | 2657 | | |
| 2658 | + | |
| 2659 | + | |
| 2660 | + | |
| 2661 | + | |
| 2662 | + | |
| 2663 | + | |
| 2664 | + | |
| 2665 | + | |
| 2666 | + | |
| 2667 | + | |
| 2668 | + | |
| 2669 | + | |
| 2670 | + | |
| 2671 | + | |
| 2672 | + | |
| 2673 | + | |
| 2674 | + | |
| 2675 | + | |
| 2676 | + | |
| 2677 | + | |
| 2678 | + | |
| 2679 | + | |
| 2680 | + | |
| 2681 | + | |
| 2682 | + | |
| 2683 | + | |
| 2684 | + | |
| 2685 | + | |
| 2686 | + | |
2657 | 2687 | | |
2658 | 2688 | | |
2659 | 2689 | | |
| |||
3291 | 3321 | | |
3292 | 3322 | | |
3293 | 3323 | | |
| 3324 | + | |
3294 | 3325 | | |
3295 | 3326 | | |
3296 | 3327 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3567 | 3567 | | |
3568 | 3568 | | |
3569 | 3569 | | |
| 3570 | + | |
| 3571 | + | |
| 3572 | + | |
| 3573 | + | |
| 3574 | + | |
| 3575 | + | |
| 3576 | + | |
3570 | 3577 | | |
3571 | 3578 | | |
3572 | 3579 | | |
| |||
0 commit comments