rman 1.0.9 → 1.0.10

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
@@ -265,11 +265,10 @@ algorithm, prerelease semantics, and `"workspace:"` dependency-range handling.
265
265
 
266
266
  ### `rman publish`
267
267
 
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"`, `"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.
268
+ Publishes every package to its configured registry - `npm` by default, or whatever each package's
269
+ own `.rmanrc "publish.target"` says (`"npm"`, `"docker"`, or both). Each target decides for itself
270
+ whether the current version is already out there: `npm view` on the npm side, `docker manifest
271
+ inspect` on the docker side.
273
272
 
274
273
  ```bash
275
274
  rman publish # show the plan, then ask for confirmation
@@ -281,7 +280,6 @@ rman publish --otp 123456
281
280
  rman publish --registry https://registry.example.com --userconfig ./ci.npmrc
282
281
  rman publish --package-manager pnpm
283
282
  rman publish --target docker # only the packages configured for the "docker" target
284
- rman publish --target github # only the GitHub Release side of it
285
283
  ```
286
284
 
287
285
  A `"workspace:*"`/`"workspace:^"`/`"workspace:~"` dependency range is automatically rewritten to a
@@ -292,10 +290,19 @@ A package opts into building/pushing a Docker image via `.rmanrc "publish.target
292
290
  a `"publish.docker"` block (`image`, `platforms`, `buildContexts`, `buildArgs`, ...) - see
293
291
  [docs/cli/publish.md#docker-publishing-publishdocker](docs/cli/publish.md#docker-publishing-publishdocker).
294
292
 
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).
293
+ ### `rman github-release`
294
+
295
+ Creates the repository's GitHub Release for the version that just shipped - one per run, named after
296
+ the repository's own release tag, with notes covering every package that shipped under it.
297
+
298
+ ```bash
299
+ rman github-release --yes
300
+ ```
301
+
302
+ It is deliberately neither a `publish.target` nor opt-in: a release isn't a registry a package ships
303
+ to, it's the repository's own record that a version shipped, and every repository wants that record.
304
+ It needs no configuration at all - see
305
+ [docs/cli/github-release.md](docs/cli/github-release.md).
299
306
 
300
307
  ### `rman import <path>`
301
308
 
package/cli.js CHANGED
@@ -11,6 +11,7 @@ import * as ciCommand from './commands/ci.command.js';
11
11
  import * as cleanCommand from './commands/clean.command.js';
12
12
  import * as diffCommand from './commands/diff.command.js';
13
13
  import * as execCommand from './commands/exec.command.js';
14
+ import * as githubReleaseCommand from './commands/github-release.command.js';
14
15
  import * as importCommand from './commands/import.command.js';
15
16
  import * as infoCommand from './commands/info.command.js';
16
17
  import * as listCommand from './commands/list.command.js';
@@ -61,6 +62,7 @@ export async function runCli(options) {
61
62
  testCommand.initCli(repository, program);
62
63
  versionCommand.initCli(repository, program);
63
64
  publishCommand.initCli(repository, program);
65
+ githubReleaseCommand.initCli(repository, program);
64
66
  execCommand.initCli(repository, program);
65
67
  changedCommand.initCli(repository, program);
66
68
  diffCommand.initCli(repository, program);
@@ -0,0 +1,3 @@
1
+ import type { Argv } from 'yargs';
2
+ import type { Repository } from '../core/repository.js';
3
+ export declare function initCli(repository: Repository, program: Argv): void;
@@ -0,0 +1,119 @@
1
+ import readline from 'node:readline/promises';
2
+ import colors from 'ansi-colors';
3
+ import { GithubReleaseService } from '../services/github-release.service.js';
4
+ import { applyBranchGuardOptions, assertAllowedBranch, readBranchGuardOptions } from '../utils/branch-guard.js';
5
+ export function initCli(repository, program) {
6
+ program.command({
7
+ command: 'github-release',
8
+ describe: "Creates the repository's GitHub Release for the version that just shipped",
9
+ builder: cmd => applyBranchGuardOptions(cmd)
10
+ .example('$0 github-release', '# Show what would be released, then ask for confirmation')
11
+ .example('$0 github-release --yes', '# Create it immediately, no confirmation (CI)')
12
+ .example('$0 github-release --dry-run', '# Only show the plan')
13
+ .option('yes', {
14
+ alias: 'y',
15
+ describe: 'Skip the confirmation prompt and create the release immediately',
16
+ type: 'boolean',
17
+ })
18
+ .option('dry-run', {
19
+ describe: 'Only show the plan - never creates anything, regardless of --yes',
20
+ type: 'boolean',
21
+ })
22
+ .option('json', {
23
+ alias: 'j',
24
+ describe: 'Print the plan as JSON instead of text',
25
+ type: 'boolean',
26
+ })
27
+ .option('repository', {
28
+ describe: 'The "owner/repo" the release is created in - default: .rmanrc "githubRelease.repository", ' +
29
+ 'falling back to the "origin" remote.',
30
+ type: 'string',
31
+ })
32
+ .option('ignore-dirty', {
33
+ describe: 'Release anyway when the working tree has uncommitted changes, instead of aborting',
34
+ type: 'boolean',
35
+ }),
36
+ handler: async (args) => {
37
+ await assertAllowedBranch(repository, readBranchGuardOptions(args));
38
+ // No package filtering: a release belongs to the repository, not to a package, so there is
39
+ // nothing for --scope/--ignore to narrow down.
40
+ const plan = await GithubReleaseService.getPlan(repository, {
41
+ ignoreDirty: args.ignoreDirty,
42
+ repository: args.repository,
43
+ });
44
+ if (args.json) {
45
+ console.log(JSON.stringify(plan.map(e => ({
46
+ tag: e.tag,
47
+ repository: e.repository,
48
+ status: e.status,
49
+ version: e.version,
50
+ reason: e.reason,
51
+ })), undefined, 2));
52
+ }
53
+ else {
54
+ for (const e of plan) {
55
+ const name = colors.cyan(e.tag ?? e.version);
56
+ switch (e.status) {
57
+ case 'publish':
58
+ console.log(colors.green('release'), name, colors.gray(`${e.repository} - ${e.reason ?? ''}`));
59
+ break;
60
+ case 'up-to-date':
61
+ console.log(colors.gray('up-to-date'), name, colors.gray(e.reason ?? ''));
62
+ break;
63
+ case 'skip':
64
+ console.log(colors.cyan('skip'), name, colors.gray(e.reason ?? ''));
65
+ break;
66
+ case 'error':
67
+ console.log(colors.red('error'), name, colors.red(e.reason ?? ''));
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ const error = plan.find(e => e.status === 'error');
73
+ if (error) {
74
+ const err = new Error(error.reason ?? 'Unable to prepare the GitHub Release');
75
+ err.logged = true;
76
+ throw err;
77
+ }
78
+ if (!plan.some(e => e.status === 'publish')) {
79
+ if (!args.json)
80
+ console.log(colors.gray('Nothing to release.'));
81
+ return;
82
+ }
83
+ if (args.dryRun)
84
+ return;
85
+ let proceed = !!args.yes;
86
+ if (!proceed) {
87
+ if (!process.stdout.isTTY) {
88
+ console.log(colors.gray('Not a TTY - refusing to prompt. Pass --yes to release non-interactively.'));
89
+ return;
90
+ }
91
+ proceed = await confirm('Create this release?');
92
+ }
93
+ if (!proceed)
94
+ return;
95
+ const applied = await GithubReleaseService.applyPlan(repository, plan);
96
+ const failed = applied.find(e => e.status === 'error');
97
+ if (failed) {
98
+ console.log(colors.red('failed'), colors.cyan(failed.tag ?? ''), colors.red(failed.reason ?? ''));
99
+ const err = new Error('"github-release" failed');
100
+ err.logged = true;
101
+ throw err;
102
+ }
103
+ for (const e of applied) {
104
+ if (e.status === 'publish')
105
+ console.log(colors.green('released'), colors.cyan(e.tag ?? ''));
106
+ }
107
+ },
108
+ });
109
+ }
110
+ async function confirm(question) {
111
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
112
+ try {
113
+ const answer = await rl.question(`${question} (y/N) `);
114
+ return /^y(es)?$/i.test(answer.trim());
115
+ }
116
+ finally {
117
+ rl.close();
118
+ }
119
+ }
@@ -2,7 +2,6 @@ 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';
6
5
  import { PublishService } from '../services/publish.service.js';
7
6
  import { applyBranchGuardOptions, assertAllowedBranch, readBranchGuardOptions } from '../utils/branch-guard.js';
8
7
  import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
@@ -15,7 +14,6 @@ export function initCli(repository, program) {
15
14
  .example('$0 publish --yes', '# Publish immediately, no confirmation')
16
15
  .example('$0 publish --dry-run', '# Only show the plan, never publish')
17
16
  .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')
19
17
  .option('yes', {
20
18
  alias: 'y',
21
19
  describe: 'Skip the confirmation prompt and publish immediately',
@@ -32,12 +30,12 @@ export function initCli(repository, program) {
32
30
  type: 'boolean',
33
31
  })
34
32
  .option('target', {
35
- describe: 'Restrict this run to just these publish target(s) ("npm"/"docker"/"github", repeatable) - default: ' +
33
+ describe: 'Restrict this run to just these publish target(s) ("npm"/"docker", repeatable) - default: ' +
36
34
  'every target each package itself is configured for (.rmanrc "publish.target", "npm" when unset). ' +
37
35
  'A package that opts into "docker" but has no "publish.docker" config errors clearly instead of ' +
38
36
  'being silently skipped.',
39
37
  type: 'array',
40
- choices: ['npm', 'docker', 'github'],
38
+ choices: ['npm', 'docker'],
41
39
  })
42
40
  .option('ignore-dirty', {
43
41
  describe: 'Exclude a package with uncommitted local changes instead of aborting the whole run',
@@ -76,18 +74,12 @@ export function initCli(repository, program) {
76
74
  describe: 'Prefixed onto a bare (no "/") "publish.docker.image" - default: the DOCKERHUB_NAMESPACE ' +
77
75
  'environment variable.',
78
76
  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',
84
77
  }),
85
78
  handler: async (args) => {
86
79
  await assertAllowedBranch(repository, readBranchGuardOptions(args));
87
80
  const targets = resolveTargets(args.target);
88
81
  const explicitTargets = !!args.target?.length;
89
82
  const explicitDockerTarget = explicitTargets && targets.has('docker');
90
- const explicitGithubTarget = explicitTargets && targets.has('github');
91
83
  const ignoreDirty = args.ignoreDirty;
92
84
  const npmOptions = {
93
85
  ...readPackageFilterOptions(args),
@@ -100,23 +92,14 @@ export function initCli(repository, program) {
100
92
  ignoreDirty,
101
93
  namespace: args.dockerNamespace,
102
94
  };
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 };
106
95
  const npmPlan = targets.has('npm') ? await PublishService.getPlan(repository, npmOptions) : [];
107
96
  const dockerPlan = targets.has('docker') ? await DockerPublishService.getPlan(repository, dockerOptions) : [];
108
- const githubPlan = targets.has('github') ? await GithubReleaseService.getPlan(repository, githubOptions) : [];
109
97
  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));
98
+ console.log(JSON.stringify([...npmPlan.map(e => jsonEntry(e, 'npm')), ...dockerPlan.map(e => jsonEntry(e, 'docker'))], undefined, 2));
115
99
  }
116
100
  else {
117
101
  printPlan(npmPlan);
118
102
  printPlan(dockerPlan, 'docker');
119
- printPlan(githubPlan, 'github');
120
103
  }
121
104
  if (explicitDockerTarget && !dockerPlan.length) {
122
105
  const message = '--target docker was given, but no package\'s .rmanrc configures "publish.docker".';
@@ -125,14 +108,7 @@ export function initCli(repository, program) {
125
108
  err.logged = true;
126
109
  throw err;
127
110
  }
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');
111
+ const errors = [...npmPlan, ...dockerPlan].filter(e => e.status === 'error');
136
112
  if (errors.length) {
137
113
  const allDirty = errors.every(e => e.reason === 'uncommitted local changes');
138
114
  const message = allDirty
@@ -144,7 +120,7 @@ export function initCli(repository, program) {
144
120
  err.logged = true;
145
121
  throw err;
146
122
  }
147
- if (![...npmPlan, ...dockerPlan, ...githubPlan].some(e => e.status === 'publish')) {
123
+ if (![...npmPlan, ...dockerPlan].some(e => e.status === 'publish')) {
148
124
  if (!args.json)
149
125
  console.log(colors.gray('Nothing to publish.'));
150
126
  return;
@@ -172,7 +148,6 @@ export function initCli(repository, program) {
172
148
  })
173
149
  : [];
174
150
  const appliedDocker = targets.has('docker') ? await DockerPublishService.applyPlan(repository, dockerPlan) : [];
175
- const appliedGithub = targets.has('github') ? await GithubReleaseService.applyPlan(repository, githubPlan) : [];
176
151
  let failed = false;
177
152
  for (const entry of appliedNpm) {
178
153
  if (entry.status === 'publish') {
@@ -193,16 +168,6 @@ export function initCli(repository, program) {
193
168
  console.log(colors.red('failed'), colors.gray('[docker]'), colors.cyan(entry.package.name), colors.red(entry.reason ?? ''));
194
169
  }
195
170
  }
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
- }
206
171
  if (failed) {
207
172
  const err = new Error('"publish" failed');
208
173
  err.logged = true;
@@ -213,7 +178,7 @@ export function initCli(repository, program) {
213
178
  }
214
179
  function resolveTargets(input) {
215
180
  if (!input?.length)
216
- return new Set(['npm', 'docker', 'github']);
181
+ return new Set(['npm', 'docker']);
217
182
  return new Set(input);
218
183
  }
219
184
  /** One `--json` row. `target` is what distinguishes otherwise-identical rows for a package that
package/constants.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.0.9';
1
+ export const version = '1.0.10';
@@ -16,6 +16,7 @@ export interface RmanConfig {
16
16
  changelog?: RmanConfig.ChangelogOptions;
17
17
  clean?: RmanConfig.CleanOptions;
18
18
  publish?: RmanConfig.PublishOptions;
19
+ githubRelease?: RmanConfig.GithubReleaseOptions;
19
20
  /** Keyed by npm script name (e.g. `"build"`, `"lint"`, `"test"`). */
20
21
  run?: Record<string, RmanConfig.RunScriptOptions>;
21
22
  /** Keyed by the in-repo package's own name. */
@@ -68,17 +69,18 @@ export declare namespace RmanConfig {
68
69
  dependencies?: string[] | Record<string, string>;
69
70
  }
70
71
  interface PublishOptions {
71
- /** Where `publish` should release this package to - default `['npm']` (every existing repo
72
+ /** Which **registry** `publish` ships this package to - default `['npm']` (every existing repo
72
73
  * 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']`).
