@supacloud/admin 0.15.3 → 0.15.4
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/index.js +122 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -26367,7 +26367,7 @@ function quoteShell(shellText) {
|
|
|
26367
26367
|
// src/shared/releases/local-upgrade-bundle.ts
|
|
26368
26368
|
import { spawn } from "node:child_process";
|
|
26369
26369
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
26370
|
-
import { accessSync, chmodSync as chmodSync2, constants as fsConstants, createWriteStream, lstatSync, mkdirSync, mkdtempSync as mkdtempSync2, readFileSync as readFileSync3, readdirSync,
|
|
26370
|
+
import { accessSync, chmodSync as chmodSync2, constants as fsConstants, createWriteStream, lstatSync, mkdirSync, mkdtempSync as mkdtempSync2, readFileSync as readFileSync3, readdirSync, rmSync as rmSync2, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
26371
26371
|
import { get } from "node:https";
|
|
26372
26372
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
26373
26373
|
import { basename, delimiter, join } from "node:path";
|
|
@@ -26649,6 +26649,7 @@ async function withSigstoreVerificationDirectory(operation) {
|
|
|
26649
26649
|
// src/shared/releases/local-upgrade-bundle.ts
|
|
26650
26650
|
var RELEASES_API = `https://api.github.com/repos/${RELEASE_REPOSITORY}/releases`;
|
|
26651
26651
|
var ATTESTATIONS_API = `https://api.github.com/repos/${RELEASE_REPOSITORY}/attestations`;
|
|
26652
|
+
var GITHUB_CLI_REPOSITORY = "cli/cli";
|
|
26652
26653
|
var GH_VERSION = "2.96.0";
|
|
26653
26654
|
var GH_ARCHIVE_SHA256 = {
|
|
26654
26655
|
amd64: "83d5c2ccad5498f58bf6368acb1ab32588cf43ab3a4b1c301bf36328b1c8bd60",
|
|
@@ -26859,6 +26860,36 @@ async function downloadDirect(url, destination, maxBytes) {
|
|
|
26859
26860
|
}
|
|
26860
26861
|
throw new AggregateError(retryFailures, `Unable to download ${parsed.hostname}${parsed.pathname}`);
|
|
26861
26862
|
}
|
|
26863
|
+
async function downloadGithubReleaseAsset(request) {
|
|
26864
|
+
const download = await runGithubCliDownload([
|
|
26865
|
+
"release",
|
|
26866
|
+
"download",
|
|
26867
|
+
request.tag,
|
|
26868
|
+
"--repo",
|
|
26869
|
+
`github.com/${request.repository}`,
|
|
26870
|
+
"--pattern",
|
|
26871
|
+
request.assetName,
|
|
26872
|
+
"--output",
|
|
26873
|
+
"-"
|
|
26874
|
+
], request.destination, request.maxBytes, DOWNLOAD_TIMEOUT_MS);
|
|
26875
|
+
if (download.exitCode !== 0) {
|
|
26876
|
+
rmSync2(request.destination, { force: true });
|
|
26877
|
+
throw new Error(`GitHub release asset download failed: ${download.stderr.trim().slice(-1000) || download.exitCode}`);
|
|
26878
|
+
}
|
|
26879
|
+
assertDownloadedReleaseAsset(request);
|
|
26880
|
+
}
|
|
26881
|
+
function assertDownloadedReleaseAsset(request) {
|
|
26882
|
+
const stats = lstatSync(request.destination);
|
|
26883
|
+
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1) {
|
|
26884
|
+
rmSync2(request.destination, { force: true });
|
|
26885
|
+
throw new Error("GitHub release asset must be a direct regular file");
|
|
26886
|
+
}
|
|
26887
|
+
if (stats.size > request.maxBytes) {
|
|
26888
|
+
rmSync2(request.destination, { force: true });
|
|
26889
|
+
throw new Error(`GitHub release asset exceeded ${request.maxBytes} bytes`);
|
|
26890
|
+
}
|
|
26891
|
+
chmodSync2(request.destination, 384);
|
|
26892
|
+
}
|
|
26862
26893
|
function parseJsonFile(filePath, label) {
|
|
26863
26894
|
const contents = readFileSync3(filePath, "utf8");
|
|
26864
26895
|
try {
|
|
@@ -26930,7 +26961,7 @@ function serializeAttestationBundles(candidate) {
|
|
|
26930
26961
|
function directEnvironment() {
|
|
26931
26962
|
const environment = { ...process.env };
|
|
26932
26963
|
for (const key of Object.keys(environment)) {
|
|
26933
|
-
if (/(?:^|_)proxy$/i.test(key) || /^(?:SUPACLOUD_GITHUB_PROXIES|NODE_USE_ENV_PROXY)$/.test(key)) {
|
|
26964
|
+
if (/(?:^|_)proxy$/i.test(key) || /^(?:GH_HOST|GH_REPO|SUPACLOUD_GITHUB_PROXIES|NODE_USE_ENV_PROXY)$/.test(key)) {
|
|
26934
26965
|
delete environment[key];
|
|
26935
26966
|
}
|
|
26936
26967
|
}
|
|
@@ -26955,15 +26986,15 @@ function githubCliExecutable(environment) {
|
|
|
26955
26986
|
}
|
|
26956
26987
|
throw new Error("GitHub CLI executable was not found in PATH");
|
|
26957
26988
|
}
|
|
26958
|
-
|
|
26959
|
-
|
|
26960
|
-
|
|
26961
|
-
|
|
26962
|
-
|
|
26963
|
-
|
|
26964
|
-
|
|
26965
|
-
|
|
26966
|
-
|
|
26989
|
+
function spawnGithubCli(arguments_) {
|
|
26990
|
+
const environment = directEnvironment();
|
|
26991
|
+
return spawn(githubCliExecutable(environment), arguments_, {
|
|
26992
|
+
env: environment,
|
|
26993
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
26994
|
+
});
|
|
26995
|
+
}
|
|
26996
|
+
function githubCliExitCode(child, timeoutMs) {
|
|
26997
|
+
return new Promise((resolve2, reject) => {
|
|
26967
26998
|
let timedOut = false;
|
|
26968
26999
|
let settled = false;
|
|
26969
27000
|
let forceKillTimer;
|
|
@@ -26982,18 +27013,46 @@ async function runGithubCli(arguments_, timeoutMs) {
|
|
|
26982
27013
|
if (error)
|
|
26983
27014
|
reject(error);
|
|
26984
27015
|
else
|
|
26985
|
-
resolve2(
|
|
27016
|
+
resolve2(timedOut ? 124 : exitCode);
|
|
26986
27017
|
};
|
|
26987
|
-
child.stdout.on("data", (chunk) => {
|
|
26988
|
-
stdout = `${stdout}${chunk.toString()}`.slice(-8000);
|
|
26989
|
-
});
|
|
26990
|
-
child.stderr.on("data", (chunk) => {
|
|
26991
|
-
stderr = `${stderr}${chunk.toString()}`.slice(-8000);
|
|
26992
|
-
});
|
|
26993
27018
|
child.once("error", (error) => settleExecution(error, 127));
|
|
26994
27019
|
child.once("close", (code) => settleExecution(undefined, code ?? 1));
|
|
26995
27020
|
});
|
|
26996
27021
|
}
|
|
27022
|
+
async function runGithubCli(arguments_, timeoutMs) {
|
|
27023
|
+
const child = spawnGithubCli(arguments_);
|
|
27024
|
+
let stdout = "";
|
|
27025
|
+
let stderr = "";
|
|
27026
|
+
child.stdout.on("data", (chunk) => {
|
|
27027
|
+
stdout = `${stdout}${chunk.toString()}`.slice(-8000);
|
|
27028
|
+
});
|
|
27029
|
+
child.stderr.on("data", (chunk) => {
|
|
27030
|
+
stderr = `${stderr}${chunk.toString()}`.slice(-8000);
|
|
27031
|
+
});
|
|
27032
|
+
const exitCode = await githubCliExitCode(child, timeoutMs);
|
|
27033
|
+
return { exitCode, stdout, stderr };
|
|
27034
|
+
}
|
|
27035
|
+
async function runGithubCliDownload(arguments_, destination, maxBytes, timeoutMs) {
|
|
27036
|
+
const child = spawnGithubCli(arguments_);
|
|
27037
|
+
let stderr = "";
|
|
27038
|
+
child.stderr.on("data", (chunk) => {
|
|
27039
|
+
stderr = `${stderr}${chunk.toString()}`.slice(-8000);
|
|
27040
|
+
});
|
|
27041
|
+
const write = pipeline(child.stdout, boundedWriter(maxBytes), createWriteStream(destination, { flags: "wx", mode: 384 })).catch((error) => {
|
|
27042
|
+
child.kill("SIGKILL");
|
|
27043
|
+
throw error;
|
|
27044
|
+
});
|
|
27045
|
+
const [writeState, exitState] = await Promise.allSettled([write, githubCliExitCode(child, timeoutMs)]);
|
|
27046
|
+
if (writeState.status === "rejected") {
|
|
27047
|
+
rmSync2(destination, { force: true });
|
|
27048
|
+
throw writeState.reason;
|
|
27049
|
+
}
|
|
27050
|
+
if (exitState.status === "rejected") {
|
|
27051
|
+
rmSync2(destination, { force: true });
|
|
27052
|
+
throw exitState.reason;
|
|
27053
|
+
}
|
|
27054
|
+
return { exitCode: exitState.value, stdout: "", stderr };
|
|
27055
|
+
}
|
|
26997
27056
|
function supportsStrictGithubVerification(execution) {
|
|
26998
27057
|
const tokens = `${execution.stdout}
|
|
26999
27058
|
${execution.stderr}`.split(/\s+/);
|
|
@@ -27071,16 +27130,22 @@ function manifestAttestationDownloadUrl(release, manifest, manifestDigest) {
|
|
|
27071
27130
|
}
|
|
27072
27131
|
async function downloadManifestAttestation(request) {
|
|
27073
27132
|
const { release, manifest, manifestPath, destination } = request;
|
|
27133
|
+
if (manifest.repository !== RELEASE_REPOSITORY) {
|
|
27134
|
+
await downloadGithubReleaseAsset({
|
|
27135
|
+
repository: RELEASE_REPOSITORY,
|
|
27136
|
+
tag: release.tag_name,
|
|
27137
|
+
assetName: RELEASE_ATTESTATION_NAME,
|
|
27138
|
+
destination,
|
|
27139
|
+
maxBytes: RELEASE_BUNDLE_SIZE_LIMITS.attestation
|
|
27140
|
+
});
|
|
27141
|
+
return;
|
|
27142
|
+
}
|
|
27074
27143
|
const responsePath = `${destination}.response`;
|
|
27075
27144
|
try {
|
|
27076
27145
|
await downloadDirect(manifestAttestationDownloadUrl(release, manifest, sha256File(manifestPath)), responsePath, RELEASE_BUNDLE_SIZE_LIMITS.attestation);
|
|
27077
|
-
|
|
27078
|
-
|
|
27079
|
-
|
|
27080
|
-
chmodSync2(destination, 384);
|
|
27081
|
-
} else {
|
|
27082
|
-
renameSync(responsePath, destination);
|
|
27083
|
-
}
|
|
27146
|
+
const bundles = serializeAttestationBundles(parseJsonFile(responsePath, "GitHub attestation response"));
|
|
27147
|
+
writeFileSync2(destination, bundles, { mode: 384, flag: "wx" });
|
|
27148
|
+
chmodSync2(destination, 384);
|
|
27084
27149
|
} finally {
|
|
27085
27150
|
rmSync2(responsePath, { force: true });
|
|
27086
27151
|
}
|
|
@@ -27089,7 +27154,14 @@ async function downloadComponent(request) {
|
|
|
27089
27154
|
const release = await downloadReleaseMetadata(request.component, request.version, request.destination);
|
|
27090
27155
|
const manifestPath = directChildPath(request.destination, RELEASE_MANIFEST_NAME);
|
|
27091
27156
|
const attestationPath = directChildPath(request.destination, RELEASE_ATTESTATION_NAME);
|
|
27092
|
-
|
|
27157
|
+
releaseAssetUrl(release, RELEASE_MANIFEST_NAME);
|
|
27158
|
+
await downloadGithubReleaseAsset({
|
|
27159
|
+
repository: RELEASE_REPOSITORY,
|
|
27160
|
+
tag: release.tag_name,
|
|
27161
|
+
assetName: RELEASE_MANIFEST_NAME,
|
|
27162
|
+
destination: manifestPath,
|
|
27163
|
+
maxBytes: RELEASE_BUNDLE_SIZE_LIMITS.manifest
|
|
27164
|
+
});
|
|
27093
27165
|
const manifest = parseReleaseManifest(readFileSync3(manifestPath, "utf8"), request);
|
|
27094
27166
|
await downloadManifestAttestation({ release, manifest, manifestPath, destination: attestationPath });
|
|
27095
27167
|
await verifyManifestAttestation({
|
|
@@ -27099,12 +27171,26 @@ async function downloadComponent(request) {
|
|
|
27099
27171
|
trustedRootPath: request.trustedRootPath
|
|
27100
27172
|
});
|
|
27101
27173
|
const checksumsPath = directChildPath(request.destination, RELEASE_CHECKSUMS_NAME);
|
|
27102
|
-
|
|
27174
|
+
releaseAssetUrl(release, RELEASE_CHECKSUMS_NAME);
|
|
27175
|
+
await downloadGithubReleaseAsset({
|
|
27176
|
+
repository: RELEASE_REPOSITORY,
|
|
27177
|
+
tag: release.tag_name,
|
|
27178
|
+
assetName: RELEASE_CHECKSUMS_NAME,
|
|
27179
|
+
destination: checksumsPath,
|
|
27180
|
+
maxBytes: RELEASE_BUNDLE_SIZE_LIMITS.checksums
|
|
27181
|
+
});
|
|
27103
27182
|
assertSignedArtifact(checksumsPath, manifest);
|
|
27104
27183
|
const checksums = parseReleaseChecksums(readFileSync3(checksumsPath, "utf8"), manifest);
|
|
27105
27184
|
for (const assetName of request.assetNames) {
|
|
27106
27185
|
const assetPath = directChildPath(request.destination, assetName);
|
|
27107
|
-
|
|
27186
|
+
releaseAssetUrl(release, assetName);
|
|
27187
|
+
await downloadGithubReleaseAsset({
|
|
27188
|
+
repository: RELEASE_REPOSITORY,
|
|
27189
|
+
tag: release.tag_name,
|
|
27190
|
+
assetName,
|
|
27191
|
+
destination: assetPath,
|
|
27192
|
+
maxBytes: releaseAssetSizeLimit(request.component, assetName)
|
|
27193
|
+
});
|
|
27108
27194
|
verifyDownloadedFile(assetPath, manifest, checksums);
|
|
27109
27195
|
}
|
|
27110
27196
|
return [RELEASE_MANIFEST_NAME, RELEASE_ATTESTATION_NAME, RELEASE_CHECKSUMS_NAME, ...request.assetNames].map((name) => localUpgradeFile(directChildPath(request.destination, name), `bundle/${request.component}/${name}`));
|
|
@@ -27112,8 +27198,13 @@ async function downloadComponent(request) {
|
|
|
27112
27198
|
async function downloadPinnedGithubCli(directory, architecture) {
|
|
27113
27199
|
const identity = githubCliArchiveIdentity(architecture);
|
|
27114
27200
|
const archivePath = directChildPath(directory, identity.archiveName);
|
|
27115
|
-
|
|
27116
|
-
|
|
27201
|
+
await downloadGithubReleaseAsset({
|
|
27202
|
+
repository: GITHUB_CLI_REPOSITORY,
|
|
27203
|
+
tag: `v${identity.version}`,
|
|
27204
|
+
assetName: identity.archiveName,
|
|
27205
|
+
destination: archivePath,
|
|
27206
|
+
maxBytes: MAX_GH_ARCHIVE_BYTES
|
|
27207
|
+
});
|
|
27117
27208
|
if (sha256File(archivePath) !== identity.sha256) {
|
|
27118
27209
|
throw new Error("Pinned GitHub CLI archive SHA256 mismatch");
|
|
27119
27210
|
}
|
|
@@ -32154,7 +32245,7 @@ Actions: list_releases, get_release, upload_release, activate_release`, {
|
|
|
32154
32245
|
// package.json
|
|
32155
32246
|
var package_default = {
|
|
32156
32247
|
name: "@supacloud/admin",
|
|
32157
|
-
version: "0.15.
|
|
32248
|
+
version: "0.15.4",
|
|
32158
32249
|
description: "Platform administration CLI for SupaCloud operators",
|
|
32159
32250
|
type: "module",
|
|
32160
32251
|
main: "./dist/index.js",
|