@git.zone/cli 6.9.0 → 6.10.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.
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/helpers.workflow.d.ts +23 -1
- package/dist_ts/helpers.workflow.js +93 -3
- package/dist_ts/mod_config/index.js +49 -7
- package/dist_ts/mod_release/classes.releasejournal.d.ts +20 -1
- package/dist_ts/mod_release/classes.releasejournal.js +191 -9
- package/dist_ts/mod_release/helpers.giteaassets.d.ts +36 -0
- package/dist_ts/mod_release/helpers.giteaassets.js +661 -0
- package/dist_ts/mod_release/helpers.releasepublication.d.ts +2 -0
- package/dist_ts/mod_release/helpers.releasepublication.js +147 -6
- package/dist_ts/mod_release/index.js +86 -11
- package/dist_ts/mod_release/interfaces.giteaassets.d.ts +50 -0
- package/dist_ts/mod_release/interfaces.giteaassets.js +2 -0
- package/package.json +2 -2
- package/readme.md +92 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/helpers.workflow.ts +154 -3
- package/ts/mod_config/index.ts +61 -6
- package/ts/mod_release/classes.releasejournal.ts +298 -14
- package/ts/mod_release/helpers.giteaassets.ts +932 -0
- package/ts/mod_release/helpers.releasepublication.ts +224 -4
- package/ts/mod_release/index.ts +111 -8
- package/ts/mod_release/interfaces.giteaassets.ts +67 -0
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@git.zone/cli',
|
|
6
|
-
version: '6.
|
|
6
|
+
version: '6.10.0',
|
|
7
7
|
description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
|
|
8
8
|
}
|
package/ts/helpers.workflow.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type TConfirmationMode = "prompt" | "auto" | "plan";
|
|
|
5
5
|
export type TCommitStep =
|
|
6
6
|
"format" | "analyze" | "test" | "build" | "changelog" | "commit" | "push";
|
|
7
7
|
|
|
8
|
-
export type TReleaseTarget = "git" | "npm" | "docker";
|
|
8
|
+
export type TReleaseTarget = "git" | "giteaAssets" | "npm" | "docker";
|
|
9
9
|
|
|
10
10
|
export interface ICommitWorkflowConfig {
|
|
11
11
|
confirmation?: TConfirmationMode;
|
|
@@ -45,6 +45,96 @@ export interface IReleaseNpmTargetConfig {
|
|
|
45
45
|
alreadyPublished?: "success" | "error";
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
export interface IReleaseGiteaAssetsTargetConfig {
|
|
49
|
+
enabled?: boolean;
|
|
50
|
+
apiOrigin?: string;
|
|
51
|
+
owner?: string;
|
|
52
|
+
repository?: string;
|
|
53
|
+
tokenEnv?: string;
|
|
54
|
+
manifestPath?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface IResolvedReleaseGiteaAssetsConfiguration {
|
|
58
|
+
apiOrigin: string;
|
|
59
|
+
owner: string;
|
|
60
|
+
repository: string;
|
|
61
|
+
tokenEnv: string;
|
|
62
|
+
manifestPath: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const resolveGiteaAssetsConfiguration = (
|
|
66
|
+
configArg: IReleaseGiteaAssetsTargetConfig,
|
|
67
|
+
): IResolvedReleaseGiteaAssetsConfiguration => {
|
|
68
|
+
const { apiOrigin, owner, repository, tokenEnv, manifestPath } = configArg;
|
|
69
|
+
let url: URL;
|
|
70
|
+
try {
|
|
71
|
+
url = new URL(apiOrigin!);
|
|
72
|
+
} catch {
|
|
73
|
+
throw new Error("Gitea assets require a canonical HTTPS API origin.");
|
|
74
|
+
}
|
|
75
|
+
if (url.protocol !== "https:" || url.origin !== apiOrigin) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"Gitea assets require a credential-free canonical HTTPS API origin.",
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (
|
|
81
|
+
typeof owner !== "string" ||
|
|
82
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(owner) ||
|
|
83
|
+
typeof repository !== "string" ||
|
|
84
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(repository)
|
|
85
|
+
)
|
|
86
|
+
throw new Error(
|
|
87
|
+
"Gitea assets require canonical owner and repository names.",
|
|
88
|
+
);
|
|
89
|
+
if (typeof tokenEnv !== "string" || !/^[A-Z_][A-Z0-9_]*$/.test(tokenEnv)) {
|
|
90
|
+
throw new Error("Gitea assets require a token environment-variable name.");
|
|
91
|
+
}
|
|
92
|
+
if (
|
|
93
|
+
typeof manifestPath !== "string" ||
|
|
94
|
+
!/^[A-Za-z0-9_-][A-Za-z0-9._/-]*\.json$/.test(manifestPath) ||
|
|
95
|
+
manifestPath
|
|
96
|
+
.split("/")
|
|
97
|
+
.some(
|
|
98
|
+
(part) =>
|
|
99
|
+
!part || part === "." || part === ".." || part.startsWith("."),
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
throw new Error(
|
|
103
|
+
"Gitea asset manifestPath must be a canonical repository-relative JSON path.",
|
|
104
|
+
);
|
|
105
|
+
return { apiOrigin, owner, repository, tokenEnv, manifestPath };
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/** Match the resolved destination, without guessing SSH aliases or URL rewrites. */
|
|
109
|
+
export const assertGiteaAssetsGitDestination = (
|
|
110
|
+
configArg: IResolvedReleaseGiteaAssetsConfiguration,
|
|
111
|
+
destinationArg: string,
|
|
112
|
+
): void => {
|
|
113
|
+
let destination: URL;
|
|
114
|
+
try {
|
|
115
|
+
const scp = destinationArg.match(/^(?:[^@/:]+@)?([^/:]+):([^/].*)$/);
|
|
116
|
+
destination = new URL(scp ? `ssh://${scp[1]}/${scp[2]}` : destinationArg);
|
|
117
|
+
} catch {
|
|
118
|
+
throw new Error(
|
|
119
|
+
"Gitea assets require a provable SSH or HTTPS Git destination.",
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (
|
|
123
|
+
!["ssh:", "https:"].includes(destination.protocol) ||
|
|
124
|
+
destination.password ||
|
|
125
|
+
destination.search ||
|
|
126
|
+
destination.hash ||
|
|
127
|
+
destination.hostname !== new URL(configArg.apiOrigin).hostname ||
|
|
128
|
+
(destination.protocol === "https:" &&
|
|
129
|
+
destination.origin !== configArg.apiOrigin) ||
|
|
130
|
+
destination.pathname.replace(/\.git$/, "") !==
|
|
131
|
+
`/${configArg.owner}/${configArg.repository}`
|
|
132
|
+
)
|
|
133
|
+
throw new Error(
|
|
134
|
+
"Gitea assets and Git must select the same host and exact repository.",
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
48
138
|
export interface IReleaseDockerTargetConfig {
|
|
49
139
|
enabled?: boolean;
|
|
50
140
|
engine?: "tsdocker";
|
|
@@ -73,6 +163,7 @@ export interface IReleaseWorkflowConfig {
|
|
|
73
163
|
targets?: {
|
|
74
164
|
git?: IReleaseGitTargetConfig;
|
|
75
165
|
npm?: IReleaseNpmTargetConfig;
|
|
166
|
+
giteaAssets?: IReleaseGiteaAssetsTargetConfig;
|
|
76
167
|
docker?: IReleaseDockerTargetConfig;
|
|
77
168
|
};
|
|
78
169
|
}
|
|
@@ -111,6 +202,7 @@ export interface IResolvedReleaseWorkflow {
|
|
|
111
202
|
npmPackageSource: "root" | "tspublish";
|
|
112
203
|
npmAccessLevel: "public" | "private";
|
|
113
204
|
npmAlreadyPublished: "success" | "error";
|
|
205
|
+
giteaAssets?: IResolvedReleaseGiteaAssetsConfiguration;
|
|
114
206
|
dockerEnabled: boolean;
|
|
115
207
|
dockerEngine: "tsdocker";
|
|
116
208
|
dockerRegistry?: string;
|
|
@@ -129,6 +221,7 @@ export interface IResolvedReleaseResumeConfiguration {
|
|
|
129
221
|
npmRegistries: string[];
|
|
130
222
|
npmAccessLevel: "public" | "private";
|
|
131
223
|
npmAlreadyPublished: "success" | "error";
|
|
224
|
+
giteaAssets?: IResolvedReleaseGiteaAssetsConfiguration;
|
|
132
225
|
}
|
|
133
226
|
|
|
134
227
|
export type TResolvedReleaseDockerConfiguration = Pick<
|
|
@@ -460,7 +553,12 @@ const normalizeCommitSteps = (rawSteps: TCommitStep[]): TCommitStep[] => {
|
|
|
460
553
|
};
|
|
461
554
|
|
|
462
555
|
const getTargetOverride = (argvArg: any): TReleaseTarget[] | undefined => {
|
|
463
|
-
const validTargets: TReleaseTarget[] = [
|
|
556
|
+
const validTargets: TReleaseTarget[] = [
|
|
557
|
+
"git",
|
|
558
|
+
"giteaAssets",
|
|
559
|
+
"npm",
|
|
560
|
+
"docker",
|
|
561
|
+
];
|
|
464
562
|
const targetKey = ["target", "targets"].find((keyArg) =>
|
|
465
563
|
Object.prototype.hasOwnProperty.call(argvArg, keyArg),
|
|
466
564
|
);
|
|
@@ -495,7 +593,12 @@ const getTargetOverride = (argvArg: any): TReleaseTarget[] | undefined => {
|
|
|
495
593
|
return targets.length > 0 ? targets : undefined;
|
|
496
594
|
};
|
|
497
595
|
|
|
498
|
-
const releaseTargetOrder: TReleaseTarget[] = [
|
|
596
|
+
const releaseTargetOrder: TReleaseTarget[] = [
|
|
597
|
+
"git",
|
|
598
|
+
"giteaAssets",
|
|
599
|
+
"npm",
|
|
600
|
+
"docker",
|
|
601
|
+
];
|
|
499
602
|
|
|
500
603
|
const buildReleasePlan = (options: {
|
|
501
604
|
mergeRequested: boolean;
|
|
@@ -511,6 +614,8 @@ const buildReleasePlan = (options: {
|
|
|
511
614
|
plan.push("core.version", "core.changelog", "core.commit", "core.tag");
|
|
512
615
|
if (options.runBuild) plan.push("core.build");
|
|
513
616
|
if (options.targets.includes("npm")) plan.push("core.packNpmArtifact");
|
|
617
|
+
if (options.targets.includes("giteaAssets"))
|
|
618
|
+
plan.push("core.freezeGiteaAssets");
|
|
514
619
|
plan.push("core.writeReleaseJournal");
|
|
515
620
|
if (options.targets.includes("docker")) {
|
|
516
621
|
plan.push("target.docker.qualify");
|
|
@@ -608,6 +713,14 @@ export const resolveReleaseWorkflow = async (
|
|
|
608
713
|
const npmEnabled = npmConfig.enabled ?? npmRegistryConfigurationPresent;
|
|
609
714
|
const gitEnabled = gitConfig.enabled ?? true;
|
|
610
715
|
const dockerEnabled = dockerConfig.enabled ?? false;
|
|
716
|
+
if (
|
|
717
|
+
targetConfig.giteaAssets?.enabled !== undefined &&
|
|
718
|
+
typeof targetConfig.giteaAssets.enabled !== "boolean"
|
|
719
|
+
) {
|
|
720
|
+
throw new Error(
|
|
721
|
+
"release.targets.giteaAssets.enabled must be true or false.",
|
|
722
|
+
);
|
|
723
|
+
}
|
|
611
724
|
const pushBranch = resolveGitPushSetting(
|
|
612
725
|
gitConfig.pushBranch,
|
|
613
726
|
"pushBranch",
|
|
@@ -638,6 +751,8 @@ export const resolveReleaseWorkflow = async (
|
|
|
638
751
|
|
|
639
752
|
const configuredTargets: TReleaseTarget[] = [];
|
|
640
753
|
if (gitEnabled) configuredTargets.push("git");
|
|
754
|
+
if (targetConfig.giteaAssets?.enabled === true)
|
|
755
|
+
configuredTargets.push("giteaAssets");
|
|
641
756
|
if (npmEnabled) configuredTargets.push("npm");
|
|
642
757
|
if (dockerEnabled) configuredTargets.push("docker");
|
|
643
758
|
let targets = getTargetOverride(argvArg) || configuredTargets;
|
|
@@ -651,6 +766,28 @@ export const resolveReleaseWorkflow = async (
|
|
|
651
766
|
targets = releaseTargetOrder.filter((target) =>
|
|
652
767
|
selectedTargets.includes(target),
|
|
653
768
|
);
|
|
769
|
+
if (
|
|
770
|
+
targetConfig.giteaAssets?.enabled === true &&
|
|
771
|
+
targets.includes("npm") &&
|
|
772
|
+
!targets.includes("giteaAssets")
|
|
773
|
+
) {
|
|
774
|
+
throw new Error(
|
|
775
|
+
"npm publication cannot bypass the configured Gitea asset target.",
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
const giteaAssets = targets.includes("giteaAssets")
|
|
779
|
+
? resolveGiteaAssetsConfiguration(targetConfig.giteaAssets || {})
|
|
780
|
+
: undefined;
|
|
781
|
+
if (giteaAssets && (!targets.includes("git") || !pushBranch || !pushTags)) {
|
|
782
|
+
throw new Error(
|
|
783
|
+
"Gitea assets require the active Git branch and tag target.",
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
if (giteaAssets && (targets.includes("docker") || argvArg.merge === true)) {
|
|
787
|
+
throw new Error(
|
|
788
|
+
"Gitea asset releases cannot combine Docker or --merge; integrate main before release.",
|
|
789
|
+
);
|
|
790
|
+
}
|
|
654
791
|
let npmRegistries: string[] = [];
|
|
655
792
|
if (targets.includes("npm")) {
|
|
656
793
|
if (
|
|
@@ -706,6 +843,7 @@ export const resolveReleaseWorkflow = async (
|
|
|
706
843
|
: "root",
|
|
707
844
|
npmAccessLevel: npmConfig.accessLevel || "public",
|
|
708
845
|
npmAlreadyPublished: npmConfig.alreadyPublished || "success",
|
|
846
|
+
...(giteaAssets ? { giteaAssets } : {}),
|
|
709
847
|
dockerEnabled,
|
|
710
848
|
dockerEngine: "tsdocker",
|
|
711
849
|
...dockerConfiguration,
|
|
@@ -715,12 +853,18 @@ export const resolveReleaseWorkflow = async (
|
|
|
715
853
|
export const resolveReleaseResumeConfiguration = async (optionsArg: {
|
|
716
854
|
git: boolean;
|
|
717
855
|
npm: boolean;
|
|
856
|
+
giteaAssets?: boolean;
|
|
718
857
|
}): Promise<IResolvedReleaseResumeConfiguration> => {
|
|
719
858
|
const cliConfig = await readCliWorkflowConfig();
|
|
720
859
|
const releaseConfig = cliConfig.release || {};
|
|
721
860
|
const targetConfig = releaseConfig.targets || {};
|
|
722
861
|
const gitConfig = targetConfig.git || {};
|
|
723
862
|
const npmConfig = targetConfig.npm || {};
|
|
863
|
+
if (optionsArg.giteaAssets && targetConfig.giteaAssets?.enabled !== true) {
|
|
864
|
+
throw new Error(
|
|
865
|
+
"The journaled Gitea asset target must remain enabled for resume.",
|
|
866
|
+
);
|
|
867
|
+
}
|
|
724
868
|
|
|
725
869
|
const gitRemote = optionsArg.git ? gitConfig.remote || "origin" : "origin";
|
|
726
870
|
if (typeof gitRemote !== "string" || !gitRemote.trim()) {
|
|
@@ -778,6 +922,13 @@ export const resolveReleaseResumeConfiguration = async (optionsArg: {
|
|
|
778
922
|
: "root",
|
|
779
923
|
npmAccessLevel,
|
|
780
924
|
npmAlreadyPublished,
|
|
925
|
+
...(optionsArg.giteaAssets
|
|
926
|
+
? {
|
|
927
|
+
giteaAssets: resolveGiteaAssetsConfiguration(
|
|
928
|
+
targetConfig.giteaAssets || {},
|
|
929
|
+
),
|
|
930
|
+
}
|
|
931
|
+
: {}),
|
|
781
932
|
};
|
|
782
933
|
};
|
|
783
934
|
|
package/ts/mod_config/index.ts
CHANGED
|
@@ -19,7 +19,10 @@ import {
|
|
|
19
19
|
CURRENT_GITZONE_CLI_SCHEMA_VERSION,
|
|
20
20
|
migrateSmartconfigData,
|
|
21
21
|
} from "../helpers.smartconfigmigrations.js";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
getDeclaredTsdockerRange,
|
|
24
|
+
resolveGiteaAssetsConfiguration,
|
|
25
|
+
} from "../helpers.workflow.js";
|
|
23
26
|
import { hasInstalledProjectTsdockerBinary } from "../helpers.tsdocker.js";
|
|
24
27
|
import { TsdockerReleaseClient } from "../mod_release/helpers.tsdockerprotocol.js";
|
|
25
28
|
import { getSealedReleaseConfigError } from "../helpers.sealedrelease.js";
|
|
@@ -304,6 +307,10 @@ async function handleShow(mode: ICliMode): Promise<void> {
|
|
|
304
307
|
|
|
305
308
|
printConfigSection("Release Targets", [
|
|
306
309
|
["git", formatTarget(targets.git?.enabled, targets.git)],
|
|
310
|
+
[
|
|
311
|
+
"giteaAssets",
|
|
312
|
+
formatTarget(targets.giteaAssets?.enabled, targets.giteaAssets),
|
|
313
|
+
],
|
|
307
314
|
["npm", formatTarget(targets.npm?.enabled, targets.npm)],
|
|
308
315
|
["docker", formatTarget(targets.docker?.enabled, targets.docker)],
|
|
309
316
|
]);
|
|
@@ -1800,6 +1807,37 @@ async function validateReleaseConfig(
|
|
|
1800
1807
|
|
|
1801
1808
|
const targets = releaseConfig.targets || {};
|
|
1802
1809
|
await validateGitTarget(targets.git || {}, findings);
|
|
1810
|
+
if (
|
|
1811
|
+
targets.giteaAssets?.enabled !== undefined &&
|
|
1812
|
+
typeof targets.giteaAssets.enabled !== "boolean"
|
|
1813
|
+
) {
|
|
1814
|
+
findings.push({
|
|
1815
|
+
level: "error",
|
|
1816
|
+
message: "Gitea assets enabled must be true or false",
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
if (targets.giteaAssets?.enabled === true) {
|
|
1820
|
+
try {
|
|
1821
|
+
resolveGiteaAssetsConfiguration(targets.giteaAssets);
|
|
1822
|
+
if (targets.git?.enabled === false || targets.docker?.enabled === true)
|
|
1823
|
+
throw new Error(
|
|
1824
|
+
"Gitea assets require Git publication and cannot combine Docker.",
|
|
1825
|
+
);
|
|
1826
|
+
findings.push({
|
|
1827
|
+
level: "ok",
|
|
1828
|
+
message:
|
|
1829
|
+
"Gitea assets configured; release verifies Git destination and publisher capability before publication",
|
|
1830
|
+
});
|
|
1831
|
+
} catch (error) {
|
|
1832
|
+
findings.push({
|
|
1833
|
+
level: "error",
|
|
1834
|
+
message:
|
|
1835
|
+
error instanceof Error
|
|
1836
|
+
? error.message
|
|
1837
|
+
: "Invalid Gitea asset configuration",
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1803
1841
|
await validateNpmTarget(targets.npm || {}, findings);
|
|
1804
1842
|
await validateDockerTarget(targets.docker || {}, smartconfigData, findings);
|
|
1805
1843
|
}
|
|
@@ -1830,9 +1868,19 @@ async function validateAssetsConfig(
|
|
|
1830
1868
|
}
|
|
1831
1869
|
if (rawAssetsConfig.kind === "tspackRelease") {
|
|
1832
1870
|
const error = getSealedReleaseConfigError(rawAssetsConfig.sealedRelease);
|
|
1833
|
-
findings.push(
|
|
1834
|
-
|
|
1835
|
-
|
|
1871
|
+
findings.push(
|
|
1872
|
+
error
|
|
1873
|
+
? {
|
|
1874
|
+
level: "error",
|
|
1875
|
+
message: error,
|
|
1876
|
+
fix: "Set @git.zone/cli.assets.sealedRelease using the documented TsPack release configuration.",
|
|
1877
|
+
}
|
|
1878
|
+
: {
|
|
1879
|
+
level: "ok",
|
|
1880
|
+
message:
|
|
1881
|
+
"Managed tspackRelease assets have valid component commands and retention output",
|
|
1882
|
+
},
|
|
1883
|
+
);
|
|
1836
1884
|
return;
|
|
1837
1885
|
}
|
|
1838
1886
|
if (rawAssetsConfig.kind !== "denoBinaryCli") {
|
|
@@ -2001,8 +2049,15 @@ async function validateNpmTarget(
|
|
|
2001
2049
|
fix: "Use success or error.",
|
|
2002
2050
|
});
|
|
2003
2051
|
}
|
|
2004
|
-
if (
|
|
2005
|
-
|
|
2052
|
+
if (
|
|
2053
|
+
npmTarget.packageSource !== undefined &&
|
|
2054
|
+
!["root", "tspublish"].includes(npmTarget.packageSource)
|
|
2055
|
+
) {
|
|
2056
|
+
findings.push({
|
|
2057
|
+
level: "error",
|
|
2058
|
+
message: `Invalid npm package source: ${npmTarget.packageSource}`,
|
|
2059
|
+
fix: "Use root or tspublish.",
|
|
2060
|
+
});
|
|
2006
2061
|
}
|
|
2007
2062
|
|
|
2008
2063
|
const smartNetwork = new plugins.smartnetwork.SmartNetwork();
|