Skip to content

ci(site): deploy the docs from a GitHub Actions workflow every 6 hours, and turn Vercel's Git-triggered builds off (objectui#12178) - #12182

Merged
hotlong merged 4 commits into
mainfrom
claude/docs-deploy-gha
Oct 12, 2026
Merged

hotlong merged 4 commits into
mainfrom
claude/docs-deploy-gha

Conversation

@hotlong

@hotlong hotlong commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

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 fix(site): build the docs deploy with the command CI already runs, so the production build stops failing (objectui#12178) #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.

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 objectui.org has not deployed since 2026-09-06: every Vercel production build fails to resolve @object-ui/example-schema-catalog, because the dashboard build command stopped building it when #7986 removed apps/site's prebuild hook #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. fix(site): build the docs deploy with the command CI already runs, so the production build stops failing (objectui#12178) #12179's build fix is part of this branch, so that run is expected to be green. If it is red, objectui.org has not deployed since 2026-09-06: every Vercel production build fails to resolve @object-ui/example-schema-catalog, because the dashboard build command stopped building it when #7986 removed apps/site's prebuild hook #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 objectui.org has not deployed since 2026-09-06: every Vercel production build fails to resolve @object-ui/example-schema-catalog, because the dashboard build command stopped building it when #7986 removed apps/site's prebuild hook #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

hotlong and others added 3 commits October 12, 2026 11:12
… the production build stops failing (objectui#12178)

Every production build of the Vercel project `objectui` (Root Directory
`apps/site`) has failed since 2026-09-06 with
`Module not found: Can't resolve '@object-ui/example-schema-catalog'`, so
objectui.org has been frozen since then.

The project's build command only exists in the Vercel dashboard:
`pnpm --filter '../../packages/*' -r build && pnpm build`. Its filter selects
`packages/*` only and never builds `examples/schema-catalog`, whose `exports`
resolve only into `dist/`. Until #7986 that gap was covered by `apps/site`'s
`prebuild` hook (`pnpm --filter @object-ui/example-schema-catalog build`).
#7986 removed the hook on purpose so that turbo's `^build` is the only source of
build order, and moved every in-repo path to the turbo form, including the root
`site:build` script. The dashboard command lives outside the repo, so it was not
updated. The deployment for #7986's commit is the first ERROR, and the one for
the commit before it is the last READY.

CI's `Build Docs` stayed green the whole time because it runs
`pnpm turbo run build --filter='@object-ui/site'`, which builds the site's
dependency closure, schema catalog included. This adds `apps/site/vercel.json`,
which Vercel reads from the Root Directory and which overrides the dashboard
values. Its `buildCommand` is that same turbo command, run from the repo root,
and its `installCommand` keeps the dashboard's current `pnpm i`. With that, the
deploy's build is in the repo and is the build CI validates.

Refs: objectui#12178

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s, and turn Vercel's Git-triggered builds off (objectui#12178)

Almost all of the maintainer's Vercel bill was "Build CPU Minutes" for the
`objectui` project. Vercel built once for every commit pushed to `main`, and
started a preview build for every other branch that the Ignored Build Step then
cancelled. Every production build since 2026-09-06 failed (objectui#12178), so
the spend deployed nothing. This repository is public, so `ubuntu-latest`
minutes are free. The maintainer decided the docs deploy only from `main`, on
free compute, every 6 hours.

- `.github/workflows/docs-deploy.yml` runs on a 6-hourly cron
  (`43 5,11,17,23 * * *`, chosen off the hour and away from the hours other
  crons already use) and on `workflow_dispatch`. There is no `push` trigger and
  no `paths` list. The workflow runs `vercel pull`, `vercel build --prod` and
  `vercel deploy --prebuilt --prod` with a pinned CLI, all from the repo root,
  because the project's Root Directory is `apps/site`. Vercel builds nothing.
  The team and project ids are inlined (they are not secrets). `VERCEL_TOKEN`
  reaches only the `pull` and `deploy` steps: the build step, which runs every
  dependency's install scripts, never sees it.
- Which way it fails: a missing `VERCEL_TOKEN`, or a run on a ref other than
  `main`, fails red with an `::error::` before checkout. It never skips green,
  because a silent skip would stop the docs updating without anyone seeing it.
  `concurrency: docs-deploy-production` with `cancel-in-progress`, because a
  later run builds a tip that contains the earlier one.
- `apps/site/vercel.json` gains `git.deploymentEnabled: false`, which turns off
  Git-triggered deployments for every branch. The workflow becomes the only
  path to production.
- `content/docs/guide/ci-cd-pipeline.md` gets the workflow's section, its
  inventory row and the `VERCEL_TOKEN` secret row.
  `scripts/__tests__/ci-cd-pipeline-doc.test.ts` declares the one command the
  section names that no `run:` step shows: `turbo run build`, which runs
  through `vercel build` and the `buildCommand` in `vercel.json`.

Refs: objectui#12178

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nly, no deploy) - reverted in the next commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dry run (run 38200568488) built the site through `vercel pull` and
`vercel build --prod` from the repository root: `vercel build` ran the
`installCommand` and `buildCommand` from `apps/site/vercel.json`, turbo
reported 30 of 30 tasks successful, and the output was written to
`.vercel/output`. The deploy step was skipped. The workflow goes back to
`schedule` plus `workflow_dispatch` only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apps ci/cd configuration documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant