@mui/internal-code-infra 0.1.1-canary.3 → 0.1.1-canary.5
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/build/changelog/fetchChangelogs.d.mts +0 -10
- package/build/changelog/index.d.mts +1 -0
- package/build/cli/cmdBaseline.d.mts +18 -0
- package/build/utils/git.d.mts +30 -9
- package/package.json +27 -27
- package/src/changelog/fetchChangelogs.mjs +0 -21
- package/src/changelog/index.mjs +3 -0
- package/src/cli/cmdBaseline.mjs +31 -0
- package/src/cli/index.mjs +2 -0
- package/src/utils/git.mjs +107 -46
|
@@ -22,16 +22,6 @@ export type FetchCommitsOptions = {
|
|
|
22
22
|
* @property {string} release
|
|
23
23
|
* @property {string} [org='mui'] - GitHub organization name, defaults to 'mui'
|
|
24
24
|
*/
|
|
25
|
-
/**
|
|
26
|
-
* @param {Object} opts
|
|
27
|
-
* @param {string} opts.cwd
|
|
28
|
-
* @param {boolean} [opts.fetchAll=true] Whether to fetch all tags from all remotes before finding the latest tag.
|
|
29
|
-
* @returns {Promise<string>}
|
|
30
|
-
*/
|
|
31
|
-
export declare function findLatestTaggedVersion(opts: {
|
|
32
|
-
cwd: string;
|
|
33
|
-
fetchAll?: boolean;
|
|
34
|
-
}): Promise<string>;
|
|
35
25
|
/**
|
|
36
26
|
* Fetches commits between two refs (lastRelease..release) including PR details.
|
|
37
27
|
* Automatically handles GitHub OAuth authentication if none provided.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export type Args = {
|
|
3
|
+
/**
|
|
4
|
+
* - Branch pull requests fork from
|
|
5
|
+
*/
|
|
6
|
+
baseBranch?: string;
|
|
7
|
+
/**
|
|
8
|
+
* - Remote the base branch is fetched from
|
|
9
|
+
*/
|
|
10
|
+
remote?: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {Object} Args
|
|
14
|
+
* @property {string} [baseBranch] - Branch pull requests fork from
|
|
15
|
+
* @property {string} [remote] - Remote the base branch is fetched from
|
|
16
|
+
*/
|
|
17
|
+
declare const _default: import('yargs').CommandModule<{}, Args>;
|
|
18
|
+
export default _default;
|
package/build/utils/git.d.mts
CHANGED
|
@@ -13,22 +13,18 @@ export type RepoInfo = {
|
|
|
13
13
|
remoteName: string;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @property {string} repo - Repository name
|
|
19
|
-
* @property {string} remoteName - Remote name
|
|
20
|
-
*/
|
|
21
|
-
/**
|
|
22
|
-
* Get current repository info from git remote
|
|
16
|
+
* The canonical repository's remote, as opposed to a fork's: `upstream`, else `origin`, each only if
|
|
17
|
+
* it points at a mui repository. Reads the configured URLs, which `insteadOf` does not rewrite.
|
|
23
18
|
* @param {string} [cwd=process.cwd()]
|
|
24
|
-
* @returns {Promise<RepoInfo>}
|
|
19
|
+
* @returns {Promise<RepoInfo>}
|
|
25
20
|
*/
|
|
26
21
|
export declare function getRepositoryInfo(cwd?: string): Promise<RepoInfo>;
|
|
27
22
|
/**
|
|
28
23
|
* Get current git SHA
|
|
24
|
+
* @param {string} [cwd=process.cwd()]
|
|
29
25
|
* @returns {Promise<string>} Current git commit SHA
|
|
30
26
|
*/
|
|
31
|
-
export declare function getCurrentGitSha(): Promise<string>;
|
|
27
|
+
export declare function getCurrentGitSha(cwd?: string): Promise<string>;
|
|
32
28
|
/**
|
|
33
29
|
* Check whether a tag already exists on the origin remote
|
|
34
30
|
* @param {string} tagName - Tag name to check (e.g. `v1.2.3`)
|
|
@@ -36,3 +32,28 @@ export declare function getCurrentGitSha(): Promise<string>;
|
|
|
36
32
|
* @returns {Promise<boolean>} True if the tag exists on origin
|
|
37
33
|
*/
|
|
38
34
|
export declare function remoteGitTagExists(tagName: string, cwd?: string): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* The commit HEAD should be compared against: where it forked from the base branch, or its parent
|
|
37
|
+
* when HEAD is already on the base branch.
|
|
38
|
+
* @param {Object} [options]
|
|
39
|
+
* @param {string} [options.cwd]
|
|
40
|
+
* @param {string} [options.remote] - Defaults to the canonical remote.
|
|
41
|
+
* @param {string} [options.baseBranch] - Defaults to the remote's default branch.
|
|
42
|
+
* @returns {Promise<string>}
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveBaseline(options?: {
|
|
45
|
+
cwd?: string;
|
|
46
|
+
remote?: string;
|
|
47
|
+
baseBranch?: string;
|
|
48
|
+
}): Promise<string>;
|
|
49
|
+
/**
|
|
50
|
+
* The most recent version tag reachable from HEAD — where a changelog's range starts.
|
|
51
|
+
* @param {Object} opts
|
|
52
|
+
* @param {string} opts.cwd
|
|
53
|
+
* @param {boolean} [opts.fetchAll=true] Whether to fetch all tags from all remotes before finding the latest tag.
|
|
54
|
+
* @returns {Promise<string>}
|
|
55
|
+
*/
|
|
56
|
+
export declare function findLatestTaggedVersion(opts: {
|
|
57
|
+
cwd: string;
|
|
58
|
+
fetchAll?: boolean;
|
|
59
|
+
}): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-code-infra",
|
|
3
|
-
"version": "0.1.1-canary.
|
|
3
|
+
"version": "0.1.1-canary.5",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "Infra scripts and configs to be used across MUI repos.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,14 +53,14 @@
|
|
|
53
53
|
"code-infra": "./bin/code-infra.mjs"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@argos-ci/core": "6.8.
|
|
57
|
-
"@babel/cli": "^8.0.
|
|
58
|
-
"@babel/core": "^8.0.
|
|
56
|
+
"@argos-ci/core": "6.8.5",
|
|
57
|
+
"@babel/cli": "^8.0.6",
|
|
58
|
+
"@babel/core": "^8.0.6",
|
|
59
59
|
"@babel/plugin-syntax-jsx": "^8.0.1",
|
|
60
|
-
"@babel/plugin-syntax-typescript": "^8.0.
|
|
60
|
+
"@babel/plugin-syntax-typescript": "^8.0.3",
|
|
61
61
|
"@babel/plugin-transform-react-pure-annotations": "^8.0.1",
|
|
62
|
-
"@babel/plugin-transform-runtime": "^8.0.
|
|
63
|
-
"@babel/preset-env": "^8.0.
|
|
62
|
+
"@babel/plugin-transform-runtime": "^8.0.6",
|
|
63
|
+
"@babel/preset-env": "^8.0.6",
|
|
64
64
|
"@babel/preset-react": "^8.0.1",
|
|
65
65
|
"@babel/preset-typescript": "^8.0.1",
|
|
66
66
|
"@eslint/compat": "^2.1.1",
|
|
@@ -68,27 +68,27 @@
|
|
|
68
68
|
"@eslint/json": "^2.1.0",
|
|
69
69
|
"@inquirer/confirm": "^6.3.2",
|
|
70
70
|
"@inquirer/select": "^5.2.5",
|
|
71
|
-
"@mui/internal-babel-plugin-display-name": "2.0.1-canary.
|
|
72
|
-
"@mui/internal-babel-plugin-minify-errors": "3.0.1-canary.
|
|
73
|
-
"@mui/internal-babel-plugin-resolve-imports": "3.0.1-canary.
|
|
74
|
-
"@napi-rs/keyring": "^2.
|
|
71
|
+
"@mui/internal-babel-plugin-display-name": "2.0.1-canary.1",
|
|
72
|
+
"@mui/internal-babel-plugin-minify-errors": "3.0.1-canary.1",
|
|
73
|
+
"@mui/internal-babel-plugin-resolve-imports": "3.0.1-canary.2",
|
|
74
|
+
"@napi-rs/keyring": "^2.1.0",
|
|
75
75
|
"@octokit/auth-action": "^6.0.3",
|
|
76
76
|
"@octokit/oauth-methods": "^6.0.5",
|
|
77
77
|
"@octokit/rest": "^22.0.1",
|
|
78
|
-
"@pnpm/config.version-policy": "^1100.2.
|
|
78
|
+
"@pnpm/config.version-policy": "^1100.2.5",
|
|
79
79
|
"@pnpm/find-workspace-dir": "^1000.1.5",
|
|
80
80
|
"@pnpm/parse-wanted-dependency": "^1001.0.0",
|
|
81
|
-
"@typescript-eslint/types": "^8.70.
|
|
82
|
-
"@typescript-eslint/utils": "^8.70.
|
|
81
|
+
"@typescript-eslint/types": "^8.70.1",
|
|
82
|
+
"@typescript-eslint/utils": "^8.70.1",
|
|
83
83
|
"@vitest/eslint-plugin": "^1.6.27",
|
|
84
84
|
"babel-plugin-optimize-clsx": "^2.6.2",
|
|
85
85
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
86
86
|
"babel-plugin-transform-import-meta": "^3.0.0",
|
|
87
87
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
|
88
88
|
"babel-plugin-transform-remove-imports": "^1.8.1",
|
|
89
|
-
"chalk": "^6.0.
|
|
89
|
+
"chalk": "^6.0.1",
|
|
90
90
|
"clipboardy": "^5.3.2",
|
|
91
|
-
"content-type": "^3.1.
|
|
91
|
+
"content-type": "^3.1.1",
|
|
92
92
|
"env-ci": "^11.2.0",
|
|
93
93
|
"es-toolkit": "^1.52.0",
|
|
94
94
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -106,11 +106,11 @@
|
|
|
106
106
|
"git-url-parse": "^16.1.0",
|
|
107
107
|
"globals": "^17.12.0",
|
|
108
108
|
"globby": "^16.2.4",
|
|
109
|
-
"html-validate": "^11.
|
|
109
|
+
"html-validate": "^11.16.1",
|
|
110
110
|
"minimatch": "^10.2.6",
|
|
111
111
|
"node-html-parser": "^9.0.4",
|
|
112
|
-
"open": "^11.0.
|
|
113
|
-
"postcss-styled-syntax": "^0.7.
|
|
112
|
+
"open": "^11.0.4",
|
|
113
|
+
"postcss-styled-syntax": "^0.7.3",
|
|
114
114
|
"regexp.escape": "^2.0.1",
|
|
115
115
|
"rehype-slug": "^6.0.0",
|
|
116
116
|
"rehype-stringify": "^10.0.1",
|
|
@@ -133,12 +133,12 @@
|
|
|
133
133
|
"resolve-pkg-maps": "^1.0.0",
|
|
134
134
|
"semver": "^7.8.5",
|
|
135
135
|
"stylelint-config-standard": "^40.0.0",
|
|
136
|
-
"typescript-eslint": "^8.70.
|
|
136
|
+
"typescript-eslint": "^8.70.1",
|
|
137
137
|
"unified": "^11.0.5",
|
|
138
138
|
"unified-lint-rule": "^3.0.1",
|
|
139
139
|
"unist-util-visit": "^5.1.0",
|
|
140
140
|
"yaml": "^2.9.1",
|
|
141
|
-
"yargs": "^18.
|
|
141
|
+
"yargs": "^18.2.0"
|
|
142
142
|
},
|
|
143
143
|
"peerDependencies": {
|
|
144
144
|
"@next/eslint-plugin-next": "*",
|
|
@@ -162,17 +162,17 @@
|
|
|
162
162
|
"@types/mdast": "4.0.4",
|
|
163
163
|
"@types/regexp.escape": "2.0.0",
|
|
164
164
|
"@types/yargs": "17.0.35",
|
|
165
|
-
"@typescript-eslint/parser": "8.70.
|
|
166
|
-
"@typescript-eslint/rule-tester": "8.70.
|
|
165
|
+
"@typescript-eslint/parser": "8.70.1",
|
|
166
|
+
"@typescript-eslint/rule-tester": "8.70.1",
|
|
167
167
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
168
|
-
"eslint": "10.
|
|
168
|
+
"eslint": "10.11.0",
|
|
169
169
|
"get-port": "7.2.0",
|
|
170
|
-
"prettier": "3.9.
|
|
170
|
+
"prettier": "3.9.9",
|
|
171
171
|
"remark": "15.0.1",
|
|
172
172
|
"remark-mdx": "3.1.1",
|
|
173
173
|
"serve": "14.2.6",
|
|
174
174
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
175
|
-
"typescript-eslint": "8.70.
|
|
175
|
+
"typescript-eslint": "8.70.1"
|
|
176
176
|
},
|
|
177
177
|
"files": [
|
|
178
178
|
"bin",
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"publishConfig": {
|
|
188
188
|
"access": "public"
|
|
189
189
|
},
|
|
190
|
-
"gitSha": "
|
|
190
|
+
"gitSha": "c2a0ca83b8dd00ae2fa2b5714dbc6684d50926d9",
|
|
191
191
|
"scripts": {
|
|
192
192
|
"build": "tsc -p tsconfig.build.json",
|
|
193
193
|
"typescript": "tsc -noEmit",
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Octokit } from '@octokit/rest';
|
|
2
|
-
import { $ } from 'execa';
|
|
3
2
|
|
|
4
|
-
import { getRepositoryInfo } from '../utils/git.mjs';
|
|
5
3
|
import { persistentAuthStrategy } from '../utils/github.mjs';
|
|
6
4
|
|
|
7
5
|
/**
|
|
@@ -20,25 +18,6 @@ import { persistentAuthStrategy } from '../utils/github.mjs';
|
|
|
20
18
|
* @property {string} [org='mui'] - GitHub organization name, defaults to 'mui'
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
|
-
/**
|
|
24
|
-
* @param {Object} opts
|
|
25
|
-
* @param {string} opts.cwd
|
|
26
|
-
* @param {boolean} [opts.fetchAll=true] Whether to fetch all tags from all remotes before finding the latest tag.
|
|
27
|
-
* @returns {Promise<string>}
|
|
28
|
-
*/
|
|
29
|
-
export async function findLatestTaggedVersion(opts) {
|
|
30
|
-
const $$ = $({ cwd: opts.cwd });
|
|
31
|
-
const fetchAll = opts.fetchAll ?? true;
|
|
32
|
-
if (fetchAll) {
|
|
33
|
-
const { remoteName } = await getRepositoryInfo();
|
|
34
|
-
// Fetch all tags from the mui remote to ensure we have the latest tags.
|
|
35
|
-
// --force to update any existing tags that may have changed to avoid the clobering error.
|
|
36
|
-
await $$`git fetch --tags --force ${remoteName}`;
|
|
37
|
-
}
|
|
38
|
-
const { stdout } = await $$`git describe --tags --abbrev=0 --match ${'v*'}`; // only include "version-tags"
|
|
39
|
-
return stdout.trim();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
21
|
/**
|
|
43
22
|
* Fetches commits between two refs (lastRelease..release) including PR details.
|
|
44
23
|
* Automatically handles GitHub OAuth authentication if none provided.
|
package/src/changelog/index.mjs
CHANGED
|
@@ -5,3 +5,6 @@
|
|
|
5
5
|
export { generateChangelog } from './generateChangelog.mjs';
|
|
6
6
|
export * from './loadChangelogConfig.mjs';
|
|
7
7
|
export * from './fetchChangelogs.mjs';
|
|
8
|
+
// Moved to the git utilities, where the rest of the local git plumbing lives. Re-exported because
|
|
9
|
+
// `@mui/internal-code-infra/changelog` is a published entry point and this was part of it.
|
|
10
|
+
export { findLatestTaggedVersion } from '../utils/git.mjs';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
|
|
5
|
+
import { resolveBaseline } from '../utils/git.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} Args
|
|
9
|
+
* @property {string} [baseBranch] - Branch pull requests fork from
|
|
10
|
+
* @property {string} [remote] - Remote the base branch is fetched from
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
14
|
+
command: 'baseline',
|
|
15
|
+
describe: 'Print the commit HEAD should be compared against',
|
|
16
|
+
builder: (yargs) => {
|
|
17
|
+
return yargs
|
|
18
|
+
.option('base-branch', {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: "Branch pull requests fork from. Default: the remote's default branch",
|
|
21
|
+
})
|
|
22
|
+
.option('remote', {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description:
|
|
25
|
+
'Remote the base branch is fetched from. Default: upstream, else origin, whichever points at a mui repository',
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
handler: async (argv) => {
|
|
29
|
+
console.log(await resolveBaseline({ baseBranch: argv.baseBranch, remote: argv.remote }));
|
|
30
|
+
},
|
|
31
|
+
});
|
package/src/cli/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import yargs from 'yargs';
|
|
|
4
4
|
import { hideBin } from 'yargs/helpers';
|
|
5
5
|
|
|
6
6
|
import cmdArgosPush from './cmdArgosPush.mjs';
|
|
7
|
+
import cmdBaseline from './cmdBaseline.mjs';
|
|
7
8
|
import cmdBuild from './cmdBuild.mjs';
|
|
8
9
|
import cmdCopyFiles from './cmdCopyFiles.mjs';
|
|
9
10
|
import cmdExtractErrorCodes from './cmdExtractErrorCodes.mjs';
|
|
@@ -38,6 +39,7 @@ await yargs(hideBin(process.argv))
|
|
|
38
39
|
globalArgv = argv;
|
|
39
40
|
}, true)
|
|
40
41
|
.command(cmdArgosPush)
|
|
42
|
+
.command(cmdBaseline)
|
|
41
43
|
.command(cmdBuild)
|
|
42
44
|
.command(cmdCopyFiles)
|
|
43
45
|
.command(cmdExtractErrorCodes)
|
package/src/utils/git.mjs
CHANGED
|
@@ -9,68 +9,63 @@ import gitUrlParse from 'git-url-parse';
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* The repository a remote URL points at, if it is a GitHub repository under `mui`.
|
|
13
|
+
* @param {string} url
|
|
14
|
+
* @returns {{ owner: string, repo: string } | null}
|
|
15
|
+
*/
|
|
16
|
+
function muiRepositoryOf(url) {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = gitUrlParse(url);
|
|
19
|
+
return parsed.source === 'github.com' && parsed.owner === 'mui'
|
|
20
|
+
? { owner: parsed.owner, repo: parsed.name }
|
|
21
|
+
: null;
|
|
22
|
+
} catch {
|
|
23
|
+
// Not a URL git-url-parse understands, such as a local path: not a mui repository either.
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The canonical repository's remote, as opposed to a fork's: `upstream`, else `origin`, each only if
|
|
30
|
+
* it points at a mui repository. Reads the configured URLs, which `insteadOf` does not rewrite.
|
|
13
31
|
* @param {string} [cwd=process.cwd()]
|
|
14
|
-
* @returns {Promise<RepoInfo>}
|
|
32
|
+
* @returns {Promise<RepoInfo>}
|
|
15
33
|
*/
|
|
16
34
|
export async function getRepositoryInfo(cwd = process.cwd()) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @type {Map<string, { owner: string, repo: string }>}
|
|
29
|
-
*/
|
|
30
|
-
const validRemotes = new Map();
|
|
31
|
-
|
|
32
|
-
for (const line of lines) {
|
|
33
|
-
// Match pattern: "remoteName url (fetch|push)"
|
|
34
|
-
const [remoteName, url, type] = line.trim().split(/\s+/, 3);
|
|
35
|
-
repoRemotes.add(remoteName);
|
|
36
|
-
if (type === '(fetch)') {
|
|
37
|
-
try {
|
|
38
|
-
const parsed = gitUrlParse(url);
|
|
39
|
-
if (parsed.source !== 'github.com' || parsed.owner !== 'mui') {
|
|
40
|
-
cause[remoteName] = `Remote is not a GitHub repository under 'mui' organization: ${url}`;
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
if (!validRemotes.has(remoteName)) {
|
|
44
|
-
validRemotes.set(remoteName, { owner: parsed.owner, repo: parsed.name });
|
|
45
|
-
}
|
|
46
|
-
} catch (error) {
|
|
47
|
-
cause[remoteName] = `Failed to parse URL for remote ${remoteName}: ${url}`;
|
|
48
|
-
}
|
|
49
|
-
} else if (type !== '(push)') {
|
|
50
|
-
throw new Error(`Unexpected line format for "git remote -v": "${line}"`);
|
|
51
|
-
}
|
|
35
|
+
// Exits 1 when neither remote is configured; the error below reports that.
|
|
36
|
+
const { stdout } = await $({
|
|
37
|
+
cwd,
|
|
38
|
+
reject: false,
|
|
39
|
+
})`git config --get-regexp ${'^remote\\.(upstream|origin)\\.url$'}`;
|
|
40
|
+
/** @type {Map<string, string>} */
|
|
41
|
+
const urls = new Map();
|
|
42
|
+
for (const line of stdout.split('\n').filter(Boolean)) {
|
|
43
|
+
const [key, url] = line.split(' ', 2);
|
|
44
|
+
urls.set(key.slice('remote.'.length, -'.url'.length), url);
|
|
52
45
|
}
|
|
53
46
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
58
|
-
return { ...
|
|
47
|
+
for (const remoteName of ['upstream', 'origin']) {
|
|
48
|
+
const url = urls.get(remoteName);
|
|
49
|
+
const repository = url ? muiRepositoryOf(url) : null;
|
|
50
|
+
if (repository) {
|
|
51
|
+
return { ...repository, remoteName };
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
|
|
55
|
+
const found = [...urls].map(([name, url]) => `${name}: ${url}`).join(', ') || 'none';
|
|
62
56
|
throw new Error(
|
|
63
|
-
`
|
|
64
|
-
|
|
57
|
+
`No canonical remote: neither \`upstream\` nor \`origin\` points at a mui repository (${found}). ` +
|
|
58
|
+
'Add an `upstream` remote for it, or name the remote explicitly where the command allows it.',
|
|
65
59
|
);
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
/**
|
|
69
63
|
* Get current git SHA
|
|
64
|
+
* @param {string} [cwd=process.cwd()]
|
|
70
65
|
* @returns {Promise<string>} Current git commit SHA
|
|
71
66
|
*/
|
|
72
|
-
export async function getCurrentGitSha() {
|
|
73
|
-
const result = await
|
|
67
|
+
export async function getCurrentGitSha(cwd = process.cwd()) {
|
|
68
|
+
const result = await $({ cwd })`git rev-parse HEAD`;
|
|
74
69
|
return result.stdout.trim();
|
|
75
70
|
}
|
|
76
71
|
|
|
@@ -84,3 +79,69 @@ export async function remoteGitTagExists(tagName, cwd = process.cwd()) {
|
|
|
84
79
|
const { stdout } = await $({ cwd })`git ls-remote --tags origin refs/tags/${tagName}`;
|
|
85
80
|
return stdout.trim().length > 0;
|
|
86
81
|
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The default branch of `remote`, as the remote itself reports it.
|
|
85
|
+
* @param {string} remote
|
|
86
|
+
* @param {string} cwd
|
|
87
|
+
* @returns {Promise<string>}
|
|
88
|
+
*/
|
|
89
|
+
async function getDefaultBranchOf(remote, cwd) {
|
|
90
|
+
const { stdout } = await $({ cwd })`git ls-remote --symref ${remote} HEAD`;
|
|
91
|
+
const match = /^ref: refs\/heads\/(\S+)\tHEAD$/m.exec(stdout);
|
|
92
|
+
if (!match) {
|
|
93
|
+
throw new Error(`Remote "${remote}" does not report a default branch.`);
|
|
94
|
+
}
|
|
95
|
+
return match[1];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The commit HEAD should be compared against: where it forked from the base branch, or its parent
|
|
100
|
+
* when HEAD is already on the base branch.
|
|
101
|
+
* @param {Object} [options]
|
|
102
|
+
* @param {string} [options.cwd]
|
|
103
|
+
* @param {string} [options.remote] - Defaults to the canonical remote.
|
|
104
|
+
* @param {string} [options.baseBranch] - Defaults to the remote's default branch.
|
|
105
|
+
* @returns {Promise<string>}
|
|
106
|
+
*/
|
|
107
|
+
export async function resolveBaseline(options = {}) {
|
|
108
|
+
const cwd = options.cwd ?? process.cwd();
|
|
109
|
+
const remote = options.remote ?? (await getRepositoryInfo(cwd)).remoteName;
|
|
110
|
+
const baseBranch = options.baseBranch ?? (await getDefaultBranchOf(remote, cwd));
|
|
111
|
+
|
|
112
|
+
await $({ cwd })`git fetch --no-tags ${remote} ${baseBranch}`;
|
|
113
|
+
const [forkPoint, head] = await Promise.all([
|
|
114
|
+
$({ cwd })`git merge-base HEAD FETCH_HEAD`.then((result) => result.stdout.trim()),
|
|
115
|
+
getCurrentGitSha(cwd),
|
|
116
|
+
]);
|
|
117
|
+
if (forkPoint !== head) {
|
|
118
|
+
return forkPoint;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const parent = await $({ cwd, reject: false })`git rev-parse --verify HEAD~1`;
|
|
122
|
+
if (parent.exitCode !== 0) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
'HEAD has no parent commit to compare against. A shallow clone is the usual cause.',
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return parent.stdout.trim();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The most recent version tag reachable from HEAD — where a changelog's range starts.
|
|
132
|
+
* @param {Object} opts
|
|
133
|
+
* @param {string} opts.cwd
|
|
134
|
+
* @param {boolean} [opts.fetchAll=true] Whether to fetch all tags from all remotes before finding the latest tag.
|
|
135
|
+
* @returns {Promise<string>}
|
|
136
|
+
*/
|
|
137
|
+
export async function findLatestTaggedVersion(opts) {
|
|
138
|
+
const $$ = $({ cwd: opts.cwd });
|
|
139
|
+
const fetchAll = opts.fetchAll ?? true;
|
|
140
|
+
if (fetchAll) {
|
|
141
|
+
// --force to update any existing tags that may have changed to avoid the clobering error.
|
|
142
|
+
const { remoteName } = await getRepositoryInfo(opts.cwd);
|
|
143
|
+
await $$`git fetch --tags --force ${remoteName}`;
|
|
144
|
+
}
|
|
145
|
+
const { stdout } = await $$`git describe --tags --abbrev=0 --match ${'v*'}`; // only include "version-tags"
|
|
146
|
+
return stdout.trim();
|
|
147
|
+
}
|