@halospv3/hce.shared-config 2.2.3 → 2.3.0

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 (89) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/LICENSE +1 -1
  3. package/README.md +116 -88
  4. package/cjs/commitlintConfig-wrapper.mjs +6 -0
  5. package/cjs/commitlintConfig.cjs +14 -0
  6. package/cjs/commitlintConfig.cjs.map +1 -0
  7. package/cjs/commitlintConfig.d.ts +4 -0
  8. package/cjs/commitlintConfig.d.ts.map +1 -0
  9. package/cjs/dotnet/MSBuildProject.cjs +85 -0
  10. package/cjs/dotnet/MSBuildProject.cjs.map +1 -0
  11. package/cjs/dotnet/MSBuildProject.d.ts +42 -0
  12. package/cjs/dotnet/MSBuildProject.d.ts.map +1 -0
  13. package/cjs/dotnet/MSBuildProjectProperties.cjs +22 -0
  14. package/cjs/dotnet/MSBuildProjectProperties.cjs.map +1 -0
  15. package/cjs/dotnet/MSBuildProjectProperties.d.ts +13 -0
  16. package/cjs/dotnet/MSBuildProjectProperties.d.ts.map +1 -0
  17. package/cjs/dotnet/dotnetGHPR.cjs +60 -0
  18. package/cjs/dotnet/dotnetGHPR.cjs.map +1 -0
  19. package/cjs/dotnet/dotnetGHPR.d.ts +14 -0
  20. package/cjs/dotnet/dotnetGHPR.d.ts.map +1 -0
  21. package/cjs/dotnet/dotnetGLPR.cjs +41 -0
  22. package/cjs/dotnet/dotnetGLPR.cjs.map +1 -0
  23. package/cjs/dotnet/dotnetGLPR.d.ts +13 -0
  24. package/cjs/dotnet/dotnetGLPR.d.ts.map +1 -0
  25. package/cjs/dotnet/dotnetHelpers.cjs +144 -0
  26. package/cjs/dotnet/dotnetHelpers.cjs.map +1 -0
  27. package/cjs/dotnet/dotnetHelpers.d.ts +26 -0
  28. package/cjs/dotnet/dotnetHelpers.d.ts.map +1 -0
  29. package/cjs/dotnet-wrapper.mjs +6 -0
  30. package/cjs/dotnet.cjs +13 -0
  31. package/cjs/dotnet.cjs.map +1 -0
  32. package/cjs/dotnet.d.ts +6 -0
  33. package/cjs/dotnet.d.ts.map +1 -0
  34. package/cjs/eslintConfig-wrapper.mjs +6 -0
  35. package/cjs/eslintConfig.cjs +55 -0
  36. package/cjs/eslintConfig.cjs.map +1 -0
  37. package/cjs/eslintConfig.d.ts +4 -0
  38. package/cjs/eslintConfig.d.ts.map +1 -0
  39. package/cjs/findStaticConfig-wrapper.mjs +6 -0
  40. package/cjs/findStaticConfig.cjs +34 -0
  41. package/cjs/findStaticConfig.cjs.map +1 -0
  42. package/cjs/findStaticConfig.d.ts +2 -0
  43. package/cjs/findStaticConfig.d.ts.map +1 -0
  44. package/cjs/index.cjs +5 -35
  45. package/cjs/index.cjs.map +1 -1
  46. package/cjs/index.d.ts +2 -5
  47. package/cjs/index.d.ts.map +1 -1
  48. package/cjs/semantic-release__git.d.cjs +2 -0
  49. package/cjs/semantic-release__git.d.cjs.map +1 -0
  50. package/cjs/semanticReleaseConfig-wrapper.mjs +6 -0
  51. package/cjs/semanticReleaseConfig.cjs +16 -0
  52. package/cjs/semanticReleaseConfig.cjs.map +1 -0
  53. package/cjs/semanticReleaseConfig.d.ts +4 -0
  54. package/cjs/semanticReleaseConfig.d.ts.map +1 -0
  55. package/cjs/semanticReleaseConfigDotnet-wrapper.mjs +6 -0
  56. package/cjs/semanticReleaseConfigDotnet.cjs +74 -0
  57. package/cjs/semanticReleaseConfigDotnet.cjs.map +1 -0
  58. package/cjs/semanticReleaseConfigDotnet.d.ts +30 -0
  59. package/cjs/semanticReleaseConfigDotnet.d.ts.map +1 -0
  60. package/cjs/setupGitPluginSpec-wrapper.mjs +6 -0
  61. package/cjs/setupGitPluginSpec.cjs +67 -0
  62. package/cjs/setupGitPluginSpec.cjs.map +1 -0
  63. package/cjs/setupGitPluginSpec.d.ts +18 -0
  64. package/cjs/setupGitPluginSpec.d.ts.map +1 -0
  65. package/dotnet/HCE.Shared.CI.props +8 -0
  66. package/dotnet/HCE.Shared.props +6 -0
  67. package/dotnet/HCE.Shared.targets +9 -0
  68. package/dotnet/PublishAll.targets +43 -0
  69. package/dotnet/ZipPublishDir.targets +20 -9
  70. package/dotnet/dotnet-build.ps1 +67 -0
  71. package/package.json +72 -41
  72. package/src/commitlintConfig.ts +15 -0
  73. package/src/dotnet/MSBuildProject.ts +83 -0
  74. package/src/dotnet/MSBuildProjectProperties.ts +28 -0
  75. package/src/dotnet/dotnetGHPR.ts +76 -0
  76. package/src/dotnet/dotnetGLPR.ts +46 -0
  77. package/src/dotnet/dotnetHelpers.ts +182 -0
  78. package/src/dotnet.ts +5 -0
  79. package/src/eslintConfig.ts +86 -0
  80. package/src/findStaticConfig.ts +31 -0
  81. package/src/index.ts +2 -40
  82. package/src/semantic-release__git.d.ts +67 -0
  83. package/src/semanticReleaseConfig.ts +15 -0
  84. package/src/semanticReleaseConfigDotnet.ts +78 -0
  85. package/src/setupGitPluginSpec.ts +75 -0
  86. package/src/tsconfig.json +10 -0
  87. package/static/.releaserc.yml +2 -3
  88. package/commitlint.config.ts +0 -10
  89. package/dotnet/.releaserc.cjs +0 -77
@@ -0,0 +1,76 @@
1
+ import type { NuGetRegistryInfo } from './dotnetHelpers.js';
2
+
3
+ // todo: support custom base URL for private GitHub instances
4
+ async function tokenCanWritePackages(tokenEnvVar: string) {
5
+ const tokenValue = process.env[tokenEnvVar];
6
+ if (tokenValue === undefined)
7
+ throw new TypeError(`The environment variable ${tokenEnvVar} is undefined!`)
8
+ const reqH = { authorization: `token ${tokenValue}` };
9
+ // CJS compatibility - import { request } from '@octokit/request
10
+ const request = (await import('@octokit/request')).request;
11
+ const response = await request('GET /', { headers: reqH });
12
+ const scopes = response.headers['x-oauth-scopes'];
13
+ if (scopes) {
14
+ return scopes.includes('write:packages') || scopes.includes('write:packages');
15
+ }
16
+ return false;
17
+ }
18
+
19
+ const { GITHUB_REPOSITORY_OWNER } = process.env;
20
+
21
+ export const nugetGitHubUrlBase = 'https://nuget.pkg.github.com';
22
+ export const nugetGitHubUrl = GITHUB_REPOSITORY_OWNER
23
+ ? `${nugetGitHubUrlBase}/${GITHUB_REPOSITORY_OWNER}/index.json`
24
+ : undefined;
25
+
26
+ /**
27
+ * Get a {@link NuGetRegistryInfo} for pushing to your GitHub Packages NuGet registry.
28
+ * todo: add support for private, custom GitHub instances. Token is only validated against github.com.
29
+ * @export
30
+ * @param {string} [tokenEnvVar="GITHUB_TOKEN"] The name of environment variable storing the GitHub Packages NuGet registry API key. Defaults to `"GITHUB_TOKEN"`;
31
+ * @param {string} [url=tokenEnvVar] The url of the GitHub Packages NuGet registry. Defaults to {@link nugetGitHubUrl}.
32
+ * @returns {(NuGetRegistryInfo | undefined)} a {@link NuGetRegistryInfo} object if {@link tokenEnvVar} and {@link url} are defined. Else, `undefined`.
33
+ * note: `url` defaults to job's repository owner's GitHub registry in GitHub Actions workflow. If GITHUB_REPOSITORY_OWNER is not defined, then an error will be logged and `undefined` will be returned.
34
+ */
35
+ export async function getGithubNugetRegistryPair(
36
+ tokenEnvVar = 'GITHUB_TOKEN',
37
+ url: string | undefined = nugetGitHubUrl,
38
+ ): Promise<NuGetRegistryInfo | undefined> {
39
+ // yes, this is stupid. No, I won't change it.
40
+ const isTokenDefined = process.env[tokenEnvVar] !== undefined;
41
+ const isUrlDefined = url !== undefined;
42
+ const canTokenWritePackages = isTokenDefined ? await tokenCanWritePackages(tokenEnvVar) : false;
43
+
44
+ const errors: Error[] = [];
45
+
46
+ if (!isTokenDefined)
47
+ errors.push(
48
+ new Error(
49
+ `The environment variable ${tokenEnvVar} was specified as the source of the token to push a NuGet package to GitHub, but the environment variable does not exist.`,
50
+ ),
51
+ );
52
+ if (!isUrlDefined) {
53
+ errors.push(
54
+ new Error(
55
+ 'The url for the GitHub Packages NuGet registry was undefined.\n' +
56
+ 'If running in a GitHub Actions workflow, something is seriously wrong.\n' +
57
+ 'If running in a different CI/CD pipeline and you wish to cross-push to GHPR, ensure GITHUB_REPOSITORY_OWNER is set correctly.\n',
58
+ ),
59
+ );
60
+ }
61
+ if (!canTokenWritePackages) {
62
+ // yes, this is a critical error that should be fixed before Semantic Release can succeed.
63
+ // yes, this is incredibly irritating to deal with in local runs.
64
+ errors.push(
65
+ new Error(
66
+ 'The provided GitHub token has insufficient permissions or is a fine-grained permissions token. Only class Personal Access Tokens (classic) or workflow tokens with `repo` or `write:packages` permission can push a package.',
67
+ ),
68
+ );
69
+ }
70
+
71
+ // conditions checked so `url` is certainly defined
72
+ if (isTokenDefined && isUrlDefined && canTokenWritePackages)
73
+ return { tokenEnvVar, url };
74
+
75
+ throw new Error(`One more more errors occurred when getting GHPR url-token pair. Errors:\n${errors.map(v => v.message).join('\n')}`);
76
+ }
@@ -0,0 +1,46 @@
1
+ import { error } from 'node:console';
2
+ import type { NuGetRegistryInfo } from './dotnetHelpers.js';
3
+
4
+ const { CI_API_V4_URL, CI_PROJECT_ID } = process.env;
5
+ const nameof = {
6
+ CI_API_V4_URL: 'CI_API_V4_URL',
7
+ CI_PROJECT_ID: 'CI_PROJECT_ID',
8
+ };
9
+
10
+ export const GitLabTokenEnvVar = 'CI_JOB_TOKEN';
11
+ export const nugetGitLabUrlBase = CI_API_V4_URL;
12
+ export const nugetGitLabUrl: string | undefined =
13
+ CI_API_V4_URL && CI_PROJECT_ID
14
+ ? `${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/nuget/index.json`
15
+ : undefined;
16
+
17
+ /**
18
+ * Get a {@link NuGetRegistryInfo} for pushing to your GitLab Packages NuGet registry.
19
+ * @export
20
+ * @param {string} [tokenEnvVar=GitLabTokenEnvVar] The name of environment variable storing the GitLab Packages NuGet registry API key. Defaults to {@link GitLabTokenEnvVar}.
21
+ * @param {string} [url=nugetGitLabUrl] The url of the GitLab Packages NuGet registry. Defaults to {@link nugetGitLabUrl}.
22
+ * @returns {(NuGetRegistryInfo | undefined)} a {@link NuGetRegistryInfo} object if {@link tokenEnvVar} and {@link url} are defined. Else, undefined.
23
+ */
24
+ export function getGitlabNugetRegistryPair(
25
+ tokenEnvVar: string = GitLabTokenEnvVar,
26
+ url: string | undefined = nugetGitLabUrl,
27
+ ): NuGetRegistryInfo | undefined {
28
+ // yes, this is stupid. No, I won't change it.
29
+ if (!process.env[tokenEnvVar]) {
30
+ error(
31
+ new Error(
32
+ `The environment variable ${tokenEnvVar} was specified as the source of the token to push a NuGet package to GitLab, but the environment variable does not exist.`,
33
+ ),
34
+ );
35
+ return undefined;
36
+ }
37
+ if (url) {
38
+ return { tokenEnvVar, url };
39
+ }
40
+ error(
41
+ new Error(
42
+ `The environment variables ${nameof.CI_API_V4_URL} or ${nameof.CI_PROJECT_ID} do not exist and a custom GitLab Packages NuGet registry URL was not provided.`,
43
+ ),
44
+ );
45
+ return undefined;
46
+ }
@@ -0,0 +1,182 @@
1
+ import { ok } from 'node:assert/strict';
2
+ import { getGithubNugetRegistryPair, nugetGitHubUrlBase } from './dotnetGHPR.js';
3
+ import { getGitlabNugetRegistryPair } from './dotnetGLPR.js';
4
+ import { MSBuildProject, MSBuildProjectPreDefinedProperties } from './MSBuildProject.js';
5
+
6
+ /**
7
+ * Build a prepareCmd string from .NET project paths and `dotnet nuget sign` arguments.
8
+ *
9
+ * todo: parse Solution files to publish all projects with default Publish parameters (as evaluated by MSBuild). If multi-targeting frameworks and/or runtime, evaluate those properties for Publish permutation matrix.
10
+ * todo: cleanup, docs
11
+ * @export
12
+ * @param {string[]} projectsToPublish
13
+ * @param {string[]} projectsToPackAndPush Relative and/or full file paths of projects to pass to `dotnet pack`. By default, these will be output to `./publish/`.
14
+ * @param {string[]} dotnetNugetSignArgs Arguments appended to `dotnet nuget sign`. You can also append '&&' if you want to start a new command or if you want to sign different sets of packages with different keys.
15
+ */
16
+ export function configurePrepareCmd(
17
+ projectsToPublish: string[],
18
+ projectsToPackAndPush: string[],
19
+ dotnetNugetSignArgs: string[] = ['./publish'],
20
+ ) {
21
+ // These are later evaluated with MSBuild, but are passed via --framework and --runtime arguments instead of -p:TargetFramework
22
+ const publishProperties = MSBuildProjectPreDefinedProperties;
23
+
24
+ function formatDotnetPublish(): string {
25
+ /* Fun Fact: You can define a property and get the evaluated value in the same command!
26
+ ```pwsh
27
+ dotnet msbuild .\src\HXE.csproj -property:RuntimeIdentifiers="""place;holder""" -getProperty:RuntimeIdentifiers
28
+ place;holder
29
+ ```
30
+ enclosing with """ is required in pwsh to prevent the semicolon from breaking the string.
31
+ */
32
+ let dotnetPublishArgs: string[][];
33
+ if (Array.isArray(projectsToPublish) && projectsToPublish.length > 0) {
34
+ // each may have TargetFramework OR TargetFrameworks (plural)
35
+ const evaluatedProjects: MSBuildProject[] = projectsToPublish.map(
36
+ (proj) => new MSBuildProject(proj, publishProperties),
37
+ );
38
+ // args appended to "dotnet publish", joined by space
39
+ dotnetPublishArgs = evaluatedProjects.flatMap((proj) => {
40
+ const args: string[] = [proj.Properties.FullPath];
41
+
42
+ function appendCustomProperties() {
43
+ // convert to dictionary and filter for user-defined properties.
44
+ const dictionary = Object.entries(proj.Properties).filter(
45
+ (p) => !publishProperties.includes(p[0]),
46
+ );
47
+ if (dictionary.length > 0) {
48
+ /* format remaining properties as "-p:Property=Value" and append to args */
49
+ args.push(
50
+ ...dictionary.map((keyValuePair) => `-p:${keyValuePair[0]}=${keyValuePair[1]}`),
51
+ );
52
+ }
53
+ }
54
+ appendCustomProperties();
55
+
56
+ const cmdPermutations: string[][] = []; // forEach, run dotnet [...args,...v]
57
+
58
+ function formatFrameworksAndRuntimes() {
59
+ const RIDs: string[] =
60
+ proj.Properties.RuntimeIdentifiers.length > 0
61
+ ? proj.Properties.RuntimeIdentifiers.split(';')
62
+ : [];
63
+ const TFMs: string[] =
64
+ proj.Properties.TargetFrameworks.length > 0
65
+ ? proj.Properties.TargetFrameworks.split(';')
66
+ : [];
67
+ if (RIDs.length > 0) {
68
+ if (TFMs.length > 0) {
69
+ for (const RID of RIDs) {
70
+ for (const TFM of TFMs) {
71
+ cmdPermutations.push(['--runtime', RID, '--framework', TFM]);
72
+ }
73
+ }
74
+ } else {
75
+ // assume singular TFM. No need to specify it.
76
+ for (const RID of RIDs) {
77
+ cmdPermutations.push(['--runtime', RID]);
78
+ }
79
+ }
80
+ } else if (TFMs.length > 0) {
81
+ for (const TFM of TFMs) {
82
+ cmdPermutations.push(['--framework', TFM]);
83
+ }
84
+ }
85
+ }
86
+ formatFrameworksAndRuntimes();
87
+
88
+ return cmdPermutations.length > 0
89
+ ? cmdPermutations.map((permArgs) => [...args, ...permArgs]) // string[][]
90
+ : [args]; // string[][]
91
+ }); // string[][][] -> string[][]
92
+ } else
93
+ throw new Error(
94
+ `Type of projectsToPublish (${typeof projectsToPublish}) is not allowed. Expected a string[] where length > 0.`,
95
+ );
96
+
97
+ return dotnetPublishArgs.map((args) => `dotnet publish ${args.join(' ')}`).join(' && ');
98
+ }
99
+
100
+ function formatDotnetPack(): string {
101
+ return projectsToPackAndPush.map((v) => `dotnet pack ${v}`).join(' && ');
102
+ }
103
+
104
+ function formatDotnetNugetSign(): string {
105
+ switch (dotnetNugetSignArgs.length) {
106
+ case 0:
107
+ return '';
108
+ default:
109
+ return `dotnet nuget sign ${dotnetNugetSignArgs.join(' ')}`;
110
+ // default: {
111
+ // throw new Error("")
112
+ // // this needs a rework.
113
+ // const packagePaths: string[] = [];
114
+ // dotnetNugetSignArgs.forEach((dotnetNugetSignArg, i) => {
115
+ // // if current arg doesn't start with '-' and (current arg is first -OR- previous arg also does not start with '-')...
116
+ // if (!dotnetNugetSignArg.startsWith("-") && (i === 0 || (i > 0 && !dotnetNugetSignArgs[i - 1].startsWith("-")))) {
117
+ // // ...then it's probably a package path.
118
+ // packagePaths.push(dotnetNugetSignArg);
119
+ // }
120
+ // });
121
+ // if (packagePaths.length === 0)
122
+ // return `dotnet nuget sign ${dotnetNugetSignArgs.join(" ")}`
123
+ // else return
124
+ // }
125
+ }
126
+ }
127
+
128
+ const dotnetPublish = formatDotnetPublish();
129
+ const dotnetPack = formatDotnetPack();
130
+ const dotnetNugetSign = formatDotnetNugetSign();
131
+ return [dotnetPublish, dotnetPack, dotnetNugetSign].join(' && ');
132
+ }
133
+
134
+ export interface NuGetRegistryInfo {
135
+ tokenEnvVar: string;
136
+ url: string;
137
+ user?: string | undefined;
138
+ }
139
+ export const nugetDefault: NuGetRegistryInfo = {
140
+ tokenEnvVar: 'NUGET_TOKEN',
141
+ url: 'https://api.nuget.org/v3/index.json',
142
+ };
143
+
144
+ /**
145
+ * todo
146
+ * @param nupkgDir
147
+ * @param registries
148
+ * @param pushToGitHub
149
+ * @returns
150
+ */
151
+ export async function configureDotnetNugetPush(
152
+ nupkgDir = './publish',
153
+ registries: NuGetRegistryInfo[] = [nugetDefault],
154
+ pushToGitHub = true,
155
+ ) {
156
+ if (registries.some((registry) => registry.url.trim() === ''))
157
+ throw new Error('The URL for one of the provided NuGet registries was empty or whitespace.');
158
+
159
+ // if user did not specify a GitHub NuGet Registry, try determine default values and add the Source.
160
+ if (pushToGitHub && !registries.some((reg) => reg.url.startsWith(nugetGitHubUrlBase))) {
161
+ const ghPair = await getGithubNugetRegistryPair();
162
+ if (ghPair) {
163
+ registries.push(ghPair);
164
+ }
165
+ }
166
+ if (!registries.some((reg) => reg.url.startsWith(nugetGitHubUrlBase))) {
167
+ const glPair = getGitlabNugetRegistryPair();
168
+ if (glPair) {
169
+ registries.push(glPair);
170
+ }
171
+ }
172
+
173
+ return registries
174
+ .map(
175
+ (registry) => {
176
+ const tokenValue = process.env[registry.tokenEnvVar];
177
+ ok(tokenValue, `The environment variable ${registry.tokenEnvVar} is undefined!`);
178
+ `dotnet nuget push ${nupkgDir} --source ${registry.url} --token ${tokenValue}`
179
+ }
180
+ )
181
+ .join(' && ');
182
+ }
package/src/dotnet.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * as dotnetGHPR from "./dotnet/dotnetGHPR.js"
2
+ export * as dotnetGLPR from "./dotnet/dotnetGLPR.js"
3
+ export * as dotnetHelpers from "./dotnet/dotnetHelpers.js"
4
+ export * as msbuildProject from "./dotnet/MSBuildProject.js"
5
+ export * as msbuildProjectProperties from "./dotnet/MSBuildProjectProperties.js"
@@ -0,0 +1,86 @@
1
+ import jsonc from "eslint-plugin-jsonc";
2
+ import tseslint from "typescript-eslint";
3
+ import { type TSESLint } from "@typescript-eslint/utils";
4
+ import eslint from "@eslint/js";
5
+ import globals from "globals" with {type: "json"};
6
+
7
+ // https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
8
+ // https://www.google.com/search?q=javascript+recurse+through+object+and+remove+undefined+properties
9
+
10
+ const globalIgnores: TSESLint.FlatConfig.Config = {
11
+ name: "global ignores",
12
+ ignores: [
13
+ "_tsout/**/*",
14
+ "_tsout/*",
15
+ "_tsout/",
16
+ "cjs/**/*",
17
+ "cjs/*/*",
18
+ "cjs/*",
19
+ "mjs/**/*",
20
+ "mjs/*",
21
+ "mjs/",
22
+ "node_modules/**/*",
23
+ "**/node_modules/**/*"
24
+ ]
25
+ };
26
+
27
+ export default tseslint.config(
28
+ {
29
+ name: "flat/recommended-with-json - https://github.com/ota-meshi/eslint-plugin-jsonc",
30
+ extends: jsonc.configs["flat/recommended-with-json"],
31
+ files: [
32
+ "*.json",
33
+ "**/*.json"
34
+ ],
35
+ ignores: globalIgnores.ignores
36
+ },
37
+ {
38
+ name: "flat/recommended-with-json5 - https://github.com/ota-meshi/eslint-plugin-jsonc",
39
+ extends: jsonc.configs["flat/recommended-with-json5"],
40
+ files: [
41
+ "*.json5",
42
+ "**/*.json5"
43
+ ],
44
+ ignores: globalIgnores.ignores
45
+ },
46
+ {
47
+ name: "flat/recommended-with-jsonc - https://github.com/ota-meshi/eslint-plugin-jsonc",
48
+ extends: jsonc.configs["flat/recommended-with-jsonc"],
49
+ files: [
50
+ "*.jsonc",
51
+ "**/*.jsonc"
52
+ ],
53
+ ignores: globalIgnores.ignores
54
+ },
55
+ {
56
+ name: "TSJS",
57
+ extends: [
58
+ eslint.configs.recommended as TSESLint.FlatConfig.Config,
59
+ ...tseslint.configs.strict,
60
+ ...tseslint.configs.stylistic
61
+ ],
62
+ files: [
63
+ "**/*.ts",
64
+ "**/*.cts",
65
+ "**/*.mts",
66
+ "**/*.js",
67
+ "**/*.cjs",
68
+ "**/*.mjs"
69
+ ],
70
+ ignores: globalIgnores.ignores,
71
+ languageOptions: {
72
+ parserOptions: {
73
+ project: true,
74
+ // @ts-expect-error TS2322 Type '{ allowDefaultProjectForFiles: string[]; }' is not assignable to type 'boolean | undefined'.
75
+ EXPERIMENTAL_useProjectService: {
76
+ allowDefaultProjectForFiles: [
77
+ "./*.js"
78
+ ],
79
+ maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING: 32
80
+ }
81
+ },
82
+ globals: globals.node
83
+ }
84
+ },
85
+ globalIgnores
86
+ );
@@ -0,0 +1,31 @@
1
+ import { existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ /// ../static/.releaserc.yml
6
+ export function findStaticConfig(): string {
7
+ const glob = 'static/.releaserc.yml';
8
+ let dirPath = fileURLToPath(path.dirname(import.meta.url));
9
+ let combinedPath = path.join(dirPath, glob);
10
+
11
+ while (!existsSync(combinedPath)) {
12
+ /* file:// + dirname behavior on Windows. 'root' is empty when 'file://' is present.
13
+ * file:///C:/Repos
14
+ * file:///C:
15
+ * file://
16
+ * .
17
+ */
18
+ // DEBUG.log(dirPath);
19
+ // DEBUG.log(combinedPath.href);
20
+ /** Throw if we reached root. */
21
+ if (path.dirname(dirPath) === '')
22
+ throw new Error(
23
+ `Failed to get full path for HCE.Shared's shared configuration. HCE.Shared recursively searched parent directories for '${glob}' starting from '${path.dirname(
24
+ import.meta.url,
25
+ )}'`,
26
+ );
27
+ dirPath = path.dirname(dirPath);
28
+ combinedPath = path.join(dirPath, glob);
29
+ }
30
+ return combinedPath;
31
+ }
package/src/index.ts CHANGED
@@ -1,42 +1,4 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import path from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import jsYaml from "js-yaml";
5
- import type { Options } from "semantic-release";
6
-
7
- /// ../static/.releaserc.yml
8
-
9
- function findStaticConfig(): string {
10
- const glob = "static/.releaserc.yml";
11
- let dirPath = fileURLToPath(path.dirname(import.meta.url));
12
- let combinedPath = path.join(dirPath, glob);
13
-
14
- while (!existsSync(combinedPath)) {
15
- /* file:// + dirname behavior on Windows. 'root' is empty when 'file://' is present.
16
- * file:///C:/Repos
17
- * file:///C:
18
- * file://
19
- * .
20
- */
21
- // DEBUG.log(dirPath);
22
- // DEBUG.log(combinedPath.href);
23
- /** Throw if we reached root. */
24
- if (path.dirname(dirPath) === "")
25
- throw new Error(
26
- `Failed to get full path for HCE.Shared's shared configuration. HCE.Shared recursively searched parent directories for '${glob}' starting from '${path.dirname(
27
- import.meta.url,
28
- )}'`,
29
- );
30
- dirPath = path.dirname(dirPath);
31
- combinedPath = path.join(dirPath, glob);
32
- }
33
- return combinedPath;
34
- }
35
-
36
- const options = jsYaml.load(readFileSync(findStaticConfig(), { encoding: "utf8" })) as Options;
37
-
38
1
  /**
39
2
  * Runs HCE.Shared and returns a semantic-release "shareable configuration" object.
40
- * @type {Options}.
41
- */
42
- export default options;
3
+ */
4
+ export { baseConfig as default } from './semanticReleaseConfig.js';
@@ -0,0 +1,67 @@
1
+ declare module '@semantic-release/git' {
2
+ export type MicromatchGlob = string;
3
+ export interface AssetObject {
4
+ path: MicromatchGlob;
5
+ }
6
+ export type AssetEntry = AssetObject | MicromatchGlob;
7
+ export interface Options {
8
+ /**
9
+ * Files to include in the release commit. Set to `false` to disable adding files to the release commit.
10
+ * @default ['CHANGELOG.md', 'package.json', 'package-lock.json', 'npm-shrinkwrap.json']
11
+ * @description
12
+ * Can be an Array or a single entry. Each entry can be either:
13
+ * - a glob
14
+ * - or an Object with a path property containing a glob.
15
+ *
16
+ * Each entry in the assets Array is globbed individually. A glob can be a String ("dist/\*\*\/\*.js" or "dist/mylib.js") or an Array of Strings that will be globbed together (["dist/\*\*", "!\*\*\/\*.css"]).
17
+ *
18
+ * If a directory is configured, all the files under this directory and its children will be included.
19
+ *
20
+ * Note: If a file has a match in assets it will be included even if it also has a match in .gitignore.
21
+ *
22
+ * @example
23
+ * // include all js files in the dist directory, but not in its sub-directories.
24
+ * 'dist/*.js'
25
+ * // include all js files in the dist directory and its sub-directories.
26
+ * 'dist/**\/*.js'
27
+ * // include all files in the dist directory and its sub-directories excluding the css files.
28
+ * [['dist', '!**\/*.css']]
29
+ * // include package.json and all files in the dist directory and its sub-directories excluding the css files.
30
+ * [['dist', '!**\/*.css'], 'package.json']
31
+ * // include all js and css files in the dist directory and its sub-directories excluding the minified version.
32
+ * [['dist/**\/*.{js,css}', '!**\/*.min.*']]
33
+ */
34
+ assets?: AssetEntry | AssetEntry[] | false;
35
+ /**
36
+ * The message for the release commit.
37
+ * @default `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`
38
+ * @description
39
+ * The message for the release commit is generated with Lodash template. The following variables are available:
40
+ * | Parameter | Description |
41
+ * | ----------------- | ----------- |
42
+ * | branch | The branch from which the release is done. |
43
+ * | branch.name | The branch name. |
44
+ * | branch.type | The type of branch. |
45
+ * | branch.channel | The distribution channel on which to publish releases from this branch. |
46
+ * | branch.range | The range of semantic versions to support on this branch. |
47
+ * | branch.prerelease | The pre-release detonation to append to semantic versions released from this branch. |
48
+ * | lastRelease | Object with version, gitTag and gitHead of the last release. |
49
+ * | nextRelease | Object with version, gitTag, gitHead and notes of the release being done. |
50
+ *
51
+ * Note: It is recommended to include `[skip ci]` in the commit message to not trigger a new build. Some CI service support the `[skip ci]` keyword only in the subject of the message.
52
+ *
53
+ * #### `message` examples
54
+ * The `message` `Release <%= nextRelease.version %> - <%= new Date().toLocaleDateString('en-US', {year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' }) %> [skip ci]\n\n<%= nextRelease.notes %>` will generate the commit message:
55
+ * > Release v1.0.0 - Oct. 21, 2015 1:24 AM [skip ci]
56
+ * >
57
+ * > ## 1.0.0
58
+ * >
59
+ * > ### Features
60
+ * > * Generate 1.21 gigawatts of electricity
61
+ * >
62
+ * > ...
63
+ *
64
+ */
65
+ message?: string;
66
+ }
67
+ }
@@ -0,0 +1,15 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import jsYaml from 'js-yaml';
3
+ import type { Options, PluginSpec } from 'semantic-release';
4
+ import { findStaticConfig } from './findStaticConfig.js';
5
+
6
+ export const defaultPlugins = [
7
+ '@semantic-release/commit-analyzer' as PluginSpec,
8
+ '@semantic-release/release-notes-generator',
9
+ '@semantic-release/npm',
10
+ '@semantic-release/github',
11
+ ];
12
+
13
+ export const baseConfig: Options = jsYaml.load(
14
+ readFileSync(findStaticConfig(), { encoding: 'utf8' }),
15
+ ) as Options;
@@ -0,0 +1,78 @@
1
+ /** Semantic-Release Config Factory (dotnet)
2
+ * A functional Semantic-Release configuration for dotnet projects
3
+ *
4
+ * extends {@link baseConfig }
5
+ *
6
+ * <-- TABLE OF CONTENTS -->
7
+ * - evaluateProperties
8
+ * - configureDotnetRelease
9
+ * - Insert-Edit Plugins
10
+ * - Append Plugins
11
+ *
12
+ */
13
+
14
+ import { log } from 'node:console';
15
+ import type { Options, PluginSpec } from 'semantic-release';
16
+ import { configureDotnetNugetPush, configurePrepareCmd } from './dotnet/dotnetHelpers.js';
17
+ import { baseConfig, defaultPlugins } from './semanticReleaseConfig.js';
18
+ import { setupGitPluginSpec } from './setupGitPluginSpec.js';
19
+
20
+ /**
21
+ * TODO: options/params for inserts/edits. NOT ready for production. Currently, this can only add Git plugin's options if undefined or one or more is missing.
22
+ * Insert (`array.splice`) and/or configure plugins.\
23
+ * Can be used to...\
24
+ * ...load plugin A before plugin B\
25
+ * ...edit a plugin's existing configuration
26
+ *
27
+ * @param config An instance of {@link Options}
28
+ * @returns a modified copy of {@link config}
29
+ */
30
+ export function insertAndEditPlugins(config: Options): Options {
31
+ const newConfig = config;
32
+ // const insertAndEditCommands = [];
33
+ newConfig.plugins = [...(config.plugins ?? defaultPlugins)];
34
+
35
+ newConfig.plugins = setupGitPluginSpec(newConfig.plugins as PluginSpec[]);
36
+
37
+ return newConfig;
38
+ }
39
+
40
+ export function appendPlugins(
41
+ config: Options,
42
+ projectsToPublish: string[],
43
+ projectsToPackAndPush: string[],
44
+ ) {
45
+ const newConfig = config;
46
+ if (newConfig.plugins === undefined)
47
+ throw new Error('Plugins array was undefined when it should be an array!');
48
+ (newConfig.plugins as PluginSpec[]).push(
49
+ // APPEND this array of [pluginName, pluginConfig] to plugins
50
+ // https://github.com/semantic-release/exec#usage
51
+ [
52
+ '@semantic-release/exec',
53
+ {
54
+ // 'ZipPublishDir' zips each publish folder to ./publish/*.zip
55
+ prepareCmd: configurePrepareCmd(projectsToPublish, projectsToPackAndPush),
56
+ publishCmd: configureDotnetNugetPush(),
57
+ },
58
+ ],
59
+ );
60
+ return newConfig;
61
+ }
62
+
63
+ /**
64
+ * @type {import("semantic-release").Options}
65
+ */
66
+ export function getConfig(projectsToPublish: string[], projectsToPackAndPush: string[]) {
67
+ if (process.argv.includes('--debug') || process.argv.includes('--verbose')) {
68
+ log(`hce.shared-config:\n${JSON.stringify(baseConfig, null, 2)}`);
69
+ }
70
+
71
+ let newConfig = { ...baseConfig };
72
+ newConfig = insertAndEditPlugins(newConfig);
73
+ newConfig = appendPlugins(newConfig, projectsToPublish, projectsToPackAndPush);
74
+
75
+ if (process.argv.includes('--debug') || process.argv.includes('--verbose')) {
76
+ log(`modified plugins array:\n${JSON.stringify(newConfig.plugins, null, 2)}`);
77
+ }
78
+ }