# 208 Fn 916 82f6f3c9

> fn-9.16 CI/CD workflow

- Skill: `tools-only/208-fn-916-82f6f3c9` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/208-fn-916-82f6f3c9`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/208-fn-916-82f6f3c9/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/208-fn-916-82f6f3c9

---

# fn-9.16 CI/CD workflow

## Description

Create GitHub Actions workflow for CI/CD and npm publishing.

### File

`.github/workflows/publish-tui.yml`

### Triggers

- Push to `tui-v*` tags
- Manual workflow_dispatch

### Packaging strategy (follows gno pattern)

Publish TypeScript source directly - Bun executes .ts natively.

**package.json fields:**
```json
{
  "bin": { "flow-next-tui": "src/index.ts", "fntui": "src/index.ts" },
  "files": ["src"],
  "engines": { "bun": ">=1.3.0" }
}
```

**Shebang required**: `src/index.ts` must start with `#!/usr/bin/env bun` for global installs to work. npm creates symlinks to the bin target; the shebang tells the OS to use bun.

### Jobs

1. **test** (matrix: ubuntu, macos)
   - Setup Bun
   - `bun install --frozen-lockfile`
   - `bun run lint:check`
   - `bun test`

2. **pack-test** (needs test, ubuntu only - Windows best-effort)
   - `npm pack`
   - `npm install -g ./gmickel-flow-next-tui-*.tgz`
   - `flow-next-tui --version`
   - `flow-next-tui --help`
   - `fntui --help` (verify both aliases)

3. **publish** (needs pack-test)
   - Setup Node 24+ (for npm OIDC)
   - Setup Bun
   - `npm publish --provenance --access public`

### OIDC publishing (trusted publishing - no NPM_TOKEN needed)

**Benefits:**
- No NPM_TOKEN secret to rotate/leak
- Provenance attestation (cryptographic proof of build origin)
- Can't be stolen from compromised CI logs

**npm side setup (one-time):**
1. Go to https://www.npmjs.com/package/@gmickel/flow-next-tui/access
2. Scroll to "Publishing access" → "Add trusted publisher"
3. Fill in:
   - Owner: `gmickel`
   - Repository: `gmickel-claude-marketplace`
   - Workflow: `publish-tui.yml` (exact filename, case-sensitive)
   - Environment: leave blank

**Workflow requirements:**

```yaml
permissions:
  id-token: write   # CRITICAL: lets GH generate OIDC token
  contents: read

steps:
  - uses: actions/checkout@v4

  # Node 24+ required (npm >= 11.5.1 for OIDC)
  - uses: actions/setup-node@v4
    with:
      node-version: "24"
      registry-url: "https://registry.npmjs.org"  # REQUIRED for npm auth

  - run: npm publish --provenance --access public
    # NO NODE_AUTH_TOKEN or NPM_TOKEN needed
```

**Key requirements:**
| Requirement | Why |
|-------------|-----|
| `id-token: write` permission | Lets GH generate OIDC token |
| `registry-url` in setup-node | Required for npm auth |
| Node.js 24+ | npm 11.5.1+ has OIDC support |
| `--provenance` flag | Enables attestation |
| Workflow filename must match | npm checks exact match (case-sensitive) |

**Troubleshooting:**
- "No matching trusted publisher found" → check workflow filename matches exactly
- "id-token permission not set" → add `permissions.id-token: write` to job
- "npm version too old" → need npm >= 11.5.1 (Node 24+)
## Acceptance
- [ ] Workflow triggers on tui-v* tags
- [ ] Tests run on ubuntu and macos
- [ ] Lint check passes
- [ ] npm publish with provenance
- [ ] Tarball contains src/index.ts (not dist)
- [ ] Installed package runs: `flow-next-tui --help`
- [ ] Manual trigger works
## Done summary
- Created .github/workflows/publish-tui.yml with:
  - Trigger: push to main (flow-next-tui/**) + workflow_dispatch
  - Test job: matrix ubuntu/macos, bun install, lint, test
  - Pack-test job: npm pack, global install, verify CLI
  - Publish job: version detection (local vs npm), OIDC publishing
- Created scripts/bump.sh for semver versioning (patch/minor/major)
- Applied oxfmt formatting to all source files

Modified from spec: triggers on main push with version detection instead of tags.

Why:
- Version detection avoids manual tag management
- OIDC eliminates NPM_TOKEN secret rotation/leak risk

Verification:
- bun test (379 pass)
- bun run lint:check (pass)
## Evidence
- Commits: d0d735be5a782b3f22180cc8998598bfe986099a
- Tests: bun test, bun run lint:check
- PRs:
