rman 1.0.7 → 1.0.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/README.md +12 -3
- package/commands/changelog.command.js +21 -6
- package/commands/publish.command.js +68 -9
- package/commands/version.command.js +4 -2
- package/constants.js +1 -1
- package/core/config.d.ts +1 -92
- package/core/package.d.ts +1 -1
- package/index.d.ts +1 -1
- package/index.js +11 -0
- package/interfaces/rman-config.interface.d.ts +130 -0
- package/interfaces/rman-config.interface.js +1 -0
- package/package.json +1 -1
- package/rmanrc.schema.json +129 -20
- package/services/changelog.service.d.ts +24 -12
- package/services/changelog.service.js +18 -17
- package/services/docker-publish.service.js +1 -1
- package/services/github-release.service.d.ts +68 -0
- package/services/github-release.service.js +265 -0
- package/services/list.service.d.ts +1 -1
- package/services/publish.service.js +9 -1
- package/services/version.service.d.ts +15 -4
- package/services/version.service.js +74 -32
- package/services.d.ts +1 -0
- package/services.js +1 -0
- package/utils/change-hash.d.ts +21 -8
- package/utils/change-hash.js +38 -20
- package/utils/conventional-commits.d.ts +13 -0
- package/utils/conventional-commits.js +47 -0
- package/utils/git.d.ts +8 -1
- package/utils/git.js +26 -2
- package/utils/release-version.d.ts +50 -0
- package/utils/release-version.js +66 -0
package/README.md
CHANGED
|
@@ -91,7 +91,7 @@ worked examples of every single command, see **[docs/cli.md](docs/cli.md)**.
|
|
|
91
91
|
| [`diff [package]`](#rman-diff-package) | Shows the git diff since a package's (or the repo's) last release tag. |
|
|
92
92
|
| [`changelog`](#rman-changelog) | Generates a changelog per package from unreleased commits. |
|
|
93
93
|
| [`version [bump]`](#rman-version-bump) | Bumps versions of changed packages (and their dependents). |
|
|
94
|
-
| [`publish`](#rman-publish) | Publishes every package to its configured target(s) - npm and/or
|
|
94
|
+
| [`publish`](#rman-publish) | Publishes every package to its configured target(s) - npm, Docker and/or GitHub Releases. |
|
|
95
95
|
| [`import <path>`](#rman-import-path) | Imports an external git repository as a new package, with history. |
|
|
96
96
|
|
|
97
97
|
Options shared across several commands:
|
|
@@ -222,7 +222,7 @@ Generates a changelog per package from unreleased commits, grouped into ✨ Feat
|
|
|
222
222
|
/ 🔧 Other Changes.
|
|
223
223
|
|
|
224
224
|
```bash
|
|
225
|
-
rman changelog # auto-detects each package's last
|
|
225
|
+
rman changelog # auto-detects each package's own last release
|
|
226
226
|
rman changelog --from a1b2c3d # since a specific commit, for every package
|
|
227
227
|
rman changelog --write # prepend into each package's own CHANGELOG.md
|
|
228
228
|
rman changelog --write --file-path docs/CHANGELOG.md
|
|
@@ -266,7 +266,10 @@ algorithm, prerelease semantics, and `"workspace:"` dependency-range handling.
|
|
|
266
266
|
### `rman publish`
|
|
267
267
|
|
|
268
268
|
Publishes every package to its configured target(s) - `npm` by default, or whatever each package's
|
|
269
|
-
own `.rmanrc "publish.target"` says (`"npm"`, `"docker"`, or
|
|
269
|
+
own `.rmanrc "publish.target"` says (`"npm"`, `"docker"`, `"github"`, or any combination). Each
|
|
270
|
+
target decides for itself whether the current version is already out there: `npm view` on the npm
|
|
271
|
+
side, `docker manifest inspect` on the docker side, and the GitHub Release for that version's own
|
|
272
|
+
tag on the github side.
|
|
270
273
|
|
|
271
274
|
```bash
|
|
272
275
|
rman publish # show the plan, then ask for confirmation
|
|
@@ -278,6 +281,7 @@ rman publish --otp 123456
|
|
|
278
281
|
rman publish --registry https://registry.example.com --userconfig ./ci.npmrc
|
|
279
282
|
rman publish --package-manager pnpm
|
|
280
283
|
rman publish --target docker # only the packages configured for the "docker" target
|
|
284
|
+
rman publish --target github # only the GitHub Release side of it
|
|
281
285
|
```
|
|
282
286
|
|
|
283
287
|
A `"workspace:*"`/`"workspace:^"`/`"workspace:~"` dependency range is automatically rewritten to a
|
|
@@ -288,6 +292,11 @@ A package opts into building/pushing a Docker image via `.rmanrc "publish.target
|
|
|
288
292
|
a `"publish.docker"` block (`image`, `platforms`, `buildContexts`, `buildArgs`, ...) - see
|
|
289
293
|
[docs/cli/publish.md#docker-publishing-publishdocker](docs/cli/publish.md#docker-publishing-publishdocker).
|
|
290
294
|
|
|
295
|
+
A package with no package registry of its own - a standalone app shipped as release assets, or one
|
|
296
|
+
deployed elsewhere with the release just recording that it shipped - opts into
|
|
297
|
+
`"publish.target": ["github"]` instead, optionally with `"publish.github": { "assets": [...] }` -
|
|
298
|
+
see [docs/cli/publish.md#github-releases-publishgithub](docs/cli/publish.md#github-releases-publishgithub).
|
|
299
|
+
|
|
291
300
|
### `rman import <path>`
|
|
292
301
|
|
|
293
302
|
Imports an external git repository as a new package, preserving its **entire commit history**
|
|
@@ -7,12 +7,13 @@ export function initCli(repository, program) {
|
|
|
7
7
|
command: 'changelog',
|
|
8
8
|
describe: 'Generates a changelog per package from unreleased commits',
|
|
9
9
|
builder: cmd => applyPackageFilterOptions(cmd)
|
|
10
|
-
.example('$0 changelog', "# Auto-detects each package's last
|
|
10
|
+
.example('$0 changelog', "# Auto-detects each package's own last release tag (or npm version)")
|
|
11
11
|
.example('$0 changelog --from <hash> --write', '# Since a specific commit, written to file')
|
|
12
12
|
.option('from', {
|
|
13
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
|
|
15
|
-
"falling back to
|
|
14
|
+
'Default (also "npm" explicitly): auto-detect per package from its own most recent release ' +
|
|
15
|
+
'tag - same as "version"/"changed" - falling back to its published npm version (no tag yet), ' +
|
|
16
|
+
"then to its whole history for a package that's never been released at all",
|
|
16
17
|
type: 'string',
|
|
17
18
|
})
|
|
18
19
|
.option('write', {
|
|
@@ -29,21 +30,35 @@ export function initCli(repository, program) {
|
|
|
29
30
|
describe: 'Generate for the whole repository even when the current directory is inside a single ' +
|
|
30
31
|
'package (which otherwise scopes it to just that package). No effect elsewhere.',
|
|
31
32
|
type: 'boolean',
|
|
33
|
+
})
|
|
34
|
+
.option('include-skipped', {
|
|
35
|
+
describe: 'Also generate for a package with .rmanrc "publish.skip" - excluded by default',
|
|
36
|
+
type: 'boolean',
|
|
37
|
+
})
|
|
38
|
+
.option('release-version', {
|
|
39
|
+
describe: 'The version these notes are for - what the entry heading shows. Default: read back from ' +
|
|
40
|
+
"each package's own latest release tag, which is only right once that release is tagged. " +
|
|
41
|
+
'Pass it when generating notes ahead of the bump (e.g. from "changed --json" in CI), ' +
|
|
42
|
+
'otherwise the heading shows the previous release.',
|
|
43
|
+
type: 'string',
|
|
32
44
|
}),
|
|
33
45
|
handler: async (args) => {
|
|
34
46
|
const from = args.from;
|
|
35
47
|
const write = args.write;
|
|
36
48
|
const logger = new Logger(args.logLevel ?? resolveRootLogLevel(repository));
|
|
37
49
|
if (!from || from === 'npm') {
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
50
|
+
// Auto-detection is mostly local git work, but the npm fallback it can reach for (only
|
|
51
|
+
// when a package has no tag at all) is a network round trip per package - without this,
|
|
52
|
+
// the command looks hung for that stretch instead of just busy.
|
|
53
|
+
logger.info(colors.gray("Detecting each package's last release..."));
|
|
41
54
|
}
|
|
42
55
|
const options = {
|
|
43
56
|
...readPackageFilterOptions(args),
|
|
44
57
|
from,
|
|
45
58
|
filePath: args.filePath,
|
|
46
59
|
root: args.root,
|
|
60
|
+
includeSkipped: args.includeSkipped,
|
|
61
|
+
version: args.releaseVersion,
|
|
47
62
|
};
|
|
48
63
|
const entries = args.write
|
|
49
64
|
? await ChangelogService.generateToFile(repository, options)
|
|
@@ -2,6 +2,7 @@ import readline from 'node:readline/promises';
|
|
|
2
2
|
import colors from 'ansi-colors';
|
|
3
3
|
import { CiService } from '../services/ci.service.js';
|
|
4
4
|
import { DockerPublishService } from '../services/docker-publish.service.js';
|
|
5
|
+
import { GithubReleaseService } from '../services/github-release.service.js';
|
|
5
6
|
import { PublishService } from '../services/publish.service.js';
|
|
6
7
|
import { applyBranchGuardOptions, assertAllowedBranch, readBranchGuardOptions } from '../utils/branch-guard.js';
|
|
7
8
|
import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
|
|
@@ -14,6 +15,7 @@ export function initCli(repository, program) {
|
|
|
14
15
|
.example('$0 publish --yes', '# Publish immediately, no confirmation')
|
|
15
16
|
.example('$0 publish --dry-run', '# Only show the plan, never publish')
|
|
16
17
|
.example('$0 publish --target docker', '# Only the packages configured for the "docker" target')
|
|
18
|
+
.example('$0 publish --target github', '# Only the GitHub Release side of it')
|
|
17
19
|
.option('yes', {
|
|
18
20
|
alias: 'y',
|
|
19
21
|
describe: 'Skip the confirmation prompt and publish immediately',
|
|
@@ -22,14 +24,20 @@ export function initCli(repository, program) {
|
|
|
22
24
|
.option('dry-run', {
|
|
23
25
|
describe: 'Only show the plan - never publishes, regardless of --yes',
|
|
24
26
|
type: 'boolean',
|
|
27
|
+
})
|
|
28
|
+
.option('json', {
|
|
29
|
+
alias: 'j',
|
|
30
|
+
describe: 'Print the plan as JSON instead of text - one entry per package and target. Combine with ' +
|
|
31
|
+
'--dry-run to ask "is there anything to publish?" without publishing (e.g. a CI release gate).',
|
|
32
|
+
type: 'boolean',
|
|
25
33
|
})
|
|
26
34
|
.option('target', {
|
|
27
|
-
describe: 'Restrict this run to just these publish target(s) ("npm"/"docker", repeatable) - default: ' +
|
|
35
|
+
describe: 'Restrict this run to just these publish target(s) ("npm"/"docker"/"github", repeatable) - default: ' +
|
|
28
36
|
'every target each package itself is configured for (.rmanrc "publish.target", "npm" when unset). ' +
|
|
29
37
|
'A package that opts into "docker" but has no "publish.docker" config errors clearly instead of ' +
|
|
30
38
|
'being silently skipped.',
|
|
31
39
|
type: 'array',
|
|
32
|
-
choices: ['npm', 'docker'],
|
|
40
|
+
choices: ['npm', 'docker', 'github'],
|
|
33
41
|
})
|
|
34
42
|
.option('ignore-dirty', {
|
|
35
43
|
describe: 'Exclude a package with uncommitted local changes instead of aborting the whole run',
|
|
@@ -68,11 +76,18 @@ export function initCli(repository, program) {
|
|
|
68
76
|
describe: 'Prefixed onto a bare (no "/") "publish.docker.image" - default: the DOCKERHUB_NAMESPACE ' +
|
|
69
77
|
'environment variable.',
|
|
70
78
|
type: 'string',
|
|
79
|
+
})
|
|
80
|
+
.option('github-repository', {
|
|
81
|
+
describe: 'The "owner/repo" GitHub Releases are created in - default: each package\'s own ' +
|
|
82
|
+
'"publish.github.repository", falling back to the "origin" remote.',
|
|
83
|
+
type: 'string',
|
|
71
84
|
}),
|
|
72
85
|
handler: async (args) => {
|
|
73
86
|
await assertAllowedBranch(repository, readBranchGuardOptions(args));
|
|
74
87
|
const targets = resolveTargets(args.target);
|
|
75
|
-
const
|
|
88
|
+
const explicitTargets = !!args.target?.length;
|
|
89
|
+
const explicitDockerTarget = explicitTargets && targets.has('docker');
|
|
90
|
+
const explicitGithubTarget = explicitTargets && targets.has('github');
|
|
76
91
|
const ignoreDirty = args.ignoreDirty;
|
|
77
92
|
const npmOptions = {
|
|
78
93
|
...readPackageFilterOptions(args),
|
|
@@ -85,10 +100,24 @@ export function initCli(repository, program) {
|
|
|
85
100
|
ignoreDirty,
|
|
86
101
|
namespace: args.dockerNamespace,
|
|
87
102
|
};
|
|
103
|
+
// No package filtering: a GitHub Release belongs to the repository, not to a package, so
|
|
104
|
+
// there is nothing for --scope/--ignore to narrow down.
|
|
105
|
+
const githubOptions = { ignoreDirty, repository: args.githubRepository };
|
|
88
106
|
const npmPlan = targets.has('npm') ? await PublishService.getPlan(repository, npmOptions) : [];
|
|
89
107
|
const dockerPlan = targets.has('docker') ? await DockerPublishService.getPlan(repository, dockerOptions) : [];
|
|
90
|
-
|
|
91
|
-
|
|
108
|
+
const githubPlan = targets.has('github') ? await GithubReleaseService.getPlan(repository, githubOptions) : [];
|
|
109
|
+
if (args.json) {
|
|
110
|
+
console.log(JSON.stringify([
|
|
111
|
+
...npmPlan.map(e => jsonEntry(e, 'npm')),
|
|
112
|
+
...dockerPlan.map(e => jsonEntry(e, 'docker')),
|
|
113
|
+
...githubPlan.map(e => jsonEntry(e, 'github')),
|
|
114
|
+
], undefined, 2));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
printPlan(npmPlan);
|
|
118
|
+
printPlan(dockerPlan, 'docker');
|
|
119
|
+
printPlan(githubPlan, 'github');
|
|
120
|
+
}
|
|
92
121
|
if (explicitDockerTarget && !dockerPlan.length) {
|
|
93
122
|
const message = '--target docker was given, but no package\'s .rmanrc configures "publish.docker".';
|
|
94
123
|
console.log(colors.red(message));
|
|
@@ -96,7 +125,14 @@ export function initCli(repository, program) {
|
|
|
96
125
|
err.logged = true;
|
|
97
126
|
throw err;
|
|
98
127
|
}
|
|
99
|
-
|
|
128
|
+
if (explicitGithubTarget && !githubPlan.length) {
|
|
129
|
+
const message = '--target github was given, but nothing in .rmanrc opts into the "github" target.';
|
|
130
|
+
console.log(colors.red(message));
|
|
131
|
+
const err = new Error(message);
|
|
132
|
+
err.logged = true;
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
const errors = [...npmPlan, ...dockerPlan, ...githubPlan].filter(e => e.status === 'error');
|
|
100
136
|
if (errors.length) {
|
|
101
137
|
const allDirty = errors.every(e => e.reason === 'uncommitted local changes');
|
|
102
138
|
const message = allDirty
|
|
@@ -108,8 +144,9 @@ export function initCli(repository, program) {
|
|
|
108
144
|
err.logged = true;
|
|
109
145
|
throw err;
|
|
110
146
|
}
|
|
111
|
-
if (!npmPlan
|
|
112
|
-
|
|
147
|
+
if (![...npmPlan, ...dockerPlan, ...githubPlan].some(e => e.status === 'publish')) {
|
|
148
|
+
if (!args.json)
|
|
149
|
+
console.log(colors.gray('Nothing to publish.'));
|
|
113
150
|
return;
|
|
114
151
|
}
|
|
115
152
|
if (args.dryRun)
|
|
@@ -135,6 +172,7 @@ export function initCli(repository, program) {
|
|
|
135
172
|
})
|
|
136
173
|
: [];
|
|
137
174
|
const appliedDocker = targets.has('docker') ? await DockerPublishService.applyPlan(repository, dockerPlan) : [];
|
|
175
|
+
const appliedGithub = targets.has('github') ? await GithubReleaseService.applyPlan(repository, githubPlan) : [];
|
|
138
176
|
let failed = false;
|
|
139
177
|
for (const entry of appliedNpm) {
|
|
140
178
|
if (entry.status === 'publish') {
|
|
@@ -155,6 +193,16 @@ export function initCli(repository, program) {
|
|
|
155
193
|
console.log(colors.red('failed'), colors.gray('[docker]'), colors.cyan(entry.package.name), colors.red(entry.reason ?? ''));
|
|
156
194
|
}
|
|
157
195
|
}
|
|
196
|
+
for (const entry of appliedGithub) {
|
|
197
|
+
if (entry.status === 'publish') {
|
|
198
|
+
console.log(colors.green('released'), colors.gray('[github]'), colors.cyan(entry.tag ?? ''));
|
|
199
|
+
}
|
|
200
|
+
else if (entry.status === 'error' &&
|
|
201
|
+
githubPlan.find(e => e.package === entry.package)?.status === 'publish') {
|
|
202
|
+
failed = true;
|
|
203
|
+
console.log(colors.red('failed'), colors.gray('[github]'), colors.cyan(entry.package.name), colors.red(entry.reason ?? ''));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
158
206
|
if (failed) {
|
|
159
207
|
const err = new Error('"publish" failed');
|
|
160
208
|
err.logged = true;
|
|
@@ -165,9 +213,20 @@ export function initCli(repository, program) {
|
|
|
165
213
|
}
|
|
166
214
|
function resolveTargets(input) {
|
|
167
215
|
if (!input?.length)
|
|
168
|
-
return new Set(['npm', 'docker']);
|
|
216
|
+
return new Set(['npm', 'docker', 'github']);
|
|
169
217
|
return new Set(input);
|
|
170
218
|
}
|
|
219
|
+
/** One `--json` row. `target` is what distinguishes otherwise-identical rows for a package that
|
|
220
|
+
* ships to several targets at once, so a consumer can tell which one still needs publishing. */
|
|
221
|
+
function jsonEntry(entry, target) {
|
|
222
|
+
return {
|
|
223
|
+
name: entry.package.name,
|
|
224
|
+
target,
|
|
225
|
+
status: entry.status,
|
|
226
|
+
version: entry.version,
|
|
227
|
+
reason: entry.reason,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
171
230
|
function printPlan(entries, label) {
|
|
172
231
|
const prefix = label ? colors.gray(`[${label}] `) : '';
|
|
173
232
|
for (const e of entries) {
|
|
@@ -54,7 +54,8 @@ export function initCli(repository, program) {
|
|
|
54
54
|
})
|
|
55
55
|
.option('changelog', {
|
|
56
56
|
describe: "Also write each bumped package's CHANGELOG.md (same as running changelog --write " +
|
|
57
|
-
'separately) and fold it into the same commit as its version bump'
|
|
57
|
+
'separately) and fold it into the same commit as its version bump. Default: .rmanrc ' +
|
|
58
|
+
'"version.changelog", or false - --no-changelog forces it off even when that\'s true.',
|
|
58
59
|
type: 'boolean',
|
|
59
60
|
})
|
|
60
61
|
.option('preid', {
|
|
@@ -100,10 +101,11 @@ export function initCli(repository, program) {
|
|
|
100
101
|
}
|
|
101
102
|
if (!apply)
|
|
102
103
|
return;
|
|
104
|
+
const changelog = args.changelog ?? repository.config?.version?.changelog ?? false;
|
|
103
105
|
const applied = await VersionService.applyPlan(repository, plan, {
|
|
104
106
|
push: args.push,
|
|
105
107
|
message: args.message,
|
|
106
|
-
changelog
|
|
108
|
+
changelog,
|
|
107
109
|
});
|
|
108
110
|
for (const entry of applied) {
|
|
109
111
|
if (entry.status === 'bump') {
|
package/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.0.
|
|
1
|
+
export const version = '1.0.9';
|
package/core/config.d.ts
CHANGED
|
@@ -1,95 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* The shape of `.rmanrc`/`.rmanrc.yml`/`.rmanrc.cjs`/`.mjs`/`.js` (and `package.json`'s own
|
|
3
|
-
* `"rman"` key) - see docs/api.md#configuration-rmanrc-rmanrcyml for the full reference. Every
|
|
4
|
-
* field is optional and cascades from the repository root down to each package's own directory.
|
|
5
|
-
* Purely a typing aid (used by `defineConfig` below, and importable on its own for a `.rmanrc.ts`/
|
|
6
|
-
* `.mts` authored config, or a plain `: RmanConfig` annotation) - never read by rman itself, which
|
|
7
|
-
* only ever sees the plain JS object a JS config file exports.
|
|
8
|
-
*/
|
|
9
|
-
export interface RmanConfig {
|
|
10
|
-
packageManager?: 'npm' | 'yarn' | 'pnpm' | 'bun';
|
|
11
|
-
logLevel?: 'silent' | 'error' | 'info' | 'verbose';
|
|
12
|
-
allowBranch?: string | string[];
|
|
13
|
-
ignoreBranch?: string | string[];
|
|
14
|
-
group?: boolean | string;
|
|
15
|
-
version?: RmanConfig.VersionOptions;
|
|
16
|
-
changelog?: RmanConfig.ChangelogOptions;
|
|
17
|
-
clean?: RmanConfig.CleanOptions;
|
|
18
|
-
publish?: RmanConfig.PublishOptions;
|
|
19
|
-
/** Keyed by npm script name (e.g. `"build"`, `"lint"`, `"test"`). */
|
|
20
|
-
run?: Record<string, RmanConfig.RunScriptOptions>;
|
|
21
|
-
/** Keyed by the in-repo package's own name. */
|
|
22
|
-
packages?: Record<string, RmanConfig.PackageOptions>;
|
|
23
|
-
}
|
|
24
|
-
export declare namespace RmanConfig {
|
|
25
|
-
interface VersionOptions {
|
|
26
|
-
commitMessage?: string;
|
|
27
|
-
script?: string | string[];
|
|
28
|
-
preScript?: string | string[];
|
|
29
|
-
postScript?: string | string[];
|
|
30
|
-
}
|
|
31
|
-
interface ChangelogOptions {
|
|
32
|
-
ignoreTypes?: string[];
|
|
33
|
-
template?: string;
|
|
34
|
-
filePath?: string;
|
|
35
|
-
tagPattern?: string;
|
|
36
|
-
}
|
|
37
|
-
interface CleanOptions {
|
|
38
|
-
include?: string | string[];
|
|
39
|
-
exclude?: string | string[];
|
|
40
|
-
skip?: boolean;
|
|
41
|
-
}
|
|
42
|
-
interface RunScriptOptions {
|
|
43
|
-
concurrency?: number;
|
|
44
|
-
topo?: boolean;
|
|
45
|
-
bail?: boolean;
|
|
46
|
-
progress?: boolean;
|
|
47
|
-
logLevel?: 'silent' | 'error' | 'info' | 'verbose';
|
|
48
|
-
changedSince?: string;
|
|
49
|
-
skip?: boolean;
|
|
50
|
-
if?: string;
|
|
51
|
-
script?: string | string[];
|
|
52
|
-
preScript?: string | string[];
|
|
53
|
-
postScript?: string | string[];
|
|
54
|
-
override?: boolean;
|
|
55
|
-
}
|
|
56
|
-
interface PackageOptions {
|
|
57
|
-
dependencies?: string[] | Record<string, string>;
|
|
58
|
-
}
|
|
59
|
-
interface PublishOptions {
|
|
60
|
-
/** Which registries `publish` should target for this package - default `['npm']` (every
|
|
61
|
-
* existing repo keeps working unchanged). A package that only ever wants Docker images
|
|
62
|
-
* (typically also `"private": true`, since it's not meant for npm at all) sets `['docker']`;
|
|
63
|
-
* one that publishes both sets `['npm', 'docker']`. */
|
|
64
|
-
target?: PublishTarget | PublishTarget[];
|
|
65
|
-
docker?: DockerPublishOptions;
|
|
66
|
-
}
|
|
67
|
-
type PublishTarget = 'npm' | 'docker';
|
|
68
|
-
/** Required once `"docker"` is one of this package's `publish.target`s - `publish --target
|
|
69
|
-
* docker` errors clearly on a package that opts in here but leaves this out. */
|
|
70
|
-
interface DockerPublishOptions {
|
|
71
|
-
/** DockerHub image name/repository - bare (e.g. `"my-app"`) to be prefixed with
|
|
72
|
-
* `--docker-namespace`/`DOCKERHUB_NAMESPACE`, or already-namespaced (contains a `/`) to use
|
|
73
|
-
* verbatim. */
|
|
74
|
-
image: string;
|
|
75
|
-
/** Relative to the package's own directory. Default `"Dockerfile"`. */
|
|
76
|
-
dockerfile?: string;
|
|
77
|
-
/** Default `["linux/amd64"]`. */
|
|
78
|
-
platforms?: string[];
|
|
79
|
-
/** Build `cwd` override, relative to the repository root - only needed when the Dockerfile's
|
|
80
|
-
* own `COPY`/`ADD` paths expect something other than the package's own directory (rare). */
|
|
81
|
-
cwd?: string;
|
|
82
|
-
/** Named `docker buildx build --build-context <name>=<path>` entries, keyed by name - each
|
|
83
|
-
* path is relative to the package's own directory (or absolute). */
|
|
84
|
-
buildContexts?: Record<string, string>;
|
|
85
|
-
/** `docker buildx build --build-arg <name>=<value>` entries - a value of exactly `"$NAME"`
|
|
86
|
-
* expands to `process.env.NAME` at build time (e.g. to pass a CI secret through). */
|
|
87
|
-
buildArgs?: Record<string, string>;
|
|
88
|
-
/** A file (relative to the package's own directory) whose contents become the DockerHub repo's
|
|
89
|
-
* full description, if present. Default `"DOCKER_README.md"`. */
|
|
90
|
-
readme?: string;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
1
|
+
import type { RmanConfig } from '../interfaces/rman-config.interface.js';
|
|
93
2
|
/**
|
|
94
3
|
* Identity helper for authoring a `.rmanrc.cjs`/`.mjs`/`.js` config with full type-checking and
|
|
95
4
|
* autocomplete - the same `defineConfig` pattern Vite/Vitest use. Returns `config` completely
|
package/core/package.d.ts
CHANGED
package/index.d.ts
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
* CLI-only concerns (argv parsing, `--help` text, and all console/file presentation) stay in
|
|
9
9
|
* `cli.ts` and the individual `commands/*.command.ts` modules, which are not exported here.
|
|
10
10
|
*/
|
|
11
|
-
export type { RmanConfig } from './core/config.js';
|
|
12
11
|
export { defineConfig } from './core/config.js';
|
|
13
12
|
export { Package } from './core/package.js';
|
|
14
13
|
export { Repository } from './core/repository.js';
|
|
14
|
+
export * from './interfaces/rman-config.interface.js';
|
|
15
15
|
export * from './services.js';
|
|
16
16
|
export type { DetectChangeHashOptions } from './utils/change-hash.js';
|
|
17
17
|
export { detectChangeHash } from './utils/change-hash.js';
|
package/index.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic API - the same logic the CLI commands run, importable directly without going
|
|
3
|
+
* through yargs/argv. Each domain's logic lives in a `<Name>` namespace under `./services/*.ts`
|
|
4
|
+
* (e.g. `ChangelogService`, `CiService`, `CleanService`, `ListService`, `RunService`,
|
|
5
|
+
* `SystemInfo`, `VersionService`), re-exported here via `./services.js`. Purpose-specific functions, not one
|
|
6
|
+
* generic `run`/`get` per domain (see e.g. `SystemInfo.getSystemInfo`/`getRepositoryInfo`, kept
|
|
7
|
+
* separate since they're genuinely independent capabilities, not just steps of one operation) -
|
|
8
|
+
* CLI-only concerns (argv parsing, `--help` text, and all console/file presentation) stay in
|
|
9
|
+
* `cli.ts` and the individual `commands/*.command.ts` modules, which are not exported here.
|
|
10
|
+
*/
|
|
1
11
|
export { defineConfig } from './core/config.js';
|
|
2
12
|
export { Package } from './core/package.js';
|
|
3
13
|
export { Repository } from './core/repository.js';
|
|
14
|
+
export * from './interfaces/rman-config.interface.js';
|
|
4
15
|
export * from './services.js';
|
|
5
16
|
export { detectChangeHash } from './utils/change-hash.js';
|
|
6
17
|
export { LOG_LEVELS, Logger, resolveRootLogLevel } from './utils/logger.js';
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape of `.rmanrc`/`.rmanrc.yml`/`.rmanrc.cjs`/`.mjs`/`.js` (and `package.json`'s own
|
|
3
|
+
* `"rman"` key) - see docs/api.md#configuration-rmanrc-rmanrcyml for the full reference. Every
|
|
4
|
+
* field is optional and cascades from the repository root down to each package's own directory.
|
|
5
|
+
* Purely a typing aid (used by `defineConfig` below, and importable on its own for a `.rmanrc.ts`/
|
|
6
|
+
* `.mts` authored config, or a plain `: RmanConfig` annotation) - never read by rman itself, which
|
|
7
|
+
* only ever sees the plain JS object a JS config file exports.
|
|
8
|
+
*/
|
|
9
|
+
export interface RmanConfig {
|
|
10
|
+
packageManager?: 'npm' | 'yarn' | 'pnpm' | 'bun';
|
|
11
|
+
logLevel?: 'silent' | 'error' | 'info' | 'verbose';
|
|
12
|
+
allowBranch?: string | string[];
|
|
13
|
+
ignoreBranch?: string | string[];
|
|
14
|
+
group?: boolean | string;
|
|
15
|
+
version?: RmanConfig.VersionOptions;
|
|
16
|
+
changelog?: RmanConfig.ChangelogOptions;
|
|
17
|
+
clean?: RmanConfig.CleanOptions;
|
|
18
|
+
publish?: RmanConfig.PublishOptions;
|
|
19
|
+
/** Keyed by npm script name (e.g. `"build"`, `"lint"`, `"test"`). */
|
|
20
|
+
run?: Record<string, RmanConfig.RunScriptOptions>;
|
|
21
|
+
/** Keyed by the in-repo package's own name. */
|
|
22
|
+
packages?: Record<string, RmanConfig.PackageOptions>;
|
|
23
|
+
}
|
|
24
|
+
export declare namespace RmanConfig {
|
|
25
|
+
interface VersionOptions {
|
|
26
|
+
commitMessage?: string;
|
|
27
|
+
/** Default for `version --changelog` when the CLI flag isn't given - a standing "always fold
|
|
28
|
+
* the changelog into the version-bump commit" policy, rather than something that behaves
|
|
29
|
+
* differently on the one run someone forgets to pass `--changelog`. An explicit `--changelog`/
|
|
30
|
+
* `--no-changelog` on the command line still wins either way. Root-level only. Default `false`. */
|
|
31
|
+
changelog?: boolean;
|
|
32
|
+
/** Tag naming the repository's own release, as opposed to the per-package/group tags
|
|
33
|
+
* `changelog.tagPattern` names - only created when the root is on a calendar version (a repo
|
|
34
|
+
* with more than one version line). Root-level only. Default `"release-*"`. Must **not** match
|
|
35
|
+
* any package's own `changelog.tagPattern`, or that package's changelog boundary will resolve
|
|
36
|
+
* to the repository release instead of its own last release. */
|
|
37
|
+
releaseTagPattern?: string;
|
|
38
|
+
script?: string | string[];
|
|
39
|
+
preScript?: string | string[];
|
|
40
|
+
postScript?: string | string[];
|
|
41
|
+
}
|
|
42
|
+
interface ChangelogOptions {
|
|
43
|
+
ignoreTypes?: string[];
|
|
44
|
+
template?: string;
|
|
45
|
+
filePath?: string;
|
|
46
|
+
tagPattern?: string;
|
|
47
|
+
}
|
|
48
|
+
interface CleanOptions {
|
|
49
|
+
include?: string | string[];
|
|
50
|
+
exclude?: string | string[];
|
|
51
|
+
skip?: boolean;
|
|
52
|
+
}
|
|
53
|
+
interface RunScriptOptions {
|
|
54
|
+
concurrency?: number;
|
|
55
|
+
topo?: boolean;
|
|
56
|
+
bail?: boolean;
|
|
57
|
+
progress?: boolean;
|
|
58
|
+
logLevel?: 'silent' | 'error' | 'info' | 'verbose';
|
|
59
|
+
changedSince?: string;
|
|
60
|
+
skip?: boolean;
|
|
61
|
+
if?: string;
|
|
62
|
+
script?: string | string[];
|
|
63
|
+
preScript?: string | string[];
|
|
64
|
+
postScript?: string | string[];
|
|
65
|
+
override?: boolean;
|
|
66
|
+
}
|
|
67
|
+
interface PackageOptions {
|
|
68
|
+
dependencies?: string[] | Record<string, string>;
|
|
69
|
+
}
|
|
70
|
+
interface PublishOptions {
|
|
71
|
+
/** Where `publish` should release this package to - default `['npm']` (every existing repo
|
|
72
|
+
* keeps working unchanged). A package that only ever wants Docker images (typically also
|
|
73
|
+
* `"private": true`, since it's not meant for npm at all) sets `['docker']`; a standalone app
|
|
74
|
+
* shipped as GitHub Release assets - or deployed elsewhere entirely, with the release only
|
|
75
|
+
* recording that it happened - sets `['github']`; any combination works (`['npm', 'github']`).
|
|
76
|
+
* Each target answers "is this version already out there?" against its own registry, so a
|
|
77
|
+
* package is never left without one: npm via `npm view`, docker via `docker manifest inspect`,
|
|
78
|
+
* github via the release for that version's tag. */
|
|
79
|
+
target?: PublishTarget | PublishTarget[];
|
|
80
|
+
docker?: DockerPublishOptions;
|
|
81
|
+
github?: GithubPublishOptions;
|
|
82
|
+
/** Excludes this package from `publish` entirely (every target), regardless of
|
|
83
|
+
* `target`/`"private"` - a single, explicit "never published" statement, e.g. for a package
|
|
84
|
+
* released through some separate, unrelated process. `changelog` also skips it by default
|
|
85
|
+
* (see its own `--include-skipped`) - there's little point changelogging something that's
|
|
86
|
+
* never actually released. Independent of `version`, which never consults this at all - a
|
|
87
|
+
* package can still be meaningfully versioned without ever being published. */
|
|
88
|
+
skip?: boolean;
|
|
89
|
+
}
|
|
90
|
+
type PublishTarget = 'npm' | 'docker' | 'github';
|
|
91
|
+
/** Required once `"docker"` is one of this package's `publish.target`s - `publish --target
|
|
92
|
+
* docker` errors clearly on a package that opts in here but leaves this out. */
|
|
93
|
+
interface DockerPublishOptions {
|
|
94
|
+
/** DockerHub image name/repository - bare (e.g. `"my-app"`) to be prefixed with
|
|
95
|
+
* `--docker-namespace`/`DOCKERHUB_NAMESPACE`, or already-namespaced (contains a `/`) to use
|
|
96
|
+
* verbatim. */
|
|
97
|
+
image: string;
|
|
98
|
+
/** Relative to the package's own directory. Default `"Dockerfile"`. */
|
|
99
|
+
dockerfile?: string;
|
|
100
|
+
/** Default `["linux/amd64"]`. */
|
|
101
|
+
platforms?: string[];
|
|
102
|
+
/** Build `cwd` override, relative to the repository root - only needed when the Dockerfile's
|
|
103
|
+
* own `COPY`/`ADD` paths expect something other than the package's own directory (rare). */
|
|
104
|
+
cwd?: string;
|
|
105
|
+
/** Named `docker buildx build --build-context <name>=<path>` entries, keyed by name - each
|
|
106
|
+
* path is relative to the package's own directory (or absolute). */
|
|
107
|
+
buildContexts?: Record<string, string>;
|
|
108
|
+
/** `docker buildx build --build-arg <name>=<value>` entries - a value of exactly `"$NAME"`
|
|
109
|
+
* expands to `process.env.NAME` at build time (e.g. to pass a CI secret through). */
|
|
110
|
+
buildArgs?: Record<string, string>;
|
|
111
|
+
/** A file (relative to the package's own directory) whose contents become the DockerHub repo's
|
|
112
|
+
* full description, if present. Default `"DOCKER_README.md"`. */
|
|
113
|
+
readme?: string;
|
|
114
|
+
}
|
|
115
|
+
/** Optional even when `"github"` is one of this package's `publish.target`s - unlike docker,
|
|
116
|
+
* every required fact (which tag, which repository, what release notes) already has a sensible
|
|
117
|
+
* source, so a bare `"target": ["github"]` is a complete configuration on its own. */
|
|
118
|
+
interface GithubPublishOptions {
|
|
119
|
+
/** Files to attach to the release, as glob patterns relative to the package's own directory
|
|
120
|
+
* (e.g. `["dist/*.tar.gz"]`). A release with no assets is still perfectly valid - it records
|
|
121
|
+
* that the version shipped, which is all a deploy-elsewhere package needs. */
|
|
122
|
+
assets?: string[];
|
|
123
|
+
/** `owner/repo`. Default: parsed from the `origin` remote's URL. */
|
|
124
|
+
repository?: string;
|
|
125
|
+
/** Create the release as an unpublished draft. Default `false`. */
|
|
126
|
+
draft?: boolean;
|
|
127
|
+
/** Default: whether the version being released is itself a semver prerelease (`1.3.0-beta.0`). */
|
|
128
|
+
prerelease?: boolean;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|