rman 1.0.12 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +90 -70
  2. package/cli.js +226 -14
  3. package/commands/build.command.js +1 -0
  4. package/commands/changed.command.js +2 -2
  5. package/commands/changelog.command.js +13 -15
  6. package/commands/config.command.js +61 -0
  7. package/commands/diff.command.js +9 -4
  8. package/commands/exec.command.js +2 -8
  9. package/commands/github-release.command.js +1 -0
  10. package/commands/info.command.d.ts +9 -0
  11. package/commands/info.command.js +12 -2
  12. package/commands/run.command.js +5 -8
  13. package/commands/test.command.js +1 -0
  14. package/commands/version.command.js +53 -14
  15. package/constants.js +1 -1
  16. package/core/config.d.ts +265 -17
  17. package/core/config.js +651 -76
  18. package/core/custom-command.d.ts +133 -0
  19. package/core/custom-command.js +99 -0
  20. package/core/extends-config.d.ts +27 -0
  21. package/core/extends-config.js +89 -0
  22. package/core/manifest.d.ts +222 -0
  23. package/core/manifest.js +150 -0
  24. package/core/merge-config.d.ts +70 -0
  25. package/core/merge-config.js +193 -0
  26. package/core/package.d.ts +73 -7
  27. package/core/package.js +86 -24
  28. package/core/plugin.d.ts +112 -0
  29. package/core/plugin.js +189 -0
  30. package/core/repository.d.ts +91 -1
  31. package/core/repository.js +277 -132
  32. package/core/resolve-target.d.ts +12 -0
  33. package/core/resolve-target.js +33 -0
  34. package/core/run-step.d.ts +75 -0
  35. package/core/run-step.js +1 -0
  36. package/core/version-scheme.d.ts +134 -0
  37. package/core/version-scheme.js +148 -0
  38. package/core/workspace.d.ts +68 -0
  39. package/core/workspace.js +83 -0
  40. package/index.d.ts +55 -8
  41. package/index.js +42 -7
  42. package/interfaces/rman-config.interface.d.ts +222 -46
  43. package/package.json +16 -7
  44. package/services/change-hash.service.d.ts +88 -0
  45. package/services/change-hash.service.js +112 -0
  46. package/services/changelog.service.d.ts +8 -13
  47. package/services/changelog.service.js +12 -11
  48. package/services/conventional-commits.service.d.ts +73 -0
  49. package/services/conventional-commits.service.js +116 -0
  50. package/services/docker-publish.service.js +1 -1
  51. package/services/exec.service.js +1 -1
  52. package/services/github-release.service.d.ts +2 -2
  53. package/services/github-release.service.js +10 -5
  54. package/services/list.service.js +5 -2
  55. package/services/run.service.d.ts +112 -6
  56. package/services/run.service.js +265 -89
  57. package/services/system-info.d.ts +22 -7
  58. package/services/system-info.js +8 -23
  59. package/services/version-plan.service.d.ts +244 -0
  60. package/services/version-plan.service.js +414 -0
  61. package/services/version.service.d.ts +102 -82
  62. package/services/version.service.js +226 -434
  63. package/services.d.ts +5 -3
  64. package/services.js +5 -3
  65. package/utils/bin-path.d.ts +59 -0
  66. package/utils/bin-path.js +82 -0
  67. package/utils/child-tracker.d.ts +16 -0
  68. package/utils/child-tracker.js +30 -0
  69. package/utils/exec.d.ts +13 -2
  70. package/utils/exec.js +17 -17
  71. package/utils/git.d.ts +9 -3
  72. package/utils/git.js +10 -2
  73. package/utils/package-filter.d.ts +33 -2
  74. package/utils/package-filter.js +47 -7
  75. package/utils/printable-config.d.ts +15 -0
  76. package/utils/printable-config.js +42 -0
  77. package/utils/release-version.js +3 -3
  78. package/utils/run-bin.d.ts +46 -0
  79. package/utils/run-bin.js +63 -0
  80. package/utils/version-stamp.d.ts +14 -6
  81. package/utils/version-stamp.js +25 -13
  82. package/commands/ci.command.js +0 -30
  83. package/commands/clean.command.d.ts +0 -3
  84. package/commands/clean.command.js +0 -36
  85. package/commands/publish.command.d.ts +0 -3
  86. package/commands/publish.command.js +0 -225
  87. package/rmanrc.schema.json +0 -392
  88. package/services/ci.service.d.ts +0 -40
  89. package/services/ci.service.js +0 -204
  90. package/services/clean.service.d.ts +0 -42
  91. package/services/clean.service.js +0 -226
  92. package/services/publish.service.d.ts +0 -79
  93. package/services/publish.service.js +0 -273
  94. package/utils/change-hash.d.ts +0 -68
  95. package/utils/change-hash.js +0 -98
  96. package/utils/conventional-commits.d.ts +0 -52
  97. package/utils/conventional-commits.js +0 -90
  98. package/utils/npm-run-path.d.ts +0 -67
  99. package/utils/npm-run-path.js +0 -63
  100. package/utils/workspace-range.d.ts +0 -17
  101. package/utils/workspace-range.js +0 -28
  102. /package/commands/{ci.command.d.ts → config.command.d.ts} +0 -0
