587ff2cf47
Publish snapshot / snapshot (push) Failing after 1m58s
Publishing infrastructure - Three Gitea workflows: ci.yml (PRs, non-main pushes), publish-snapshot.yml (main -> Gitea under dist-tag @main) and release.yml (tags -> Gitea + npmjs) - Tag-driven releases as <package-dir>-v<version>; the manifest stays the source of truth and release.yml refuses to run if tag and manifest disagree - Every publish is idempotent: each step checks the registry first, so a run that fails on the second registry can simply be re-run - Hard coverage gate (85% branches) shared by CI, the pre-push hook and local runs, since the thresholds live in vitest.config.ts rather than a CI flag - README.PUBLISH.md documents the whole mechanism Toolchain - TypeScript 7 native compiler; drop tsgo and ts-node, use tsx for dev runs - Biome 1.9 -> 2.x, Vitest 1 -> 4, zod 3 -> 4, inquirer 8 -> 14, pnpm 11.17.0 - Replace inquirer-checkbox-plus-prompt, which is peer-capped at inquirer <9, with enquirer's AutoComplete; the CubeSelection contract is unchanged - Stand in for zod 4's removed z.AnyZodObject with a local AnyObjectSchema Repo hygiene - Stop tracking dist/; ignore coverage/, *.tsbuildinfo, .npmrc* and release.json - Drop package-lock.json in favour of pnpm-lock.yaml Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
63 lines
2.9 KiB
Markdown
63 lines
2.9 KiB
Markdown
# ansiblings
|
|
|
|
Infrastructure tooling monorepo: two published CLIs plus the pyinfra "cubes"
|
|
they deploy.
|
|
|
|
| Path | Package | Binary | What it is |
|
|
| ----------------- | ------------------ | -------- | --------------------------------------------------- |
|
|
| `packages/nopy` | `@bitstack/nopy` | `nopy` | interactive pyinfra script management and execution |
|
|
| `packages/keyman` | `@bitstack/keyman` | `keyman` | SSH key management with `age` encryption |
|
|
| `cubes/` | — | — | the deployment units `nopy` runs |
|
|
|
|
```sh
|
|
npm install -g @bitstack/nopy @bitstack/keyman
|
|
```
|
|
|
|
See each package's README for usage, and
|
|
[README.PUBLISH.md](README.PUBLISH.md) for how they get published.
|
|
|
|
## Development
|
|
|
|
Requires Node ≥ 22 (the repo pins 24 in `.nvmrc`) and pnpm — the version is
|
|
pinned by `packageManager`, so `corepack enable` is enough.
|
|
|
|
```sh
|
|
pnpm install
|
|
```
|
|
|
|
| Command | Does |
|
|
| --------------------------- | --------------------------------------------------- |
|
|
| `pnpm run build` | compiles both packages with `tsc` |
|
|
| `pnpm run typecheck` | `tsc --build --noEmit` across the workspace |
|
|
| `pnpm run lint` | Biome check |
|
|
| `pnpm run lint:fix` | Biome check with fixes applied |
|
|
| `pnpm test` | vitest, both packages |
|
|
| `pnpm run test:coverage` | vitest with the coverage gate |
|
|
| `pnpm run coverage:summary` | renders the last coverage run as a Markdown table |
|
|
|
|
`typescript` is on the 7.x native compiler, so `tsc` *is* the fast one — there is
|
|
no separate `tsgo` binary to keep in sync. Each package also has a dev-run script
|
|
(`pnpm --filter @bitstack/nopy run nopy`) that executes the TypeScript sources
|
|
directly through `tsx`.
|
|
|
|
## Git hooks
|
|
|
|
Installed by `simple-git-hooks` on `pnpm install`, configured in the root
|
|
`package.json`:
|
|
|
|
- **pre-commit** — Biome check with fixes, on staged files only, re-staging what
|
|
it fixed. Fast; blocks only on problems it cannot fix itself.
|
|
- **pre-push** — `lint:ci` → `typecheck` → `test:coverage`. This is the same gate
|
|
CI runs, so a push that survives it will not surprise you on the runner.
|
|
|
|
Set `SKIP_SIMPLE_GIT_HOOKS=1` to bypass either one; re-install them after
|
|
changing the config with `pnpm exec simple-git-hooks`.
|
|
|
|
## Coverage
|
|
|
|
Both packages hold a hard **85 % branch** floor, enforced by
|
|
`coverage.thresholds` in their `vitest.config.ts` rather than by a CI-only flag —
|
|
`pnpm run test:coverage` fails the same way locally, in the `pre-push` hook, and
|
|
on the runner. Barrel files and CLI argv wiring are excluded; everything with
|
|
behaviour in it is not.
|