@git.zone/cli 6.4.0 → 6.6.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/assets/templates/asset_tspack_release_gitea/.gitea/workflows/release.yml +60 -0
- package/assets/templates/asset_tspack_release_gitea/scripts/gitzone-release-api.mjs +150 -0
- package/assets/templates/asset_tspack_release_gitea/scripts/gitzone-sealed-release.mjs +122 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/helpers.sealedrelease.d.ts +2 -0
- package/dist_ts/helpers.sealedrelease.js +14 -0
- package/dist_ts/mod_config/index.js +10 -2
- package/dist_ts/mod_format/formatters/assets.formatter.js +16 -1
- package/dist_ts/mod_release/helpers.releasebranch.d.ts +2 -0
- package/dist_ts/mod_release/helpers.releasebranch.js +37 -5
- package/dist_ts/mod_release/helpers.releasepublication.js +6 -3
- package/package.json +2 -1
- package/readme.md +56 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/helpers.sealedrelease.ts +13 -0
- package/ts/mod_config/index.ts +9 -1
- package/ts/mod_format/formatters/assets.formatter.ts +15 -0
- package/ts/mod_release/helpers.releasebranch.ts +74 -11
- package/ts/mod_release/helpers.releasepublication.ts +5 -2
|
@@ -4,6 +4,7 @@ import * as plugins from '../mod.plugins.js';
|
|
|
4
4
|
import * as paths from '../../paths.js';
|
|
5
5
|
import { logger, logVerbose } from '../../gitzone.logging.js';
|
|
6
6
|
import { getCliConfigValue, readSmartconfigFile } from '../../helpers.smartconfig.js';
|
|
7
|
+
import { getSealedReleaseConfigError } from '../../helpers.sealedrelease.js';
|
|
7
8
|
|
|
8
9
|
interface IAssetFileMapping {
|
|
9
10
|
from: string;
|
|
@@ -131,6 +132,16 @@ const normalizeBinaryTargets = (
|
|
|
131
132
|
};
|
|
132
133
|
|
|
133
134
|
const buildDefaultEntries = (assetsConfig: Record<string, any>, cliName: string): IAssetTemplateEntry[] => {
|
|
135
|
+
if (assetsConfig.kind === 'tspackRelease') {
|
|
136
|
+
return [{
|
|
137
|
+
template: 'asset_tspack_release_gitea',
|
|
138
|
+
files: [
|
|
139
|
+
{ from: '.gitea/workflows/release.yml', to: '.gitea/workflows/release.yml' },
|
|
140
|
+
{ from: 'scripts/gitzone-sealed-release.mjs', to: 'scripts/gitzone-sealed-release.mjs' },
|
|
141
|
+
{ from: 'scripts/gitzone-release-api.mjs', to: 'scripts/gitzone-release-api.mjs' },
|
|
142
|
+
],
|
|
143
|
+
}];
|
|
144
|
+
}
|
|
134
145
|
if (assetsConfig.kind !== 'denoBinaryCli') {
|
|
135
146
|
return [];
|
|
136
147
|
}
|
|
@@ -241,6 +252,10 @@ export class AssetsFormatter extends BaseFormatter {
|
|
|
241
252
|
if (!isPlainObject(assetsConfig) || assetsConfig.enabled === false) {
|
|
242
253
|
return [];
|
|
243
254
|
}
|
|
255
|
+
if (assetsConfig.kind === 'tspackRelease') {
|
|
256
|
+
const error = getSealedReleaseConfigError(assetsConfig.sealedRelease);
|
|
257
|
+
return error ? [{ level: 'error', module: this.name, message: error }] : [];
|
|
258
|
+
}
|
|
244
259
|
if (assetsConfig.kind && assetsConfig.kind !== 'denoBinaryCli') {
|
|
245
260
|
return [{ level: 'error', module: this.name, message: `Unsupported managed asset kind: ${assetsConfig.kind}` }];
|
|
246
261
|
}
|
|
@@ -438,28 +438,64 @@ const resolvePushUrl = async (
|
|
|
438
438
|
return resolvedPushUrl;
|
|
439
439
|
};
|
|
440
440
|
|
|
441
|
+
/** Git's exact absent-ref lease identity; null remains the disabled-target state. */
|
|
442
|
+
export const isAbsentGitOid = (valueArg: string): boolean =>
|
|
443
|
+
/^(?:0{40}|0{64})$/.test(valueArg);
|
|
444
|
+
|
|
441
445
|
const resolveRemoteMainOid = async (
|
|
442
446
|
smartshellArg: TSmartshell,
|
|
443
447
|
cwdArg: string,
|
|
444
448
|
pushUrlArg: string,
|
|
445
449
|
readOnlyArg = false,
|
|
446
450
|
): Promise<string> => {
|
|
447
|
-
const result =
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
451
|
+
const result = await runGit(
|
|
452
|
+
smartshellArg,
|
|
453
|
+
cwdArg,
|
|
454
|
+
["ls-remote", "--exit-code", pushUrlArg, mainBranchRef],
|
|
455
|
+
readOnlyArg,
|
|
456
|
+
);
|
|
457
|
+
if (result.exitCode === 2 && !result.stdout.trim()) {
|
|
458
|
+
const allRefs = requireGitSuccess(
|
|
459
|
+
await runGit(
|
|
460
|
+
smartshellArg,
|
|
461
|
+
cwdArg,
|
|
462
|
+
["ls-remote", pushUrlArg],
|
|
463
|
+
readOnlyArg,
|
|
464
|
+
),
|
|
465
|
+
"Unable to verify the empty Git push destination.",
|
|
466
|
+
);
|
|
467
|
+
if (allRefs.stdout.trim()) {
|
|
468
|
+
throw new Error(
|
|
469
|
+
"First release requires an empty Git remote; main is missing from a nonempty destination.",
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
const format = requireGitSuccess(
|
|
473
|
+
await runGit(
|
|
474
|
+
smartshellArg,
|
|
475
|
+
cwdArg,
|
|
476
|
+
["rev-parse", "--show-object-format"],
|
|
477
|
+
readOnlyArg,
|
|
478
|
+
),
|
|
479
|
+
"Unable to identify the repository object format.",
|
|
480
|
+
).stdout.trim();
|
|
481
|
+
if (format !== "sha1" && format !== "sha256") {
|
|
482
|
+
throw new Error("Unsupported Git object format for first release.");
|
|
483
|
+
}
|
|
484
|
+
return "0".repeat(format === "sha256" ? 64 : 40);
|
|
485
|
+
}
|
|
486
|
+
requireGitSuccess(
|
|
487
|
+
result,
|
|
488
|
+
"Unable to inspect main at the configured Git push destination.",
|
|
455
489
|
);
|
|
456
|
-
const
|
|
457
|
-
|
|
490
|
+
const match = result.stdout
|
|
491
|
+
.trim()
|
|
492
|
+
.match(/^([0-9a-f]{40}|[0-9a-f]{64})\s+refs\/heads\/main$/i);
|
|
493
|
+
if (!match || isAbsentGitOid(match[1])) {
|
|
458
494
|
throw new Error(
|
|
459
495
|
"The configured Git push destination returned an invalid main commit ID.",
|
|
460
496
|
);
|
|
461
497
|
}
|
|
462
|
-
return
|
|
498
|
+
return match[1];
|
|
463
499
|
};
|
|
464
500
|
|
|
465
501
|
const hasCommitObject = async (
|
|
@@ -788,6 +824,15 @@ export async function inspectReleaseBranch(
|
|
|
788
824
|
context.pushUrl,
|
|
789
825
|
true,
|
|
790
826
|
);
|
|
827
|
+
if (isAbsentGitOid(context.remoteMainOid)) {
|
|
828
|
+
if (symbolic.branch !== mainBranch) {
|
|
829
|
+
throw new Error(
|
|
830
|
+
"First release into an empty Git remote must run directly from main.",
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
context.planAncestryVerified = true;
|
|
834
|
+
return context;
|
|
835
|
+
}
|
|
791
836
|
if (
|
|
792
837
|
await hasCommitObject(
|
|
793
838
|
optionsArg.smartshell,
|
|
@@ -850,6 +895,24 @@ export async function prepareReleaseIntegration(
|
|
|
850
895
|
"Remote main changed during release preparation. Fetch, rebase cleanly, and retry.",
|
|
851
896
|
);
|
|
852
897
|
}
|
|
898
|
+
if (isAbsentGitOid(remoteMainOid)) {
|
|
899
|
+
if (
|
|
900
|
+
contextArg.sourceBranch !== mainBranch ||
|
|
901
|
+
contextArg.remoteMainOid !== remoteMainOid
|
|
902
|
+
) {
|
|
903
|
+
throw new Error(
|
|
904
|
+
"First release requires unchanged empty remote state and local main.",
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
await verifySourceState(smartshellArg, contextArg);
|
|
908
|
+
await verifyMainWorktree(
|
|
909
|
+
smartshellArg,
|
|
910
|
+
contextArg.mainWorktreePath,
|
|
911
|
+
contextArg.localMainOid,
|
|
912
|
+
contextArg.mainWorktreeGitDir,
|
|
913
|
+
);
|
|
914
|
+
return { ...contextArg, planAncestryVerified: true };
|
|
915
|
+
}
|
|
853
916
|
requireGitSuccess(
|
|
854
917
|
await runGit(smartshellArg, contextArg.sourceCwd, [
|
|
855
918
|
"fetch",
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
type INpmArtifactProbeOptions,
|
|
20
20
|
type INpmArtifactProbeResult,
|
|
21
21
|
} from "./helpers.npmartifact.js";
|
|
22
|
-
import { releaseGitEnv } from "./helpers.releasebranch.js";
|
|
22
|
+
import { isAbsentGitOid, releaseGitEnv } from "./helpers.releasebranch.js";
|
|
23
23
|
import {
|
|
24
24
|
TsdockerReleaseCommandError,
|
|
25
25
|
TsdockerReleaseRequestCleanupError,
|
|
@@ -292,7 +292,10 @@ const inspectRemoteRelease = async (
|
|
|
292
292
|
return { status: "exact" };
|
|
293
293
|
}
|
|
294
294
|
if (
|
|
295
|
-
mainOid === journalArg.git.expectedRemoteMainOid
|
|
295
|
+
(mainOid === journalArg.git.expectedRemoteMainOid ||
|
|
296
|
+
(mainOid === undefined &&
|
|
297
|
+
journalArg.git.expectedRemoteMainOid !== null &&
|
|
298
|
+
isAbsentGitOid(journalArg.git.expectedRemoteMainOid))) &&
|
|
296
299
|
tagOid === undefined &&
|
|
297
300
|
tagCommitOid === undefined
|
|
298
301
|
) {
|