rman 1.0.8 → 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 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 Docker. |
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 published npm version
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 both).
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 published version on npm")
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 published npm version, ' +
15
- "falling back to not-yet-pushed commits for a package that can't be resolved this way",
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', {
@@ -33,15 +34,23 @@ export function initCli(repository, program) {
33
34
  .option('include-skipped', {
34
35
  describe: 'Also generate for a package with .rmanrc "publish.skip" - excluded by default',
35
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',
36
44
  }),
37
45
  handler: async (args) => {
38
46
  const from = args.from;
39
47
  const write = args.write;
40
48
  const logger = new Logger(args.logLevel ?? resolveRootLogLevel(repository));
41
49
  if (!from || from === 'npm') {
42
- // A network round trip per package, even run concurrently, can still take a visible
43
- // moment - without this, the command looks hung for that stretch instead of just busy.
44
- logger.info(colors.gray('Checking published npm versions...'));
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..."));
45
54
  }
46
55
  const options = {
47
56
  ...readPackageFilterOptions(args),
@@ -49,6 +58,7 @@ export function initCli(repository, program) {
49
58
  filePath: args.filePath,
50
59
  root: args.root,
51
60
  includeSkipped: args.includeSkipped,
61
+ version: args.releaseVersion,
52
62
  };
53
63
  const entries = args.write
54
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 explicitDockerTarget = !!args.target?.length && targets.has('docker');
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
- printPlan(npmPlan);
91
- printPlan(dockerPlan, 'docker');
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
- const errors = [...npmPlan, ...dockerPlan].filter(e => e.status === 'error');
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.some(e => e.status === 'publish') && !dockerPlan.some(e => e.status === 'publish')) {
112
- console.log(colors.gray('Nothing to publish.'));
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: args.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.8';
1
+ export const version = '1.0.9';
package/core/config.d.ts CHANGED
@@ -1,102 +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
- /** Excludes this package from `publish` entirely (npm and docker both), regardless of
67
- * `target`/`"private"` - a single, explicit "never published" statement, e.g. for a package
68
- * released through some separate, unrelated process. `changelog` also skips it by default
69
- * (see its own `--include-skipped`) - there's little point changelogging something that's
70
- * never actually released. Independent of `version`, which never consults this at all - a
71
- * package can still be meaningfully versioned without ever being published. */
72
- skip?: boolean;
73
- }
74
- type PublishTarget = 'npm' | 'docker';
75
- /** Required once `"docker"` is one of this package's `publish.target`s - `publish --target
76
- * docker` errors clearly on a package that opts in here but leaves this out. */
77
- interface DockerPublishOptions {
78
- /** DockerHub image name/repository - bare (e.g. `"my-app"`) to be prefixed with
79
- * `--docker-namespace`/`DOCKERHUB_NAMESPACE`, or already-namespaced (contains a `/`) to use
80
- * verbatim. */
81
- image: string;
82
- /** Relative to the package's own directory. Default `"Dockerfile"`. */
83
- dockerfile?: string;
84
- /** Default `["linux/amd64"]`. */
85
- platforms?: string[];
86
- /** Build `cwd` override, relative to the repository root - only needed when the Dockerfile's
87
- * own `COPY`/`ADD` paths expect something other than the package's own directory (rare). */
88
- cwd?: string;
89
- /** Named `docker buildx build --build-context <name>=<path>` entries, keyed by name - each
90
- * path is relative to the package's own directory (or absolute). */
91
- buildContexts?: Record<string, string>;
92
- /** `docker buildx build --build-arg <name>=<value>` entries - a value of exactly `"$NAME"`
93
- * expands to `process.env.NAME` at build time (e.g. to pass a CI secret through). */
94
- buildArgs?: Record<string, string>;
95
- /** A file (relative to the package's own directory) whose contents become the DockerHub repo's
96
- * full description, if present. Default `"DOCKER_README.md"`. */
97
- readme?: string;
98
- }
99
- }
1
+ import type { RmanConfig } from '../interfaces/rman-config.interface.js';
100
2
  /**
101
3
  * Identity helper for authoring a `.rmanrc.cjs`/`.mjs`/`.js` config with full type-checking and
102
4
  * autocomplete - the same `defineConfig` pattern Vite/Vitest use. Returns `config` completely
package/core/package.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RmanConfig } from './config.js';
1
+ import type { RmanConfig } from '../interfaces/rman-config.interface.js';
2
2
  export declare class Package {
3
3
  readonly dirname: string;
4
4
  private _json;
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 {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rman",
3
3
  "description": "Repository manager",
4
- "version": "1.0.8",
4
+ "version": "1.0.9",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
7
7
  "dependencies": {