74
+ * `"private": true`, since it's not meant for npm at all) sets `['docker']`; both works too.
76
75
  * 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. */
76
+ * package is never left without one: npm via `npm view`, docker via `docker manifest inspect`.
77
+ *
78
+ * Note this is strictly about *package distribution*. The repository's GitHub Release is not
79
+ * a target here - it isn't a place a package ships to, it's the repository's own record that
80
+ * a release happened, and it is never opted into: see `githubRelease` and the
81
+ * `github-release` command. */
79
82
  target?: PublishTarget | PublishTarget[];
80
83
  docker?: DockerPublishOptions;
81
- github?: GithubPublishOptions;
82
84
  /** Excludes this package from `publish` entirely (every target), regardless of
83
85
  * `target`/`"private"` - a single, explicit "never published" statement, e.g. for a package
84
86
  * released through some separate, unrelated process. `changelog` also skips it by default
@@ -87,7 +89,7 @@ export declare namespace RmanConfig {
87
89
  * package can still be meaningfully versioned without ever being published. */
88
90
  skip?: boolean;
89
91
  }
90
- type PublishTarget = 'npm' | 'docker' | 'github';
92
+ type PublishTarget = 'npm' | 'docker';
91
93
  /** Required once `"docker"` is one of this package's `publish.target`s - `publish --target
92
94
  * docker` errors clearly on a package that opts in here but leaves this out. */
