@nurix/etna 0.19.8 → 0.19.9
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/data/harness-index.json
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# pnpm — `@nurix/*` Workspaces: naming, boundaries, and consuming
|
|
2
|
+
|
|
3
|
+
How a `@nurix/*` multi-package repo is **named**, **structured**, and how its published packages are **consumed**. Publishing one — the pipeline, tokens, and the publish workflow — lives in the `nustack-publish` skill, not here. TypeScript language conventions are [`typescript.md`](typescript.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Package naming
|
|
8
|
+
|
|
9
|
+
Every workspace package is scoped to **`@nurix/`**. The segment after the scope encodes **intent** — the dot vs. hyphen is semantic, not cosmetic:
|
|
10
|
+
|
|
11
|
+
| Form | Meaning | Examples |
|
|
12
|
+
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
13
|
+
| `@nurix/workflows-sdk` (hyphen, single segment) | The **published, externally-destined** surface. A clean `@nurix/*` name is a published _contract_ — changing an export or peer dep is a breaking change for consumers outside this repo. | `@nurix/workflows-sdk` |
|
|
14
|
+
| `@nurix/workflows.<name>` (dot separator) | **Internal** to the workflows product — `private: true`, refactor freely, no external consumers. | `@nurix/workflows.agent-core`, `.worker`, `.gateway`, `.secrets`, `.connector`, `.playground`, `.playground-tests` |
|
|
15
|
+
| `@nurix/<name>` (plain, no `workflows` prefix) | Cross-repo **shared libs** owned _elsewhere_ and merely consumed here — never renamed. | `@nurix/contracts`, `@nurix/components` |
|
|
16
|
+
|
|
17
|
+
- The `<name>` segment is always **kebab-case** (`agent-core`, `playground-tests`).
|
|
18
|
+
- The dot is **not** a path separator, so subpath exports still resolve: `@nurix/workflows.agent-core/nodes`.
|
|
19
|
+
- The dot tracks "internal product package," not the `private` flag exactly — `@nurix/workflows.secrets` is `private: false` because it's extraction-bound (slated to move to a sibling repo/namespace), yet still wears the dotted internal name. Today `-sdk` is the only clean published form.
|
|
20
|
+
|
|
21
|
+
**Naming a new package:** internal to this repo? → `@nurix/workflows.<thing>`, `private: true`, kebab-case `<thing>` (the default). Externally consumed contract? → clean `@nurix/<thing>` (rare). Shared lib from another repo? → keep its existing `@nurix/<name>`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. Monorepo & package boundaries
|
|
26
|
+
|
|
27
|
+
One `tsconfig.base.json` at the repo root is the **single owner of TS policy** — the strict set (see [`typescript.md`](typescript.md)), `target`, and any option uniform across packages (here, `module`/`moduleResolution`). Each package's `tsconfig.json` is thin: it `extends` the base, then adds only its own *coordinates* (`rootDir`/`outDir`/`include`) and genuine *environment* overrides (`lib`/`types`/`jsx`, plus `module`/`moduleResolution` when a package's module system genuinely differs — a Worker, browser, or NodeNext package). That is environment, not policy. Never re-declare or weaken a *policy* option locally (no per-package `strict: false`, no widening `noUncheckedIndexedAccess`). A framework that owns its own base (e.g. an Astro app on `astro/tsconfigs/strict`) is the one allowed exception.
|
|
28
|
+
|
|
29
|
+
- **Internal packages are source-first.** A `private: true` workspace package exposes its API through the `exports` field pointing at TypeScript source (`"types"`/`"default"` → `./src/index.ts`) — consumed across the workspace with **no build step**. Prefer the `exports` field; don't add a bare `main`/`module` to new packages. Add one typed subpath per public surface (`"./nodes": { "types": "./src/nodes/index.ts", "default": "./src/nodes/index.ts" }`); consumers import the subpath, **never** a deep relative path into another package's `src/`.
|
|
30
|
+
- **Published packages build to `dist` — never ship raw `src`.** The moment a package crosses a publish boundary (`private: false`), it compiles with `tsc` (`declaration: true`, `declarationMap: true` from the base), ships `files: ["dist"]`, and points `exports`/`types` at `./dist/*` (use `publishConfig.exports` to swap source→dist on publish if the dev entry stays on source). `prepublishOnly` runs the build.
|
|
31
|
+
- **Declare host singletons as `peerDependencies`** on published libraries (`react`, `react-dom`, the framework client) so consumers keep one copy; never bundle them. Apps depend on them directly.
|
|
32
|
+
- **Single-source shared dep versions with pnpm `catalog:`** — `typescript`, `zod`, `vitest`, `react`, type packages. One version per dependency across the workspace so every package's types resolve identically; no per-manifest version drift.
|
|
33
|
+
- **Reach for TS project references only when it hurts** — adopt `references` once the typecheck/build graph is slow enough to feel. Until then, `pnpm -r typecheck` over independent `extends` configs is the correct default.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Consuming `@nurix/*` packages
|
|
38
|
+
|
|
39
|
+
`@nurix/*` packages publish to npm with **`restricted`** access — installing needs read rights to the `nurix` org. (Publishing one is the `nustack-publish` skill.)
|
|
40
|
+
|
|
41
|
+
- **Auth** — `npm login` once (the npm user must be a `nurix` member), **or** drop a read token in `.npmrc` (the only CI option; with it you don't need `npm login`):
|
|
42
|
+
```ini
|
|
43
|
+
@nurix:registry=https://registry.npmjs.org/
|
|
44
|
+
//registry.npmjs.org/:_authToken=${NPM_READ_TOKEN}
|
|
45
|
+
```
|
|
46
|
+
A `403` on install means auth failed — check `npm whoami` (local) or the `NPM_READ_TOKEN` secret (CI). The read token only needs `Read` on the `nurix` scope.
|
|
47
|
+
- **Install** — `npm install @nurix/<name>` (or `pnpm add` / `yarn add`).
|
|
48
|
+
- **Import by subpath, never the barrel** — bundlers tree-shake subpaths reliably; root-barrel imports less so. Available subpaths are the package's `exports` keys.
|
|
49
|
+
```tsx
|
|
50
|
+
import { Button } from "@nurix/components/button";
|
|
51
|
+
import { useMobile } from "@nurix/components/hooks/use-mobile";
|
|
52
|
+
```
|
|
53
|
+
- **Styles** — packages that ship CSS need their stylesheet imported **once** at the app entry: `import "@nurix/components/styles.css";`. Unstyled components are almost always a missing styles import. Tailwind v4 doesn't scan `node_modules`, but the shipped stylesheet is precompiled — no `@source` directive needed unless you consume the source via a workspace link.
|
|
54
|
+
- **CLIs** ship a `bin` — run directly: `npx @nurix/etna@latest` (or `npm install -g`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TypeScript
|
|
2
2
|
|
|
3
|
-
TypeScript conventions. Compiles under `strict: true` and `noUncheckedIndexedAccess: true`.
|
|
3
|
+
TypeScript conventions. Compiles under `strict: true` and `noUncheckedIndexedAccess: true`. Workspace layout and consuming `@nurix/*` packages are [`pnpm.md`](pnpm.md).
|
|
4
4
|
|
|
5
5
|
## Type Safety
|
|
6
6
|
|
|
@@ -18,23 +18,4 @@ Shared libraries (`@nurix/components`, etc.) are generic on purpose — that's w
|
|
|
18
18
|
|
|
19
19
|
Don't repeat `fn<Type>(…)` / `<Comp<Type>>` at every call site — cosmetic only (same safety, same emitted JS).
|
|
20
20
|
|
|
21
|
-
> Monorepo TS policy (`tsconfig.base.json` + thin per-package `extends`, source-first internal packages, `peerDependencies`, pnpm `catalog:`) lives in [`
|
|
22
|
-
|
|
23
|
-
## Consuming `@nurix/*` packages
|
|
24
|
-
|
|
25
|
-
`@nurix/*` packages publish to npm with **`restricted`** access — installing needs read rights to the `nurix` org. (Publishing one is [`nustack.md`](nustack.md) §3.)
|
|
26
|
-
|
|
27
|
-
- **Auth** — `npm login` once (the npm user must be a `nurix` member), **or** drop a read token in `.npmrc` (the only CI option; with it you don't need `npm login`):
|
|
28
|
-
```ini
|
|
29
|
-
@nurix:registry=https://registry.npmjs.org/
|
|
30
|
-
//registry.npmjs.org/:_authToken=${NPM_READ_TOKEN}
|
|
31
|
-
```
|
|
32
|
-
A `403` on install means auth failed — check `npm whoami` (local) or the `NPM_READ_TOKEN` secret (CI). The read token only needs `Read` on the `nurix` scope.
|
|
33
|
-
- **Install** — `npm install @nurix/<name>` (or `pnpm add` / `yarn add`).
|
|
34
|
-
- **Import by subpath, never the barrel** — bundlers tree-shake subpaths reliably; root-barrel imports less so. Available subpaths are the package's `exports` keys.
|
|
35
|
-
```tsx
|
|
36
|
-
import { Button } from "@nurix/components/button";
|
|
37
|
-
import { useMobile } from "@nurix/components/hooks/use-mobile";
|
|
38
|
-
```
|
|
39
|
-
- **Styles** — packages that ship CSS need their stylesheet imported **once** at the app entry: `import "@nurix/components/styles.css";`. Unstyled components are almost always a missing styles import. Tailwind v4 doesn't scan `node_modules`, but the shipped stylesheet is precompiled — no `@source` directive needed unless you consume the source via a workspace link.
|
|
40
|
-
- **CLIs** ship a `bin` — run directly: `npx @nurix/etna@latest` (or `npm install -g`).
|
|
21
|
+
> Monorepo TS policy (`tsconfig.base.json` + thin per-package `extends`, source-first internal packages, `peerDependencies`, pnpm `catalog:`) lives in [`pnpm.md`](pnpm.md) §2 — it travels with package boundaries.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.9",
|
|
4
4
|
"description": "Bootstrap a project with a Nurix harness — copies the harness's CLAUDE.md, skills, agents, rules, and hooks directly into the project from a bundled payload (no marketplace fetch, no network).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
# Nustack — `@nurix/*` Packages: naming, monorepo layout, and publishing
|
|
2
|
-
|
|
3
|
-
How a `@nurix/*` multi-package repo is **named**, **structured**, and **shipped**. For consuming an already-published `@nurix/*` package (auth, install, imports), see the Consuming section of [`typescript.md`](typescript.md).
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Package naming
|
|
8
|
-
|
|
9
|
-
Every workspace package is scoped to **`@nurix/`**. The segment after the scope encodes **intent** — the dot vs. hyphen is semantic, not cosmetic:
|
|
10
|
-
|
|
11
|
-
| Form | Meaning | Examples |
|
|
12
|
-
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
13
|
-
| `@nurix/workflows-sdk` (hyphen, single segment) | The **published, externally-destined** surface. A clean `@nurix/*` name is a published _contract_ — changing an export or peer dep is a breaking change for consumers outside this repo. | `@nurix/workflows-sdk` |
|
|
14
|
-
| `@nurix/workflows.<name>` (dot separator) | **Internal** to the workflows product — `private: true`, refactor freely, no external consumers. | `@nurix/workflows.agent-core`, `.worker`, `.gateway`, `.secrets`, `.connector`, `.playground`, `.playground-tests` |
|
|
15
|
-
| `@nurix/<name>` (plain, no `workflows` prefix) | Cross-repo **shared libs** owned _elsewhere_ and merely consumed here — never renamed. | `@nurix/contracts`, `@nurix/components` |
|
|
16
|
-
|
|
17
|
-
- The `<name>` segment is always **kebab-case** (`agent-core`, `playground-tests`).
|
|
18
|
-
- The dot is **not** a path separator, so subpath exports still resolve: `@nurix/workflows.agent-core/nodes`.
|
|
19
|
-
- The dot tracks "internal product package," not the `private` flag exactly — `@nurix/workflows.secrets` is `private: false` because it's extraction-bound (slated to move to a sibling repo/namespace), yet still wears the dotted internal name. Today `-sdk` is the only clean published form.
|
|
20
|
-
|
|
21
|
-
**Naming a new package:** internal to this repo? → `@nurix/workflows.<thing>`, `private: true`, kebab-case `<thing>` (the default). Externally consumed contract? → clean `@nurix/<thing>` (rare). Shared lib from another repo? → keep its existing `@nurix/<name>`.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 2. Monorepo & package boundaries
|
|
26
|
-
|
|
27
|
-
One `tsconfig.base.json` at the repo root is the **single owner of TS policy** — the strict set (see [`typescript.md`](typescript.md)), `target`, and any option uniform across packages (here, `module`/`moduleResolution`). Each package's `tsconfig.json` is thin: it `extends` the base, then adds only its own *coordinates* (`rootDir`/`outDir`/`include`) and genuine *environment* overrides (`lib`/`types`/`jsx`, plus `module`/`moduleResolution` when a package's module system genuinely differs — a Worker, browser, or NodeNext package). That is environment, not policy. Never re-declare or weaken a *policy* option locally (no per-package `strict: false`, no widening `noUncheckedIndexedAccess`). A framework that owns its own base (e.g. an Astro app on `astro/tsconfigs/strict`) is the one allowed exception.
|
|
28
|
-
|
|
29
|
-
- **Internal packages are source-first.** A `private: true` workspace package exposes its API through the `exports` field pointing at TypeScript source (`"types"`/`"default"` → `./src/index.ts`) — consumed across the workspace with **no build step**. Prefer the `exports` field; don't add a bare `main`/`module` to new packages. Add one typed subpath per public surface (`"./nodes": { "types": "./src/nodes/index.ts", "default": "./src/nodes/index.ts" }`); consumers import the subpath, **never** a deep relative path into another package's `src/`.
|
|
30
|
-
- **Published packages build to `dist` — never ship raw `src`.** The moment a package crosses a publish boundary (`private: false`), it compiles with `tsc` (`declaration: true`, `declarationMap: true` from the base), ships `files: ["dist"]`, and points `exports`/`types` at `./dist/*` (use `publishConfig.exports` to swap source→dist on publish if the dev entry stays on source). `prepublishOnly` runs the build.
|
|
31
|
-
- **Declare host singletons as `peerDependencies`** on published libraries (`react`, `react-dom`, the framework client) so consumers keep one copy; never bundle them. Apps depend on them directly.
|
|
32
|
-
- **Single-source shared dep versions with pnpm `catalog:`** — `typescript`, `zod`, `vitest`, `react`, type packages. One version per dependency across the workspace so every package's types resolve identically; no per-manifest version drift.
|
|
33
|
-
- **Reach for TS project references only when it hurts** — adopt `references` once the typecheck/build graph is slow enough to feel. Until then, `pnpm -r typecheck` over independent `extends` configs is the correct default.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 3. Publishing & the release pipeline
|
|
38
|
-
|
|
39
|
-
`@nurix/*` packages publish to **npmjs.org with `restricted` access** — only npm users with read rights to the `nurix` org can install them. Reference implementations: `~/dev/components` (`@nurix/components`, library) and `~/dev/etna/packages/cli` (`@nurix/etna`, CLI).
|
|
40
|
-
|
|
41
|
-
### 3.1 Prerequisites (one-time, org-wide)
|
|
42
|
-
|
|
43
|
-
1. **npm org `nurix`** exists and you're a member with publish rights — <https://www.npmjs.com/settings/nurix/packages>.
|
|
44
|
-
2. **An npm automation token** with `Read and write` for the `nurix` scope — npm → Generate New Token → Automation.
|
|
45
|
-
3. **The token added as a GitHub Actions secret** named `NPM_PUBLISH_TOKEN` on every publishing repo. `NPM_PUBLISH_TOKEN` is the convention; pick another name only with a strong reason.
|
|
46
|
-
|
|
47
|
-
### 3.2 `package.json` — required fields
|
|
48
|
-
|
|
49
|
-
```jsonc
|
|
50
|
-
{
|
|
51
|
-
"name": "@nurix/<package-name>", // The scope makes it discoverable to org members.
|
|
52
|
-
"version": "0.1.0", // Start at 0.1.0; the workflow bumps from here.
|
|
53
|
-
"private": false, // MUST be false (or omitted). `npm publish` refuses if true.
|
|
54
|
-
"publishConfig": { "access": "restricted" }, // Scoped + private: only org members can install.
|
|
55
|
-
"files": ["dist"] // Whitelist of what ships. Anything outside is excluded.
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
- **`publishConfig.access`** — `"restricted"` (recommended): visible only to `nurix`-org readers. `"public"`: world-readable (free, but only if you mean it). Omitting it on a scoped package defaults to `restricted`; be explicit anyway.
|
|
60
|
-
- **`files`** — without it, npm publishes everything not in `.gitignore`, **including source**. Library → `["dist"]`; CLI (etna) → `["bin/", "data/", "README.md"]`. Don't list `package.json`/`README.md` — npm always includes them.
|
|
61
|
-
- **Build hooks** — `prepack` for build steps that must produce files in `files` (also runs on install-as-git-dep); `prepublishOnly` for publish-only steps. Either alone is fine; `@nurix/components` runs both.
|
|
62
|
-
- **Other useful fields** — `type: "module"`, `engines.node`, `bin` (CLIs), `main`/`module`/`types`/`exports` (libraries), `sideEffects: ["**/*.css"]`, `repository` (with `directory` for monorepos), `license: "UNLICENSED"`.
|
|
63
|
-
|
|
64
|
-
### 3.3 The publish workflow (generic template)
|
|
65
|
-
|
|
66
|
-
The dual-trigger pattern: a push to the default branch auto-ships a patch; a manual dispatch picks minor/major.
|
|
67
|
-
|
|
68
|
-
```yaml
|
|
69
|
-
name: Publish to npm
|
|
70
|
-
on:
|
|
71
|
-
push:
|
|
72
|
-
branches: [dev] # your default branch
|
|
73
|
-
paths: # ONLY paths that change what ships — else every README edit publishes
|
|
74
|
-
- 'src/**'
|
|
75
|
-
- 'scripts/**'
|
|
76
|
-
- 'package.json'
|
|
77
|
-
- 'package-lock.json'
|
|
78
|
-
- '.github/workflows/publish.yml'
|
|
79
|
-
workflow_dispatch:
|
|
80
|
-
inputs:
|
|
81
|
-
bump: { description: 'Version bump', type: choice, options: [patch, minor, major], default: patch }
|
|
82
|
-
permissions: { contents: write } # push the version-bump commit + tag
|
|
83
|
-
concurrency: { group: publish, cancel-in-progress: false } # monorepo: group: publish-<pkg>
|
|
84
|
-
jobs:
|
|
85
|
-
publish:
|
|
86
|
-
runs-on: ubuntu-latest
|
|
87
|
-
steps:
|
|
88
|
-
- uses: actions/checkout@v5
|
|
89
|
-
with: { fetch-depth: 0, token: '${{ secrets.GITHUB_TOKEN }}' }
|
|
90
|
-
- uses: actions/setup-node@v5
|
|
91
|
-
with: { node-version: 22, registry-url: 'https://registry.npmjs.org' } # writes .npmrc using $NODE_AUTH_TOKEN
|
|
92
|
-
- run: npm ci # skip ONLY if the build is pure-Node with no deps (e.g. @nurix/etna)
|
|
93
|
-
- run: |
|
|
94
|
-
git config user.name "github-actions[bot]"
|
|
95
|
-
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
96
|
-
- run: npm version ${{ inputs.bump || 'patch' }} -m "chore: release v%s [skip ci]"
|
|
97
|
-
- run: npm publish # prepublishOnly / prepack runs the build
|
|
98
|
-
env: { NODE_AUTH_TOKEN: '${{ secrets.NPM_PUBLISH_TOKEN }}' }
|
|
99
|
-
- run: git push --follow-tags # pushes the bump commit AND the v<version> tag npm created
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
**Why dual-trigger is safe** — three safeguards prevent an infinite publish loop: (1) `paths:` scopes the push trigger to artifact-affecting files; (2) `[skip ci]` in the bump commit makes GitHub skip the workflow that bump would otherwise re-trigger; (3) `concurrency: cancel-in-progress: false` queues near-simultaneous merges instead of racing for a version number.
|
|
103
|
-
|
|
104
|
-
**`registry-url` is load-bearing** — without `registry-url: https://registry.npmjs.org` on `setup-node`, it never writes the `.npmrc` line that uses `$NODE_AUTH_TOKEN`, and the publish falls back to anonymous auth and fails.
|
|
105
|
-
|
|
106
|
-
### 3.4 The three ways to ship
|
|
107
|
-
|
|
108
|
-
- **A. Auto on merge (common).** Land on the default branch; if a `paths:`-filtered file changed, the workflow fires and ships a patch.
|
|
109
|
-
- **B. Manual dispatch (minor/major).** **Actions → Publish to npm → Run workflow**, pick `bump = minor|major`.
|
|
110
|
-
- **C. Local (CI down / one-off):** `npm version <patch|minor|major>` → `npm publish` → `git push --follow-tags`.
|
|
111
|
-
|
|
112
|
-
Local auth uses two tokens, two homes: a **read** token in `~/.npmrc` (`//registry.npmjs.org/:_authToken=…`) for `npm install`, and `NPM_PUBLISH_TOKEN` as an env var (sourced from `~/.zsh_secrets` or equivalent, **not** in `.npmrc` or the repo) for `npm publish`.
|
|
113
|
-
|
|
114
|
-
> **Agent guard — if `NPM_PUBLISH_TOKEN` isn't in the environment, do not work around it.** No `npm login` to swap the user's auth, no rewriting `~/.npmrc`, no substituting the read token (it lacks publish rights → `403`), no `--registry` overrides, no temp-file token. Instead **stop and report**: "This repo can't publish locally — `NPM_PUBLISH_TOKEN` isn't set. Source `~/.zsh_secrets` (or wherever you keep it) and re-run, or trigger the CI workflow." Some users publish exclusively from CI — that's the default path for a reason.
|
|
115
|
-
|
|
116
|
-
Verify after any flow: `https://www.npmjs.com/package/@nurix/<name>` and a clean-dir `npx @nurix/<name>@latest`.
|
|
117
|
-
|
|
118
|
-
### 3.5 Monorepo deviations
|
|
119
|
-
|
|
120
|
-
When the package lives in `packages/<pkg>/` of a multi-package repo:
|
|
121
|
-
|
|
122
|
-
- **`working-directory: packages/<pkg>`** on the bump and publish steps so they operate on the right `package.json`.
|
|
123
|
-
- **Scoped concurrency** — `group: publish-<pkg>` lets sibling packages publish in parallel.
|
|
124
|
-
- **Tag prefix — only with multiple tagging packages.** `npm version --tag-version-prefix="<pkg>-v"` (→ `<pkg>-v0.2.0`) is worth it only when more than one package cuts release tags, so they don't collide. A single publishable package (etna's case, even though it's laid out as a monorepo) uses plain `v0.2.0`.
|
|
125
|
-
|
|
126
|
-
A repo with one publishable package only needs `working-directory`; skip the prefix, and concurrency scoping is optional.
|
|
127
|
-
|
|
128
|
-
### 3.6 Common pitfalls
|
|
129
|
-
|
|
130
|
-
- **402 Payment Required** — `access: "public"` on an org without a plan for free public scoped packages. Use `"restricted"` (or upgrade the plan).
|
|
131
|
-
- **403 Forbidden** — `NPM_PUBLISH_TOKEN` missing/wrong, or its user lacks `nurix` write access, or it's a read-only (not Automation) token.
|
|
132
|
-
- **"Cannot publish over previously published version x.y.z"** — a bump ran but publish failed and was re-run without rebasing. `git reset` the bump and let CI re-bump, or `npm version patch && git push --follow-tags && npm publish`.
|
|
133
|
-
- **Publish succeeds but `npx @nurix/foo` is "command not found"** — no `bin` field, or `bin` points outside `files`, or the script is missing its `#!/usr/bin/env node` shebang.
|
|
134
|
-
- **"Git working directory not clean" on `npm version`** — the checkout has untracked/modified files; build only into `.gitignore`d paths (the components repo builds into `dist/`).
|
|
135
|
-
- **Published tarball contains source** — missing `files` in `package.json`. Add `["dist"]` and republish.
|
|
136
|
-
- **Auto-publish fires too often** — no `paths:` filter or one that's too broad. Tighten it to artifact-affecting files, or drop the push trigger for `workflow_dispatch`-only.
|
|
137
|
-
- **Workflow loops forever** — the bump commit lacks `[skip ci]`. Invoke `npm version` with `-m "chore: release v%s [skip ci]"`.
|
|
138
|
-
- **A normal commit silently skips its own push** — the inverse trap. GitHub scans the head commit's **whole message** (subject _and_ body) for skip directives (`[skip ci]`, `[ci skip]`, `[no ci]`, `[skip actions]`, `***NO_CI***`). If any hand-written commit merely _mentions_ the literal token in prose, the entire push is skipped and the publish never fires (symptom: branch moved, paths matched, Actions on — yet zero runs for the SHA). Never write the literal token in a commit message or PR body unless you mean it; to ship a push that carried it by accident, re-trigger via **Run workflow** / `gh workflow run … --ref dev`.
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## 4. Quick checklist for a new `@nurix/*` package
|
|
143
|
-
|
|
144
|
-
- [ ] `package.json`: `name: "@nurix/X"`, `version: "0.1.0"`, `private: false`, `publishConfig.access: "restricted"`, `files: [...]`
|
|
145
|
-
- [ ] Build step wired into `prepack` (or `prepublishOnly`)
|
|
146
|
-
- [ ] Name follows §1; if it's a workspace member, boundaries follow §2
|
|
147
|
-
- [ ] `.github/workflows/publish.yml` from §3.3
|
|
148
|
-
- [ ] `NPM_PUBLISH_TOKEN` secret added to the repo
|
|
149
|
-
- [ ] First publish from local (`npm publish`) to verify the pipeline, then a no-op commit to verify CI
|
|
150
|
-
- [ ] README notes the `@nurix` scope so consumers know they need org access
|