@layr-labs/ecloud-cli 0.2.0-dev → 0.2.0-dev.2

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 (71) hide show
  1. package/VERSION +2 -2
  2. package/dist/commands/auth/generate.js +2 -2
  3. package/dist/commands/auth/generate.js.map +1 -1
  4. package/dist/commands/auth/login.js +2 -2
  5. package/dist/commands/auth/login.js.map +1 -1
  6. package/dist/commands/auth/logout.js +2 -2
  7. package/dist/commands/auth/logout.js.map +1 -1
  8. package/dist/commands/auth/migrate.js +2 -2
  9. package/dist/commands/auth/migrate.js.map +1 -1
  10. package/dist/commands/auth/whoami.js +2 -2
  11. package/dist/commands/auth/whoami.js.map +1 -1
  12. package/dist/commands/billing/cancel.js +4 -5
  13. package/dist/commands/billing/cancel.js.map +1 -1
  14. package/dist/commands/billing/status.js +3 -3
  15. package/dist/commands/billing/status.js.map +1 -1
  16. package/dist/commands/billing/subscribe.js +4 -5
  17. package/dist/commands/billing/subscribe.js.map +1 -1
  18. package/dist/commands/compute/app/create.js +2 -2
  19. package/dist/commands/compute/app/create.js.map +1 -1
  20. package/dist/commands/compute/app/deploy.js +17 -545
  21. package/dist/commands/compute/app/deploy.js.map +1 -1
  22. package/dist/commands/compute/app/info.js +3 -5
  23. package/dist/commands/compute/app/info.js.map +1 -1
  24. package/dist/commands/compute/app/list.js +4 -6
  25. package/dist/commands/compute/app/list.js.map +1 -1
  26. package/dist/commands/compute/app/logs.js +5 -8
  27. package/dist/commands/compute/app/logs.js.map +1 -1
  28. package/dist/commands/compute/app/profile/set.js +3 -3
  29. package/dist/commands/compute/app/profile/set.js.map +1 -1
  30. package/dist/commands/compute/app/start.js +5 -8
  31. package/dist/commands/compute/app/start.js.map +1 -1
  32. package/dist/commands/compute/app/stop.js +5 -8
  33. package/dist/commands/compute/app/stop.js.map +1 -1
  34. package/dist/commands/compute/app/terminate.js +5 -8
  35. package/dist/commands/compute/app/terminate.js.map +1 -1
  36. package/dist/commands/compute/app/upgrade.js +11 -520
  37. package/dist/commands/compute/app/upgrade.js.map +1 -1
  38. package/dist/commands/compute/environment/list.js +2 -2
  39. package/dist/commands/compute/environment/list.js.map +1 -1
  40. package/dist/commands/compute/environment/set.js +2 -2
  41. package/dist/commands/compute/environment/set.js.map +1 -1
  42. package/dist/commands/compute/environment/show.js +2 -2
  43. package/dist/commands/compute/environment/show.js.map +1 -1
  44. package/dist/commands/compute/undelegate.js +5 -8
  45. package/dist/commands/compute/undelegate.js.map +1 -1
  46. package/dist/commands/{telemetry.js → telemetry/disable.js} +15 -64
  47. package/dist/commands/telemetry/disable.js.map +1 -0
  48. package/dist/commands/telemetry/enable.js +164 -0
  49. package/dist/commands/telemetry/enable.js.map +1 -0
  50. package/dist/commands/telemetry/status.js +159 -0
  51. package/dist/commands/telemetry/status.js.map +1 -0
  52. package/dist/commands/upgrade.js +2 -2
  53. package/dist/commands/upgrade.js.map +1 -1
  54. package/dist/commands/version.js +2 -2
  55. package/dist/commands/version.js.map +1 -1
  56. package/package.json +2 -5
  57. package/dist/commands/compute/app/releases.js +0 -1144
  58. package/dist/commands/compute/app/releases.js.map +0 -1
  59. package/dist/commands/compute/build/info.js +0 -501
  60. package/dist/commands/compute/build/info.js.map +0 -1
  61. package/dist/commands/compute/build/list.js +0 -575
  62. package/dist/commands/compute/build/list.js.map +0 -1
  63. package/dist/commands/compute/build/logs.js +0 -460
  64. package/dist/commands/compute/build/logs.js.map +0 -1
  65. package/dist/commands/compute/build/status.js +0 -482
  66. package/dist/commands/compute/build/status.js.map +0 -1
  67. package/dist/commands/compute/build/submit.js +0 -619
  68. package/dist/commands/compute/build/submit.js.map +0 -1
  69. package/dist/commands/compute/build/verify.js +0 -392
  70. package/dist/commands/compute/build/verify.js.map +0 -1
  71. package/dist/commands/telemetry.js.map +0 -1
@@ -3,11 +3,10 @@
3
3
  // src/commands/compute/app/deploy.ts
4
4
  import { Command, Flags as Flags2 } from "@oclif/core";
5
5
  import {
6
- getEnvironmentConfig as getEnvironmentConfig3,
6
+ getEnvironmentConfig as getEnvironmentConfig2,
7
7
  UserApiClient as UserApiClient3,
8
8
  isMainnet,
9
9
  prepareDeploy,
10
- prepareDeployFromVerifiableBuild,
11
10
  executeDeploy,
12
11
  watchDeployment
13
12
  } from "@layr-labs/ecloud-sdk";
@@ -117,8 +116,8 @@ function createCLITelemetryClient() {
117
116
  const environment = createAppEnvironment(userUUID);
118
117
  const telemetryEnabled = getGlobalTelemetryPreference();
119
118
  return createTelemetryClient(environment, "ecloud-cli", {
120
- telemetryEnabled: telemetryEnabled === true
121
- // Only enabled if explicitly set to true
119
+ telemetryEnabled: telemetryEnabled !== false
120
+ // Enabled by default, disabled only if explicitly set to false
122
121
  });
123
122
  }
124
123
  async function withTelemetry(command, action) {
@@ -257,7 +256,7 @@ function findAvailableName(environment, baseName) {
257
256
 
258
257
  // src/utils/version.ts
259
258
  function getCliVersion() {
260
- return true ? "0.2.0-dev" : "0.0.0";
259
+ return true ? "0.2.0-dev.2" : "0.0.0";
261
260
  }
262
261
  function getClientId() {
263
262
  return `ecloud-cli/v${getCliVersion()}`;
@@ -291,113 +290,6 @@ Found Dockerfile in ${cwd}`);
291
290
  throw new Error(`Unexpected choice: ${choice}`);
292
291
  }
293
292
  }
294
- async function promptUseVerifiableBuild() {
295
- return confirmWithDefault("Build from verifiable source?", false);
296
- }
297
- async function promptVerifiableSourceType() {
298
- return select({
299
- message: "Choose verifiable source type:",
300
- choices: [
301
- { name: "Build from git source (public repo required)", value: "git" },
302
- { name: "Use a prebuilt verifiable image (eigencloud-containers)", value: "prebuilt" }
303
- ]
304
- });
305
- }
306
- async function promptVerifiableGitSourceInputs() {
307
- const repoUrl = (await input({
308
- message: "Enter public git repository URL:",
309
- default: "",
310
- validate: (value) => {
311
- if (!value.trim()) return "Repository URL is required";
312
- try {
313
- const url = new URL(value.trim());
314
- if (url.protocol !== "https:") return "Repository URL must start with https://";
315
- if (url.hostname.toLowerCase() !== "github.com")
316
- return "Repository URL must be a public GitHub HTTPS URL (github.com)";
317
- const parts = url.pathname.replace(/\/+$/, "").split("/").filter(Boolean);
318
- if (parts.length < 2) return "Repository URL must be https://github.com/<owner>/<repo>";
319
- const [owner, repo] = parts;
320
- if (!owner || !repo) return "Repository URL must be https://github.com/<owner>/<repo>";
321
- if (repo.toLowerCase() === "settings") return "Repository URL looks invalid";
322
- if (url.search || url.hash)
323
- return "Repository URL must not include query params or fragments";
324
- } catch {
325
- return "Invalid URL format";
326
- }
327
- return true;
328
- }
329
- })).trim();
330
- const gitRef = (await input({
331
- message: "Enter git commit SHA (40 hex chars):",
332
- default: "",
333
- validate: (value) => {
334
- const trimmed = value.trim();
335
- if (!trimmed) return "Commit SHA is required";
336
- if (!/^[0-9a-f]{40}$/i.test(trimmed))
337
- return "Commit must be a 40-character hexadecimal SHA";
338
- return true;
339
- }
340
- })).trim();
341
- const buildContextPath = (await input({
342
- message: "Enter build context path (relative to repo):",
343
- default: ".",
344
- validate: (value) => value.trim() ? true : "Build context path cannot be empty"
345
- })).trim();
346
- const dockerfilePath = (await input({
347
- message: "Enter Dockerfile path (relative to build context):",
348
- default: "Dockerfile",
349
- validate: (value) => value.trim() ? true : "Dockerfile path cannot be empty"
350
- })).trim();
351
- const caddyfileRaw = (await input({
352
- message: "Enter Caddyfile path (relative to build context, optional):",
353
- default: "",
354
- validate: (value) => {
355
- const trimmed = value.trim();
356
- if (!trimmed) return true;
357
- if (trimmed.includes("..")) return "Caddyfile path must not contain '..'";
358
- return true;
359
- }
360
- })).trim();
361
- const depsRaw = (await input({
362
- message: "Enter dependency digests (comma-separated sha256:..., optional):",
363
- default: "",
364
- validate: (value) => {
365
- const trimmed = value.trim();
366
- if (!trimmed) return true;
367
- const parts = trimmed.split(",").map((p) => p.trim()).filter(Boolean);
368
- for (const p of parts) {
369
- if (!/^sha256:[0-9a-f]{64}$/i.test(p)) {
370
- return `Invalid dependency digest: ${p} (expected sha256:<64 hex>)`;
371
- }
372
- }
373
- return true;
374
- }
375
- })).trim();
376
- const dependencies = depsRaw === "" ? [] : depsRaw.split(",").map((p) => p.trim()).filter(Boolean);
377
- return {
378
- repoUrl,
379
- gitRef,
380
- dockerfilePath,
381
- caddyfilePath: caddyfileRaw === "" ? void 0 : caddyfileRaw,
382
- buildContextPath,
383
- dependencies
384
- };
385
- }
386
- async function promptVerifiablePrebuiltImageRef() {
387
- const ref = await input({
388
- message: "Enter prebuilt verifiable image ref:",
389
- default: "docker.io/eigenlayer/eigencloud-containers:",
390
- validate: (value) => {
391
- const trimmed = value.trim();
392
- if (!trimmed) return "Image reference is required";
393
- if (!/^docker\.io\/eigenlayer\/eigencloud-containers:[^@\s]+$/i.test(trimmed)) {
394
- return "Image ref must match docker.io/eigenlayer/eigencloud-containers:<tag>";
395
- }
396
- return true;
397
- }
398
- });
399
- return ref.trim();
400
- }
401
293
  function extractHostname(registry) {
402
294
  let hostname = registry.replace(/^https?:\/\//, "");
403
295
  hostname = hostname.split("/")[0];
@@ -646,8 +538,8 @@ async function getImageReferenceInteractive(imageRef, buildFromDockerfile = fals
646
538
  });
647
539
  return imageRefInput;
648
540
  }
649
- async function getAvailableAppNameInteractive(environment, imageRef, suggestedBaseName) {
650
- const baseName = suggestedBaseName || extractAppNameFromImage(imageRef);
541
+ async function getAvailableAppNameInteractive(environment, imageRef) {
542
+ const baseName = extractAppNameFromImage(imageRef);
651
543
  const suggestedName = findAvailableName(environment, baseName);
652
544
  while (true) {
653
545
  console.log("\nApp name selection:");
@@ -671,16 +563,16 @@ async function getAvailableAppNameInteractive(environment, imageRef, suggestedBa
671
563
  console.log(`Suggested alternative: ${newSuggested}`);
672
564
  }
673
565
  }
674
- async function getOrPromptAppName(appName, environment, imageRef, suggestedBaseName) {
566
+ async function getOrPromptAppName(appName, environment, imageRef) {
675
567
  if (appName) {
676
568
  validateAppName(appName);
677
569
  if (isAppNameAvailable(environment, appName)) {
678
570
  return appName;
679
571
  }
680
572
  console.log(`Warning: App name '${appName}' is already taken.`);
681
- return getAvailableAppNameInteractive(environment, imageRef, suggestedBaseName);
573
+ return getAvailableAppNameInteractive(environment, imageRef);
682
574
  }
683
- return getAvailableAppNameInteractive(environment, imageRef, suggestedBaseName);
575
+ return getAvailableAppNameInteractive(environment, imageRef);
684
576
  }
685
577
  async function getEnvFileInteractive(envFilePath) {
686
578
  if (envFilePath && fs3.existsSync(envFilePath)) {
@@ -818,8 +710,8 @@ async function getPrivateKeyInteractive(privateKey) {
818
710
  }
819
711
  return privateKey;
820
712
  }
821
- const { getPrivateKeyWithSource: getPrivateKeyWithSource2 } = await import("@layr-labs/ecloud-sdk");
822
- const result = await getPrivateKeyWithSource2({ privateKey: void 0 });
713
+ const { getPrivateKeyWithSource } = await import("@layr-labs/ecloud-sdk");
714
+ const result = await getPrivateKeyWithSource({ privateKey: void 0 });
823
715
  if (result) {
824
716
  return result.key;
825
717
  }
@@ -838,50 +730,6 @@ async function getPrivateKeyInteractive(privateKey) {
838
730
  });
839
731
  return key.trim();
840
732
  }
841
- async function getEnvironmentInteractive(environment) {
842
- if (environment) {
843
- try {
844
- getEnvironmentConfig(environment);
845
- if (!isEnvironmentAvailable(environment)) {
846
- throw new Error(`Environment ${environment} is not available in this build`);
847
- }
848
- return environment;
849
- } catch {
850
- }
851
- }
852
- const availableEnvs = getAvailableEnvironments();
853
- let defaultEnv;
854
- const configDefaultEnv = getDefaultEnvironment();
855
- if (configDefaultEnv && availableEnvs.includes(configDefaultEnv)) {
856
- try {
857
- getEnvironmentConfig(configDefaultEnv);
858
- defaultEnv = configDefaultEnv;
859
- } catch {
860
- }
861
- }
862
- const choices = [];
863
- if (availableEnvs.includes("sepolia")) {
864
- choices.push({ name: "sepolia - Ethereum Sepolia testnet", value: "sepolia" });
865
- }
866
- if (availableEnvs.includes("sepolia-dev")) {
867
- choices.push({ name: "sepolia-dev - Ethereum Sepolia testnet (dev)", value: "sepolia-dev" });
868
- }
869
- if (availableEnvs.includes("mainnet-alpha")) {
870
- choices.push({
871
- name: "mainnet-alpha - Ethereum mainnet (\u26A0\uFE0F uses real funds)",
872
- value: "mainnet-alpha"
873
- });
874
- }
875
- if (choices.length === 0) {
876
- throw new Error("No environments available in this build");
877
- }
878
- const env = await select({
879
- message: "Select environment:",
880
- choices,
881
- default: defaultEnv
882
- });
883
- return env;
884
- }
885
733
  var MAX_DESCRIPTION_LENGTH = 1e3;
886
734
  var MAX_IMAGE_SIZE = 4 * 1024 * 1024;
887
735
  var VALID_IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png"];
@@ -1127,209 +975,9 @@ var commonFlags = {
1127
975
  default: false
1128
976
  })
1129
977
  };
1130
- async function validateCommonFlags(flags, options) {
1131
- if (!flags["environment"]) {
1132
- flags["environment"] = getDefaultEnvironment();
1133
- }
1134
- flags["environment"] = await getEnvironmentInteractive(flags["environment"]);
1135
- if (options?.requirePrivateKey !== false) {
1136
- flags["private-key"] = await getPrivateKeyInteractive(flags["private-key"]);
1137
- }
1138
- return flags;
1139
- }
1140
978
 
1141
979
  // src/commands/compute/app/deploy.ts
1142
980
  import chalk from "chalk";
1143
-
1144
- // src/client.ts
1145
- import {
1146
- createComputeModule,
1147
- createBillingModule,
1148
- createBuildModule,
1149
- getEnvironmentConfig as getEnvironmentConfig2,
1150
- requirePrivateKey,
1151
- getPrivateKeyWithSource
1152
- } from "@layr-labs/ecloud-sdk";
1153
- async function createBuildClient(flags) {
1154
- flags = await validateCommonFlags(flags, { requirePrivateKey: false });
1155
- return createBuildModule({
1156
- verbose: flags.verbose,
1157
- privateKey: flags["private-key"],
1158
- environment: flags.environment,
1159
- clientId: getClientId(),
1160
- skipTelemetry: true
1161
- // CLI already has telemetry, skip SDK telemetry
1162
- });
1163
- }
1164
-
1165
- // src/utils/build.ts
1166
- function formatSourceLink(repoUrl, gitRef) {
1167
- const normalizedRepo = repoUrl.replace(/\.git$/, "");
1168
- try {
1169
- const url = new URL(normalizedRepo);
1170
- const host = url.host.toLowerCase();
1171
- if (host === "github.com") {
1172
- const path4 = url.pathname.replace(/\/+$/, "");
1173
- if (path4.split("/").filter(Boolean).length >= 2) {
1174
- return `https://github.com${path4}/tree/${gitRef}`;
1175
- }
1176
- }
1177
- } catch {
1178
- }
1179
- return `${repoUrl}@${gitRef}`;
1180
- }
1181
- function extractRepoName(repoUrl) {
1182
- const normalized = repoUrl.replace(/\.git$/, "");
1183
- const match = normalized.match(/\/([^/]+?)$/);
1184
- return match?.[1];
1185
- }
1186
- function formatDependencyLines(dependencies) {
1187
- if (!dependencies || Object.keys(dependencies).length === 0) return [];
1188
- const lines = [];
1189
- lines.push("Dependencies (resolved builds):");
1190
- for (const [digest, dep] of Object.entries(dependencies)) {
1191
- const name = extractRepoName(dep.repoUrl);
1192
- const depSource = formatSourceLink(dep.repoUrl, dep.gitRef);
1193
- lines.push(` - ${digest} \u2713${name ? ` ${name}` : ""}`);
1194
- lines.push(` ${depSource}`);
1195
- }
1196
- return lines;
1197
- }
1198
- function formatVerifiableBuildSummary(options) {
1199
- const lines = [];
1200
- lines.push("Build completed successfully \u2713");
1201
- lines.push("");
1202
- lines.push(`Image: ${options.imageUrl}`);
1203
- lines.push(`Digest: ${options.imageDigest}`);
1204
- lines.push(`Source: ${formatSourceLink(options.repoUrl, options.gitRef)}`);
1205
- const depLines = formatDependencyLines(options.dependencies);
1206
- if (depLines.length) {
1207
- lines.push("");
1208
- lines.push(...depLines);
1209
- }
1210
- lines.push("");
1211
- lines.push("Provenance signature verified \u2713");
1212
- lines.push(`provenance_signature: ${options.provenanceSignature}`);
1213
- if (options.buildId) {
1214
- lines.push("");
1215
- lines.push(`Build ID: ${options.buildId}`);
1216
- }
1217
- return lines;
1218
- }
1219
-
1220
- // src/utils/verifiableBuild.ts
1221
- import { BUILD_STATUS } from "@layr-labs/ecloud-sdk";
1222
- function assertCommitSha40(commit) {
1223
- if (!/^[0-9a-f]{40}$/i.test(commit)) {
1224
- throw new Error("Commit must be a 40-character hexadecimal SHA");
1225
- }
1226
- }
1227
- async function runVerifiableBuildAndVerify(client, request, options = {}) {
1228
- const { buildId } = await client.submit(request);
1229
- const completed = await client.waitForBuild(buildId, { onLog: options.onLog });
1230
- if (completed.status !== BUILD_STATUS.SUCCESS) {
1231
- throw new Error(`Build did not complete successfully (status: ${completed.status})`);
1232
- }
1233
- const [build, verify] = await Promise.all([client.get(buildId), client.verify(buildId)]);
1234
- if (verify.status !== "verified") {
1235
- throw new Error(`Provenance verification failed: ${verify.error}`);
1236
- }
1237
- return { build, verified: verify };
1238
- }
1239
-
1240
- // src/utils/dockerhub.ts
1241
- var DOCKERHUB_OWNER = "eigenlayer";
1242
- var DOCKERHUB_REPO = "eigencloud-containers";
1243
- function parseEigencloudContainersImageRef(imageRef) {
1244
- const trimmed = imageRef.trim();
1245
- const match = /^docker\.io\/([^/]+)\/([^:@]+):([^@\s]+)$/i.exec(trimmed);
1246
- if (!match) {
1247
- throw new Error("Image ref must match docker.io/eigenlayer/eigencloud-containers:<tag>");
1248
- }
1249
- const owner = match[1].toLowerCase();
1250
- const repo = match[2].toLowerCase();
1251
- const tag = match[3];
1252
- if (owner !== DOCKERHUB_OWNER || repo !== DOCKERHUB_REPO) {
1253
- throw new Error(`Image ref must be from docker.io/${DOCKERHUB_OWNER}/${DOCKERHUB_REPO}:<tag>`);
1254
- }
1255
- if (!tag.trim()) {
1256
- throw new Error("Image tag cannot be empty");
1257
- }
1258
- return { owner, repo, tag };
1259
- }
1260
- function assertEigencloudContainersImageRef(imageRef) {
1261
- parseEigencloudContainersImageRef(imageRef);
1262
- }
1263
- async function getDockerHubToken(owner, repo) {
1264
- const url = new URL("https://auth.docker.io/token");
1265
- url.searchParams.set("service", "registry.docker.io");
1266
- url.searchParams.set("scope", `repository:${owner}/${repo}:pull`);
1267
- const res = await fetch(url.toString(), { method: "GET" });
1268
- if (!res.ok) {
1269
- const body = await safeReadText(res);
1270
- throw new Error(`Failed to fetch Docker Hub token (${res.status}): ${body || res.statusText}`);
1271
- }
1272
- const data = await res.json();
1273
- if (!data.token) {
1274
- throw new Error("Docker Hub token response missing 'token'");
1275
- }
1276
- return data.token;
1277
- }
1278
- async function safeReadText(res) {
1279
- try {
1280
- return (await res.text()).trim();
1281
- } catch {
1282
- return "";
1283
- }
1284
- }
1285
- async function resolveDockerHubImageDigest(imageRef) {
1286
- const { owner, repo, tag } = parseEigencloudContainersImageRef(imageRef);
1287
- const token = await getDockerHubToken(owner, repo);
1288
- const manifestUrl = `https://registry-1.docker.io/v2/${owner}/${repo}/manifests/${encodeURIComponent(tag)}`;
1289
- const headers = {
1290
- Authorization: `Bearer ${token}`,
1291
- Accept: "application/vnd.docker.distribution.manifest.v2+json"
1292
- };
1293
- let res = await fetch(manifestUrl, { method: "HEAD", headers });
1294
- if (!res.ok) {
1295
- res = await fetch(manifestUrl, { method: "GET", headers });
1296
- }
1297
- if (!res.ok) {
1298
- const body = await safeReadText(res);
1299
- throw new Error(
1300
- `Failed to resolve digest for ${imageRef} (${res.status}) at ${manifestUrl}: ${body || res.statusText}`
1301
- );
1302
- }
1303
- const digest = res.headers.get("docker-content-digest") || res.headers.get("Docker-Content-Digest");
1304
- if (!digest) {
1305
- throw new Error(
1306
- `Docker registry response missing Docker-Content-Digest header for ${imageRef}`
1307
- );
1308
- }
1309
- if (!/^sha256:[0-9a-f]{64}$/i.test(digest)) {
1310
- throw new Error(`Unexpected digest format from Docker registry: ${digest}`);
1311
- }
1312
- return digest;
1313
- }
1314
-
1315
- // src/utils/tls.ts
1316
- import fs4 from "fs";
1317
- function isTlsEnabledFromDomain(domain) {
1318
- const d = (domain ?? "").trim();
1319
- if (!d) return false;
1320
- if (d.toLowerCase() === "localhost") return false;
1321
- return true;
1322
- }
1323
- function isTlsEnabledFromEnvFile(envFilePath) {
1324
- if (!envFilePath) return false;
1325
- if (!fs4.existsSync(envFilePath)) return false;
1326
- const envContent = fs4.readFileSync(envFilePath, "utf-8");
1327
- const match = envContent.match(/^DOMAIN=(.+)$/m);
1328
- if (!match?.[1]) return false;
1329
- return isTlsEnabledFromDomain(match[1]);
1330
- }
1331
-
1332
- // src/commands/compute/app/deploy.ts
1333
981
  var AppDeploy = class _AppDeploy extends Command {
1334
982
  static description = "Deploy new app";
1335
983
  static flags = {
@@ -1392,33 +1040,6 @@ var AppDeploy = class _AppDeploy extends Command {
1392
1040
  image: Flags2.string({
1393
1041
  required: false,
1394
1042
  description: "Path to app icon/logo image - JPG/PNG, max 4MB, square recommended (optional)"
1395
- }),
1396
- // Verifiable build flags
1397
- verifiable: Flags2.boolean({
1398
- description: "Enable verifiable build mode (either build from git source via --repo/--commit, or deploy a prebuilt verifiable image via --image-ref)",
1399
- default: false
1400
- }),
1401
- repo: Flags2.string({
1402
- description: "Git repository URL (required with --verifiable git source mode)",
1403
- env: "ECLOUD_BUILD_REPO"
1404
- }),
1405
- commit: Flags2.string({
1406
- description: "Git commit SHA (required with --verifiable git source mode)",
1407
- env: "ECLOUD_BUILD_COMMIT"
1408
- }),
1409
- "build-dockerfile": Flags2.string({
1410
- description: "Dockerfile path for verifiable build (git source mode)",
1411
- default: "Dockerfile",
1412
- env: "ECLOUD_BUILD_DOCKERFILE"
1413
- }),
1414
- "build-context": Flags2.string({
1415
- description: "Build context path for verifiable build (git source mode)",
1416
- default: ".",
1417
- env: "ECLOUD_BUILD_CONTEXT"
1418
- }),
1419
- "build-dependencies": Flags2.string({
1420
- description: "Dependency digests for verifiable build (git source mode) (sha256:...)",
1421
- multiple: true
1422
1043
  })
1423
1044
  };
1424
1045
  async run() {
@@ -1431,148 +1052,14 @@ var AppDeploy = class _AppDeploy extends Command {
1431
1052
  debug: (msg) => flags.verbose && this.log(msg)
1432
1053
  };
1433
1054
  const environment = flags.environment || "sepolia";
1434
- const environmentConfig = getEnvironmentConfig3(environment);
1055
+ const environmentConfig = getEnvironmentConfig2(environment);
1435
1056
  const rpcUrl = flags["rpc-url"] || environmentConfig.defaultRPCURL;
1436
1057
  const privateKey = await getPrivateKeyInteractive(flags["private-key"]);
1437
- let buildClient;
1438
- const getBuildClient = async () => {
1439
- if (buildClient) return buildClient;
1440
- buildClient = await createBuildClient({
1441
- ...flags,
1442
- "private-key": privateKey
1443
- });
1444
- return buildClient;
1445
- };
1446
- let verifiableImageUrl;
1447
- let verifiableImageDigest;
1448
- let suggestedAppBaseName;
1449
- let verifiableMode = "none";
1450
- let envFilePath;
1451
- const suggestAppBaseNameFromRepoUrl = (repoUrl) => {
1452
- const normalized = String(repoUrl || "").trim().replace(/\.git$/i, "").replace(/\/+$/, "");
1453
- if (!normalized) return void 0;
1454
- const lastSlash = normalized.lastIndexOf("/");
1455
- const lastColon = normalized.lastIndexOf(":");
1456
- const idx = Math.max(lastSlash, lastColon);
1457
- const raw = (idx >= 0 ? normalized.slice(idx + 1) : normalized).trim();
1458
- if (!raw) return void 0;
1459
- const cleaned = raw.toLowerCase().replace(/_/g, "-").replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
1460
- return cleaned || void 0;
1461
- };
1462
- if (flags.verifiable) {
1463
- if (flags.repo || flags.commit) {
1464
- verifiableMode = "git";
1465
- if (!flags.repo)
1466
- this.error("--repo is required when using --verifiable (git source mode)");
1467
- if (!flags.commit)
1468
- this.error("--commit is required when using --verifiable (git source mode)");
1469
- try {
1470
- assertCommitSha40(flags.commit);
1471
- } catch (e) {
1472
- this.error(e?.message || String(e));
1473
- }
1474
- } else if (flags["image-ref"]) {
1475
- verifiableMode = "prebuilt";
1476
- try {
1477
- assertEigencloudContainersImageRef(flags["image-ref"]);
1478
- } catch (e) {
1479
- this.error(e?.message || String(e));
1480
- }
1481
- } else {
1482
- this.error(
1483
- "When using --verifiable, you must provide either --repo/--commit or --image-ref"
1484
- );
1485
- }
1486
- } else {
1487
- if (!flags.dockerfile) {
1488
- const useVerifiable = await promptUseVerifiableBuild();
1489
- if (useVerifiable) {
1490
- const sourceType = await promptVerifiableSourceType();
1491
- verifiableMode = sourceType;
1492
- }
1493
- }
1494
- }
1495
- if (verifiableMode === "git") {
1496
- const inputs = flags.verifiable ? {
1497
- repoUrl: flags.repo,
1498
- gitRef: flags.commit,
1499
- dockerfilePath: flags["build-dockerfile"],
1500
- caddyfilePath: void 0,
1501
- buildContextPath: flags["build-context"],
1502
- dependencies: flags["build-dependencies"]
1503
- } : await promptVerifiableGitSourceInputs();
1504
- envFilePath = await getEnvFileInteractive(flags["env-file"]);
1505
- const includeTlsCaddyfile = isTlsEnabledFromEnvFile(envFilePath);
1506
- if (includeTlsCaddyfile && !inputs.caddyfilePath) {
1507
- inputs.caddyfilePath = "Caddyfile";
1508
- }
1509
- this.log(chalk.blue("Building from source with verifiable build..."));
1510
- this.log("");
1511
- const buildClient2 = await getBuildClient();
1512
- const { build, verified } = await runVerifiableBuildAndVerify(buildClient2, inputs, {
1513
- onLog: (chunk) => process.stdout.write(chunk)
1514
- });
1515
- if (!build.imageUrl || !build.imageDigest) {
1516
- this.error(
1517
- "Build completed but did not return imageUrl/imageDigest; cannot deploy verifiable build"
1518
- );
1519
- }
1520
- verifiableImageUrl = build.imageUrl;
1521
- verifiableImageDigest = build.imageDigest;
1522
- suggestedAppBaseName = suggestAppBaseNameFromRepoUrl(build.repoUrl);
1523
- for (const line of formatVerifiableBuildSummary({
1524
- buildId: build.buildId,
1525
- imageUrl: build.imageUrl,
1526
- imageDigest: build.imageDigest,
1527
- repoUrl: build.repoUrl,
1528
- gitRef: build.gitRef,
1529
- dependencies: build.dependencies,
1530
- provenanceSignature: verified.provenanceSignature
1531
- })) {
1532
- this.log(line);
1533
- }
1534
- }
1535
- if (verifiableMode === "prebuilt") {
1536
- const imageRef2 = flags.verifiable ? flags["image-ref"] : await promptVerifiablePrebuiltImageRef();
1537
- try {
1538
- assertEigencloudContainersImageRef(imageRef2);
1539
- } catch (e) {
1540
- this.error(e?.message || String(e));
1541
- }
1542
- this.log(chalk.blue("Resolving and verifying prebuilt verifiable image..."));
1543
- this.log("");
1544
- const digest = await resolveDockerHubImageDigest(imageRef2);
1545
- const buildClient2 = await getBuildClient();
1546
- const verify = await buildClient2.verify(digest);
1547
- if (verify.status !== "verified") {
1548
- this.error(`Provenance verification failed: ${verify.error}`);
1549
- }
1550
- verifiableImageUrl = imageRef2;
1551
- verifiableImageDigest = digest;
1552
- suggestedAppBaseName = suggestAppBaseNameFromRepoUrl(verify.repoUrl);
1553
- for (const line of formatVerifiableBuildSummary({
1554
- buildId: verify.buildId,
1555
- imageUrl: imageRef2,
1556
- imageDigest: digest,
1557
- repoUrl: verify.repoUrl,
1558
- gitRef: verify.gitRef,
1559
- dependencies: void 0,
1560
- provenanceSignature: verify.provenanceSignature
1561
- })) {
1562
- this.log(line);
1563
- }
1564
- }
1565
- const isVerifiable = verifiableMode !== "none";
1566
- const dockerfilePath = isVerifiable ? "" : await getDockerfileInteractive(flags.dockerfile);
1058
+ const dockerfilePath = await getDockerfileInteractive(flags.dockerfile);
1567
1059
  const buildFromDockerfile = dockerfilePath !== "";
1568
- const imageRef = verifiableImageUrl ? verifiableImageUrl : await getImageReferenceInteractive(flags["image-ref"], buildFromDockerfile);
1569
- const appName = await getOrPromptAppName(
1570
- flags.name,
1571
- environment,
1572
- imageRef,
1573
- suggestedAppBaseName
1574
- );
1575
- envFilePath = envFilePath ?? await getEnvFileInteractive(flags["env-file"]);
1060
+ const imageRef = await getImageReferenceInteractive(flags["image-ref"], buildFromDockerfile);
1061
+ const appName = await getOrPromptAppName(flags.name, environment, imageRef);
1062
+ const envFilePath = await getEnvFileInteractive(flags["env-file"]);
1576
1063
  const availableTypes = await fetchAvailableInstanceTypes(
1577
1064
  environmentConfig,
1578
1065
  privateKey,
@@ -1591,22 +1078,7 @@ var AppDeploy = class _AppDeploy extends Command {
1591
1078
  flags["resource-usage-monitoring"]
1592
1079
  );
1593
1080
  const logVisibility = logSettings.publicLogs ? "public" : logSettings.logRedirect ? "private" : "off";
1594
- const { prepared, gasEstimate } = isVerifiable ? await prepareDeployFromVerifiableBuild(
1595
- {
1596
- privateKey,
1597
- rpcUrl,
1598
- environment,
1599
- imageRef,
1600
- imageDigest: verifiableImageDigest,
1601
- envFilePath,
1602
- appName,
1603
- instanceType,
1604
- logVisibility,
1605
- resourceUsageMonitoring,
1606
- skipTelemetry: true
1607
- },
1608
- logger
1609
- ) : await prepareDeploy(
1081
+ const { prepared, gasEstimate } = await prepareDeploy(
1610
1082
  {
1611
1083
  privateKey,
1612
1084
  rpcUrl,