rman 0.37.4 → 1.0.1
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/README.md +364 -21
- package/cli.d.ts +1 -0
- package/cli.js +52 -28
- package/commands/build.command.d.ts +3 -0
- package/commands/build.command.js +14 -0
- package/commands/changed.command.d.ts +3 -0
- package/commands/changed.command.js +29 -0
- package/commands/changelog.command.d.ts +3 -0
- package/commands/changelog.command.js +63 -0
- package/commands/ci.command.d.ts +3 -0
- package/commands/ci.command.js +30 -0
- package/commands/clean.command.d.ts +3 -0
- package/commands/clean.command.js +36 -0
- package/commands/diff.command.d.ts +3 -0
- package/commands/diff.command.js +51 -0
- package/commands/exec.command.d.ts +3 -0
- package/commands/exec.command.js +83 -0
- package/commands/import.command.d.ts +3 -0
- package/commands/import.command.js +27 -0
- package/commands/info.command.d.ts +3 -0
- package/commands/info.command.js +61 -0
- package/commands/list.command.d.ts +3 -0
- package/commands/list.command.js +113 -0
- package/commands/publish.command.d.ts +3 -0
- package/commands/publish.command.js +147 -0
- package/commands/run.command.d.ts +6 -0
- package/commands/run.command.js +80 -0
- package/commands/test.command.d.ts +3 -0
- package/commands/test.command.js +14 -0
- package/commands/version.command.d.ts +3 -0
- package/commands/version.command.js +125 -0
- package/constants.js +1 -1
- package/core/config.d.ts +13 -0
- package/core/config.js +61 -0
- package/core/package.d.ts +2 -0
- package/core/package.js +2 -0
- package/core/repository.d.ts +36 -3
- package/core/repository.js +90 -45
- package/index.d.ts +17 -1
- package/index.js +15 -1
- package/package.json +11 -8
- package/services/changelog.service.d.ts +99 -0
- package/services/changelog.service.js +272 -0
- package/services/ci.service.d.ts +40 -0
- package/services/ci.service.js +204 -0
- package/services/clean.service.d.ts +42 -0
- package/services/clean.service.js +226 -0
- package/services/exec.service.d.ts +35 -0
- package/services/exec.service.js +114 -0
- package/services/import.service.d.ts +30 -0
- package/services/import.service.js +84 -0
- package/services/list.service.d.ts +27 -0
- package/services/list.service.js +25 -0
- package/services/publish.service.d.ts +79 -0
- package/services/publish.service.js +199 -0
- package/services/run.service.d.ts +99 -0
- package/services/run.service.js +432 -0
- package/services/system-info.d.ts +16 -0
- package/services/system-info.js +25 -0
- package/services/version.service.d.ts +95 -0
- package/services/version.service.js +450 -0
- package/services.d.ts +10 -0
- package/services.js +10 -0
- package/utils/branch-guard.d.ts +25 -0
- package/utils/branch-guard.js +61 -0
- package/utils/change-hash.d.ts +55 -0
- package/utils/change-hash.js +80 -0
- package/utils/conventional-commits.d.ts +39 -0
- package/utils/conventional-commits.js +43 -0
- package/utils/exec.d.ts +5 -6
- package/utils/exec.js +46 -60
- package/utils/git.d.ts +86 -0
- package/utils/git.js +276 -0
- package/utils/live-region.d.ts +16 -0
- package/utils/live-region.js +59 -0
- package/utils/logger.d.ts +24 -0
- package/utils/logger.js +39 -0
- package/utils/npm-run-path.d.ts +1 -1
- package/utils/npm-run-path.js +10 -10
- package/utils/package-filter.d.ts +32 -0
- package/utils/package-filter.js +73 -0
- package/utils/progress-panel.d.ts +59 -0
- package/utils/progress-panel.js +149 -0
- package/utils/workspace-range.d.ts +17 -0
- package/utils/workspace-range.js +28 -0
- package/bin/rman.mjs +0 -4
- package/commands/build-command.d.ts +0 -11
- package/commands/build-command.js +0 -24
- package/commands/changed-command.d.ts +0 -16
- package/commands/changed-command.js +0 -32
- package/commands/ci-command.d.ts +0 -24
- package/commands/ci-command.js +0 -68
- package/commands/execute-command.d.ts +0 -19
- package/commands/execute-command.js +0 -72
- package/commands/info-command.d.ts +0 -10
- package/commands/info-command.js +0 -55
- package/commands/list-command.d.ts +0 -38
- package/commands/list-command.js +0 -134
- package/commands/multi-task-command.d.ts +0 -22
- package/commands/multi-task-command.js +0 -65
- package/commands/publish-command.d.ts +0 -24
- package/commands/publish-command.js +0 -131
- package/commands/run-command.d.ts +0 -28
- package/commands/run-command.js +0 -131
- package/commands/version-command.d.ts +0 -25
- package/commands/version-command.js +0 -195
- package/core/command.d.ts +0 -35
- package/core/command.js +0 -116
- package/core/constants.d.ts +0 -1
- package/core/constants.js +0 -2
- package/core/logger.d.ts +0 -12
- package/core/logger.js +0 -2
- package/utils/file-utils.d.ts +0 -4
- package/utils/file-utils.js +0 -28
- package/utils/git-utils.d.ts +0 -25
- package/utils/git-utils.js +0 -66
- package/utils/npm-utils.d.ts +0 -11
- package/utils/npm-utils.js +0 -33
- package/utils/package-not-found-error.d.ts +0 -2
- package/utils/package-not-found-error.js +0 -2
package/README.md
CHANGED
|
@@ -1,33 +1,376 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# rman
|
|
2
|
+
|
|
3
3
|
[![NPM Version][npm-image]][npm-url]
|
|
4
4
|
[![NPM Downloads][downloads-image]][downloads-url]
|
|
5
|
-
[![
|
|
6
|
-
[![
|
|
5
|
+
[![Quality Check][qc-image]][qc-url]
|
|
6
|
+
[![License][license-image]][license-url]
|
|
7
|
+
|
|
8
|
+
**rman** is a monorepo management CLI: a self-contained alternative to reaching for Lerna,
|
|
9
|
+
Changesets, and a handful of shell scripts glued together. One tool for running scripts across
|
|
10
|
+
packages, computing semantic version bumps from your commit history, publishing, changelogs,
|
|
11
|
+
importing external repos with history intact, and more - all driven by a single, cascading
|
|
12
|
+
`.rmanrc`/`.rman.yml` config.
|
|
13
|
+
|
|
14
|
+
Every command is also available as a **programmatic API** - see [docs/api.md](docs/api.md) if you
|
|
15
|
+
want to call `rman`'s logic directly from a Node.js script instead of shelling out to the CLI.
|
|
16
|
+
|
|
17
|
+
## Table of contents
|
|
18
|
+
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Quick start](#quick-start)
|
|
21
|
+
- [Commands](#commands)
|
|
22
|
+
- [Configuration](#configuration)
|
|
23
|
+
- [Programmatic API](#programmatic-api)
|
|
24
|
+
- [Node compatibility](#node-compatibility)
|
|
25
|
+
- [License](#license)
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install --save-dev rman
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or run it without installing, via `npx`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx rman list
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`rman` requires **Node.js >= 20**.
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
`rman` auto-detects your repository layout - point it at a directory containing a `package.json`
|
|
44
|
+
with a `workspaces` array (npm/yarn/pnpm-style) and every matched package becomes available to
|
|
45
|
+
every command:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
// package.json (repository root)
|
|
49
|
+
{
|
|
50
|
+
"name": "my-monorepo",
|
|
51
|
+
"private": true,
|
|
52
|
+
"workspaces": ["packages/*"]
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# See what's in the repository
|
|
58
|
+
rman list
|
|
59
|
+
|
|
60
|
+
# Run "build" in every package, dependencies first
|
|
61
|
+
rman build
|
|
62
|
+
|
|
63
|
+
# See what the next release would look like, without changing anything
|
|
64
|
+
rman version
|
|
65
|
+
|
|
66
|
+
# Apply it: bump versions, write CHANGELOG.md, commit, tag
|
|
67
|
+
rman version --changelog
|
|
68
|
+
|
|
69
|
+
# Publish everything that isn't already on the registry
|
|
70
|
+
rman publish
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Run any command with `--help` for its full option list (`rman version --help`, `rman run --help`, ...).
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
76
|
+
|
|
77
|
+
The summaries and examples below cover the common cases. For the full option list, defaults, and
|
|
78
|
+
worked examples of every single command, see **[docs/cli.md](docs/cli.md)**.
|
|
79
|
+
|
|
80
|
+
| Command | Purpose |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| [`list` (`ls`)](#rman-list) | Lists packages in the repository. |
|
|
83
|
+
| [`info`](#rman-info) | Prints local environment and repository information. |
|
|
84
|
+
| [`run <script>`](#rman-run-script) | Runs an npm script in each package. |
|
|
85
|
+
| [`build`](#rman-build) | Alias for `run build`. |
|
|
86
|
+
| [`test`](#rman-test) | Alias for `run test`. |
|
|
87
|
+
| [`exec <command..>`](#rman-exec-command) | Runs an arbitrary shell command in each package. |
|
|
88
|
+
| [`ci`](#rman-ci) | Deletes `node_modules`/lockfiles everywhere, then reinstalls from scratch. |
|
|
89
|
+
| [`clean`](#rman-clean) | Removes compiled TypeScript output and configured extra files/dirs. |
|
|
90
|
+
| [`changed`](#rman-changed) | Shows which packages the next `version` run would bump. |
|
|
91
|
+
| [`diff [package]`](#rman-diff-package) | Shows the git diff since a package's (or the repo's) last release tag. |
|
|
92
|
+
| [`changelog`](#rman-changelog) | Generates a changelog per package from unreleased commits. |
|
|
93
|
+
| [`version [bump]`](#rman-version-bump) | Bumps versions of changed packages (and their dependents). |
|
|
94
|
+
| [`publish`](#rman-publish) | Publishes every non-private package not already on the registry. |
|
|
95
|
+
| [`import <path>`](#rman-import-path) | Imports an external git repository as a new package, with history. |
|
|
96
|
+
|
|
97
|
+
Options shared across several commands:
|
|
98
|
+
|
|
99
|
+
- **Package filtering** (`list`, `run`/`build`/`test`, `exec`, `ci`, `clean`, `version`, `publish`,
|
|
100
|
+
`changelog`): `--scope <glob>`, `--ignore <glob>`, `--deps`, `--dependents` - see
|
|
101
|
+
[Package filtering](docs/api.md#package-filtering-scopeignoredepsdependents) for the full
|
|
102
|
+
semantics.
|
|
103
|
+
- **Branch guard** (every command that mutates state or runs scripts - `run`/`build`/`test`,
|
|
104
|
+
`exec`, `ci`, `clean`, `version`, `publish`): `--allow-branch <glob>`, `--ignore-branch <glob>` -
|
|
105
|
+
refuses to run unless (or if) the current git branch matches, the same idea as GitHub Actions'
|
|
106
|
+
own `branches`/`branches-ignore` workflow filters.
|
|
107
|
+
|
|
108
|
+
### `rman list`
|
|
109
|
+
|
|
110
|
+
Lists packages in the repository (alias: `ls`).
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
rman list # table: Package / Version / Private / Changed / Path
|
|
114
|
+
rman ls --short # just the bare package names
|
|
115
|
+
rman list --json # full detail as JSON
|
|
116
|
+
rman list --parseable # location::name::version::PRIVATE::STATUS lines, for scripting
|
|
117
|
+
rman list --toposort # dependencies before dependents, instead of directory order
|
|
118
|
+
rman list --graph # dependency graph as a JSON adjacency list
|
|
119
|
+
rman list --changed # only packages changed since the last publish
|
|
120
|
+
rman list --changed-since HEAD~5
|
|
121
|
+
rman list --scope '@myorg/*' --ignore '*-internal'
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `rman info`
|
|
125
|
+
|
|
126
|
+
Prints local environment (OS/CPU/memory, Node/npm/Yarn versions, git) and repository information.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
rman info
|
|
130
|
+
rman info --json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `rman run <script>`
|
|
134
|
+
|
|
135
|
+
Runs an npm script in each package, in dependency order by default.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
rman run build
|
|
139
|
+
rman run lint --topo=false # independent packages, alphabetical order, no dependency waiting
|
|
140
|
+
rman run test --changed # only in packages changed since the last publish
|
|
141
|
+
rman run build --changed-since v1.2.0
|
|
142
|
+
rman run build --parallel 4 # at most 4 packages at once
|
|
143
|
+
rman run build --parallel false # serially, one at a time
|
|
144
|
+
rman run build --bail=false # don't stop the whole batch on one package's failure
|
|
145
|
+
rman run build --scope pkg-a --deps # pkg-a plus everything it depends on
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Per-package/script behavior (pre/post hooks, `if` conditions, skip, concurrency, ...) is
|
|
149
|
+
configurable via `.rmanrc run.<script>.*` - see [Configuration](#configuration) below and the full
|
|
150
|
+
writeup in [docs/api.md](docs/api.md#runservice).
|
|
151
|
+
|
|
152
|
+
### `rman build`
|
|
153
|
+
|
|
154
|
+
Alias for `rman run build`.
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
rman build
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `rman test`
|
|
161
|
+
|
|
162
|
+
Alias for `rman run test`.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
rman test
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `rman exec <command..>`
|
|
169
|
+
|
|
170
|
+
Runs an arbitrary shell command in each package - unlike `run`, it isn't tied to any npm script.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
rman exec rm -rf dist
|
|
174
|
+
rman exec -- eslint --fix # "--" needed only if the command shares a flag name with exec's own
|
|
175
|
+
rman exec --scope pkg-a -- ls -la
|
|
176
|
+
rman exec --topo=false pwd # every package independently, alphabetical order
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### `rman ci`
|
|
180
|
+
|
|
181
|
+
Deletes `node_modules` and any lockfile in every package (or runs the package's own `"ci"` script
|
|
182
|
+
instead, if it defines one), then installs once at the root.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
rman ci
|
|
186
|
+
rman ci --package-manager pnpm
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### `rman clean`
|
|
190
|
+
|
|
191
|
+
Removes compiled TypeScript output (`.js`/`.js.map`/`.d.ts` under `src`/`test`, plus any
|
|
192
|
+
`*.tsbuildinfo`) and whatever `.rmanrc clean.include`/`clean.exclude` configures. Never touches
|
|
193
|
+
`node_modules` - that's `ci`'s job.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
rman clean
|
|
197
|
+
rman clean --dry-run # preview what would be removed
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### `rman changed`
|
|
201
|
+
|
|
202
|
+
Shows which packages the next `rman version` run would bump, without changing anything.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
rman changed
|
|
206
|
+
rman changed --json
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### `rman diff [package]`
|
|
210
|
+
|
|
211
|
+
Shows the git diff since a package's (or the whole repository's) last release tag.
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
rman diff # since the repository's own last tag
|
|
215
|
+
rman diff pkg-a # since pkg-a's own last tag, scoped to its directory
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### `rman changelog`
|
|
219
|
+
|
|
220
|
+
Generates a changelog per package from unreleased commits, grouped into ✨ Features / 🐛 Bug Fixes
|
|
221
|
+
/ 🔧 Other Changes.
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
rman changelog # auto-detects each package's last published npm version
|
|
225
|
+
rman changelog --from a1b2c3d # since a specific commit, for every package
|
|
226
|
+
rman changelog --write # prepend into each package's own CHANGELOG.md
|
|
227
|
+
rman changelog --write --file-path docs/CHANGELOG.md
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### `rman version [bump]`
|
|
231
|
+
|
|
232
|
+
Bumps versions of changed packages (and their in-group dependents), grouped via `.rmanrc "group"`.
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
rman version # auto-detect severity from commits, preview only - writes nothing
|
|
236
|
+
rman version --interactive # preview, then ask for confirmation either way
|
|
237
|
+
rman version patch # apply a patch bump to every changed package/group, immediately
|
|
238
|
+
rman version minor
|
|
239
|
+
rman version major
|
|
240
|
+
rman version 2.0.0-rc.1 # an explicit semver version, applied verbatim
|
|
241
|
+
rman version minor --preid beta # 1.2.3 -> 1.3.0-beta.0 (run again with --preid beta to increment it)
|
|
242
|
+
rman version --changelog # also write/fold in each bumped package's CHANGELOG.md
|
|
243
|
+
rman version patch --push # commit, tag, and push in one go
|
|
244
|
+
rman version patch --message "chore(release): {version}"
|
|
245
|
+
rman version --ignore-dirty # exclude dirty packages instead of aborting the whole run
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Severity, when not given explicitly, is auto-detected per package/group from
|
|
249
|
+
[Conventional Commits](https://www.conventionalcommits.org/) since that group's last release tag -
|
|
250
|
+
`fix:` → patch, `feat:` → minor, `feat!:`/a `BREAKING CHANGE:` footer → major. A `Release-As:
|
|
251
|
+
patch|minor|major` commit-body footer can override one specific commit's own contribution to that
|
|
252
|
+
- e.g. to ship a `feat:` as a patch right now instead of waiting for the rest of a minor's worth of
|
|
253
|
+
work:
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
feat: needs to ship right now
|
|
257
|
+
|
|
258
|
+
Release-As: patch
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
See [docs/api.md#versionservice](docs/api.md#versionservice) for the full grouping/propagation
|
|
262
|
+
algorithm, prerelease semantics, and `"workspace:"` dependency-range handling.
|
|
263
|
+
|
|
264
|
+
### `rman publish`
|
|
265
|
+
|
|
266
|
+
Publishes every non-private package whose local version isn't already on the registry.
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
rman publish # show the plan, then ask for confirmation
|
|
270
|
+
rman publish --yes # publish immediately, no confirmation
|
|
271
|
+
rman publish --dry-run # only show the plan, never publish
|
|
272
|
+
rman publish --access public # required for a new scoped package
|
|
273
|
+
rman publish --tag next
|
|
274
|
+
rman publish --otp 123456
|
|
275
|
+
rman publish --registry https://registry.example.com --userconfig ./ci.npmrc
|
|
276
|
+
rman publish --package-manager pnpm
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
A `"workspace:*"`/`"workspace:^"`/`"workspace:~"` dependency range is automatically rewritten to a
|
|
280
|
+
real, registry-consumable range immediately before each package's publish, and restored right
|
|
281
|
+
after - see [docs/api.md#publishservice](docs/api.md#publishservice).
|
|
282
|
+
|
|
283
|
+
### `rman import <path>`
|
|
284
|
+
|
|
285
|
+
Imports an external git repository as a new package, preserving its **entire commit history**
|
|
286
|
+
(`git blame`/`git log --follow` keep working on the imported files afterward).
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
rman import ../my-old-standalone-repo
|
|
290
|
+
rman import ../my-old-standalone-repo --dest libs # under libs/ instead of packages/
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`path` must be a local clone (not a URL) - clone the source repository first if it isn't local
|
|
294
|
+
already. After importing, add the new directory to your `workspaces` glob if it isn't already
|
|
295
|
+
covered, then run `rman ci` to install it.
|
|
296
|
+
|
|
297
|
+
## Configuration
|
|
298
|
+
|
|
299
|
+
`rman` reads config cascaded from the repository root down to each package's own directory (the
|
|
300
|
+
same way a `tsconfig.json` `extends` chain works) - a value set closer to a package overrides the
|
|
301
|
+
same key set further up. Three file forms are supported per directory, merged in increasing
|
|
302
|
+
precedence: `package.json`'s own `"rman"` key, `.rman.yml` (YAML), and `.rmanrc` (**JSON**, despite
|
|
303
|
+
the dotfile-style name).
|
|
304
|
+
|
|
305
|
+
```yaml
|
|
306
|
+
# .rman.yml, at the repository root
|
|
307
|
+
packageManager: pnpm
|
|
308
|
+
logLevel: info
|
|
309
|
+
allowBranch: [main, release/*]
|
|
310
|
+
|
|
311
|
+
group: true # implicit repo-wide version group by default
|
|
312
|
+
|
|
313
|
+
version:
|
|
314
|
+
commitMessage: 'chore(release): v{version}'
|
|
315
|
+
|
|
316
|
+
changelog:
|
|
317
|
+
ignoreTypes: [chore, ci]
|
|
318
|
+
tagPattern: 'v*'
|
|
319
|
+
|
|
320
|
+
run:
|
|
321
|
+
build:
|
|
322
|
+
concurrency: 4
|
|
323
|
+
lint:
|
|
324
|
+
topo: false
|
|
325
|
+
bail: false
|
|
326
|
+
test:
|
|
327
|
+
changedSince: v1.0.0
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
```json
|
|
331
|
+
// packages/core/.rmanrc - this one package overrides just its own group
|
|
332
|
+
{ "group": false }
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
```json
|
|
336
|
+
// packages/plugin-a/.rmanrc - versions together with plugin-b, independent of everyone else
|
|
337
|
+
{ "group": "plugins" }
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
See [docs/api.md#configuration-rmanrc-rmanyml](docs/api.md#configuration-rmanrc-rmanyml) for the
|
|
341
|
+
full key reference (every `run.<script>.*` sub-key, `clean.*`, `changelog.*`, precedence rules,
|
|
342
|
+
and which keys are root-level-only today).
|
|
343
|
+
|
|
344
|
+
## Programmatic API
|
|
345
|
+
|
|
346
|
+
Every command above is a thin wrapper around an exported service function - call them directly
|
|
347
|
+
from your own Node.js scripts without shelling out to the `rman` binary:
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
import { Repository, VersionService } from 'rman';
|
|
351
|
+
|
|
352
|
+
const repository = Repository.create();
|
|
353
|
+
const plan = await VersionService.getPlan(repository);
|
|
354
|
+
await VersionService.applyPlan(repository, plan, { changelog: true, push: true });
|
|
355
|
+
```
|
|
7
356
|
|
|
357
|
+
Full reference, with detailed examples for every service (`VersionService`, `PublishService`,
|
|
358
|
+
`ChangelogService`, `RunService`, `CiService`, `CleanService`, `ExecService`, `ListService`,
|
|
359
|
+
`ImportService`, `SystemInfo`) and the `Repository`/`Package` core classes: **[docs/api.md](docs/api.md)**.
|
|
8
360
|
|
|
9
|
-
|
|
361
|
+
## Node compatibility
|
|
10
362
|
|
|
11
|
-
|
|
363
|
+
- Node.js >= 20
|
|
12
364
|
|
|
13
|
-
|
|
365
|
+
## License
|
|
14
366
|
|
|
15
|
-
|
|
16
|
-
rman is available under [MIT](LICENSE) license.
|
|
367
|
+
rman is available under the [MIT](LICENSE) license.
|
|
17
368
|
|
|
18
369
|
[npm-image]: https://img.shields.io/npm/v/rman.svg
|
|
19
370
|
[npm-url]: https://npmjs.org/package/rman
|
|
20
|
-
[travis-image]: https://img.shields.io/travis/panates/rman/master.svg
|
|
21
|
-
[travis-url]: https://travis-ci.com/panates/rman
|
|
22
|
-
[coveralls-image]: https://img.shields.io/coveralls/panates/rman/master.svg
|
|
23
|
-
[coveralls-url]: https://coveralls.io/r/panates/rman
|
|
24
371
|
[downloads-image]: https://img.shields.io/npm/dm/rman.svg
|
|
25
372
|
[downloads-url]: https://npmjs.org/package/rman
|
|
26
|
-
[
|
|
27
|
-
[
|
|
28
|
-
[
|
|
29
|
-
[
|
|
30
|
-
[devdependencies-image]: https://david-dm.org/panates/rman/dev-status.svg
|
|
31
|
-
[devdependencies-url]:https://david-dm.org/panates/rman?type=dev
|
|
32
|
-
[quality-image]: http://npm.packagequality.com/shield/rman.png
|
|
33
|
-
[quality-url]: http://packagequality.com/#?package=rman
|
|
373
|
+
[qc-image]: https://github.com/panates/rman/actions/workflows/qc.yml/badge.svg
|
|
374
|
+
[qc-url]: https://github.com/panates/rman/actions/workflows/qc.yml
|
|
375
|
+
[license-image]: https://img.shields.io/npm/l/rman.svg
|
|
376
|
+
[license-url]: https://github.com/panates/rman/blob/main/LICENSE
|
package/cli.d.ts
CHANGED
package/cli.js
CHANGED
|
@@ -1,30 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
1
4
|
import colors from 'ansi-colors';
|
|
2
5
|
import yargs from 'yargs';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
6
|
+
import { hideBin } from 'yargs/helpers';
|
|
7
|
+
import * as buildCommand from './commands/build.command.js';
|
|
8
|
+
import * as changedCommand from './commands/changed.command.js';
|
|
9
|
+
import * as changelogCommand from './commands/changelog.command.js';
|
|
10
|
+
import * as ciCommand from './commands/ci.command.js';
|
|
11
|
+
import * as cleanCommand from './commands/clean.command.js';
|
|
12
|
+
import * as diffCommand from './commands/diff.command.js';
|
|
13
|
+
import * as execCommand from './commands/exec.command.js';
|
|
14
|
+
import * as importCommand from './commands/import.command.js';
|
|
15
|
+
import * as infoCommand from './commands/info.command.js';
|
|
16
|
+
import * as listCommand from './commands/list.command.js';
|
|
17
|
+
import * as publishCommand from './commands/publish.command.js';
|
|
18
|
+
import * as runCommand from './commands/run.command.js';
|
|
19
|
+
import * as testCommand from './commands/test.command.js';
|
|
20
|
+
import * as versionCommand from './commands/version.command.js';
|
|
12
21
|
import { version } from './constants.js';
|
|
13
|
-
import { Command } from './core/command.js';
|
|
14
22
|
import { Repository } from './core/repository.js';
|
|
23
|
+
import { LOG_LEVELS } from './utils/logger.js';
|
|
15
24
|
export async function runCli(options) {
|
|
16
25
|
try {
|
|
17
26
|
const repository = Repository.create(options?.cwd);
|
|
18
|
-
const _argv = options?.argv || process.argv
|
|
19
|
-
const globalKeys = Object.keys(Command.globalOptions).concat(['help', 'version']);
|
|
27
|
+
const _argv = options?.argv || hideBin(process.argv);
|
|
20
28
|
const program = yargs(_argv)
|
|
21
|
-
|
|
22
|
-
.strict()
|
|
29
|
+
.scriptName('rman2')
|
|
23
30
|
.version(version)
|
|
24
31
|
.alias('version', 'v')
|
|
25
32
|
.usage('$0 <cmd> [options...]')
|
|
26
33
|
.help('help')
|
|
27
34
|
.alias('help', 'h')
|
|
35
|
+
.option('log-level', {
|
|
36
|
+
describe: 'Default verbosity of the per-step log for run/build/ci (default: info, or .rmanrc "logLevel"; ' +
|
|
37
|
+
'overridable per-package via .rmanrc run.<script>.logLevel)',
|
|
38
|
+
choices: LOG_LEVELS,
|
|
39
|
+
})
|
|
28
40
|
.showHelpOnFail(false, 'Run with --help for available options')
|
|
29
41
|
.fail((msg, err) => {
|
|
30
42
|
if (!err?.logged) {
|
|
@@ -38,19 +50,22 @@ export async function runCli(options) {
|
|
|
38
50
|
}
|
|
39
51
|
else
|
|
40
52
|
process.exit(1);
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
});
|
|
54
|
+
infoCommand.initCli(repository, program);
|
|
55
|
+
listCommand.initCli(repository, program);
|
|
56
|
+
runCommand.initCli(repository, program);
|
|
57
|
+
buildCommand.initCli(repository, program);
|
|
58
|
+
ciCommand.initCli(repository, program);
|
|
59
|
+
cleanCommand.initCli(repository, program);
|
|
60
|
+
changelogCommand.initCli(repository, program);
|
|
61
|
+
testCommand.initCli(repository, program);
|
|
62
|
+
versionCommand.initCli(repository, program);
|
|
63
|
+
publishCommand.initCli(repository, program);
|
|
64
|
+
execCommand.initCli(repository, program);
|
|
65
|
+
changedCommand.initCli(repository, program);
|
|
66
|
+
diffCommand.initCli(repository, program);
|
|
67
|
+
importCommand.initCli(repository, program);
|
|
68
|
+
program.demandCommand(1).strict().completion();
|
|
54
69
|
if (!_argv.length)
|
|
55
70
|
program.showHelp();
|
|
56
71
|
else
|
|
@@ -58,6 +73,15 @@ export async function runCli(options) {
|
|
|
58
73
|
}
|
|
59
74
|
catch (e) {
|
|
60
75
|
console.error(colors.red(e.message));
|
|
61
|
-
// logger.error('rman', e.message);
|
|
62
76
|
}
|
|
63
77
|
}
|
|
78
|
+
function isMain() {
|
|
79
|
+
try {
|
|
80
|
+
return !!process.argv[1] && realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1]);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (isMain())
|
|
87
|
+
runCli().catch(() => 0);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RunService } from '../services/run.service.js';
|
|
2
|
+
import { assertAllowedBranch, readBranchGuardOptions } from '../utils/branch-guard.js';
|
|
3
|
+
import { applyRunOptions, readRunOptions } from './run.command.js';
|
|
4
|
+
export function initCli(repository, program) {
|
|
5
|
+
program.command({
|
|
6
|
+
command: 'build',
|
|
7
|
+
describe: 'Alias for "run build"',
|
|
8
|
+
builder: cmd => applyRunOptions(cmd).example('$0 build', '# Builds packages'),
|
|
9
|
+
handler: async (args) => {
|
|
10
|
+
await assertAllowedBranch(repository, readBranchGuardOptions(args));
|
|
11
|
+
await RunService.runScript(repository, 'build', { ...readRunOptions(args), commandName: 'build' });
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import colors from 'ansi-colors';
|
|
2
|
+
import { VersionService } from '../services/version.service.js';
|
|
3
|
+
import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
|
|
4
|
+
export function initCli(repository, program) {
|
|
5
|
+
program.command({
|
|
6
|
+
command: 'changed',
|
|
7
|
+
describe: 'Shows which packages the next "version" run would bump, without changing anything',
|
|
8
|
+
builder: cmd => applyPackageFilterOptions(cmd).example('$0 changed', '').example('$0 changed --json', '').option('json', {
|
|
9
|
+
alias: 'j',
|
|
10
|
+
describe: 'Print output as JSON',
|
|
11
|
+
type: 'boolean',
|
|
12
|
+
}),
|
|
13
|
+
handler: async (args) => {
|
|
14
|
+
const plan = await VersionService.getPlan(repository, readPackageFilterOptions(args));
|
|
15
|
+
const changed = plan.filter(e => e.status === 'bump');
|
|
16
|
+
if (args.json) {
|
|
17
|
+
console.log(JSON.stringify(changed.map(e => ({ name: e.package.name, group: e.group, from: e.from, to: e.to, reason: e.reason })), undefined, 2));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (!changed.length) {
|
|
21
|
+
console.log(colors.gray('Nothing has changed.'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const e of changed) {
|
|
25
|
+
console.log(colors.green('changed'), colors.cyan(e.package.name), colors.gray(`(${e.group})`), e.from, '->', colors.yellow(e.to));
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import colors from 'ansi-colors';
|
|
2
|
+
import { ChangelogService } from '../services/changelog.service.js';
|
|
3
|
+
import { Logger, resolveRootLogLevel } from '../utils/logger.js';
|
|
4
|
+
import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
|
|
5
|
+
export function initCli(repository, program) {
|
|
6
|
+
program.command({
|
|
7
|
+
command: 'changelog',
|
|
8
|
+
describe: 'Generates a changelog per package from unreleased commits',
|
|
9
|
+
builder: cmd => applyPackageFilterOptions(cmd)
|
|
10
|
+
.example('$0 changelog', "# Auto-detects each package's last published version on npm")
|
|
11
|
+
.example('$0 changelog --from <hash> --write', '# Since a specific commit, written to file')
|
|
12
|
+
.option('from', {
|
|
13
|
+
describe: 'Generate the changelog since this commit/hash, applied the same way to every package. ' +
|
|
14
|
+
'Default (also "npm" explicitly): auto-detect per package from its published npm version, ' +
|
|
15
|
+
"falling back to not-yet-pushed commits for a package that can't be resolved this way",
|
|
16
|
+
type: 'string',
|
|
17
|
+
})
|
|
18
|
+
.option('write', {
|
|
19
|
+
describe: "Prepend the entry into each package's own changelog file instead of printing it",
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
})
|
|
22
|
+
.option('file-path', {
|
|
23
|
+
describe: "With --write, the file to prepend into, relative to each package's own directory " +
|
|
24
|
+
'(default: "CHANGELOG.md", or .rmanrc "changelog.filePath")',
|
|
25
|
+
type: 'string',
|
|
26
|
+
})
|
|
27
|
+
.option('root', {
|
|
28
|
+
alias: 'r',
|
|
29
|
+
describe: 'Generate for the whole repository even when the current directory is inside a single ' +
|
|
30
|
+
'package (which otherwise scopes it to just that package). No effect elsewhere.',
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
}),
|
|
33
|
+
handler: async (args) => {
|
|
34
|
+
const from = args.from;
|
|
35
|
+
const write = args.write;
|
|
36
|
+
const logger = new Logger(args.logLevel ?? resolveRootLogLevel(repository));
|
|
37
|
+
if (!from || from === 'npm') {
|
|
38
|
+
// A network round trip per package, even run concurrently, can still take a visible
|
|
39
|
+
// moment - without this, the command looks hung for that stretch instead of just busy.
|
|
40
|
+
logger.info(colors.gray('Checking published npm versions...'));
|
|
41
|
+
}
|
|
42
|
+
const options = {
|
|
43
|
+
...readPackageFilterOptions(args),
|
|
44
|
+
from,
|
|
45
|
+
filePath: args.filePath,
|
|
46
|
+
root: args.root,
|
|
47
|
+
};
|
|
48
|
+
const entries = args.write
|
|
49
|
+
? await ChangelogService.generateToFile(repository, options)
|
|
50
|
+
: await ChangelogService.getEntries(repository, options);
|
|
51
|
+
if (!entries.length) {
|
|
52
|
+
logger.info(colors.gray('No unreleased changes.'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
if (write)
|
|
57
|
+
logger.info(colors.green('updated'), colors.cyan(entry.label), entry.filePath);
|
|
58
|
+
else
|
|
59
|
+
console.log(entry.content);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CiService } from '../services/ci.service.js';
|
|
2
|
+
import { applyBranchGuardOptions, assertAllowedBranch, readBranchGuardOptions } from '../utils/branch-guard.js';
|
|
3
|
+
import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
|
|
4
|
+
export function initCli(repository, program) {
|
|
5
|
+
program.command({
|
|
6
|
+
command: 'ci',
|
|
7
|
+
describe: 'Deletes node_modules and lockfiles in every package, then reinstalls from scratch',
|
|
8
|
+
builder: cmd => applyBranchGuardOptions(applyPackageFilterOptions(cmd))
|
|
9
|
+
.example('$0 ci', '')
|
|
10
|
+
.option('package-manager', {
|
|
11
|
+
describe: 'Package manager to install with (default: npm, or .rmanrc "packageManager")',
|
|
12
|
+
choices: PACKAGE_MANAGERS,
|
|
13
|
+
})
|
|
14
|
+
.option('progress', {
|
|
15
|
+
describe: 'Show a live progress panel while running (default: true; auto-disabled when not a TTY). ' +
|
|
16
|
+
'Unlike run/build, completion is not reported as a per-package tally - only failures are called out.',
|
|
17
|
+
type: 'boolean',
|
|
18
|
+
}),
|
|
19
|
+
handler: async (args) => {
|
|
20
|
+
await assertAllowedBranch(repository, readBranchGuardOptions(args));
|
|
21
|
+
await CiService.reinstall(repository, {
|
|
22
|
+
...readPackageFilterOptions(args),
|
|
23
|
+
packageManager: args.packageManager,
|
|
24
|
+
progress: args.progress,
|
|
25
|
+
logLevel: args.logLevel,
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const PACKAGE_MANAGERS = ['npm', 'yarn', 'pnpm', 'bun'];
|