93
95
  interface DockerPublishOptions {
@@ -112,19 +114,22 @@ export declare namespace RmanConfig {
112
114
  * full description, if present. Default `"DOCKER_README.md"`. */
113
115
  readme?: string;
114
116
  }
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 {
117
+ /** Entirely optional - `github-release` needs no configuration at all, since every required fact
118
+ * (which tag, which repository, what the notes say) already has a sensible source. Nothing here
119
+ * decides *whether* a release is cut: a release records that the repository shipped, so it is
120
+ * always cut, and these are only details about how. */
121
+ interface GithubReleaseOptions {
119
122
  /** 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. */
123
+ * (e.g. `["dist/*.tar.gz"]`). Read from **every** package, since one release covers the whole
124
+ * source tree. A release with no assets at all is still perfectly valid - it records that the
125
+ * version shipped, which is all a deploy-elsewhere package needs. */
122
126
  assets?: string[];
123
- /** `owner/repo`. Default: parsed from the `origin` remote's URL. */
127
+ /** `owner/repo`. Default: parsed from the `origin` remote's URL. Root-level only. */
124
128
  repository?: string;
125
- /** Create the release as an unpublished draft. Default `false`. */
129
+ /** Create the release as an unpublished draft. Default `false`. Root-level only. */
126
130
  draft?: boolean;
127
- /** Default: whether the version being released is itself a semver prerelease (`1.3.0-beta.0`). */
131
+ /** Default: whether the version being released is itself a semver prerelease (`1.3.0-beta.0`).
132
+ * Root-level only. */
128
133
  prerelease?: boolean;
129
134
  }
130
135
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rman",
3
3
  "description": "Repository manager",
4
- "version": "1.0.9",
4
+ "version": "1.0.10",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
7
7
  "dependencies": {
@@ -131,11 +131,11 @@
131
131
  },
132
132
  "publish": {
133
133
  "type": "object",
134
- "description": "Options for the \"publish\" command/PublishService, DockerPublishService and GithubReleaseService. Per-package cascaded.",
134
+ "description": "Options for the \"publish\" command/PublishService and DockerPublishService. Per-package cascaded.",
135
135
  "additionalProperties": false,
136
136
  "properties": {
137
137
  "target": {
138
- "description": "Where \"publish\" releases this package to. Default [\"npm\"]. A package that only ships Docker images (typically also \"private\": true) sets [\"docker\"]; a standalone app shipped as GitHub Release assets - or deployed elsewhere, with the release only recording that it shipped - sets [\"github\"]; any combination works. Each target answers \"is this version already out there?\" against its own registry: npm via \"npm view\", docker via \"docker manifest inspect\", github via the release for that version's tag.",
138
+ "description": "Which registry \"publish\" ships this package to. Default [\"npm\"]. A package that only ships Docker images (typically also \"private\": true) sets [\"docker\"]; both works too. Each target answers \"is this version already out there?\" against its own registry: npm via \"npm view\", docker via \"docker manifest inspect\". This is strictly about package distribution - the repository's GitHub Release is not a target here, see \"githubRelease\" and the \"github-release\" command.",
139
139
  "default": [
140
140
  "npm"
141
141
  ],
@@ -155,10 +155,6 @@
155
155
  "$ref": "#/definitions/dockerPublishConfig",
156
156
  "description": "Required once \"docker\" is one of this package's \"publish.target\"s."
157
157
  },
158
- "github": {
159
- "$ref": "#/definitions/githubPublishConfig",
160
- "description": "Optional even when \"github\" is one of this package's \"publish.target\"s - every required fact already has a sensible default source."
161
- },
162
158
  "skip": {
163
159
  "type": "boolean",
164
160
  "default": false,
@@ -166,6 +162,10 @@
166
162
  }
167
163
  }
168
164
  },
165
+ "githubRelease": {
166
+ "$ref": "#/definitions/githubReleaseConfig",
167
+ "description": "Details of the repository's GitHub Release (\"github-release\"/GithubReleaseService). Entirely optional - every required fact already has a sensible default source. Nothing here decides whether a release is cut: a release records that the repository shipped, so it is always cut. \"assets\" is per-package cascaded; the rest is root-level only."
168
+ },
169
169
  "run": {
170
170
  "type": "object",
171
171
  "description": "Per-script options for \"run\"/\"build\"/\"test\"/RunService, keyed by npm script name (e.g. \"build\", \"lint\", \"test\").",
@@ -230,8 +230,7 @@
230
230
  "type": "string",
231
231
  "enum": [
232
232
  "npm",
233
- "docker",
234
- "github"
233
+ "docker"
235
234
  ]
236
235
  },
237
236
  "dockerPublishConfig": {
@@ -286,7 +285,7 @@
286
285
  }
287
286
  }
288
287
  },