@@ -1,33 +1,18 @@
1
1
  import type { Package } from '../core/package.js';
2
2
  import type { Repository } from '../core/repository.js';
3
- import { type PackageFilterOptions } from '../utils/package-filter.js';
3
+ import type { RunStepValue } from '../core/run-step.js';
4
+ import { VersionPlanService } from './version-plan.service.js';
5
+ /**
6
+ * Applying a version plan: the writes. Every manifest edit, dependency-range refresh, stamp,
7
+ * commit and tag lives here; **what** to write is `VersionPlanService`'s answer.
8
+ *
9
+ * Nothing here knows what a `package.json` is, names an npm script, or runs a command: the version
10
+ * goes through `Manifest`/`ManifestProvider`, refreshing a sibling's dependency range goes through
11
+ * the same provider, and the lifecycle hooks around the write go through
12
+ * `RunService.runLifecycleSlot` - this module only supplies the `.rmanrc version.<slot>` fallback,
13
+ * which is its own config. What is left is git, that config, and the version stamps.
14
+ */
4
15
  export declare namespace VersionService {
5
- type BumpKeyword = 'patch' | 'minor' | 'major';
6
- function isBumpKeyword(value: unknown): value is BumpKeyword;
7
- interface Options extends PackageFilterOptions {
8
- /** A release-type keyword (applied as the severity for every group that has real changes) or
9
- * a concrete semver version (applied as the literal new version wherever something changed) -
10
- * either way, this replaces auto-detection entirely. Omit to auto-detect the severity per
11
- * group from conventional-commit subjects since each package's/group's last release tag. */
12
- bump?: string;
13
- /** A package with uncommitted local changes is excluded from bumping (status `'skip'`)
14
- * instead of aborting the whole plan (status `'error'`). Default false. */
15
- ignoreDirty?: boolean;
16
- /** Makes every computed bump a prerelease (`1.2.3` -> `1.3.0-beta.0` for a `minor`, say)
17
- * tagged with this identifier, instead of a normal release - same idea as `npm version
18
- * <type> --preid <name>`. A group already sitting on a matching prerelease (same identifier)
19
- * just has its prerelease counter incremented instead of jumping to a new base version - see
20
- * `incVersion`. Has no effect when `bump` is an explicit semver version rather than a keyword
21
- * (there's no severity left to "pre-fix" at that point). */
22
- preid?: string;
23
- /** Overrides the npm registry lookup `detectChangeHash` falls back to for a package that has
24
- * no release tag yet - mainly for tests, so they don't depend on network access or a real
25
- * published package. Same shape as `ChangelogService.Deps`/`PublishService.Deps`' own. */
26
- npmViewVersion?: (name: string, cwd: string) => Promise<string | undefined>;
27
- /** Clock behind a monorepo root's calendar release version - injectable so tests are
28
- * deterministic. Default `() => new Date()`. */
29
- now?: () => Date;
30
- }
31
16
  interface ApplyOptions {
32
17
  /** Push the resulting commit(s) and tag(s) to the remote once applied. Default false - same
33
18
  * as a plain `npm version`, which never pushes on its own either. */
@@ -40,67 +25,102 @@ export declare namespace VersionService {
40
25
  * same per-group commit, instead of requiring a separate `rman changelog --write` run. */
41
26
  changelog?: boolean;
42
27
  }
43
- /** One package's outcome in a version plan - see `getPlan`. */
44
- interface Entry {
45
- package: Package;
46
- /** Internal group identity packages are batched by (not for display) - see `resolveGroupKey`. */
47
- groupKey: string;
48
- /** Human-readable group name: `'default'` for the implicit repo-wide group, the configured
49
- * name for a named `group`, or the package's own name when it isn't grouped with anyone. */
50
- group: string;
51
- status: 'bump' | 'skip' | 'error' | 'no-change';
52
- from: string;
53
- /** Only set when `status === 'bump'`. */
54
- to?: string;
55
- /** Human-readable explanation - e.g. why a package was skipped, or why it's being bumped
56
- * despite having no commits of its own (a dependency of it changed elsewhere). */
57
- reason?: string;
58
- }
59
28
  /**
60
- * Computes what a version bump *would* do, across every package `.rmanrc group` puts together -
61
- * never writes anything (no package.json edits, no git commits/tags) and safe to call any time,
62
- * including as the "preview" a bare `rman version` (no bump given) stops at.
63
- *
64
- * Packages are partitioned into groups by their resolved `group` value (cascaded): `true`
65
- * (the default) puts every such package into one implicit repo-wide group; a string joins
66
- * exactly the other packages sharing that same string, regardless of the repo's default; `false`
67
- * makes a package its own solo group. Each group's "current version" is always the highest
68
- * version currently found among its own members (never persisted anywhere) - see
69
- * `resolveGroupKey`.
29
+ * **What `applyPlan` actually did** - which is not derivable from the plan it was given.
70
30
  *
71
- * Within a group, a member with real commits since its own last release (or an explicit `bump`)
72
- * sets the group's severity to the highest found among changed members; the new version
73
- * is that current version bumped by that severity. Which members actually receive it depends on
74
- * the severity: **patch** only the changed member(s) (a caret dependency range already tolerates
75
- * a patch bump, no republish needed downstream); **minor** also every transitive in-group
76
- * dependent; **major** the entire group, changed or not - see `computeGroupPlan`.
31
+ * It used to return that plan, untouched, so the one caller could only re-print the table it had
32
+ * already shown while the commits, the tags and the push stayed silent - the three things a
33
+ * reader does not already know. A `version` run can produce several commits (one per group, plus
34
+ * the root's informational one), tag each group, add a repository release tag, and skip a tag that
35
+ * already existed; none of that is visible from the outside.
36
+ */
37
+ interface ApplyResult {
38
+ /** The plan, as given - `'bump'` entries included, so a caller can still relate the rest to it. */
39
+ entries: VersionPlanService.Entry[];
40
+ /** The entries whose manifest was actually written. **Not every `'bump'` entry**: a monorepo
41
+ * root's is informational, and `updated` is the number worth reporting. */
42
+ updated: VersionPlanService.Entry[];
43
+ commits: Commit[];
44
+ /** Every tag this run considered, in creation order. `created: false` means it was already
45
+ * there and left alone - which is a different outcome from having made it. */
46
+ tags: Tag[];
47
+ /** Whether `git push` ran. `false` is the default and the common case, and saying so is the
48
+ * point: a release that is committed but not pushed looks identical otherwise. */
49
+ pushed: boolean;
50
+ }
51
+ interface Commit {
52
+ /** Short sha. */
53
+ sha: string;
54
+ message: string;
55
+ /** The packages whose version this commit carries - empty for the root's informational sync. */
56
+ packages: string[];
57
+ }
58
+ interface Tag {
59
+ name: string;
60
+ created: boolean;
61
+ /** True for the repository's own release tag, which belongs to no single package. */
62
+ release?: boolean;
63
+ }
64
+ /**
65
+ * Writes every `'bump'` entry's new version into its own manifest (and refreshes any other bumped
66
+ * package's dependency range on it), runs that package's own version-lifecycle hooks or its
67
+ * `.rmanrc version.before`/`.exec`/`.after` around the write - see the `hook` closure below -
68
+ * then commits and tags **once per group** - so independently-versioned groups each get their own clean commit/tag rather than one entangled
69
+ * commit spanning unrelated version lines. Pushes only when `options.push` is set - same as a
70
+ * plain `npm version`, this never reaches the network on its own otherwise.
71
+ */
72
+ function applyPlan(repository: Repository, plan: VersionPlanService.Entry[], options?: ApplyOptions): Promise<ApplyResult>;
73
+ /** `.rmanrc version.commitMessage` (root-level; `{version}` is replaced when every bumped package
74
+ * in this commit shares one version) - defaults to `"chore(release): v{version}"`, or a plain
75
+ * listing of `name@version` pairs when this particular commit spans different versions (a
76
+ * cross-group ripple can land a lone forced patch in a group that otherwise didn't move). */
77
+ function buildCommitMessage(repository: Repository, entries: VersionPlanService.Entry[], messageOverride?: string): string;
78
+ /**
79
+ * A `version.<slot>` value: one step, or several to run in sequence - the same shape, and now the
80
+ * same function, as `run.<script>.before`/`.exec`/`.after`.
77
81
  *
78
- * Across groups: a package depending on another group's bumped package always gets exactly a
79
- * **patch** bump of its own (never inheriting the source's severity) - the dependency reference
80
- * itself is the only thing that changed for it. This never re-triggers *its own* group's
81
- * minor/major cascade (a patch never cascades), but can itself ripple into a third group, and so
82
- * on, until nothing new is affected - see `rippleCrossGroup`.
82
+ * It used to be a second implementation living here, and it differed in two ways that both had to
83
+ * go. It **joined an array with `' && '`** into one shell line, which a function step cannot be
84
+ * part of and which was not even right for shell steps - `cd x && y` in one process is not two
85
+ * processes. And it **dropped anything it did not recognize**, so a function here was silently
86
+ * never run. (The doc comment also still named `.script`/`.preScript`/`.postScript`, three keys
87
+ * that have been `before`/`exec`/`after` for a long time.)
88
+ */
89
+ function normalizeScriptValue(value: unknown, at: string): RunStepValue[];
90
+ /**
91
+ * Keeps a package's Dockerfile `org.opencontainers.image.version` label in step with the version
92
+ * just written, returning the absolute path when it actually changed (so the caller can fold it
93
+ * into the same commit) and `undefined` otherwise.
83
94
  *
84
- * A monorepo's root package is never a real member of any group (it's never published on its
85
- * own) - it gets one trailing entry instead, carrying the repository's own release identity: the
86
- * single group's version when there is one, a calendar version once there are several - see
87
- * `buildRootEntry`.
95
+ * Here rather than in a build script: the label is a *statement of the package's version*, so it
96
+ * belongs to whatever writes that version - which keeps it in the bump commit, leaves the tree
97
+ * clean, and makes it right for anyone building the Dockerfile by hand. A build-time rewrite is
98
+ * both later than it needs to be and invisible to git.
88
99
  *
89
- * "Since its own last release" is resolved by the shared `detectChangeHash` - the same boundary
90
- * `changelog` measures from, so the two never disagree about which commits are unreleased.
100
+ * The same path `publish --target docker` builds from (`publish.docker.dockerfile`, default
101
+ * `Dockerfile`), so the two can never disagree about which file this is. Opt out with `.rmanrc
102
+ * "version": { "stampDockerfile": false }`; a package with no Dockerfile, or one that doesn't
103
+ * declare the label, is a no-op either way.
91
104
  */
92
- function getPlan(repository: Repository, options?: Options): Promise<Entry[]>;
105
+ function stampDockerfile(pkg: Package, version: string): string | undefined;
93
106
  /**
94
- * Same as `getPlan`, and additionally writes every `'bump'` entry's new version into its own
95
- * `package.json` (and refreshes any other bumped package's dependency range on it), runs that
96
- * package's `version.preScript`/`.script`/`.postScript` (or its own real `preversion`/`version`/
97
- * `postversion` npm scripts) around the write, then commits and tags **once per group** - so
98
- * independently-versioned groups each get their own clean commit/tag rather than one entangled
99
- * commit spanning unrelated version lines. Pushes only when `options.push` is set - same as a
100
- * plain `npm version`, this never reaches the network on its own otherwise.
107
+ * Keeps every `.rmanrc "version.stamp"` file's hard-coded version in step with the one just
108
+ * written, returning the absolute paths of the ones that actually changed.
109
+ *
110
+ * Explicitly listed rather than discovered: unlike the OCI Dockerfile label there is no standard
111
+ * saying "this file holds the version". **A listed file a package does not have stays a silent
112
+ * no-op** - that is what lets one `"[*]"` declaration cover a repo where only some packages carry
113
+ * one.
114
+ *
115
+ * **A listed file that exists and cannot be stamped throws.** It used to be the same silent
116
+ * no-op as a missing file, and the two are not the same thing at all: the second means "not this
117
+ * package", the first means the repository asked for something and did not get it. Measured, and
118
+ * it is the bad kind of quiet - a package listing a file holding `const VERSION` (capital, so the
119
+ * pattern missed it) released a tagged commit with a stale constant and said nothing. The error
120
+ * names the file and, when the package's ecosystem declared none, says so.
121
+ *
122
+ * *How* a version is declared is the provider's (`ManifestProvider.stampVersion`); *which* files
123
+ * hold one is the repository's, which is why the list is config and the rewrite is a seam.
101
124
  */
102
- function applyPlan(repository: Repository, plan: Entry[], options?: ApplyOptions): Promise<Entry[]>;
125
+ function stampSourceFiles(pkg: Package, version: string): string[];
103
126
  }
104
- /** Every `package.json` field holding dependency ranges - shared with `PublishService`'s own
105
- * `"workspace:"` rewrite-for-publish step, since it needs to scan the same fields. */
106
- export declare const DEPENDENCY_KEYS: readonly ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];