Skip to content

ci: wire nself-ci gate into plugins (dogfood adoption) - #91

Merged
acamarata merged 1 commit into
mainfrom
ci/wire-nself-ci-gate
Sep 12, 2026
Merged

acamarata merged 1 commit into
mainfrom
ci/wire-nself-ci-gate

Conversation

@acamarata

Copy link
Copy Markdown
Contributor

Summary

  • Closes the ADOPTION gap: nself ci (built in free/ci) was wired into 0 of 13 nself-org repos, not even this one, which owns the source.
  • Adds .github/workflows/nself-ci.yml: builds the gate via scripts/nself-ci.sh and posts a nself-ci commit status using gh api + GH_TOKEN: ${{ github.token }}.
  • Adds .github/wiki/guides/Nself-CI-Adoption.md: the copy-paste pattern for the other 12 repos, the real verified local output, and an honest list of what this gate does NOT check on this repo today (see below).

Verified locally (not just "should work")

$ scripts/nself-ci.sh --check -v .
Stacks: node
  secrets:gitleaks   PASS  (3.617s)
Overall: PASSED  (4s)

Known gap (documented in the wiki guide, not hidden)

This repo's root package.json has no lint/typecheck/test/build scripts (only a custom ci:local stub) and no pnpm-workspace.yaml, so nself-ci's node-gate detection currently runs only the secret scan here — same shape of issue as .claude/memory/lesson_hollow_ci_gates.md. This PR does not paper over that: the wiki guide calls it out explicitly and recommends requiring nself-ci in branch protection in addition to, not instead of, validate.yml/build-test.yml/gitleaks.yml until it's fixed.

Branch protection is not changed by this PR — that's the owner's call (recipe already in ~/Sites/nself/.claude/docs/CI-LOCAL.md).

Test plan

  • Built free/ci/nself-ci locally and ran scripts/nself-ci.sh --check -v . against this worktree — real output above.
  • Workflow YAML validated (yaml.safe_load).
  • Confirm the nself-ci.yml workflow runs green on this PR and posts the nself-ci status (GitHub Actions, free public-repo runner).

Closes the ADOPTION gap found in the 2026-09-11 audit: nself-ci existed in
free/ci but was wired into zero of the 13 nself-org repos, not even this
one, which owns the source. Adds a workflow that builds and runs the
gate via scripts/nself-ci.sh and posts a nself-ci commit status, plus a
wiki guide documenting the pattern, real verified local output, and the
gaps found (this repo's package.json has no lint/typecheck/test/build
scripts and no pnpm-workspace.yaml, so the node gate currently runs
nothing but the secret scan). Branch protection is proposed, not applied.
@acamarata
acamarata merged commit 858c228 into main Sep 12, 2026
29 checks passed
@acamarata
acamarata deleted the ci/wire-nself-ci-gate branch September 12, 2026 14:08
acamarata added a commit that referenced this pull request Sep 12, 2026
…sdk (#93)

* fix(ci): green the node:typecheck gate for plugins-registry and feature-flags sdk

nself-ci's new implicit-workspace-member discovery (gate_workspace.go, #91)
found and ran node:typecheck against .workers/plugins-registry and
free/feature-flags/sdk-ts for the first time, and both failed on main.

.workers/plugins-registry already declared @cloudflare/workers-types
correctly in package.json/tsconfig and had a valid committed lockfile — the
TS2688 only happened because nself-ci.yml never installed this directory's
dependencies before running its typecheck script, so tsc fell back to the
runner's global toolchain with no project node_modules at all. Same root
cause produced the sdk-ts TS2307 on 'react'. Added an install step for both
nested packages (this repo has no pnpm-workspace.yaml, so pnpm never
recurses into them on its own) and committed a lockfile for sdk-ts, which
had none.

Separately, sdk-ts's evaluate() typed its ctx parameter as the full
EvaluateRequest even though flag_key is always supplied by the explicit key
argument, never by ctx — evaluateFlag()/useFlag() correctly pass
Omit<EvaluateRequest, 'flag_key'>, which the wider parameter type rejected
(TS2345). Narrowed evaluate()'s ctx type to match what it actually needs,
and swapped the request-body spread order so an explicit key can never be
silently overridden by a flag_key on ctx.

free/file-processing/ts, free/media-processing/ts, and the sdk-ts jest
config remain red for unrelated pre-existing reasons and are out of scope
here.

* fix(ci): install+build deps for file-processing/media-processing, wire jest transform for feature-flags sdk (#94)

nself-ci's node gate surfaced three more pre-existing reds beyond PR #93's
scope (same root cause class: nothing installs a nested package's own
dependencies before typecheck/test/build runs):

- free/file-processing/ts and free/media-processing/ts both had every
  declared dependency (commander, fastify, @types/node, @nself/plugin-utils,
  etc.) present in package.json but never installed. Added the same
  `pnpm install --frozen-lockfile --dir <pkg>` pattern PR #93 introduced.
  Their @nself/plugin-utils dependency is a file: path to shared/, whose
  dist/ output pnpm never builds on link — added a build step for shared
  ahead of the gate so the type/JS output exists.
- Installing file-processing surfaced a genuine bug once tsc could actually
  resolve @nself/plugin-utils: src/server.ts imports createMetrics, which
  was never implemented in the shared package. Added a minimal
  dependency-free Prometheus-text-format counter (shared/src/metrics.ts)
  matching the incrementRequest/incrementError/format surface the plugin
  already calls.
- free/feature-flags/sdk-ts had ts-jest installed but no jest config at
  all, so jest ran with zero TypeScript transform. Added jest.config.js
  (ts-jest preset + a moduleNameMapper for the NodeNext-style `.js` import
  extensions). That surfaced two more real gaps: the tsconfig's
  Node16/NodeNext module kind needs isolatedModules for ts-jest's per-file
  transpile, and the test file's `global.fetch` mock needed @types/node
  (never a declared dependency here).

scripts/nself-ci.sh --check --no-gitleaks -v . now reports PASS for every
node:typecheck, node:test, and node:build entry across all 5 discovered
workspace members.

* fix(ci): build shared before installing its dependents

The nself-ci gate still failed with 'Cannot find module @nself/plugin-utils'
across every importing file in free/file-processing/ts and
free/media-processing/ts, even though shared was installed and built.

Cause: pnpm does not symlink a file: dependency back to the source tree. It
takes a real directory COPY into its store at install time. Building shared
afterwards populates shared/dist in the source tree but not in the copy the
dependents resolve against, and @nself/plugin-utils' main/types point at
./dist/*, so tsc finds no module.

Reordered so shared is built before file-processing and media-processing are
installed, which means their copies already contain dist/. Verified from a
clean state (dist and node_modules removed): both typechecks pass.

No gate was weakened and no dependency changed - only step ordering.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant