@moku-labs/ci 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 moku-labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ <div align="center">
2
+
3
+ # @moku-labs/ci
4
+
5
+ **One CI and release pipeline for every moku package.**
6
+
7
+ Reusable GitHub workflows pinned by tag, plus the `moku-release` CLI that installs them
8
+ into a project and runs a release. A project keeps two 20-line files and seven scripts;
9
+ everything else lives here, once. Not a build tool and not a framework — it calls your
10
+ `package.json` scripts and never the tools behind them.
11
+
12
+ <br/>
13
+
14
+ [![npm](https://img.shields.io/npm/v/@moku-labs/ci?logo=npm&color=cb3837&label=npm)](https://www.npmjs.com/package/@moku-labs/ci)
15
+ [![self test](https://github.com/moku-labs/ci/actions/workflows/self-test.yml/badge.svg)](https://github.com/moku-labs/ci/actions/workflows/self-test.yml)
16
+ [![workflows](https://img.shields.io/badge/workflows-%40v1-1864ab)](#versioning)
17
+ [![node](https://img.shields.io/badge/node-%3E%3D24-339933?logo=node.js&logoColor=white)](#requirements)
18
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
19
+
20
+ <br/>
21
+
22
+ [Install](#install) ·
23
+ [How it works](#how-it-works) ·
24
+ [Workflows](#workflows) ·
25
+ [CLI](#cli) ·
26
+ [The contract](#the-contract) ·
27
+ [Versioning](#versioning) ·
28
+ [Scripts](#scripts)
29
+
30
+ </div>
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ ```sh
37
+ bun add -d @moku-labs/ci
38
+ bun run release:setup
39
+ ```
40
+
41
+ `setup` writes the two workflow files, adds the missing scripts, does the first publish,
42
+ registers the trusted publisher and applies the branch ruleset. Run it again any time — it
43
+ only does what is still missing.
44
+
45
+ > [!NOTE]
46
+ > **Status: `1.x`, early.** `package-ci.yml` runs on this repo's own PRs. `package-release.yml`
47
+ > and the CLI's `setup` and `release` have passed dry-run and unit tests only; they have not
48
+ > yet released a live package.
49
+
50
+ > [!IMPORTANT]
51
+ > Two steps are yours alone. The CLI never handles a credential, and there is no `NPM_TOKEN`
52
+ > anywhere — publishing is tokenless OIDC.
53
+ >
54
+ > ```sh
55
+ > gh auth login
56
+ > npm login
57
+ > ```
58
+
59
+ ## Why @moku-labs/ci
60
+
61
+ - **One copy of the pipeline.** Seven repos had seven different `ci.yml` and six different
62
+ `publish.yml`. A fix now lands here and reaches every project through the `@v1` tag.
63
+ - **Scripts are the interface, not tools.** The workflows call `bun run lint`, never `biome`.
64
+ A project with special needs changes its own script, not the central YAML.
65
+ - **The CLI and its templates are one package.** `moku-release` reads `examples/` and
66
+ `rulesets/` from its own install. There is no second copy to drift.
67
+ - **No tokens.** npm Trusted Publishing with `id-token: write`. Build and publish run in
68
+ separate jobs, so no dependency's postinstall ever sees the credential.
69
+ - **Not a dependency of your app.** A dev dependency with zero runtime dependencies of its
70
+ own, so even `@moku-labs/core` can use it without a cycle.
71
+
72
+ ## How it works
73
+
74
+ ```mermaid
75
+ flowchart LR
76
+ P["your project<br/>ci.yml · publish.yml<br/>7 scripts"] -->|"uses: …@v1"| W["moku-labs/ci<br/>reusable workflows"]
77
+ C["moku-release<br/>setup · doctor · release"] -->|writes| P
78
+ C -->|dispatches| W
79
+ W --> N["checks on the PR<br/>tag · GitHub release · npm"]
80
+ classDef u fill:#0b7285,stroke:#08525f,color:#fff;
81
+ classDef m fill:#1864ab,stroke:#0d3d6e,color:#fff;
82
+ class P,N u
83
+ class W,C m
84
+ ```
85
+
86
+ 1. `release:setup` writes two thin callers into `.github/workflows/`.
87
+ 2. Every PR runs `package-ci.yml`: four jobs, reported as `ci / lint`, `ci / types`,
88
+ `ci / test`, `ci / build`.
89
+ 3. `release patch` dispatches `publish.yml`, which calls `package-release.yml`:
90
+ check → tag → pack → publish. The CLI watches the run and verifies the version on npm.
91
+
92
+ ## Workflows
93
+
94
+ | Workflow | Called from | Jobs | Inputs (all optional) |
95
+ |---|---|---|---|
96
+ | [`package-ci.yml`](.github/workflows/package-ci.yml) | [`examples/package/ci.yml`](examples/package/ci.yml) | `lint` · `types` · `test` · `build` | `runs_on`, `bun_version`, `validate` |
97
+ | [`package-release.yml`](.github/workflows/package-release.yml) | [`examples/package/publish.yml`](examples/package/publish.yml) | `check` → `release` → `package` → `publish` | `release_type`, `publish`, `runs_on`, `bun_version`, `node_version`, `artifact_name`, `validate` |
98
+ | [`app-deploy.yml`](.github/workflows/app-deploy.yml) | [`examples/app/ci.yml`](examples/app/ci.yml) | `validate` → `deploy` to Cloudflare | script names (`lint_script`, `build_script`, `deploy_script`, …) and two required secrets |
99
+ | [`self-test.yml`](.github/workflows/self-test.yml) | this repo only | `actionlint` over workflows and examples | — |
100
+
101
+ `package-release.yml` outputs `tag`, `version`, `prev_tag` and `artifact_name`.
102
+
103
+ | Other file | What it is |
104
+ |---|---|
105
+ | [`examples/package/publish.local-publish.yml`](examples/package/publish.local-publish.yml) | Fallback: publish from the project's own job. Use it only if the central publish fails npm auth. |
106
+ | [`rulesets/main.json`](rulesets/main.json) | Branch ruleset for `main`: PR only, no force-push, the four `ci / …` checks required. |
107
+
108
+ > [!TIP]
109
+ > A Layer-3 app copies `examples/app/ci.yml` by hand and needs a `deploy` script. The CLI
110
+ > sets up packages only.
111
+
112
+ ## CLI
113
+
114
+ | Command | When | What it does |
115
+ |---|---|---|
116
+ | `bun run release:setup` | once per project | Idempotent wizard: workflows, script contract, first publish, first tag, trusted publisher, branch ruleset, then `doctor`. `--dry-run` prints every action and changes nothing. |
117
+ | `bun run release:doctor` | any time | Read-only. Eleven checks, one line each, and the exact `fix:` command for every red line. `--json` for machines. |
118
+ | `bun run release <patch\|minor\|major\|prerelease>` | each release | Refuses unless the tree is clean and `HEAD == origin/main`. Dispatches `publish.yml`, watches the run, verifies the version and dist-tag on npm. |
119
+
120
+ The scripts are plain aliases of the `moku-release` bin. Internals and the list of checks:
121
+ [src/README.md](src/README.md).
122
+
123
+ ## The contract
124
+
125
+ A package exposes exactly these seven scripts. `setup` adds the ones that are missing;
126
+ `doctor` reports them.
127
+
128
+ | Script | Used by |
129
+ |---|---|
130
+ | `build` | `build` job, and again before `npm pack` |
131
+ | `validate` | `build` job — publint + attw |
132
+ | `lint` | `lint` job — biome check + eslint |
133
+ | `typecheck` | `types` job — `tsc --noEmit` |
134
+ | `test` | `test` job — `vitest run`, never `bun test` |
135
+ | `lint:fix` | local only |
136
+ | `format` | local only |
137
+
138
+ Project-specific work goes inside the script. `room` needs a second typecheck pass, so its
139
+ script is `"typecheck": "tsc --noEmit && tsc -p tsconfig.worker.json --noEmit"`. The central
140
+ YAML stays the same for everyone.
141
+
142
+ > [!IMPORTANT]
143
+ > Keep the caller's job id `ci` and the filename `publish.yml`. GitHub prefixes the check
144
+ > names with the job id (`ci / lint`), and npm Trusted Publishing is registered against the
145
+ > filename. Rename either and the ruleset or the publish breaks.
146
+
147
+ ## Versioning
148
+
149
+ | Ref | Meaning |
150
+ |---|---|
151
+ | `@v1` | Moving major tag. Projects pin this and get fixes automatically. Moves only for backwards-compatible changes. |
152
+ | `@v1.x.y` | Immutable tag on every change. Pin it to freeze a project. |
153
+ | `@v2` | Any breaking change: a removed input, a changed default, a renamed job. `v1` stays where it was. |
154
+
155
+ A change here runs in every moku repo with `contents: write` and `id-token: write`. Review it
156
+ like release engineering, not like config.
157
+
158
+ ## When a release fails
159
+
160
+ One risk is still open: npm may reject a publish that runs inside a workflow owned by another
161
+ repository. It is unverified until the first live release. The fallback and sixteen other
162
+ traps the workflows already handle are in [docs/release-notes.md](docs/release-notes.md).
163
+
164
+ ## Scripts
165
+
166
+ ```sh
167
+ bun run build # tsdown → dist/release.mjs
168
+ bun run validate # publint
169
+ bun run lint # biome check + eslint
170
+ bun run lint:fix
171
+ bun run format
172
+ bun run typecheck # tsc --noEmit
173
+ bun run test # vitest run
174
+ ```
175
+
176
+ ## Requirements
177
+
178
+ Node ≥ 24 · Bun ≥ 1.3.14 · `gh` and `npm` ≥ 11.5.1 on the machine that runs `setup` or
179
+ `release`. The CLI prints through the
180
+ [@moku-labs/common](https://github.com/moku-labs/common) brand kit, bundled at build time.
181
+
182
+ ## License
183
+
184
+ [MIT](./LICENSE) © [moku-labs](https://github.com/moku-labs)