Skip to content

Commit 78bec78

Browse files
authored
Initial build infrastructure
Factor out shared build, test, and release infrastructure
2 parents da67920 + db50a5f commit 78bec78

62 files changed

Lines changed: 11164 additions & 3 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: "/"
5+
schedule:
6+
interval: daily
7+
open-pull-requests-limit: 10
8+
9+
- package-ecosystem: npm
10+
directory: "/"
11+
schedule:
12+
interval: daily
13+
open-pull-requests-limit: 10
14+
groups:
15+
vitest:
16+
patterns:
17+
- "*vitest*"
18+
hyperjump:
19+
patterns:
20+
- "@hyperjump/*"
21+
markdown:
22+
patterns:
23+
- "markdown-*"
24+
- "markdownlint-*"
25+
publishing:
26+
patterns:
27+
- "respec"
28+
- "@umbrelladocs/linkspector"

.github/workflows/test.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Test
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Check out repository
16+
uses: actions/checkout@v7
17+
18+
- name: Set up Node.js
19+
uses: actions/setup-node@v6
20+
with:
21+
node-version: "24.x"
22+
cache: npm
23+
24+
- name: Install dependencies
25+
run: npm ci
26+
27+
- name: Run tests
28+
run: npm test

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
coverage/

CONTRIBUTING.md

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# Contributing To Build Infrastructure
2+
3+
The goal is to keep the specification repositories uncluttered: each spec repo
4+
should call clear npm scripts, while this package owns the tool versions and
5+
reusable logic.
6+
7+
## Mental Model
8+
9+
There are four layers:
10+
11+
1. Specification repositories contain Markdown, schemas, tests, workflows, and
12+
`spec.config.json`.
13+
2. Their `package.json` scripts call commands installed by `@oai/build-infra`.
14+
3. This repository implements those commands and owns the JavaScript
15+
dependencies they need.
16+
4. GitHub Actions in each specification repository run the same npm scripts that
17+
maintainers run locally.
18+
19+
If something is reusable across specification repositories, put it here. If it is
20+
specific to one repository's governance, labels, reviewers, or branch policy,
21+
leave it in that repository.
22+
23+
## Command Overview
24+
25+
Build and validation:
26+
27+
* `oai-spec-build` renders Markdown to HTML using Markdown-it and ReSpec.
28+
* `oai-spec-format-markdown` applies shared Markdown formatting.
29+
* `oai-spec-validate-markdown` runs markdownlint and linkspector.
30+
* `oai-spec-publish-schemas` publishes dated JSON schema iterations.
31+
32+
Tests:
33+
34+
* `oai-spec-test` runs `c8` and `vitest`.
35+
* `@oai/build-infra/test` re-exports Vitest helpers.
36+
* `@oai/build-infra/schema/test-config` registers YAML schema loading and any
37+
configured custom vocabulary keywords.
38+
* `@oai/build-infra/schema/vitest` re-exports schema coverage helpers.
39+
40+
Release lifecycle:
41+
42+
* `oai-spec-start-release` starts the next development PR branch.
43+
* `oai-spec-adjust-release-branch` prepares a release branch for merge to
44+
`main`.
45+
46+
## Before Changing Code
47+
48+
Read the consuming repository's `spec.config.json` and `package.json` first.
49+
Most behavior is configured there.
50+
51+
Be especially careful with release commands. They create branches, commit files,
52+
delete configured paths, and may push branches. Test release-command changes in a
53+
scratch repository before asking maintainers to trust them.
54+
55+
## Testing
56+
57+
Run the package tests:
58+
59+
```sh
60+
npm test
61+
```
62+
63+
These tests include self-contained fixture repositories. They exercise the
64+
public commands against temporary consumer-shaped Git repositories, so they can
65+
run locally and in GitHub CI without another checkout.
66+
67+
For changes that affect behavior not covered by those fixtures, also test in at
68+
least one specification repository with a temporary local dependency:
69+
70+
```json
71+
{
72+
"dependencies": {
73+
"@oai/build-infra": "file:../build-infra"
74+
}
75+
}
76+
```
77+
78+
Then run the relevant consumer scripts:
79+
80+
```sh
81+
npm ci
82+
npm test
83+
npm run validate-markdown
84+
npm run build
85+
npm run build-src
86+
```
87+
88+
Not every repository has all of those scripts.
89+
90+
Before committing consumer changes, change the dependency back to the GitHub
91+
dependency and refresh the lockfile after the build-infra commit is available on
92+
GitHub.
93+
94+
## Dependency Maintenance
95+
96+
This repository owns most npm dependencies for the specification repositories.
97+
Dependabot is configured here for npm updates.
98+
99+
When Dependabot opens a pull request:
100+
101+
1. Read the release notes for major updates and security updates.
102+
2. Run `npm ci` and `npm test`.
103+
3. If the update touches build, markdown, schema, or test behavior, test a
104+
consumer repository with the local `file:../build-infra` dependency.
105+
4. Merge the build-infra update.
106+
5. In each consumer repository that should pick up the change, run:
107+
108+
```sh
109+
npm update @oai/build-infra
110+
```
111+
112+
6. Commit the consumer repository's `package-lock.json` update.
113+
114+
The consumer `package.json` should keep requesting
115+
`git+https://github.com/OAI/build-infra.git#main`. The consumer
116+
`package-lock.json` records that request at the root of the lockfile, and
117+
records the exact resolved Git commit under
118+
`packages["node_modules/@oai/build-infra"].resolved`. That resolved commit is
119+
intentional: it prevents CI from silently changing behavior because
120+
`OAI/build-infra` moved forward.
121+
122+
### Lockfile Maintenance Warning
123+
124+
Use `npm ci` as the normal install command in this repository and in consumer
125+
specification repositories, including on macOS. Do not use `npm install` merely
126+
to get a working local `node_modules` tree.
127+
128+
This matters because npm has sometimes produced an incomplete `package-lock.json`
129+
for platform-specific optional dependencies on macOS. Known failure modes
130+
include omitting optional peer-resolution entries for packages such as
131+
`@emnapi/core` and `@emnapi/runtime`, or leaving stale transitive entries from a
132+
previous dependency tree. The lockfile can appear to work locally but then fail
133+
in GitHub Actions, where `npm ci` checks the lockfile strictly on Linux.
134+
135+
Only use `npm install`, `npm update`, or similar commands when you are
136+
intentionally creating or changing a lockfile. After any dependency change in
137+
this repository or in a consumer repository:
138+
139+
1. Run `npm ci`.
140+
2. Run `npm test`.
141+
3. Run any repository-specific build or validation scripts.
142+
4. Check that GitHub Actions also passes `npm ci`.
143+
5. If `npm ci` says packages are missing from the lockfile, fix the lockfile and
144+
re-run `npm ci`. Do not paper over the problem by switching CI to
145+
`npm install`.
146+
147+
When setting up a new specification repository whose only npm dependency is
148+
`@oai/build-infra`, the consumer `package-lock.json` should contain the
149+
dependency tree needed by the resolved build-infra commit. If `npm ci` reports
150+
missing or invalid transitive packages after adding build-infra, compare the
151+
consumer lockfile with this repository's verified `package-lock.json` and make
152+
sure the consumer lockfile includes the same transitive package entries. This is
153+
especially important for optional dependencies, because those are where
154+
platform-specific lockfile gaps usually appear.
155+
156+
## Release Command Maintenance
157+
158+
The release commands are intentionally conservative.
159+
160+
`oai-spec-adjust-release-branch`:
161+
162+
* must run on a branch named `vX.Y.Z-rel`;
163+
* requires a clean working tree;
164+
* copies the active source Markdown to `versions/X.Y.Z.md`;
165+
* replaces `| TBD |` with the current date;
166+
* copies `EDITORS.md` to `versions/X.Y.Z-editors.md`, unless disabled;
167+
* removes paths listed in `release.removeOnReleaseBranch`.
168+
169+
`oai-spec-start-release`:
170+
171+
* must run on a branch named `vX.Y-dev`;
172+
* requires a clean working tree;
173+
* finds the latest published version under `versions/` on the configured main
174+
branch;
175+
* creates `vX.Y-dev-start-X.Y.Z`;
176+
* resets the active source Markdown history from the previous published version;
177+
* updates the version heading and history table;
178+
* optionally rewrites schema/test files for a new minor version;
179+
* pushes the branch unless `--no-push` is used.
180+
181+
Use `--no-push` in scratch tests.
182+
183+
## Common Failure Modes
184+
185+
* `npm ci` fails in a consumer repository: the package lock's resolved
186+
build-infra commit may not be reachable from GitHub yet, `package.json` and
187+
`package-lock.json` may disagree about the requested dependency, or the
188+
consumer lockfile may be missing transitive entries from build-infra's
189+
dependency tree. Verify with `npm ci` before opening the pull request.
190+
* Release command says the working tree is dirty: commit or stash local changes
191+
first. These commands intentionally refuse to mix release edits with unrelated
192+
work.
193+
* `oai-spec-start-release` cannot find published versions: check the configured
194+
remote, main branch, and `versions/` directory.
195+
* Generated HTML looks wrong: check `spec.config.json` first, especially `slug`,
196+
`shortName`, `titleName`, `specSrc`, and metadata links.
197+
198+
## What Belongs Here
199+
200+
Good candidates for this repository:
201+
202+
* shared command-line tools;
203+
* shared JavaScript dependency versions;
204+
* Markdown, link, schema, and ReSpec behavior;
205+
* release lifecycle mechanics used by multiple specification repositories;
206+
* templates for new specification repositories.
207+
208+
Keep these in individual specification repositories:
209+
210+
* contributor policy;
211+
* branch sync policy;
212+
* CODEOWNERS;
213+
* issue templates;
214+
* labels, reviewers, and pull request wording;
215+
* one-off scripts for that repository's issue management or governance.

0 commit comments

Comments
 (0)