@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 +21 -0
- package/README.md +184 -0
- package/dist/release.mjs +2497 -0
- package/examples/app/ci.yml +28 -0
- package/examples/package/ci.yml +22 -0
- package/examples/package/publish.local-publish.yml +84 -0
- package/examples/package/publish.yml +36 -0
- package/package.json +54 -0
- package/rulesets/main.json +33 -0
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
|
+
[](https://www.npmjs.com/package/@moku-labs/ci)
|
|
15
|
+
[](https://github.com/moku-labs/ci/actions/workflows/self-test.yml)
|
|
16
|
+
[](#versioning)
|
|
17
|
+
[](#requirements)
|
|
18
|
+
[](./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)
|