Skip to content

feat: monorepo#3

Merged
askuzminov merged 1 commit into
masterfrom
feature/monorepo
Apr 12, 2026
Merged

feat: monorepo#3
askuzminov merged 1 commit into
masterfrom
feature/monorepo

Conversation

@askuzminov

Copy link
Copy Markdown
Owner

What's new

Zero dependencies — for real

  • Removed semver package — implemented own inc() + satisfies() with 595 cross-validated tests against original
  • Removed npm version command — direct file writing for package.json, package-lock.json (v1/v2/v3), npm-shrinkwrap.json
  • Removed eslint (8 packages) — migrated to oxlint with type-aware linting via tsgolint
  • Removed ts-node — using tsx

Workspace / Monorepo support

  • Auto-detect workspaces from package.json (npm, yarn, bun) and pnpm-workspace.yaml (pnpm)
  • Independent versioning — each package bumped based on its own changes
  • Topological sort — dependencies released before dependents
  • Per-package CHANGELOG.md, git tags (@org/pkg@1.2.0), GitHub/GitLab releases
  • Single git commit for all version bumps
  • Cross-package dependency cascade with 3 modes:
    • --cascade full (default) — always bump + publish dependents
    • --cascade lazy — bump only when version range doesn't cover new version
    • --cascade none — only release packages with actual code changes
  • Smart range handling: preserves ^, ~, exact, >= prefixes
  • workspace:* / workspace:^ / workspace:~ protocol support
  • --workspace to select specific packages, --contents to publish from subdirectory

Bun / pnpm / yarn support

  • Auto-detect package manager by lockfile for publish
  • Registry per PM: --registry (npm/pnpm/bun), YARN_REGISTRY + YARN_NPM_REGISTRY_SERVER (yarn)
  • Multiple registries in one run — publish-github publish-npmjs --publish-custom URL
  • Lifecycle scripts (preversion, version, postversion) run via shell directly — no dependency on any PM
  • npm_package_version env variable available in scripts

New features

  • dry-run — preview what would happen without making changes (shows changed vs skipped packages)
  • verbose — detailed output with commits, tags, changelog preview
  • provenance — npm provenance attestation support
  • Config in package.json"simple-release": { "contents": "dist", "cascade": "full" }
  • GitHub Action — uses: askuzminov/simple-release@v1
  • OIDC Trusted Publishing support for npmjs.org (no tokens needed)
  • GitHub App support for protected branch bypass

Bug fixes

  • getDate() now returns YYYY-MM-DD (zero-padded) instead of YYYY-M-D
  • sp() handles ENOENT errors (command not found)
  • GitLab release logs correctly say "Gitlab" instead of "Github"
  • arg() no longer reads out of bounds for trailing options
  • markdown.ts last() safe on empty arrays

Robustness

  • Git tag already exists — skip instead of crash
  • No commits in repo — fallback to empty tree hash
  • Detached HEAD — warning before git operations
  • Partial publish failure — continue all registries, report failures, exit 1
  • Preversion script modifies package.json — re-read after hook
  • Symlink recursion in workspace discovery — cycle detection via realpathSync
  • BOM in package.json — parseJSON() strips UTF-8 BOM
  • Windows support — cmd /c for lifecycle scripts, NUL for empty tree hash

CI / Auth

  • Updated workflow: actions/checkout@v4, actions/setup-node@v4, Node 22
  • GitHub App setup guide for protected branches (no service accounts needed)
  • OIDC Trusted Publishing guide for npmjs.org (no token rotation)
  • npm 2FA / passkey documentation

Tests

  • 906 tests (was 0), 0 lint errors, 0 warnings
  • Unit tests: semver, workspace discovery, topological sort, cascade deps, satisfies, lifecycle scripts, CLI flags, changelog, config parsing, extractPrefix, resolveWorkspace
  • Integration tests: real git repo — getHash, getTag, getCommitsRaw, parseCommits, writeGit, writeWorkspaceGit, detectPackageChanges, checkBranch, sp(), parseJSON, full single-package flow
  • Cross-validated: 595 tests comparing our inc() against original semver package

Documentation

  • Complete README rewrite with comparison table, cascade mode guide, decision tree
  • GitHub App setup guide, OIDC Trusted Publishing guide
  • Migration guide from Lerna
  • Edge cases, environment variables, generated CHANGELOG example
  • npm 2FA / passkey / security key documentation

## What's new

