{"version":3,"file":"snapStorePublisher.js","sourceRoot":"","sources":["../src/snapStorePublisher.ts"],"names":[],"mappings":"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","sourcesContent":["import { exec, loadCscLink, spawn } from \"builder-util\"\nimport { SnapStoreOptions } from \"builder-util-runtime/out/publishOptions\"\nimport * as path from \"path\"\nimport { PublishContext, UploadTask } from \".\"\nimport { Publisher } from \"./publisher\"\n\nexport class SnapStorePublisher extends Publisher {\n  readonly providerName = \"snapStore\"\n\n  constructor(\n    readonly context: PublishContext,\n    private readonly options: SnapStoreOptions,\n    private readonly credentials: {\n      cscLink: string | undefined\n      resourcesDir: string\n    }\n  ) {\n    super(context)\n  }\n\n  async upload(task: UploadTask): Promise<any> {\n    this.createProgressBar(path.basename(task.file), -1)\n\n    await checkSnapcraft()\n\n    // Credentials are injected via SNAPCRAFT_STORE_CREDENTIALS so that the\n    // snapcraft subprocess authenticates without an interactive login session.\n    // Generate credentials with: snapcraft export-login -\n    // https://documentation.ubuntu.com/snapcraft/stable/how-to/publishing/authenticate/\n    const credEnv = await resolveSnapCredentials(this.credentials.cscLink, this.credentials.resourcesDir)\n\n    // Channel format: [<track>/]<risk>[/<branch>]  e.g. \"stable\", \"edge\", \"lts/stable\"\n    // Multiple channels are comma-separated: \"beta,edge\"\n    let channels = this.options.channels ?? [\"edge\"]\n    if (typeof channels === \"string\") {\n      channels = channels.split(\",\")\n    }\n\n    // `snapcraft upload <snap-file> --release <channels>` uploads the snap and\n    // immediately releases it to the specified channels upon store review.\n    // https://documentation.ubuntu.com/snapcraft/stable/reference/commands/upload/\n    const args = [\"upload\", task.file]\n    if (channels.length > 0) {\n      args.push(\"--release\", channels.join(\",\"))\n    }\n\n    return spawn(\"snapcraft\", args, {\n      stdio: [\"ignore\", \"inherit\", \"inherit\"],\n      env: { ...process.env, ...credEnv },\n    })\n  }\n\n  toString(): string {\n    return \"Snap Store\"\n  }\n}\n\n// Resolves Snap Store credentials from cscLink / SNAP_CSC_LINK and returns\n// them as { SNAPCRAFT_STORE_CREDENTIALS } so they can be injected into the\n// snapcraft subprocess environment. The value is the raw export-login output\n// (base64-encoded or a file path handled by loadCscLink).\n// https://documentation.ubuntu.com/snapcraft/stable/how-to/publishing/authenticate/\nexport async function resolveSnapCredentials(cscLink: string | undefined, resourcesDir: string | undefined): Promise<Record<string, string>> {\n  const link = (cscLink ?? process.env.SNAP_CSC_LINK)?.trim()\n  if (!link) {\n    return {}\n  }\n\n  const credentials = await loadCscLink(link, resourcesDir)\n  const trimmed = credentials.trim()\n  if (!trimmed) {\n    throw new Error(\"Resolved snap store credentials are empty\")\n  }\n  return { SNAPCRAFT_STORE_CREDENTIALS: trimmed }\n}\n\n// Snapcraft 7 introduced SNAPCRAFT_STORE_CREDENTIALS as the standard\n// non-interactive credential mechanism. Earlier versions used a different\n// auth format that is no longer compatible with this publisher.\n// https://documentation.ubuntu.com/snapcraft/stable/how-to/publishing/authenticate/\nconst REQUIRED_SNAPCRAFT_MAJOR = 7\n\nasync function checkSnapcraft(): Promise<void> {\n  const installMessage = process.platform === \"darwin\" ? \"brew install snapcraft\" : \"sudo snap install snapcraft --classic\"\n\n  let versionOutput: string\n  try {\n    versionOutput = await exec(\"snapcraft\", [\"--version\"])\n  } catch {\n    throw new Error(`snapcraft is not installed, please: ${installMessage}`)\n  }\n\n  const trimmed = versionOutput.trim()\n  // Edge-channel installs report \"snapcraft, version edge\" with no semver — skip the check.\n  if (trimmed === \"snapcraft, version edge\") {\n    return\n  }\n\n  // Handles both output formats:\n  //   \"snapcraft, version X.Y.Z\"  (snapcraft ≤ 6)\n  //   \"snapcraft X.Y.Z\"           (snapcraft 7+)\n  let s = trimmed.replace(/^snapcraft/, \"\").trim()\n  s = s.replace(/^,/, \"\").trim()\n  s = s.replace(/^version/, \"\").trim()\n  s = s.replace(/^'|'$/g, \"\")\n\n  const major = parseInt(s.split(\".\")[0], 10)\n  if (!Number.isFinite(major) || major < REQUIRED_SNAPCRAFT_MAJOR) {\n    throw new Error(`at least snapcraft ${REQUIRED_SNAPCRAFT_MAJOR}.0.0 is required, but ${trimmed} installed, please: ${installMessage}`)\n  }\n}\n"]}