rman 1.3.0 → 2.0.0-beta.3
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 +65 -31
- package/builtins/platforms/node/augmentation/rmanrc.augmentation.d.ts +83 -0
- package/builtins/platforms/node/augmentation/system-info.augmentation.d.ts +26 -0
- package/builtins/platforms/node/augmentation/system-info.augmentation.js +79 -0
- package/builtins/platforms/node/commands/ci.command.d.ts +133 -0
- package/builtins/platforms/node/commands/ci.command.js +60 -0
- package/builtins/platforms/node/commands/clean.command.d.ts +185 -0
- package/builtins/platforms/node/commands/clean.command.js +74 -0
- package/builtins/platforms/node/index.d.ts +8 -0
- package/builtins/platforms/node/index.js +8 -0
- package/builtins/platforms/node/node-config.interface.d.ts +76 -0
- package/builtins/platforms/node/node-config.interface.js +7 -0
- package/builtins/platforms/node/node-manifest.provider.d.ts +68 -0
- package/builtins/platforms/node/node-manifest.provider.js +125 -0
- package/builtins/platforms/node/node.platform.d.ts +53 -0
- package/builtins/platforms/node/node.platform.js +134 -0
- package/builtins/platforms/node/services/ci.service.d.ts +47 -0
- package/builtins/platforms/node/services/ci.service.js +213 -0
- package/builtins/platforms/node/services/clean.service.d.ts +53 -0
- package/builtins/platforms/node/services/clean.service.js +237 -0
- package/builtins/platforms/node/services/publish.service.d.ts +114 -0
- package/builtins/platforms/node/services/publish.service.js +371 -0
- package/builtins/platforms/node/services/version-plan.service.d.ts +44 -0
- package/builtins/platforms/node/services/version-plan.service.js +58 -0
- package/builtins/platforms/node/utils/workspace-range.d.ts +26 -0
- package/builtins/platforms/node/utils/workspace-range.js +28 -0
- package/builtins/presets/index.d.ts +15 -0
- package/builtins/presets/index.js +57 -0
- package/builtins/presets/node.d.ts +16 -0
- package/builtins/presets/node.js +57 -0
- package/{services → builtins/publish-targets/docker}/docker-publish.service.d.ts +52 -31
- package/{services → builtins/publish-targets/docker}/docker-publish.service.js +49 -26
- package/builtins/publish-targets/docker/docker.target.d.ts +54 -0
- package/builtins/publish-targets/docker/docker.target.js +40 -0
- package/builtins/publish-targets/docker/index.d.ts +2 -0
- package/builtins/publish-targets/docker/index.js +2 -0
- package/builtins/publish-targets/npm/index.d.ts +2 -0
- package/builtins/publish-targets/npm/index.js +2 -0
- package/builtins/publish-targets/npm/npm-publish-target.d.ts +73 -0
- package/builtins/publish-targets/npm/npm-publish-target.js +95 -0
- package/builtins/publish-targets/npm/npm-view.d.ts +48 -0
- package/builtins/publish-targets/npm/npm-view.js +71 -0
- package/cli.d.ts +8 -0
- package/cli.js +228 -93
- package/commands/build.command.d.ts +177 -3
- package/commands/build.command.js +20 -10
- package/commands/changelog.command.d.ts +296 -3
- package/commands/changelog.command.js +127 -43
- package/commands/config.command.d.ts +44 -3
- package/commands/config.command.js +53 -24
- package/commands/diff.command.d.ts +37 -3
- package/commands/diff.command.js +25 -16
- package/commands/exec.command.d.ts +193 -3
- package/commands/exec.command.js +60 -58
- package/commands/github-release.command.d.ts +154 -3
- package/commands/github-release.command.js +67 -37
- package/commands/import.command.d.ts +36 -3
- package/commands/import.command.js +28 -20
- package/commands/info.command.d.ts +35 -7
- package/commands/info.command.js +36 -30
- package/commands/lint.command.d.ts +176 -0
- package/commands/lint.command.js +34 -0
- package/commands/list.command.d.ts +163 -3
- package/commands/list.command.js +109 -71
- package/commands/publish.command.d.ts +231 -0
- package/commands/publish.command.js +304 -0
- package/commands/run.command.d.ts +186 -6
- package/commands/run.command.js +26 -72
- package/commands/test.command.d.ts +173 -3
- package/commands/test.command.js +16 -10
- package/commands/version.command.d.ts +330 -3
- package/commands/version.command.js +292 -78
- package/commands.d.ts +32 -0
- package/commands.js +28 -0
- package/constants.js +1 -1
- package/core/application.d.ts +116 -0
- package/core/application.js +160 -0
- package/core/classes/package.d.ts +219 -0
- package/core/classes/package.js +214 -0
- package/core/classes/registry.d.ts +30 -0
- package/core/classes/registry.js +47 -0
- package/core/{repository.d.ts → classes/repository.d.ts} +69 -20
- package/core/{repository.js → classes/repository.js} +195 -75
- package/core/classes/service.d.ts +49 -0
- package/core/classes/service.js +40 -0
- package/core/{version-scheme.d.ts → classes/version-scheme.d.ts} +23 -1
- package/core/{version-scheme.js → classes/version-scheme.js} +29 -1
- package/core/classes/workspace.d.ts +275 -0
- package/core/classes/workspace.js +537 -0
- package/core/command-builder.d.ts +14 -0
- package/core/command-builder.js +94 -0
- package/core/config/config-file-scope.d.ts +107 -0
- package/core/config/config-file-scope.js +226 -0
- package/core/config/config-interpolator.d.ts +164 -0
- package/core/config/config-interpolator.js +577 -0
- package/core/config/config-paths.d.ts +65 -0
- package/core/config/config-paths.js +78 -0
- package/core/config/config-reader.d.ts +192 -0
- package/core/config/config-reader.js +727 -0
- package/core/{merge-config.d.ts → config/merge-config.d.ts} +33 -34
- package/core/config/merge-config.js +260 -0
- package/core/{resolve-target.d.ts → config/resolve-config-target.d.ts} +1 -1
- package/core/{resolve-target.js → config/resolve-config-target.js} +1 -1
- package/core/{custom-command.d.ts → interfaces/custom-command.d.ts} +46 -10
- package/core/{custom-command.js → interfaces/custom-command.js} +44 -17
- package/core/{manifest.d.ts → interfaces/manifest.d.ts} +49 -27
- package/core/interfaces/manifest.js +132 -0
- package/core/interfaces/plugin.d.ts +174 -0
- package/core/interfaces/plugin.js +124 -0
- package/core/interfaces/publish-target.d.ts +136 -0
- package/core/interfaces/publish-target.js +43 -0
- package/core/{run-step.d.ts → interfaces/run-step.d.ts} +4 -4
- package/core/interfaces/run-step.js +1 -0
- package/core/plugin-loader.d.ts +25 -0
- package/core/plugin-loader.js +53 -0
- package/index.d.ts +122 -24
- package/index.js +66 -16
- package/interfaces/config-scope.interface.d.ts +223 -0
- package/interfaces/config-scope.interface.js +1 -0
- package/interfaces/rman-config.interface.d.ts +821 -203
- package/interfaces/rman-config.interface.js +78 -1
- package/package.json +3 -1
- package/services/change-hash.service.d.ts +42 -8
- package/services/change-hash.service.js +92 -13
- package/services/changelog.service.d.ts +91 -52
- package/services/changelog.service.js +460 -74
- package/services/config-service.d.ts +8 -0
- package/services/config-service.js +3 -0
- package/services/exec.service.d.ts +23 -12
- package/services/exec.service.js +14 -9
- package/services/github-release.service.d.ts +45 -34
- package/services/github-release.service.js +15 -12
- package/services/import.service.d.ts +25 -14
- package/services/import.service.js +9 -5
- package/services/list.service.d.ts +67 -13
- package/services/list.service.js +62 -15
- package/services/run.service.d.ts +35 -22
- package/services/run.service.js +316 -233
- package/services/system-info.d.ts +1 -1
- package/services/version-plan.service.d.ts +35 -8
- package/services/version-plan.service.js +96 -36
- package/services/version.service.d.ts +34 -14
- package/services/version.service.js +35 -16
- package/services.d.ts +1 -1
- package/services.js +1 -1
- package/utils/bin-path.d.ts +6 -7
- package/utils/bin-path.js +7 -18
- package/utils/branch-guard.d.ts +30 -1
- package/utils/branch-guard.js +31 -0
- package/utils/color-yaml.d.ts +8 -0
- package/utils/color-yaml.js +86 -0
- package/utils/exec.d.ts +10 -0
- package/utils/exec.js +1 -1
- package/utils/git.d.ts +26 -0
- package/utils/git.js +65 -0
- package/utils/logger.d.ts +2 -2
- package/utils/logger.js +1 -1
- package/utils/package-filter.d.ts +135 -8
- package/utils/package-filter.js +204 -16
- package/utils/printable-config.d.ts +9 -1
- package/utils/printable-config.js +46 -1
- package/utils/progress-panel.d.ts +9 -0
- package/utils/progress-panel.js +23 -1
- package/utils/release-version.d.ts +1 -1
- package/utils/run-bin.d.ts +10 -0
- package/utils/run-bin.js +1 -1
- package/utils/run-options.d.ts +97 -0
- package/utils/run-options.js +81 -0
- package/utils/version-group.d.ts +31 -0
- package/utils/version-group.js +43 -0
- package/utils/version-stamp.d.ts +1 -1
- package/utils/version-stamp.js +1 -1
- package/commands/changed.command.d.ts +0 -3
- package/commands/changed.command.js +0 -29
- package/core/config.d.ts +0 -409
- package/core/config.js +0 -939
- package/core/extends-config.d.ts +0 -27
- package/core/extends-config.js +0 -89
- package/core/manifest.js +0 -150
- package/core/merge-config.js +0 -219
- package/core/package.d.ts +0 -83
- package/core/package.js +0 -106
- package/core/plugin.d.ts +0 -112
- package/core/plugin.js +0 -189
- package/core/workspace.d.ts +0 -68
- package/core/workspace.js +0 -83
- /package/{core/run-step.js → builtins/platforms/node/augmentation/rmanrc.augmentation.js} +0 -0
package/utils/branch-guard.js
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
import colors from 'ansi-colors';
|
|
2
2
|
import micromatch from 'micromatch';
|
|
3
3
|
import { GitHelper } from './git.js';
|
|
4
|
+
/**
|
|
5
|
+
* `--allow-branch`/`--ignore-branch` as a declaration, to spread into a command's `config` block.
|
|
6
|
+
* See `packageFilterOptions` for why this is `satisfies` rather than an annotation.
|
|
7
|
+
*
|
|
8
|
+
* **The key is the camelCase one and `cliName` carries the flag's spelling.** `allowBranch` is what
|
|
9
|
+
* a `.rmanrc` writes and what `assertAllowedBranch` reads off the config; `--allow-branch` is what
|
|
10
|
+
* the shell sees. The `Argv` version relied on yargs converting one into the other silently, which
|
|
11
|
+
* is why `applyBranchGuardOptions` declares `'allow-branch'` and `readBranchGuardOptions` reads
|
|
12
|
+
* `args.allowBranch`.
|
|
13
|
+
*
|
|
14
|
+
* **`target: 'cli'`, even though `allowBranch` *is* a config key.** It is a repo-wide core key read
|
|
15
|
+
* off the root, not any command's - so it belongs on `RmanConfig` directly, and a command that
|
|
16
|
+
* reads it names it in `configKeys`. Declaring it `'both'` here would contribute `version.allowBranch`,
|
|
17
|
+
* which nothing reads.
|
|
18
|
+
*/
|
|
19
|
+
export const branchGuardOptions = {
|
|
20
|
+
allowBranch: {
|
|
21
|
+
target: 'cli',
|
|
22
|
+
cliName: 'allow-branch',
|
|
23
|
+
describe: 'Refuse to run unless the current branch matches this glob (repeatable) - default: .rmanrc ' +
|
|
24
|
+
'"allowBranch", or no restriction at all',
|
|
25
|
+
type: 'string',
|
|
26
|
+
},
|
|
27
|
+
ignoreBranch: {
|
|
28
|
+
target: 'cli',
|
|
29
|
+
cliName: 'ignore-branch',
|
|
30
|
+
describe: 'Refuse to run if the current branch matches this glob (repeatable) - default: .rmanrc ' +
|
|
31
|
+
'"ignoreBranch", or no restriction at all',
|
|
32
|
+
type: 'string',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
4
35
|
/** `--allow-branch`/`--ignore-branch`, the same shape and describe text in every command that
|
|
5
36
|
* supports them - mirrors `package-filter.ts`'s own `applyPackageFilterOptions`. */
|
|
6
37
|
export function applyBranchGuardOptions(cmd) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A YAML document with syntax colour, for the two commands that print one to be **looked at** -
|
|
3
|
+
* `rman config` and `--config`.
|
|
4
|
+
*
|
|
5
|
+
* **Only call this when `process.stdout.isTTY`.** Colouring a document that is being redirected
|
|
6
|
+
* makes it unloadable, which is the whole reason the callers gate on a terminal.
|
|
7
|
+
*/
|
|
8
|
+
export declare function colorYaml(text: string): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import colors from 'ansi-colors';
|
|
2
|
+
/**
|
|
3
|
+
* A YAML document with syntax colour, for the two commands that print one to be **looked at** -
|
|
4
|
+
* `rman config` and `--config`.
|
|
5
|
+
*
|
|
6
|
+
* **Only call this when `process.stdout.isTTY`.** Colouring a document that is being redirected
|
|
7
|
+
* makes it unloadable, which is the whole reason the callers gate on a terminal.
|
|
8
|
+
*/
|
|
9
|
+
/* **Line-based and deliberately shallow.** This is a highlighter, not a parser: it colours what a
|
|
10
|
+
* reader's eye uses to navigate - the key, the list marker, a literal - and leaves anything it is
|
|
11
|
+
* not sure about alone. A real parse would have to round-trip js-yaml's own output to gain nothing
|
|
12
|
+
* a reader would notice, and every extra rule is a new way to mangle a value.
|
|
13
|
+
*
|
|
14
|
+
* **What it colours and why that set**:
|
|
15
|
+
*
|
|
16
|
+
* - the **key**, in cyan, because that is what you scan a config for;
|
|
17
|
+
* - **`${{ ... }}`**, in magenta, because rman's configs are full of them and because a `version`
|
|
18
|
+
* hook is printed *raw* (`DEFERRED_PATHS`) - the one place an unresolved expression is correct
|
|
19
|
+
* rather than a bug, and the colour is what stops it reading as a mistake;
|
|
20
|
+
* - **numbers, booleans and `null`**, in yellow, since `skip: false` and `skip: "false"` mean
|
|
21
|
+
* different things and nothing else in the output tells them apart;
|
|
22
|
+
* - **`[Function: name]`**, in grey, because it is this printer's placeholder rather than anything
|
|
23
|
+
* the config says - the one value in the output that is not a value;
|
|
24
|
+
* - the **`-`** of a list item and a `#` comment, in grey, as structure rather than content.
|
|
25
|
+
*
|
|
26
|
+
* A plain string value is left uncoloured on purpose. It is the *content*, usually the longest
|
|
27
|
+
* thing on the line, and colouring it competes with the key for attention - which is the failure
|
|
28
|
+
* mode of a highlighter that paints everything.
|
|
29
|
+
*
|
|
30
|
+
* **The two places a shallow pass has to be careful, and neither is hypothetical:**
|
|
31
|
+
*
|
|
32
|
+
* - **A `:` inside a value.** js-yaml quotes any scalar holding one, so the line is
|
|
33
|
+
* `key: 'a: b'` - and the key pattern stops at the *first* colon, which is the right one. Nothing
|
|
34
|
+
* to do, but it is why the pattern is written `[^:]*` rather than anything greedier.
|
|
35
|
+
* - **A folded block scalar.** `lineWidth: 100` makes js-yaml emit `describe: >-` and continue on
|
|
36
|
+
* deeper-indented lines, and a continuation line is prose: one holding `(default: ...)` would
|
|
37
|
+
* otherwise have half a sentence coloured as a key. So the block's indent is tracked and its
|
|
38
|
+
* content is left alone but for expressions. A `#` there is prose too, not a comment. */
|
|
39
|
+
export function colorYaml(text) {
|
|
40
|
+
/** The indent of the key that opened a block scalar, while one is open. Anything indented past it
|
|
41
|
+
* is that block's content; the first line that is not ends it. */
|
|
42
|
+
let blockIndent;
|
|
43
|
+
return text
|
|
44
|
+
.split('\n')
|
|
45
|
+
.map(line => {
|
|
46
|
+
const indent = line.length - line.trimStart().length;
|
|
47
|
+
if (blockIndent !== undefined) {
|
|
48
|
+
if (line.trim() === '' || indent > blockIndent)
|
|
49
|
+
return colorExpressions(line);
|
|
50
|
+
blockIndent = undefined;
|
|
51
|
+
}
|
|
52
|
+
if (BLOCK_SCALAR.test(line))
|
|
53
|
+
blockIndent = indent;
|
|
54
|
+
return colorLine(line);
|
|
55
|
+
})
|
|
56
|
+
.join('\n');
|
|
57
|
+
}
|
|
58
|
+
/** `key: >-`, `key: |`, `key: >2-`, and the bare `- >-` of a list item. */
|
|
59
|
+
const BLOCK_SCALAR = /:\s*[|>][0-9]*[-+]?\s*$/;
|
|
60
|
+
const EXPRESSION = /\$\{\{[\s\S]*?\}\}/g;
|
|
61
|
+
const LITERAL = /^(true|false|null|~|-?\d+(?:\.\d+)?)$/;
|
|
62
|
+
const FUNCTION = /^"?\[Function(?::[^\]]*)?\]"?$/;
|
|
63
|
+
function colorLine(line) {
|
|
64
|
+
const comment = /^(\s*)#(.*)$/.exec(line);
|
|
65
|
+
if (comment)
|
|
66
|
+
return comment[1] + colors.gray(`#${comment[2]}`);
|
|
67
|
+
/** `indent`, an optional `- ` for a list item, then either `key:` plus a value or a bare item. */
|
|
68
|
+
const parsed = /^(\s*)(- )?(?:([^\s:][^:]*):(\s|$))?([\s\S]*)$/.exec(line);
|
|
69
|
+
if (!parsed)
|
|
70
|
+
return line;
|
|
71
|
+
const [, indent = '', dash, key, gap = '', rest = ''] = parsed;
|
|
72
|
+
return indent + (dash ? colors.gray(dash) : '') + (key ? `${colors.cyan(key)}:${gap}` : '') + colorValue(rest);
|
|
73
|
+
}
|
|
74
|
+
function colorValue(value) {
|
|
75
|
+
const trimmed = value.trim();
|
|
76
|
+
if (!trimmed)
|
|
77
|
+
return value;
|
|
78
|
+
if (LITERAL.test(trimmed))
|
|
79
|
+
return value.replace(trimmed, colors.yellow(trimmed));
|
|
80
|
+
if (FUNCTION.test(trimmed))
|
|
81
|
+
return value.replace(trimmed, colors.gray(trimmed));
|
|
82
|
+
return colorExpressions(value);
|
|
83
|
+
}
|
|
84
|
+
function colorExpressions(value) {
|
|
85
|
+
return value.replace(EXPRESSION, match => colors.magenta(match));
|
|
86
|
+
}
|
package/utils/exec.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import type { RmanApplication } from '../core/application.js';
|
|
1
2
|
export interface ExecOptions {
|
|
3
|
+
/**
|
|
4
|
+
* The application whose technologies put a repository's locally installed binaries on PATH -
|
|
5
|
+
* `node_modules/.bin` for a Node repository, whatever another technology uses.
|
|
6
|
+
*
|
|
7
|
+
* Passed rather than looked up, so a command run against one repository can never pick up the
|
|
8
|
+
* binaries of another in the same process. Omitted (a caller outside any repository) leaves the
|
|
9
|
+
* inherited PATH exactly as it was, which is also what a repository naming no plugin gets.
|
|
10
|
+
*/
|
|
11
|
+
app?: RmanApplication;
|
|
2
12
|
/** 'inherit' streams the child directly to our stdio (used for non-TTY/CI passthrough).
|
|
3
13
|
* 'pipe' (default) captures output so the caller can drive a live view via onLine. */
|
|
4
14
|
stdio?: 'inherit' | 'pipe';
|
package/utils/exec.js
CHANGED
package/utils/git.d.ts
CHANGED
|
@@ -46,6 +46,19 @@ export declare class GitHelper {
|
|
|
46
46
|
/** Tag names matching the glob `pattern` (e.g. `"v*"`, `"pkg-a@*"`), newest version first. */
|
|
47
47
|
listTags(pattern: string): Promise<string[]>;
|
|
48
48
|
/** Whether `tag` exists as an exact git tag name (not a glob - a literal ref check). */
|
|
49
|
+
/**
|
|
50
|
+
* Every tag matching `pattern`, paired with the **commit** it points at - newest version first,
|
|
51
|
+
* the same order `listTags` returns.
|
|
52
|
+
*
|
|
53
|
+
* `%(*objectname)` is the dereferenced target and is empty for a lightweight tag, so the commit
|
|
54
|
+
* is that or `%(objectname)`. rman's own tags are lightweight; a repository's existing ones may
|
|
55
|
+
* not be, and an annotated tag's `objectname` is the *tag object*, which matches no commit and
|
|
56
|
+
* would make the tag silently invisible to anything comparing shas.
|
|
57
|
+
*/
|
|
58
|
+
listTagCommits(pattern: string): Promise<{
|
|
59
|
+
tag: string;
|
|
60
|
+
sha: string;
|
|
61
|
+
}[]>;
|
|
49
62
|
tagExists(tag: string): Promise<boolean>;
|
|
50
63
|
/** The most recent commit that changed `file` (tracked history only) - `undefined` if it has
|
|
51
64
|
* never been committed. Answers "since when has this file last been updated", independent of
|
|
@@ -61,6 +74,19 @@ export declare class GitHelper {
|
|
|
61
74
|
/** The repository's very first commit (the oldest root commit, for a history with several) -
|
|
62
75
|
* `undefined` for a repository with no commits at all. The "since the beginning" boundary for
|
|
63
76
|
* a package being released for the first time, with no earlier tag to measure from. */
|
|
77
|
+
/** HEAD's own sha, or `undefined` in a repository with no commits yet (or none at all) - the
|
|
78
|
+
* same "answer nothing rather than throw" shape `rootCommit` and `describeTag` take, because
|
|
79
|
+
* every caller here already has a "nothing to go on" branch. */
|
|
80
|
+
/** The date a ref points at, as `YYYY-MM-DD`. The **committer** date, not the author's: a
|
|
81
|
+
* rebased or cherry-picked release commit was authored earlier than it shipped, and what a
|
|
82
|
+
* changelog heading states is when the release happened. `undefined` for a ref that resolves to
|
|
83
|
+
* nothing. */
|
|
84
|
+
commitDate(ref: string): Promise<string | undefined>;
|
|
85
|
+
/** The commit `ref` names - a sha, a tag, a branch - or `undefined` when git does not recognize
|
|
86
|
+
* it. `^{commit}` so an annotated tag answers with the commit rather than the tag object, and
|
|
87
|
+
* so a tree or blob answers with nothing rather than a sha that matches no commit. */
|
|
88
|
+
resolveCommit(ref: string): Promise<string | undefined>;
|
|
89
|
+
headSha(): Promise<string | undefined>;
|
|
64
90
|
rootCommit(): Promise<string | undefined>;
|
|
65
91
|
/**
|
|
66
92
|
* Stages and commits exactly `files` (relative to `cwd`, or absolute) with `message` - never a
|
package/utils/git.js
CHANGED
|
@@ -148,6 +148,32 @@ export class GitHelper {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
/** Whether `tag` exists as an exact git tag name (not a glob - a literal ref check). */
|
|
151
|
+
/**
|
|
152
|
+
* Every tag matching `pattern`, paired with the **commit** it points at - newest version first,
|
|
153
|
+
* the same order `listTags` returns.
|
|
154
|
+
*
|
|
155
|
+
* `%(*objectname)` is the dereferenced target and is empty for a lightweight tag, so the commit
|
|
156
|
+
* is that or `%(objectname)`. rman's own tags are lightweight; a repository's existing ones may
|
|
157
|
+
* not be, and an annotated tag's `objectname` is the *tag object*, which matches no commit and
|
|
158
|
+
* would make the tag silently invisible to anything comparing shas.
|
|
159
|
+
*/
|
|
160
|
+
async listTagCommits(pattern) {
|
|
161
|
+
try {
|
|
162
|
+
const { stdout } = await execFileAsync('git', ['tag', '--list', pattern, '--sort=-v:refname', '--format=%(refname:short)%09%(objectname)%09%(*objectname)'], { cwd: this.cwd });
|
|
163
|
+
return stdout
|
|
164
|
+
.trim()
|
|
165
|
+
.split(/\r?\n/)
|
|
166
|
+
.filter(Boolean)
|
|
167
|
+
.map(line => {
|
|
168
|
+
const [tag, objectname, deref] = line.split('\t');
|
|
169
|
+
return { tag, sha: deref || objectname };
|
|
170
|
+
})
|
|
171
|
+
.filter(t => t.tag && t.sha);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
151
177
|
async tagExists(tag) {
|
|
152
178
|
try {
|
|
153
179
|
await execFileAsync('git', ['rev-parse', '--verify', '--quiet', `refs/tags/${tag}`], { cwd: this.cwd });
|
|
@@ -197,6 +223,45 @@ export class GitHelper {
|
|
|
197
223
|
/** The repository's very first commit (the oldest root commit, for a history with several) -
|
|
198
224
|
* `undefined` for a repository with no commits at all. The "since the beginning" boundary for
|
|
199
225
|
* a package being released for the first time, with no earlier tag to measure from. */
|
|
226
|
+
/** HEAD's own sha, or `undefined` in a repository with no commits yet (or none at all) - the
|
|
227
|
+
* same "answer nothing rather than throw" shape `rootCommit` and `describeTag` take, because
|
|
228
|
+
* every caller here already has a "nothing to go on" branch. */
|
|
229
|
+
/** The date a ref points at, as `YYYY-MM-DD`. The **committer** date, not the author's: a
|
|
230
|
+
* rebased or cherry-picked release commit was authored earlier than it shipped, and what a
|
|
231
|
+
* changelog heading states is when the release happened. `undefined` for a ref that resolves to
|
|
232
|
+
* nothing. */
|
|
233
|
+
async commitDate(ref) {
|
|
234
|
+
try {
|
|
235
|
+
const { stdout } = await execFileAsync('git', ['log', '-1', '--format=%cI', ref], { cwd: this.cwd });
|
|
236
|
+
return stdout.trim().slice(0, 10) || undefined;
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/** The commit `ref` names - a sha, a tag, a branch - or `undefined` when git does not recognize
|
|
243
|
+
* it. `^{commit}` so an annotated tag answers with the commit rather than the tag object, and
|
|
244
|
+
* so a tree or blob answers with nothing rather than a sha that matches no commit. */
|
|
245
|
+
async resolveCommit(ref) {
|
|
246
|
+
try {
|
|
247
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], {
|
|
248
|
+
cwd: this.cwd,
|
|
249
|
+
});
|
|
250
|
+
return stdout.trim() || undefined;
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async headSha() {
|
|
257
|
+
try {
|
|
258
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', 'HEAD'], { cwd: this.cwd });
|
|
259
|
+
return stdout.trim() || undefined;
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
200
265
|
async rootCommit() {
|
|
201
266
|
try {
|
|
202
267
|
const { stdout } = await execFileAsync('git', ['rev-list', '--max-parents=0', 'HEAD'], { cwd: this.cwd });
|
package/utils/logger.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Repository } from '../core/repository.js';
|
|
1
|
+
import type { Repository } from '../core/classes/repository.js';
|
|
2
2
|
export type LogLevel = 'silent' | 'error' | 'info' | 'verbose';
|
|
3
3
|
export declare const LOG_LEVELS: LogLevel[];
|
|
4
4
|
/**
|
|
5
5
|
* Gates console output by verbosity (`--log-level`/`.rmanrc logLevel`) so a command's routine
|
|
6
6
|
* narration can be turned down without losing failure output - the same semantics `run`'s own
|
|
7
|
-
* classic per-step log already used (see `resolveLogLevel` in `commands/run.ts`), centralized here
|
|
7
|
+
* classic per-step log already used (see `resolveLogLevel` in `commands/run.command.ts`), centralized here
|
|
8
8
|
* so every command can respect `--log-level` instead of reimplementing the checks, or ignoring it
|
|
9
9
|
* altogether via plain `console.log`.
|
|
10
10
|
*/
|
package/utils/logger.js
CHANGED
|
@@ -2,7 +2,7 @@ export const LOG_LEVELS = ['silent', 'error', 'info', 'verbose'];
|
|
|
2
2
|
/**
|
|
3
3
|
* Gates console output by verbosity (`--log-level`/`.rmanrc logLevel`) so a command's routine
|
|
4
4
|
* narration can be turned down without losing failure output - the same semantics `run`'s own
|
|
5
|
-
* classic per-step log already used (see `resolveLogLevel` in `commands/run.ts`), centralized here
|
|
5
|
+
* classic per-step log already used (see `resolveLogLevel` in `commands/run.command.ts`), centralized here
|
|
6
6
|
* so every command can respect `--log-level` instead of reimplementing the checks, or ignoring it
|
|
7
7
|
* altogether via plain `console.log`.
|
|
8
8
|
*/
|
|
@@ -1,15 +1,41 @@
|
|
|
1
1
|
import type { Argv } from 'yargs';
|
|
2
|
-
import type { Package } from '../core/package.js';
|
|
2
|
+
import type { Package } from '../core/classes/package.js';
|
|
3
3
|
/** Shared by every command that iterates packages (`run`/`build`/`test`/`exec`, `list`, `ci`,
|
|
4
4
|
* `clean`, `version`, `publish`, `changelog`) - narrows *which* packages a command applies to,
|
|
5
5
|
* independent of what the command actually does to them. The repository's own standing filter,
|
|
6
6
|
* `.rmanrc "skip"`, is applied by `filterPackages` itself rather than being an option here: it is
|
|
7
7
|
* the repository's statement, not the caller's. */
|
|
8
8
|
export interface PackageFilterOptions {
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* The technologies the **command itself** is for - `clean` and `ci` are npm's alone. Absent means
|
|
11
|
+
* every platform, which is what a command that speaks for no one in particular says.
|
|
12
|
+
*
|
|
13
|
+
* Declared as `CommandMetadata.platforms` and carried here; a repository never writes it.
|
|
14
|
+
*/
|
|
15
|
+
commandPlatforms?: string[];
|
|
16
|
+
/** Only include packages whose name matches at least one of these globs (e.g. `@scope/*`), or
|
|
17
|
+
* **`"/"`** for the repository's own root package - see `ROOT_SELECTOR`. */
|
|
10
18
|
scope?: string | string[];
|
|
11
|
-
/** Exclude packages whose name matches at least one of these globs - applied after
|
|
19
|
+
/** Exclude packages whose name matches at least one of these globs (or `"/"`) - applied after
|
|
20
|
+
* `scope`. */
|
|
12
21
|
ignore?: string | string[];
|
|
22
|
+
/**
|
|
23
|
+
* Only include packages belonging to one of these **platforms** (`Package.provider`) - `['node']`,
|
|
24
|
+
* or `'node,cargo'` as one comma-separated value.
|
|
25
|
+
*
|
|
26
|
+
* **Which technology a package belongs to only became a per-package question when the walk
|
|
27
|
+
* started finding nested packages of another platform**, and this is the filter that question
|
|
28
|
+
* needs: in a polyglot repository `rman run build --platform node` is the whole npm half of it,
|
|
29
|
+
* and there was no way to say that. Where every package is one technology it selects everything
|
|
30
|
+
* or nothing, which is the honest answer rather than a flag that does nothing.
|
|
31
|
+
*
|
|
32
|
+
* **Names, not globs.** A platform's name is a short identifier a plugin chose (`'node'`), so the
|
|
33
|
+
* set of valid values is known and finite - which is also why a name that no package in the
|
|
34
|
+
* repository belongs to is an **error** listing the ones that are there, the same call
|
|
35
|
+
* `publish --target` makes. A glob would put this back to guessing, and a typo back to a silent
|
|
36
|
+
* empty result.
|
|
37
|
+
*/
|
|
38
|
+
platform?: string | string[];
|
|
13
39
|
/** Also include every package the matched set depends on (transitively) - e.g. to build
|
|
14
40
|
* everything a scoped app actually needs. */
|
|
15
41
|
deps?: boolean;
|
|
@@ -17,6 +43,99 @@ export interface PackageFilterOptions {
|
|
|
17
43
|
* everything that could be affected by a scoped library's change. */
|
|
18
44
|
dependents?: boolean;
|
|
19
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* **`--scope /` is the repository's own root package**, the one selector that is not a glob.
|
|
48
|
+
*
|
|
49
|
+
* The same `/` `.rmanrc`'s `"[/]"` block uses, and for the same reason stated there: *the root is
|
|
50
|
+
* never selected by name.* A glob matches package names, and a name can be anything - so
|
|
51
|
+
* `--scope rman-repo` happened to work (measured) while being exactly the name-based addressing the
|
|
52
|
+
* config selectors were redesigned to remove. `/` is structural, cannot collide with a package
|
|
53
|
+
* (nothing can be named it), and gives "the root" one spelling across config and CLI.
|
|
54
|
+
*
|
|
55
|
+
* Accepted by `--ignore` too. The asymmetry would be the thing to remember, and `--ignore /` -
|
|
56
|
+
* every package but the root - is a real thing to want of `clean`.
|
|
57
|
+
*
|
|
58
|
+
* **It selects nothing on a command whose candidates exclude the root**, which is most of them:
|
|
59
|
+
* `repository.packages` holds the workspace members only, so `rman list --scope /` and
|
|
60
|
+
* `rman run build --scope /` match nothing and say so. That is the honest answer rather than a
|
|
61
|
+
* special case - the root has no `list` row and contributes only `pre`/`post` bookends to `run`.
|
|
62
|
+
* `clean` and `changelog`, which put the root in their candidate list on purpose, are where it bites.
|
|
63
|
+
*/
|
|
64
|
+
export declare const ROOT_SELECTOR = "/";
|
|
65
|
+
/**
|
|
66
|
+
* `--scope`/`--ignore`/`--deps`/`--dependents` as a **declaration** rather than a builder call -
|
|
67
|
+
* spread into a command's `config` block:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* config: { ...packageFilterOptions, ...branchGuardOptions, changelog: { ... } }
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* **`satisfies`, never a `: Record<...>` annotation.** An annotation widens `type: 'string'` back to
|
|
74
|
+
* `string`, and every type derived from the declaration - the config contribution, the option's own
|
|
75
|
+
* value type - collapses with it. `satisfies` checks the shape and keeps the literals, and it also
|
|
76
|
+
* catches a misspelled key *here*, at the group's own line, rather than in the ten commands that
|
|
77
|
+
* spread it. The `Argv` chaining this replaces could not: a typo there was simply a new option.
|
|
78
|
+
*
|
|
79
|
+
* **Every option is `target: 'cli'`, including the ones that have a config twin.** A shared group
|
|
80
|
+
* belongs to no command, so declaring one `'both'` would contribute `version.scope` - a key nothing
|
|
81
|
+
* reads. Where a `.rmanrc` equivalent exists it is a core key in its own right (`allowBranch`), and
|
|
82
|
+
* a command that reads it names it in `configKeys`.
|
|
83
|
+
*/
|
|
84
|
+
export declare const packageFilterOptions: {
|
|
85
|
+
scope: {
|
|
86
|
+
target: "cli";
|
|
87
|
+
describe: string;
|
|
88
|
+
type: "string";
|
|
89
|
+
};
|
|
90
|
+
ignore: {
|
|
91
|
+
target: "cli";
|
|
92
|
+
describe: string;
|
|
93
|
+
type: "string";
|
|
94
|
+
};
|
|
95
|
+
platform: {
|
|
96
|
+
target: "cli";
|
|
97
|
+
describe: string;
|
|
98
|
+
type: "string";
|
|
99
|
+
};
|
|
100
|
+
deps: {
|
|
101
|
+
target: "cli";
|
|
102
|
+
describe: string;
|
|
103
|
+
type: "boolean";
|
|
104
|
+
};
|
|
105
|
+
dependents: {
|
|
106
|
+
target: "cli";
|
|
107
|
+
describe: string;
|
|
108
|
+
type: "boolean";
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* `--from-root`/`-r` - a group of one, and a function because its text is the command's own word
|
|
113
|
+
* for what it does. Spread it like the others: `...fromRootOption('Build')`.
|
|
114
|
+
*
|
|
115
|
+
* Only where a command scopes by the current directory; see `applyFromRootOption` for why adding it
|
|
116
|
+
* elsewhere is worse than leaving it out.
|
|
117
|
+
*
|
|
118
|
+
* **It was `--root` through 1.x, and the name said the opposite of what it does.** Every reader
|
|
119
|
+
* spells it the same single line - `options.fromRoot ? undefined : repository.currentPackage` - so
|
|
120
|
+
* the flag means *ignore where I am standing*, i.e. the **whole repository**. `--root` reads as "the
|
|
121
|
+
* root alone", which is the narrowest possible set rather than the widest, and the confusion was
|
|
122
|
+
* about to become a contradiction: a `--root-only` beside a `--root` that meant "everything" is
|
|
123
|
+
* unreadable.
|
|
124
|
+
*
|
|
125
|
+
* **`-r` is kept, and a two-letter `-fr` is not possible.** yargs' `short-option-groups` is on by
|
|
126
|
+
* default, so `-fr` parses as `-f -r` and `.strict()` answers `Unknown arguments: f, r` (measured).
|
|
127
|
+
* Turning that off makes `-fr` work and breaks every grouped short - `rman list -sj` works today.
|
|
128
|
+
* So the long name carries the meaning and the incumbent short stays.
|
|
129
|
+
*/
|
|
130
|
+
export declare function fromRootOption(verb: string): {
|
|
131
|
+
fromRoot: {
|
|
132
|
+
target: "cli";
|
|
133
|
+
cliName: string;
|
|
134
|
+
alias: string;
|
|
135
|
+
describe: string;
|
|
136
|
+
type: "boolean";
|
|
137
|
+
};
|
|
138
|
+
};
|
|
20
139
|
/** `--scope`/`--ignore`/`--deps`/`--dependents`, the same shape and describe text in every command
|
|
21
140
|
* that supports them - mirrors `run.command.ts`'s own `applyRunOptions`. */
|
|
22
141
|
export declare function applyPackageFilterOptions<T>(cmd: Argv<T>): Argv<T>;
|
|
@@ -24,7 +143,8 @@ export declare function readPackageFilterOptions(args: any): PackageFilterOption
|
|
|
24
143
|
/**
|
|
25
144
|
* Narrows `packages` (the full, already-resolved list - toposort order, if any, is preserved)
|
|
26
145
|
* down to what `options` selects. `scope`/`ignore` match against each package's bare name (glob
|
|
27
|
-
* syntax via `micromatch` - `*`, `**`, `{a,b}`, ...)
|
|
146
|
+
* syntax via `micromatch` - `*`, `**`, `{a,b}`, ...), plus `ROOT_SELECTOR` (`"/"`) for the root
|
|
147
|
+
* package, which is matched structurally rather than by name; `ignore` is applied after `scope`, on
|
|
28
148
|
* whatever it left. `deps`/`dependents` then each independently expand *that* matched set along
|
|
29
149
|
* `Package.dependencies` (already the full transitive closure - see
|
|
30
150
|
* `Repository`'s own `_updateDependencies`) and their results are unioned in - so `--deps
|
|
@@ -46,7 +166,7 @@ export declare function filterPackages(packages: Package[], options: PackageFilt
|
|
|
46
166
|
*/
|
|
47
167
|
applySkip?: boolean): Package[];
|
|
48
168
|
/**
|
|
49
|
-
* `--root`/`-r`, with one describe text instead of four near-identical ones.
|
|
169
|
+
* `--from-root`/`-r`, with one describe text instead of four near-identical ones.
|
|
50
170
|
*
|
|
51
171
|
* **It only means anything where a command scopes by the current directory** - `run`/`build`/`test`,
|
|
52
172
|
* `exec`, `clean`, `changelog` and `diff` narrow to `Repository.currentPackage` when you stand
|
|
@@ -54,10 +174,17 @@ applySkip?: boolean): Package[];
|
|
|
54
174
|
* repository (`version`, `publish`, `list`, `changed`) it would be a flag that does nothing, which
|
|
55
175
|
* is worse than not offering it: a no-op flag reads as a promise.
|
|
56
176
|
*
|
|
177
|
+
* That same rule is why there is no `--root-only` beside it, however naturally the pair reads: it
|
|
178
|
+
* would be a no-op on `run`/`build`/`test` (the root is not in `repository.packages` at all and
|
|
179
|
+
* contributes only `pre`/`post` bookends), identical to this flag on `diff`, already what this flag
|
|
180
|
+
* does on `config`, and on `clean` actively misleading - the root's own sweep recurses through
|
|
181
|
+
* `packages/*`, so a `--root-only` there deletes *more* than a package-scoped run, not less
|
|
182
|
+
* (measured). Where the root genuinely is a candidate, `--scope /` says so - see `ROOT_SELECTOR`.
|
|
183
|
+
*
|
|
57
184
|
* `verb` is the command's own word for what it does, so the text stays the sentence each command was
|
|
58
185
|
* already saying.
|
|
59
186
|
*/
|
|
60
|
-
export declare function
|
|
61
|
-
/** The `--root` flag as the services read it - beside `readPackageFilterOptions`, so a command
|
|
187
|
+
export declare function applyFromRootOption<T>(cmd: Argv<T>, verb: string): Argv<T>;
|
|
188
|
+
/** The `--from-root` flag as the services read it - beside `readPackageFilterOptions`, so a command
|
|
62
189
|
* reads both the same way. */
|
|
63
|
-
export declare function
|
|
190
|
+
export declare function readFromRootOption(args: any): boolean | undefined;
|