289
- "githubPublishConfig": {
288
+ "githubReleaseConfig": {
290
289
  "type": "object",
291
290
  "additionalProperties": false,
292
291
  "properties": {
@@ -295,7 +294,7 @@
295
294
  "items": {
296
295
  "type": "string"
297
296
  },
298
- "description": "Files to attach to the release, as glob patterns relative to the package's own directory (e.g. [\"dist/*.tar.gz\"]). A release with no assets is still valid."
297
+ "description": "Files to attach to the release, as glob patterns relative to the package's own directory (e.g. [\"dist/*.tar.gz\"]). Read from every package, since one release covers the whole source tree. A release with no assets is still valid."
299
298
  },
300
299
  "repository": {
301
300
  "type": "string",
@@ -11,7 +11,7 @@ export declare namespace GithubReleaseService {
11
11
  /** Uncommitted local changes anywhere in the repository make the release `'skip'` instead of
12
12
  * `'error'` - same as `version`/`publish`'s other targets. */
13
13
  ignoreDirty?: boolean;
14
- /** `owner/repo` override - otherwise the root's own `publish.github.repository`, falling back
14
+ /** `owner/repo` override - otherwise the root's own `githubRelease.repository`, falling back
15
15
  * to the `origin` remote's URL. */
16
16
  repository?: string;
17
17
  }
@@ -31,13 +31,14 @@ export declare namespace GithubReleaseService {
31
31
  reason?: string;
32
32
  }
33
33
  /**
34
- * Computes what `publish --target github` *would* do - **one** release per run, or none.
34
+ * Computes what `github-release` *would* do - **one** release per run.
35
35
  *
36
36
  * A GitHub Release is a property of the repository, not of a package: the tag covers the whole
37
- * source tree, so everything that shipped under it belongs in it. That makes the `"github"`
38
- * target a repository-level opt-in (typically in the root `.rmanrc`, alongside `"npm"`); it's
39
- * honored as soon as *any* package resolves it, since a per-package release would have to invent
40
- * a tag no package owns.
37
+ * source tree, so everything that shipped under it belongs in it. There is deliberately **no
38
+ * opt-in**: it isn't a place a package ships to (that's `publish.target`, which is about
39
+ * registries - npm, Docker Hub, GitHub Packages), it's the repository's own record that a
40
+ * release happened, and a repository always wants that record. Re-running is harmless - an
41
+ * existing release for the tag reads `'up-to-date'`.
41
42
  *
42
43
  * The release is identified by the repository's own version (the root's - see
43
44
  * `VersionService`'s `buildRootEntry`): its release tag when that version is a calendar one, and
@@ -52,9 +53,9 @@ export declare namespace GithubReleaseService {
52
53
  */
53
54
  function getPlan(repository: Repository, options?: Options, deps?: Deps): Promise<Entry[]>;
54
55
  /**
55
- * Creates the repository's GitHub Release, then uploads whatever `publish.github.assets` globs
56
- * match. The body covers **every** package that shipped under this release - not just the ones
57
- * naming `"github"` as a target - since the tag covers all of their code either way.
56
+ * Creates the repository's GitHub Release, then uploads whatever `githubRelease.assets` globs
57
+ * match, across every package. The body covers **every** package that shipped under this
58
+ * release, since the tag covers all of their code either way.
58
59
  *
59
60
  * Each package's notes are bounded by the *previous repository release*, and headed with that
60
61
  * package's own version, so a repo whose packages sit on different version lines still reads
@@ -9,13 +9,14 @@ import { ChangelogService } from './changelog.service.js';
9
9
  export var GithubReleaseService;
10
10
  (function (GithubReleaseService) {
11
11
  /**
12
- * Computes what `publish --target github` *would* do - **one** release per run, or none.
12
+ * Computes what `github-release` *would* do - **one** release per run.
13
13
  *
14
14
  * A GitHub Release is a property of the repository, not of a package: the tag covers the whole
15
- * source tree, so everything that shipped under it belongs in it. That makes the `"github"`
16
- * target a repository-level opt-in (typically in the root `.rmanrc`, alongside `"npm"`); it's
17
- * honored as soon as *any* package resolves it, since a per-package release would have to invent
18
- * a tag no package owns.
15
+ * source tree, so everything that shipped under it belongs in it. There is deliberately **no
16
+ * opt-in**: it isn't a place a package ships to (that's `publish.target`, which is about
17
+ * registries - npm, Docker Hub, GitHub Packages), it's the repository's own record that a
18
+ * release happened, and a repository always wants that record. Re-running is harmless - an
19
+ * existing release for the tag reads `'up-to-date'`.
19
20
  *
20
21
  * The release is identified by the repository's own version (the root's - see
21
22
  * `VersionService`'s `buildRootEntry`): its release tag when that version is a calendar one, and
@@ -30,18 +31,15 @@ export var GithubReleaseService;
30
31
  */
31
32
  async function getPlan(repository, options = {}, deps = {}) {
32
33
  const root = repository.rootPackage;
33
- const wanted = [root, ...repository.getPackages()].some(pkg => targetsGithub(pkg) && !pkg.config.publish?.skip);
34
- if (!wanted)
35
- return [];
36
34
  const git = new GitHelper({ cwd: repository.dirname });
37
35
  const base = { package: root, version: root.version };
38
- const repo = options.repository ?? root.config?.publish?.github?.repository ?? repoFromRemoteUrl(await git.remoteUrl());
36
+ const repo = options.repository ?? root.config?.githubRelease?.repository ?? repoFromRemoteUrl(await git.remoteUrl());
39
37
  if (!repo) {
40
38
  return [
41
39
  {
42
40
  ...base,
43
41
  status: 'error',
44
- reason: 'cannot resolve "owner/repo" - set "publish.github.repository" or an "origin" remote',
42
+ reason: 'cannot resolve "owner/repo" - set "githubRelease.repository" or an "origin" remote',
45
43
  },
46
44
  ];
47
45
  }
@@ -91,9 +89,9 @@ export var GithubReleaseService;
91
89
  }
92
90
  GithubReleaseService.getPlan = getPlan;
93
91
  /**
94
- * Creates the repository's GitHub Release, then uploads whatever `publish.github.assets` globs
95
- * match. The body covers **every** package that shipped under this release - not just the ones
96
- * naming `"github"` as a target - since the tag covers all of their code either way.
92
+ * Creates the repository's GitHub Release, then uploads whatever `githubRelease.assets` globs
93
+ * match, across every package. The body covers **every** package that shipped under this
94
+ * release, since the tag covers all of their code either way.
97
95
  *
98
96
  * Each package's notes are bounded by the *previous repository release*, and headed with that
99
97
  * package's own version, so a repo whose packages sit on different version lines still reads
@@ -113,7 +111,7 @@ export var GithubReleaseService;
113
111
  const release = await createOrUpdateRelease(entry.repository, entry.tag, {
114
112
  name: entry.tag,
115
113
  body,
116
- draft: !!repository.rootPackage.config?.publish?.github?.draft,
114
+ draft: !!repository.rootPackage.config?.githubRelease?.draft,
117
115
  prerelease: resolvePrerelease(repository.rootPackage, entry.version),
118
116
  });
119
117
  await uploadAssets(repository, entry.repository, release.id);
@@ -127,11 +125,6 @@ export var GithubReleaseService;
127
125
  })(GithubReleaseService || (GithubReleaseService = {}));
128
126
  const GITHUB_API = 'https://api.github.com';
129
127
  const GITHUB_UPLOADS = 'https://uploads.github.com';
130
- function targetsGithub(pkg) {
131
- const target = pkg.config.publish?.target;
132
- const targets = Array.isArray(target) ? target : target ? [target] : ['npm'];
133
- return targets.includes('github');
134
- }
135
128
  /** The tag naming this repository's release. A calendar root version means several version lines,
136
129
  * so the release needs a name of its own (`release-*`); a plain one means every package shares it,
137
130
  * and that shared version's tag already *is* the release. */
@@ -144,7 +137,7 @@ function releaseTagGlob(root) {
144
137
  return pattern.replace('{name}', root.name);
145
138
  }
146
139
  function resolvePrerelease(root, version) {
147
- const configured = root.config?.publish?.github?.prerelease;
140
+ const configured = root.config?.githubRelease?.prerelease;
148
141
  // A calendar version's time part is a semver prerelease identifier by construction - it says
149
142
  // nothing about the release being a preview, so it must not be read as one.
150
143
  return configured ?? (!isCalendarVersion(version) && !!semver.prerelease(version));
@@ -242,12 +235,12 @@ async function createOrUpdateRelease(repository, tag, fields) {
242
235
  }
243
236
  return release;
244
237
  }
245
- /** Every `publish.github.assets` glob across the repository, each resolved against its own
238
+ /** Every `githubRelease.assets` glob across the repository, each resolved against its own
246
239
  * package's directory - an app ships its artifacts from its own folder, but they all land on the
247
240
  * one release the repository cut. */
248
241
  async function uploadAssets(repository, repo, releaseId) {
249
242
  for (const pkg of [repository.rootPackage, ...repository.getPackages()]) {
250
- const patterns = pkg.config.publish?.github?.assets;
243
+ const patterns = pkg.config.githubRelease?.assets;
251
244
  if (!patterns?.length)
252
245
  continue;
253
246
  const files = await fastGlob(patterns, { cwd: pkg.dirname, absolute: true, onlyFiles: true });
@@ -15,8 +15,8 @@ export declare function tagPattern(pkg: Package): string;
15
15
  export declare function findLatestTag(git: GitHelper, pkg: Package): Promise<string | undefined>;
16
16
  /** The forward direction of `findLatestTag`: expands `pkg`'s (cascaded) `.rmanrc
17
17
  * changelog.tagPattern` into the concrete tag name `version` belongs under - `{name}` becomes the
18
- * package's own name, `*` becomes `version`. Shared by `version` (creating the tag), `publish
19
- * --target github` (finding the release that tag belongs to), and `detectChangeHash`'s own npm
18
+ * package's own name, `*` becomes `version`. Shared by `version` (creating the tag),
19
+ * `github-release` (finding the release that tag belongs to), and `detectChangeHash`'s own npm
20
20
  * fallback (mapping a published version back onto a tag), so all three name tags identically. */
21
21
  export declare function expandTag(pkg: Package, version: string): string;
22
22
  /** The pattern expansion `expandTag` performs, on any pattern - `{name}` becomes `name`, `*` becomes
@@ -22,8 +22,8 @@ export async function findLatestTag(git, pkg) {
22
22
  }
23
23
  /** The forward direction of `findLatestTag`: expands `pkg`'s (cascaded) `.rmanrc
24
24
  * changelog.tagPattern` into the concrete tag name `version` belongs under - `{name}` becomes the
25
- * package's own name, `*` becomes `version`. Shared by `version` (creating the tag), `publish
26
- * --target github` (finding the release that tag belongs to), and `detectChangeHash`'s own npm
25
+ * package's own name, `*` becomes `version`. Shared by `version` (creating the tag),
26
+ * `github-release` (finding the release that tag belongs to), and `detectChangeHash`'s own npm
27
27
  * fallback (mapping a published version back onto a tag), so all three name tags identically. */
28
28
  export function expandTag(pkg, version) {
29
29
  return applyTagPattern(tagPattern(pkg), pkg.name, version);