fork-version 4.1.10 → 5.0.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.
- package/CHANGELOG.md +20 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +54 -193
- package/dist/commands/inspect.d.ts +9 -0
- package/dist/commands/inspect.js +41 -0
- package/dist/commands/main.d.ts +16 -0
- package/dist/commands/main.js +30 -0
- package/dist/commands/validate-config.d.ts +6 -0
- package/dist/commands/validate-config.js +11 -0
- package/dist/commit-parser/commit-parser.d.ts +114 -0
- package/dist/commit-parser/commit-parser.js +327 -0
- package/dist/commit-parser/filter-reverted-commits.d.ts +17 -0
- package/dist/commit-parser/filter-reverted-commits.js +34 -0
- package/dist/commit-parser/options.d.ts +74 -0
- package/dist/commit-parser/options.js +70 -0
- package/dist/commit-parser/parser-error.js +14 -0
- package/dist/commit-parser/types.d.ts +53 -0
- package/dist/config/changelog-preset-config.js +41 -0
- package/dist/config/cli-arguments.d.ts +109 -0
- package/dist/config/cli-arguments.js +141 -0
- package/dist/config/defaults.js +38 -0
- package/dist/config/define-config.d.ts +9 -0
- package/dist/config/define-config.js +9 -0
- package/dist/config/load-config.js +45 -0
- package/dist/config/merge-files.js +12 -0
- package/dist/config/schema.d.ts +50 -0
- package/dist/config/schema.js +61 -0
- package/dist/config/types.d.ts +279 -0
- package/dist/config/user-config.d.ts +6 -0
- package/dist/config/user-config.js +50 -0
- package/dist/detect-git-host/detect-git-host.js +35 -0
- package/dist/detect-git-host/host-azure-devops.js +28 -0
- package/dist/detect-git-host/host-bitbucket.js +28 -0
- package/dist/detect-git-host/host-github.js +32 -0
- package/dist/detect-git-host/host-gitlab.js +48 -0
- package/dist/files/arm-bicep.js +38 -0
- package/dist/files/file-manager.d.ts +56 -0
- package/dist/files/file-manager.js +87 -0
- package/dist/files/install-shield-ism.js +55 -0
- package/dist/files/json-package.js +64 -0
- package/dist/files/ms-build-project.js +55 -0
- package/dist/files/plain-text.js +31 -0
- package/dist/files/yaml-package.js +57 -0
- package/dist/index.d.ts +21 -655
- package/dist/index.js +19 -10
- package/dist/process/changelog.d.ts +7 -0
- package/dist/process/changelog.js +69 -0
- package/dist/process/commit.d.ts +9 -0
- package/dist/process/commit.js +22 -0
- package/dist/process/get-commits.d.ts +14 -0
- package/dist/process/get-commits.js +25 -0
- package/dist/process/get-current-version.d.ts +13 -0
- package/dist/process/get-current-version.js +35 -0
- package/dist/process/get-next-version.d.ts +21 -0
- package/dist/process/get-next-version.js +72 -0
- package/dist/process/tag.d.ts +8 -0
- package/dist/process/tag.js +15 -0
- package/dist/services/git.d.ts +141 -0
- package/dist/services/git.js +236 -0
- package/dist/services/logger.d.ts +18 -0
- package/dist/services/logger.js +35 -0
- package/dist/utils/clean-tag.js +21 -0
- package/dist/utils/escape-regex.js +17 -0
- package/dist/utils/file-state.js +19 -0
- package/dist/utils/format-commit-message.js +13 -0
- package/dist/utils/parse-regexp-string.js +31 -0
- package/dist/utils/release-type.js +47 -0
- package/dist/utils/trim-string-array.js +20 -0
- package/package.json +11 -29
- package/dist/chunk-33WIJWQZ.cjs +0 -2306
- package/dist/chunk-33WIJWQZ.cjs.map +0 -1
- package/dist/chunk-L5UDUEHE.js +0 -2262
- package/dist/chunk-L5UDUEHE.js.map +0 -1
- package/dist/cli.cjs +0 -205
- package/dist/cli.cjs.map +0 -1
- package/dist/cli.d.cts +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.cjs +0 -80
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -655
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { getCliArguments } from "./cli-arguments.js";
|
|
2
|
+
import { ParserOptions } from "../commit-parser/options.js";
|
|
3
|
+
|
|
4
|
+
//#region src/config/types.d.ts
|
|
5
|
+
interface ChangelogPresetConfigType {
|
|
6
|
+
/**
|
|
7
|
+
* The type of commit message.
|
|
8
|
+
* @example "feat", "fix", "chore", etc..
|
|
9
|
+
*/
|
|
10
|
+
type: string;
|
|
11
|
+
/**
|
|
12
|
+
* The scope of the commit message.
|
|
13
|
+
*/
|
|
14
|
+
scope?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The section of the `CHANGELOG` the commit should show up in.
|
|
17
|
+
*/
|
|
18
|
+
section?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Should show in the generated changelog message?
|
|
21
|
+
*/
|
|
22
|
+
hidden?: boolean;
|
|
23
|
+
}
|
|
24
|
+
interface ChangelogPresetConfig {
|
|
25
|
+
/**
|
|
26
|
+
* List of explicitly supported commit message types.
|
|
27
|
+
*/
|
|
28
|
+
types: ChangelogPresetConfigType[];
|
|
29
|
+
/**
|
|
30
|
+
* A URL representing a specific commit at a hash.
|
|
31
|
+
* @default "{{host}}/{{owner}}/{{repository}}/commit/{{hash}}"
|
|
32
|
+
*/
|
|
33
|
+
commitUrlFormat: string;
|
|
34
|
+
/**
|
|
35
|
+
* A URL representing the comparison between two git SHAs.
|
|
36
|
+
* @default "{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}"
|
|
37
|
+
*/
|
|
38
|
+
compareUrlFormat: string;
|
|
39
|
+
/**
|
|
40
|
+
* A URL representing the issue format (allowing a different URL format to be swapped in
|
|
41
|
+
* for Gitlab, Bitbucket, etc).
|
|
42
|
+
* @default "{{host}}/{{owner}}/{{repository}}/issues/{{id}}"
|
|
43
|
+
*/
|
|
44
|
+
issueUrlFormat: string;
|
|
45
|
+
/**
|
|
46
|
+
* A URL representing a user's profile on GitHub, Gitlab, etc. This URL is used
|
|
47
|
+
* for substituting @eglavin with https://github.com/eglavin in commit messages.
|
|
48
|
+
* @default "{{host}}/{{user}}"
|
|
49
|
+
*/
|
|
50
|
+
userUrlFormat: string;
|
|
51
|
+
/**
|
|
52
|
+
* A string to be used to format the auto-generated release commit message.
|
|
53
|
+
* @default "chore(release): {{currentTag}}"
|
|
54
|
+
*/
|
|
55
|
+
releaseCommitMessageFormat: string;
|
|
56
|
+
/**
|
|
57
|
+
* List of prefixes used to detect references to issues.
|
|
58
|
+
* @default ["#"]
|
|
59
|
+
*/
|
|
60
|
+
issuePrefixes: string[];
|
|
61
|
+
}
|
|
62
|
+
interface ForkConfig {
|
|
63
|
+
/**
|
|
64
|
+
* The command to run, can be one of the following:
|
|
65
|
+
*
|
|
66
|
+
* - `main` - Bumps the version, update files, generate changelog, commit, and tag.
|
|
67
|
+
* - `inspect-version` - Prints the current version and exits.
|
|
68
|
+
* - `inspect-tag` - Prints the current git tag and exits.
|
|
69
|
+
* - `inspect` - Prints the current version and git tag and exits.
|
|
70
|
+
* - `validate-config` - Validates the configuration and exits.
|
|
71
|
+
*
|
|
72
|
+
* @default "main"
|
|
73
|
+
*/
|
|
74
|
+
command: "main" | "inspect" | "inspect-version" | "inspect-tag" | "validate-config";
|
|
75
|
+
/**
|
|
76
|
+
* If set, Fork-Version will print the current version and exit.
|
|
77
|
+
* @default false
|
|
78
|
+
*
|
|
79
|
+
* @deprecated Set the `inspect-version` command instead.
|
|
80
|
+
*/
|
|
81
|
+
inspectVersion?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* List of the files to be updated.
|
|
84
|
+
* @default
|
|
85
|
+
* ```js
|
|
86
|
+
* ["bower.json", "deno.json", "deno.jsonc", "jsr.json", "jsr.jsonc", "manifest.json", "npm-shrinkwrap.json", "package-lock.json", "package.json"]
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
files: string[];
|
|
90
|
+
/**
|
|
91
|
+
* Glob pattern to match files to be updated.
|
|
92
|
+
*
|
|
93
|
+
* Internally we're using [glob](https://github.com/isaacs/node-glob) to match files.
|
|
94
|
+
*
|
|
95
|
+
* Read more about the pattern syntax [here](https://github.com/isaacs/node-glob/tree/v10.3.12?tab=readme-ov-file#glob-primer).
|
|
96
|
+
*
|
|
97
|
+
* @default undefined
|
|
98
|
+
* @example "*.json"
|
|
99
|
+
*/
|
|
100
|
+
glob?: string;
|
|
101
|
+
/**
|
|
102
|
+
* The path Fork-Version will run from.
|
|
103
|
+
* @default
|
|
104
|
+
* ```js
|
|
105
|
+
* process.cwd()
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
path: string;
|
|
109
|
+
/**
|
|
110
|
+
* Name of the changelog file.
|
|
111
|
+
* @default "CHANGELOG.md"
|
|
112
|
+
*/
|
|
113
|
+
changelog: string;
|
|
114
|
+
/**
|
|
115
|
+
* The header text for the changelog.
|
|
116
|
+
* @default
|
|
117
|
+
* ```markdown
|
|
118
|
+
* # Changelog
|
|
119
|
+
*
|
|
120
|
+
* All notable changes to this project will be documented in this file. See [fork-version](https://github.com/eglavin/fork-version) for commit guidelines.
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
header: string;
|
|
124
|
+
/**
|
|
125
|
+
* Specify a prefix for the created tag.
|
|
126
|
+
*
|
|
127
|
+
* For instance if your version tag is prefixed by "version/" instead of "v" you have to specify
|
|
128
|
+
* `tagPrefix: "version/"`.
|
|
129
|
+
*
|
|
130
|
+
* `tagPrefix` can also be used for a monorepo environment where you might want to deploy
|
|
131
|
+
* multiple package from the same repository. In this case you can specify a prefix for
|
|
132
|
+
* each package:
|
|
133
|
+
*
|
|
134
|
+
* | Example Value | Tag Created |
|
|
135
|
+
* |:-------------------------|:------------------------------|
|
|
136
|
+
* | "" | `1.2.3` |
|
|
137
|
+
* | "version/" | `version/1.2.3` |
|
|
138
|
+
* | "@eglavin/fork-version-" | `@eglavin/fork-version-1.2.3` |
|
|
139
|
+
*
|
|
140
|
+
* @example "", "version/", "@eglavin/fork-version-"
|
|
141
|
+
* @default "v"
|
|
142
|
+
*/
|
|
143
|
+
tagPrefix: string;
|
|
144
|
+
/**
|
|
145
|
+
* Make a pre-release with optional label if given value is a string.
|
|
146
|
+
*
|
|
147
|
+
* | Example Value | Produced Version |
|
|
148
|
+
* |:--------------|:-----------------|
|
|
149
|
+
* | true | `1.2.3-0` |
|
|
150
|
+
* | "alpha" | `1.2.3-alpha-0` |
|
|
151
|
+
* | "beta" | `1.2.3-beta-0` |
|
|
152
|
+
*
|
|
153
|
+
* @example true, "alpha", "beta", "rc"
|
|
154
|
+
* @default undefined
|
|
155
|
+
*/
|
|
156
|
+
preRelease?: string | boolean;
|
|
157
|
+
/**
|
|
158
|
+
* If set, Fork-Version will use this version instead of trying to determine one.
|
|
159
|
+
* @example "1.0.0"
|
|
160
|
+
* @default undefined
|
|
161
|
+
*/
|
|
162
|
+
currentVersion?: string;
|
|
163
|
+
/**
|
|
164
|
+
* If set, Fork-Version will attempt to update to this version, instead of incrementing using "conventional-commit".
|
|
165
|
+
* @example "2.0.0"
|
|
166
|
+
* @default undefined
|
|
167
|
+
*/
|
|
168
|
+
nextVersion?: string;
|
|
169
|
+
/**
|
|
170
|
+
* Release as increments the version by the specified level. Overrides the default behaviour of "conventional-commit".
|
|
171
|
+
* @example "major", "minor", "patch"
|
|
172
|
+
* @default undefined
|
|
173
|
+
*/
|
|
174
|
+
releaseAs?: "major" | "minor" | "patch";
|
|
175
|
+
/**
|
|
176
|
+
* Don't throw an error if multiple versions are found in the given files.
|
|
177
|
+
* @default true
|
|
178
|
+
*/
|
|
179
|
+
allowMultipleVersions: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Commit all changes, not just files updated by Fork-Version.
|
|
182
|
+
* @default false
|
|
183
|
+
*/
|
|
184
|
+
commitAll: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* By default the conventional-changelog spec will only add commit types of `feat` and `fix` to the generated changelog.
|
|
187
|
+
* If this flag is set, all [default commit types](https://github.com/conventional-changelog/conventional-changelog-config-spec/blob/238093090c14bd7d5151eb5316e635623ce633f9/versions/2.2.0/schema.json#L18)
|
|
188
|
+
* will be added to the changelog.
|
|
189
|
+
* @default false
|
|
190
|
+
*/
|
|
191
|
+
changelogAll: boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Output debug information.
|
|
194
|
+
* @default false
|
|
195
|
+
*/
|
|
196
|
+
debug: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* No output will be written to disk or committed.
|
|
199
|
+
* @default false
|
|
200
|
+
*/
|
|
201
|
+
dryRun: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Run without logging to the terminal.
|
|
204
|
+
* @default false
|
|
205
|
+
*/
|
|
206
|
+
silent: boolean;
|
|
207
|
+
/**
|
|
208
|
+
* If unable to find a version in the given files, fallback and attempt to use the latest git tag.
|
|
209
|
+
* @default true
|
|
210
|
+
*/
|
|
211
|
+
gitTagFallback: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* If true, git will sign the commit with the systems GPG key.
|
|
214
|
+
* @see {@link https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--Sltkeyidgt Git - GPG Sign Commits}
|
|
215
|
+
* @default false
|
|
216
|
+
*/
|
|
217
|
+
sign: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* If true, git will run user defined git hooks before committing.
|
|
220
|
+
* @see {@link https://git-scm.com/docs/githooks Git - Git Hooks}
|
|
221
|
+
* @default false
|
|
222
|
+
*/
|
|
223
|
+
verify: boolean;
|
|
224
|
+
/**
|
|
225
|
+
* Print inspected output as a parsable json string.
|
|
226
|
+
* @default false
|
|
227
|
+
*/
|
|
228
|
+
asJson: boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Skip the bump step.
|
|
231
|
+
* @default false
|
|
232
|
+
*/
|
|
233
|
+
skipBump: boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Skip the changelog step.
|
|
236
|
+
* @default false
|
|
237
|
+
*/
|
|
238
|
+
skipChangelog: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* Skip the commit step.
|
|
241
|
+
* @default false
|
|
242
|
+
*/
|
|
243
|
+
skipCommit: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* Skip the tag step.
|
|
246
|
+
* @default false
|
|
247
|
+
*/
|
|
248
|
+
skipTag: boolean;
|
|
249
|
+
/**
|
|
250
|
+
* The detected git host:
|
|
251
|
+
* - `GitHub`
|
|
252
|
+
* - `GitLab`
|
|
253
|
+
* - `Bitbucket`
|
|
254
|
+
* - `Azure Devops`
|
|
255
|
+
* - Or undefined if unknown or not detected.
|
|
256
|
+
*/
|
|
257
|
+
detectedGitHost?: string;
|
|
258
|
+
/**
|
|
259
|
+
* Override the default "conventional-changelog-conventionalcommits" preset configuration.
|
|
260
|
+
*/
|
|
261
|
+
changelogPresetConfig?: Partial<ChangelogPresetConfig>;
|
|
262
|
+
/**
|
|
263
|
+
* Add a suffix to the release commit message.
|
|
264
|
+
* @example "[skip ci]"
|
|
265
|
+
*/
|
|
266
|
+
releaseMessageSuffix?: string;
|
|
267
|
+
/**
|
|
268
|
+
* Options to pass to commits parser.
|
|
269
|
+
*/
|
|
270
|
+
commitParserOptions?: Partial<ParserOptions>;
|
|
271
|
+
}
|
|
272
|
+
type Config = Partial<ForkConfig>;
|
|
273
|
+
type CLIArguments = ReturnType<typeof getCliArguments>;
|
|
274
|
+
interface ForkVersionCLIArgs {
|
|
275
|
+
input: CLIArguments["input"];
|
|
276
|
+
flags: Partial<CLIArguments["flags"]>;
|
|
277
|
+
}
|
|
278
|
+
//#endregion
|
|
279
|
+
export { ChangelogPresetConfig, ChangelogPresetConfigType, Config, ForkConfig, ForkVersionCLIArgs };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getChangelogPresetConfig } from "./changelog-preset-config.js";
|
|
2
|
+
import { DEFAULT_CONFIG } from "./defaults.js";
|
|
3
|
+
import { detectGitHost } from "../detect-git-host/detect-git-host.js";
|
|
4
|
+
import { loadConfigFile } from "./load-config.js";
|
|
5
|
+
import { mergeFiles } from "./merge-files.js";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
import { glob } from "node:fs/promises";
|
|
8
|
+
//#region src/config/user-config.ts
|
|
9
|
+
async function getUserConfig(cliArguments) {
|
|
10
|
+
const cwd = cliArguments.flags.path ? resolve(cliArguments.flags.path) : process.cwd();
|
|
11
|
+
const configFile = await loadConfigFile(cwd);
|
|
12
|
+
const mergedConfig = {
|
|
13
|
+
...DEFAULT_CONFIG,
|
|
14
|
+
...configFile,
|
|
15
|
+
...cliArguments.flags
|
|
16
|
+
};
|
|
17
|
+
const globResults = [];
|
|
18
|
+
if (mergedConfig.glob) {
|
|
19
|
+
const IGNORE_LIST = new Set(["node_modules", ".git"]);
|
|
20
|
+
const entries = glob(mergedConfig.glob, {
|
|
21
|
+
cwd,
|
|
22
|
+
withFileTypes: true,
|
|
23
|
+
exclude: (entry) => IGNORE_LIST.has(entry.name)
|
|
24
|
+
});
|
|
25
|
+
for await (const entry of entries) if (entry.isFile()) globResults.push(join(entry.parentPath, entry.name));
|
|
26
|
+
}
|
|
27
|
+
const files = mergeFiles(configFile?.files, cliArguments.flags.files, globResults);
|
|
28
|
+
const detectedGitHost = await detectGitHost(cwd);
|
|
29
|
+
let command = DEFAULT_CONFIG.command;
|
|
30
|
+
if (cliArguments.input.length > 0 && cliArguments.input[0].trim()) command = cliArguments.input[0].trim().toLowerCase();
|
|
31
|
+
else if (mergedConfig.command.trim()) command = mergedConfig.command.trim().toLowerCase();
|
|
32
|
+
if (mergedConfig.inspectVersion) command = "inspect-version";
|
|
33
|
+
const shouldBeSilent = ![DEFAULT_CONFIG.command].includes(command);
|
|
34
|
+
return {
|
|
35
|
+
...mergedConfig,
|
|
36
|
+
command,
|
|
37
|
+
files,
|
|
38
|
+
path: cwd,
|
|
39
|
+
preRelease: cliArguments.flags.preReleaseTag ?? cliArguments.flags.preRelease ?? configFile.preRelease,
|
|
40
|
+
silent: shouldBeSilent || mergedConfig.silent,
|
|
41
|
+
detectedGitHost: detectedGitHost?.hostName,
|
|
42
|
+
changelogPresetConfig: getChangelogPresetConfig(mergedConfig, cliArguments.flags, detectedGitHost?.changelogOptions),
|
|
43
|
+
commitParserOptions: {
|
|
44
|
+
...detectedGitHost?.commitParserOptions,
|
|
45
|
+
...mergedConfig.commitParserOptions
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { getUserConfig };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Git } from "../services/git.js";
|
|
2
|
+
import { detectGitHubOptions } from "./host-github.js";
|
|
3
|
+
import { detectGitlabOptions } from "./host-gitlab.js";
|
|
4
|
+
import { detectBitbucketOptions } from "./host-bitbucket.js";
|
|
5
|
+
import { detectAzureDevopsOptions } from "./host-azure-devops.js";
|
|
6
|
+
//#region src/detect-git-host/detect-git-host.ts
|
|
7
|
+
/**
|
|
8
|
+
* Detects the Git hosting service based on the remote URL of the Git repository at the given path.
|
|
9
|
+
*
|
|
10
|
+
* Supports `GitHub`, `GitLab`, `Bitbucket`, and `Azure DevOps`.
|
|
11
|
+
*
|
|
12
|
+
* @param path - The file system path to the Git repository.
|
|
13
|
+
* @returns A promise that resolves to a DetectedGitHost object if a supported host is detected, or undefined if no supported host is found.
|
|
14
|
+
*/
|
|
15
|
+
async function detectGitHost(path) {
|
|
16
|
+
const remoteUrl = await new Git({ path }).getRemoteUrl();
|
|
17
|
+
if (remoteUrl.includes("github.com")) {
|
|
18
|
+
const githubOptions = detectGitHubOptions(remoteUrl);
|
|
19
|
+
if (githubOptions) return githubOptions;
|
|
20
|
+
}
|
|
21
|
+
if (remoteUrl.includes("gitlab.com")) {
|
|
22
|
+
const gitlabOptions = detectGitlabOptions(remoteUrl);
|
|
23
|
+
if (gitlabOptions) return gitlabOptions;
|
|
24
|
+
}
|
|
25
|
+
if (/bitbucket\.(org|com)/.test(remoteUrl)) {
|
|
26
|
+
const bitbucketOptions = detectBitbucketOptions(remoteUrl);
|
|
27
|
+
if (bitbucketOptions) return bitbucketOptions;
|
|
28
|
+
}
|
|
29
|
+
if (remoteUrl.includes("dev.azure.com")) {
|
|
30
|
+
const azureDevopsOptions = detectAzureDevopsOptions(remoteUrl);
|
|
31
|
+
if (azureDevopsOptions) return azureDevopsOptions;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { detectGitHost };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/detect-git-host/host-azure-devops.ts
|
|
2
|
+
/**
|
|
3
|
+
* A checked out Azure Devops remote URL looks like one of these:
|
|
4
|
+
*
|
|
5
|
+
* | Checkout Type | Remote URL |
|
|
6
|
+
* |:------------- |:----------------------------------------------------------------------------------------- |
|
|
7
|
+
* | HTTPS | `https://{{ORGANISATION}}@dev.azure.com/{{ORGANISATION}}/{{PROJECT}}/_git/{{REPOSITORY}}` |
|
|
8
|
+
* | SSH | `git@ssh.dev.azure.com:v3/{{ORGANISATION}}/{{PROJECT}}/{{REPOSITORY}}` |
|
|
9
|
+
*/
|
|
10
|
+
function detectAzureDevopsOptions(remoteUrl) {
|
|
11
|
+
let matches = null;
|
|
12
|
+
if (/^https:\/\/(.*)?dev\.azure\.com/.test(remoteUrl)) matches = /^https:\/\/(.*)?dev\.azure\.com\/(?<organisation>.*?)\/(?<project>.*?)\/_git\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
13
|
+
else if (remoteUrl.startsWith("git@ssh.dev.azure.com:")) matches = /^git@ssh\.dev\.azure\.com:v\d\/(?<organisation>.*?)\/(?<project>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
14
|
+
if (matches?.groups) {
|
|
15
|
+
const { organisation = "", project = "", repository = "" } = matches.groups;
|
|
16
|
+
return {
|
|
17
|
+
hostName: "Azure Devops",
|
|
18
|
+
changelogOptions: {
|
|
19
|
+
commitUrlFormat: `https://dev.azure.com/${organisation}/${project}/_git/${repository}/commit/{{hash}}`,
|
|
20
|
+
compareUrlFormat: `https://dev.azure.com/${organisation}/${project}/_git/${repository}/branchCompare?baseVersion=GT{{previousTag}}&targetVersion=GT{{currentTag}}`,
|
|
21
|
+
issueUrlFormat: `https://dev.azure.com/${organisation}/${project}/_workitems/edit/{{id}}`
|
|
22
|
+
},
|
|
23
|
+
commitParserOptions: { mergePattern: /^Merged PR (?<id>\d*): (?<source>.*)/i }
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { detectAzureDevopsOptions };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/detect-git-host/host-bitbucket.ts
|
|
2
|
+
/**
|
|
3
|
+
* A checked out Bitbucket remote URL looks like one of these:
|
|
4
|
+
*
|
|
5
|
+
* | Checkout Type | Remote URL |
|
|
6
|
+
* |:------------- |:------------------------------------------------------------------------- |
|
|
7
|
+
* | HTTPS | `https://{{WORKSPACE}}@bitbucket.org/{{ORGANISATION}}/{{REPOSITORY}}.git` |
|
|
8
|
+
* | SSH | `git@bitbucket.org:{{ORGANISATION}}/{{REPOSITORY}}.git` |
|
|
9
|
+
*/
|
|
10
|
+
function detectBitbucketOptions(remoteUrl) {
|
|
11
|
+
let matches = null;
|
|
12
|
+
if (/^https:\/\/(.*)?bitbucket\.(org|com)/.test(remoteUrl)) matches = /^https:\/\/(.*)?bitbucket\.(?<domain>org|com)\/(?<organisation>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
13
|
+
else if (remoteUrl.startsWith("git@bitbucket.org:")) matches = /^git@bitbucket\.(?<domain>org|com):(?<organisation>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
14
|
+
if (matches?.groups) {
|
|
15
|
+
const { domain = "", organisation = "", repository = "" } = matches.groups;
|
|
16
|
+
return {
|
|
17
|
+
hostName: "Bitbucket",
|
|
18
|
+
changelogOptions: {
|
|
19
|
+
commitUrlFormat: `https://bitbucket.${domain}/${organisation}/${repository}/commits/{{hash}}`,
|
|
20
|
+
compareUrlFormat: `https://bitbucket.${domain}/${organisation}/${repository}/branches/compare/{{currentTag}}..{{previousTag}}`,
|
|
21
|
+
issueUrlFormat: `https://bitbucket.${domain}/${organisation}/${repository}/issues/{{id}}`
|
|
22
|
+
},
|
|
23
|
+
commitParserOptions: { mergePattern: /^Merged in (?<source>.*) \(pull request #(?<id>\d*)\)/i }
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { detectBitbucketOptions };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/detect-git-host/host-github.ts
|
|
2
|
+
/**
|
|
3
|
+
* A checked out GitHub remote URL looks like one of these:
|
|
4
|
+
*
|
|
5
|
+
* | Checkout Type | Remote URL |
|
|
6
|
+
* |:------------- |:-------------------------------------------------------- |
|
|
7
|
+
* | HTTPS | `https://github.com/{{ORGANISATION}}/{{REPOSITORY}}.git` |
|
|
8
|
+
* | SSH | `git@github.com:{{ORGANISATION}}/{{REPOSITORY}}.git` |
|
|
9
|
+
*/
|
|
10
|
+
function detectGitHubOptions(remoteUrl) {
|
|
11
|
+
let matches = null;
|
|
12
|
+
if (/^https:\/\/(.*)?github\.com/.test(remoteUrl)) matches = /^https:\/\/(.*)?github\.com\/(?<organisation>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
13
|
+
else if (remoteUrl.startsWith("git@github.com:")) matches = /^git@github\.com:(?<organisation>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
14
|
+
if (matches?.groups) {
|
|
15
|
+
const { organisation = "", repository = "" } = matches.groups;
|
|
16
|
+
return {
|
|
17
|
+
hostName: "GitHub",
|
|
18
|
+
changelogOptions: {
|
|
19
|
+
commitUrlFormat: `https://github.com/${organisation}/${repository}/commit/{{hash}}`,
|
|
20
|
+
compareUrlFormat: `https://github.com/${organisation}/${repository}/compare/{{previousTag}}...{{currentTag}}`,
|
|
21
|
+
issueUrlFormat: `https://github.com/${organisation}/${repository}/issues/{{id}}`,
|
|
22
|
+
issuePrefixes: ["#", "gh-"]
|
|
23
|
+
},
|
|
24
|
+
commitParserOptions: {
|
|
25
|
+
mergePattern: /^Merge pull request #(?<id>\d*) from (?<source>.*)/i,
|
|
26
|
+
issuePrefixes: ["#", "gh-"]
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { detectGitHubOptions };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region src/detect-git-host/host-gitlab.ts
|
|
2
|
+
/**
|
|
3
|
+
* A checked out GitLab remote URL looks like one of these:
|
|
4
|
+
*
|
|
5
|
+
* | Checkout Type | Remote URL |
|
|
6
|
+
* |:------------- |:-------------------------------------------------------- |
|
|
7
|
+
* | HTTPS | `https://gitlab.com/{{ORGANISATION}}/{{REPOSITORY}}.git` |
|
|
8
|
+
* | SSH | `git@gitlab.com:{{ORGANISATION}}/{{REPOSITORY}}.git` |
|
|
9
|
+
*/
|
|
10
|
+
function detectGitlabOptions(remoteUrl) {
|
|
11
|
+
let matches = null;
|
|
12
|
+
if (/^https:\/\/(.*)?gitlab\.com/.test(remoteUrl)) matches = /^https:\/\/(.*)?gitlab\.com\/(?<organisation>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
13
|
+
else if (remoteUrl.startsWith("git@gitlab.com:")) matches = /^git@gitlab\.com:(?<organisation>.*?)\/(?<repository>.*?)(?:\.git)?$/.exec(remoteUrl);
|
|
14
|
+
if (matches?.groups) {
|
|
15
|
+
const { organisation = "", repository = "" } = matches.groups;
|
|
16
|
+
return {
|
|
17
|
+
hostName: "GitLab",
|
|
18
|
+
changelogOptions: {
|
|
19
|
+
commitUrlFormat: `https://gitlab.com/${organisation}/${repository}/-/commit/{{hash}}`,
|
|
20
|
+
compareUrlFormat: `https://gitlab.com/${organisation}/${repository}/-/compare/{{previousTag}}...{{currentTag}}`,
|
|
21
|
+
issueUrlFormat: `https://gitlab.com/${organisation}/${repository}/-/issues/{{id}}`
|
|
22
|
+
},
|
|
23
|
+
commitParserOptions: {
|
|
24
|
+
mergePattern: /^Merge branch '(?<source>.*)' into '(.*)'/i,
|
|
25
|
+
referenceActions: [
|
|
26
|
+
"close",
|
|
27
|
+
"closes",
|
|
28
|
+
"closed",
|
|
29
|
+
"closing",
|
|
30
|
+
"fix",
|
|
31
|
+
"fixes",
|
|
32
|
+
"fixed",
|
|
33
|
+
"fixing",
|
|
34
|
+
"resolve",
|
|
35
|
+
"resolves",
|
|
36
|
+
"resolved",
|
|
37
|
+
"resolving",
|
|
38
|
+
"implement",
|
|
39
|
+
"implements",
|
|
40
|
+
"implemented",
|
|
41
|
+
"implementing"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { detectGitlabOptions };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { MissingPropertyException } from "./file-manager.js";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
//#region src/files/arm-bicep.ts
|
|
5
|
+
/**
|
|
6
|
+
* An ARM bicep file with metadata and variable called contentVersion.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```bicep
|
|
10
|
+
* metadata contentVersion = '1.2.3.4'
|
|
11
|
+
* var contentVersion string = '1.2.3.4'
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
var ARMBicep = class {
|
|
15
|
+
/** https://regex101.com/r/Lriphb/2 */
|
|
16
|
+
#metadataRegex = /(metadata contentVersion *= *['"])(?<version>[^'"]+)(['"])/;
|
|
17
|
+
/** https://regex101.com/r/iKCTF9/1 */
|
|
18
|
+
#varRegex = /(var contentVersion(?: string)? *= *['"])(?<version>[^'"]+)(['"])/;
|
|
19
|
+
read(filePath) {
|
|
20
|
+
const fileContents = readFileSync(filePath, "utf8");
|
|
21
|
+
const metadataMatch = this.#metadataRegex.exec(fileContents);
|
|
22
|
+
if (metadataMatch?.groups?.version) return {
|
|
23
|
+
name: basename(filePath),
|
|
24
|
+
path: filePath,
|
|
25
|
+
version: metadataMatch.groups.version
|
|
26
|
+
};
|
|
27
|
+
throw new MissingPropertyException("ARM Bicep", "metadata contentVersion");
|
|
28
|
+
}
|
|
29
|
+
write(fileState, newVersion) {
|
|
30
|
+
const updatedContent = readFileSync(fileState.path, "utf8").replace(this.#metadataRegex, `$1${newVersion}$3`).replace(this.#varRegex, `$1${newVersion}$3`);
|
|
31
|
+
writeFileSync(fileState.path, updatedContent, "utf8");
|
|
32
|
+
}
|
|
33
|
+
isSupportedFile(fileName) {
|
|
34
|
+
return fileName.endsWith(".bicep");
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { ARMBicep };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ForkConfig } from "../config/types.js";
|
|
2
|
+
import { Logger } from "../services/logger.js";
|
|
3
|
+
|
|
4
|
+
//#region src/files/file-manager.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Exception thrown if a file manager encounters a file missing a required property,
|
|
7
|
+
* such as the "version" property in a JSON package file.
|
|
8
|
+
*/
|
|
9
|
+
declare class MissingPropertyException extends Error {
|
|
10
|
+
fileType: string;
|
|
11
|
+
propertyName: string;
|
|
12
|
+
constructor(fileType: string, propertyName: string);
|
|
13
|
+
}
|
|
14
|
+
interface FileState {
|
|
15
|
+
name: string;
|
|
16
|
+
path: string;
|
|
17
|
+
version: string;
|
|
18
|
+
[other: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
interface IFileManager {
|
|
21
|
+
read(fileName: string): FileState | undefined;
|
|
22
|
+
write(fileState: FileState, newVersion: string): void;
|
|
23
|
+
isSupportedFile(fileName: string): boolean;
|
|
24
|
+
}
|
|
25
|
+
declare class FileManager {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(config: ForkConfig, logger: Logger);
|
|
28
|
+
/**
|
|
29
|
+
* Get the state from the given file name.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* fileManager.read("package.json");
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @returns
|
|
37
|
+
* ```json
|
|
38
|
+
* { "name": "package.json", "path": "/path/to/package.json", "version": "1.2.3", "isPrivate": true }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
read(pathOrName: string): FileState | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Write the new version to the given file.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* fileManager.write(
|
|
48
|
+
* { name: "package.json", path: "/path/to/package.json", version: "1.2.2" },
|
|
49
|
+
* "1.2.3"
|
|
50
|
+
* );
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
write(fileState: FileState, newVersion: string): void;
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { FileManager, FileState, IFileManager, MissingPropertyException };
|