### Zero dependencies — for real

- Removed `semver` package — implemented own `inc()` + `satisfies()` with 595 cross-validated tests against original
- Removed `npm version` command — direct file writing for `package.json`, `package-lock.json` (v1/v2/v3), `npm-shrinkwrap.json`
- Removed `eslint` (8 packages) — migrated to `oxlint` with type-aware linting via `tsgolint`
- Removed `ts-node` — using `tsx`

### Workspace / Monorepo support

- Auto-detect workspaces from `package.json` (npm, yarn, bun) and `pnpm-workspace.yaml` (pnpm)
- Independent versioning — each package bumped based on its own changes
- Topological sort — dependencies released before dependents
- Per-package CHANGELOG.md, git tags (`@org/pkg@1.2.0`), GitHub/GitLab releases
- Single git commit for all version bumps
- Cross-package dependency cascade with 3 modes:
  - `--cascade full` (default) — always bump + publish dependents
  - `--cascade lazy` — bump only when version range doesn't cover new version
  - `--cascade none` — only release packages with actual code changes
- Smart range handling: preserves `^`, `~`, exact, `>=` prefixes
- `workspace:*` / `workspace:^` / `workspace:~` protocol support
- `--workspace` to select specific packages, `--contents` to publish from subdirectory

### Bun / pnpm / yarn support

- Auto-detect package manager by lockfile for publish
- Registry per PM: `--registry` (npm/pnpm/bun), `YARN_REGISTRY` + `YARN_NPM_REGISTRY_SERVER` (yarn)
- Multiple registries in one run — `publish-github publish-npmjs --publish-custom URL`
- Lifecycle scripts (`preversion`, `version`, `postversion`) run via shell directly — no dependency on any PM
- `npm_package_version` env variable available in scripts

### New features

- `dry-run` — preview what would happen without making changes (shows changed vs skipped packages)
- `verbose` — detailed output with commits, tags, changelog preview
- `provenance` — npm provenance attestation support
- Config in `package.json` — `"simple-release": { "contents": "dist", "cascade": "full" }`
- GitHub Action — `uses: askuzminov/simple-release@v1`
- OIDC Trusted Publishing support for npmjs.org (no tokens needed)
- GitHub App support for protected branch bypass

### Bug fixes

- `getDate()` now returns `YYYY-MM-DD` (zero-padded) instead of `YYYY-M-D`
- `sp()` handles ENOENT errors (command not found)
- GitLab release logs correctly say "Gitlab" instead of "Github"
- `arg()` no longer reads out of bounds for trailing options
- `markdown.ts` `last()` safe on empty arrays

### Robustness

- Git tag already exists — skip instead of crash
- No commits in repo — fallback to empty tree hash
- Detached HEAD — warning before git operations
- Partial publish failure — continue all registries, report failures, exit 1
- Preversion script modifies package.json — re-read after hook
- Symlink recursion in workspace discovery — cycle detection via `realpathSync`
- BOM in package.json — `parseJSON()` strips UTF-8 BOM
- Windows support — `cmd /c` for lifecycle scripts, `NUL` for empty tree hash

### CI / Auth

- Updated workflow: `actions/checkout@v4`, `actions/setup-node@v4`, Node 22
- GitHub App setup guide for protected branches (no service accounts needed)
- OIDC Trusted Publishing guide for npmjs.org (no token rotation)
- npm 2FA / passkey documentation

### Tests

- 906 tests (was 0), 0 lint errors, 0 warnings
- Unit tests: semver, workspace discovery, topological sort, cascade deps, satisfies, lifecycle scripts, CLI flags, changelog, config parsing, extractPrefix, resolveWorkspace
- Integration tests: real git repo — getHash, getTag, getCommitsRaw, parseCommits, writeGit, writeWorkspaceGit, detectPackageChanges, checkBranch, sp(), parseJSON, full single-package flow
- Cross-validated: 595 tests comparing our `inc()` against original `semver` package

### Documentation

- Complete README rewrite with comparison table, cascade mode guide, decision tree
- GitHub App setup guide, OIDC Trusted Publishing guide
- Migration guide from Lerna
- Edge cases, environment variables, generated CHANGELOG example
- npm 2FA / passkey / security key documentation
@askuzminov askuzminov merged commit 269b425 into master Apr 12, 2026
2 checks passed
@askuzminov askuzminov deleted the feature/monorepo branch April 12, 2026 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant