@infracraft/pulumi 1.28.0 → 1.28.1

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.
@@ -27,7 +27,7 @@ var RailwayDeploy = class extends _pulumi_pulumi.ComponentResource {
27
27
  constructor(name, args, opts) {
28
28
  const { provider, project, environment, service, projectToken, ...pulumiOpts } = opts;
29
29
  super("infracraft:railway:Deploy", name, {}, pulumiOpts);
30
- const cli = _pulumi_pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e "process.stdout.write(String(Date.now()))"); IC_UP_OUT=$(RAILWAY_TOKEN="$IC_TOK" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); IC_UP_EXIT=$?; printf '%s\\n' "$IC_UP_OUT"; if [ -n "$INFRACRAFT_SKIP_DEPLOY_WAIT" ]; then exit "$IC_UP_EXIT"; fi; IC_UP_OUT="$IC_UP_OUT" IC_UP_EXIT=$IC_UP_EXIT IC_TOK="$IC_TOK" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node "${MONITOR_BIN}"`;
30
+ const cli = _pulumi_pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e "process.stdout.write(String(Date.now()))"); if IC_UP_OUT=$(RAILWAY_TOKEN="$IC_TOK" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); then IC_UP_EXIT=0; else IC_UP_EXIT=$?; fi; printf '%s\\n' "$IC_UP_OUT"; if [ -n "$INFRACRAFT_SKIP_DEPLOY_WAIT" ]; then exit "$IC_UP_EXIT"; fi; IC_UP_OUT="$IC_UP_OUT" IC_UP_EXIT=$IC_UP_EXIT IC_TOK="$IC_TOK" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node "${MONITOR_BIN}"`;
31
31
  const setup = args.railpackConfig ? `printf '%s' '${JSON.stringify(args.railpackConfig).replace(/'/g, "'\\''")}' > railpack.json` : void 0;
32
32
  const { deploymentUrl } = require_commands_deploy.createDeployCommand({
33
33
  name,
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.cjs","names":["pulumi","createDeployCommand"],"sources":["../../src/railway/deploy.ts"],"sourcesContent":["// src/railway/deploy.ts (replace entire file)\nimport { fileURLToPath } from \"node:url\";\n\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand } from \"../commands/deploy\";\nimport type { RailwayEnvironment } from \"./environment\";\nimport type { RailwayProject } from \"./project\";\nimport type { RailwayProvider } from \"./provider\";\nimport { RailwayBuilder, type RailwayService } from \"./service\";\n\nexport interface RailwayDeployConfig {\n\tbuilder?: RailwayBuilder;\n\tstartCommand?: string;\n\tpreDeployCommand?: string;\n}\n\nexport interface RailwayDeployArgs {\n\t/** Redeploy triggers (e.g. source hashes, env hashes). */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** Paths excluded from the upload when running with `DeploySandbox` + `GitGuard`. */\n\texcludePaths?: string[];\n\t/** Railpack configuration written to `railpack.json` before deploy. */\n\trailpackConfig?: Record<string, unknown>;\n}\n\ntype RailwayDeployOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\tprovider: RailwayProvider;\n\tproject: RailwayProject;\n\tenvironment: RailwayEnvironment;\n\tservice: RailwayService;\n\t/** Environment-scoped Railway deploy token (provision via RailwayProjectToken). */\n\tprojectToken: pulumi.Input<string>;\n};\n\n/**\n * Absolute path to the runnable deploy monitor, resolved next to this module in `dist`.\n * `railway up` only uploads + triggers; this bin makes the Railway GraphQL API — not the\n * CLI's exit code — the source of truth for pass/fail, and dumps build + deploy logs on\n * failure. Its logic lives in the unit-tested `deployment-monitor` module.\n */\nconst MONITOR_BIN = fileURLToPath(\n\tnew URL(\"./bin/monitor-deployment.mjs\", import.meta.url),\n);\n\n/**\n * Deploys a Railway service and waits for a terminal status. Isolation/git are the\n * seam's job (list a `DeploySandbox` and optionally a `GitGuard` in `dependsOn`).\n *\n * @example\n * ```typescript\n * new RailwayDeploy(\"mesh\", { triggers: [sourceHash], railpackConfig: { apt: [\"libatomic1\"] } },\n * { provider, project, environment, service, projectToken: token.token, dependsOn: [sandbox, gitGuard] });\n * ```\n */\nexport class RailwayDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (Railway service URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: RailwayDeployArgs,\n\t\topts: RailwayDeployOptions,\n\t) {\n\t\tconst {\n\t\t\tprovider,\n\t\t\tproject,\n\t\t\tenvironment,\n\t\t\tservice,\n\t\t\tprojectToken,\n\t\t\t...pulumiOpts\n\t\t} = opts;\n\n\t\tsuper(\"infracraft:railway:Deploy\", name, {}, pulumiOpts);\n\n\t\t// `railway up --detach` uploads + triggers WITHOUT attaching to the build-log\n\t\t// stream — that long-lived stream is what intermittently times out and makes the\n\t\t// CLI exit non-zero even when the deploy actually succeeds. We capture its `--json`\n\t\t// output (for the exact deployment id) and exit code, re-emit it for visibility,\n\t\t// then hand off to the monitor bin which polls the Railway API to a terminal status.\n\t\t// The API — not the CLI exit code — decides pass/fail.\n\t\t//\n\t\t// The token travels via the command's STDIN, never in the script text: on failure\n\t\t// pulumi-command embeds the executed command verbatim in its error message, and\n\t\t// Pulumi does not scrub secrets from provider diagnostics — an inlined token prints\n\t\t// in plaintext exactly when a deploy fails. The `environment` map is no alternative:\n\t\t// an unknown secret there makes `pulumi preview` fail (the token is a resource\n\t\t// output, unknown on first preview). `|| true` keeps `set -e` alive when the stdin\n\t\t// payload has no trailing newline (read then exits 1 but still fills IC_TOK).\n\t\t// IC_SINCE is captured just before `railway up` as a createdAt fallback for id\n\t\t// resolution.\n\t\tconst cli = pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e \"process.stdout.write(String(Date.now()))\"); IC_UP_OUT=$(RAILWAY_TOKEN=\"$IC_TOK\" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); IC_UP_EXIT=$?; printf '%s\\\\n' \"$IC_UP_OUT\"; if [ -n \"$INFRACRAFT_SKIP_DEPLOY_WAIT\" ]; then exit \"$IC_UP_EXIT\"; fi; IC_UP_OUT=\"$IC_UP_OUT\" IC_UP_EXIT=$IC_UP_EXIT IC_TOK=\"$IC_TOK\" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node \"${MONITOR_BIN}\"`;\n\n\t\t// `printf '%s'` (not a bare format string) so railpack values containing %\n\t\t// are literal; the JSON is single-quote-escaped the POSIX way (' -> '\\'').\n\t\tconst setup = args.railpackConfig\n\t\t\t? `printf '%s' '${JSON.stringify(args.railpackConfig).replace(/'/g, \"'\\\\''\")}' > railpack.json`\n\t\t\t: undefined;\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers: args.triggers,\n\t\t\t\texcludePaths: args.excludePaths,\n\t\t\t\tsetup,\n\t\t\t\tstdin: projectToken,\n\t\t\t},\n\t\t\t{ parent: this, ...pulumiOpts },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AA4CA,MAAM,0CACL,IAAI,IAAI,6EAA+C,CACxD;;;;;;;;;;;AAYA,IAAa,gBAAb,cAAmCA,eAAO,kBAAkB;CAI3D,YACC,MACA,MACA,MACC;EACD,MAAM,EACL,UACA,SACA,aACA,SACA,cACA,GAAG,eACA;EAEJ,MAAM,6BAA6B,MAAM,CAAC,GAAG,UAAU;EAkBvD,MAAM,MAAM,eAAO,WAAW,yKAAyK,QAAQ,GAAG,aAAa,QAAQ,GAAG,iBAAiB,YAAY,GAAG,oMAAoM,QAAQ,GAAG,UAAU,YAAY,GAAG,UAAU,QAAQ,GAAG,4BAA4B,YAAY;EAI/iB,MAAM,QAAQ,KAAK,iBAChB,gBAAgB,KAAK,UAAU,KAAK,cAAc,EAAE,QAAQ,MAAM,OAAO,EAAE,qBAC3E;EAEH,MAAM,EAAE,kBAAkBC,4CACzB;GACC;GACA;GACA,UAAU,KAAK;GACf,cAAc,KAAK;GACnB;GACA,OAAO;EACR,GACA;GAAE,QAAQ;GAAM,GAAG;EAAW,CAC/B;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
1
+ {"version":3,"file":"deploy.cjs","names":["pulumi","createDeployCommand"],"sources":["../../src/railway/deploy.ts"],"sourcesContent":["// src/railway/deploy.ts (replace entire file)\nimport { fileURLToPath } from \"node:url\";\n\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand } from \"../commands/deploy\";\nimport type { RailwayEnvironment } from \"./environment\";\nimport type { RailwayProject } from \"./project\";\nimport type { RailwayProvider } from \"./provider\";\nimport { RailwayBuilder, type RailwayService } from \"./service\";\n\nexport interface RailwayDeployConfig {\n\tbuilder?: RailwayBuilder;\n\tstartCommand?: string;\n\tpreDeployCommand?: string;\n}\n\nexport interface RailwayDeployArgs {\n\t/** Redeploy triggers (e.g. source hashes, env hashes). */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** Paths excluded from the upload when running with `DeploySandbox` + `GitGuard`. */\n\texcludePaths?: string[];\n\t/** Railpack configuration written to `railpack.json` before deploy. */\n\trailpackConfig?: Record<string, unknown>;\n}\n\ntype RailwayDeployOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\tprovider: RailwayProvider;\n\tproject: RailwayProject;\n\tenvironment: RailwayEnvironment;\n\tservice: RailwayService;\n\t/** Environment-scoped Railway deploy token (provision via RailwayProjectToken). */\n\tprojectToken: pulumi.Input<string>;\n};\n\n/**\n * Absolute path to the runnable deploy monitor, resolved next to this module in `dist`.\n * `railway up` only uploads + triggers; this bin makes the Railway GraphQL API — not the\n * CLI's exit code — the source of truth for pass/fail, and dumps build + deploy logs on\n * failure. Its logic lives in the unit-tested `deployment-monitor` module.\n */\nconst MONITOR_BIN = fileURLToPath(\n\tnew URL(\"./bin/monitor-deployment.mjs\", import.meta.url),\n);\n\n/**\n * Deploys a Railway service and waits for a terminal status. Isolation/git are the\n * seam's job (list a `DeploySandbox` and optionally a `GitGuard` in `dependsOn`).\n *\n * @example\n * ```typescript\n * new RailwayDeploy(\"mesh\", { triggers: [sourceHash], railpackConfig: { apt: [\"libatomic1\"] } },\n * { provider, project, environment, service, projectToken: token.token, dependsOn: [sandbox, gitGuard] });\n * ```\n */\nexport class RailwayDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (Railway service URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: RailwayDeployArgs,\n\t\topts: RailwayDeployOptions,\n\t) {\n\t\tconst {\n\t\t\tprovider,\n\t\t\tproject,\n\t\t\tenvironment,\n\t\t\tservice,\n\t\t\tprojectToken,\n\t\t\t...pulumiOpts\n\t\t} = opts;\n\n\t\tsuper(\"infracraft:railway:Deploy\", name, {}, pulumiOpts);\n\n\t\t// `railway up --detach` uploads + triggers WITHOUT attaching to the build-log\n\t\t// stream — that long-lived stream is what intermittently times out and makes the\n\t\t// CLI exit non-zero even when the deploy actually succeeds. We capture its `--json`\n\t\t// output (for the exact deployment id) and exit code, re-emit it for visibility,\n\t\t// then hand off to the monitor bin which polls the Railway API to a terminal status.\n\t\t// The API — not the CLI exit code — decides pass/fail.\n\t\t//\n\t\t// The token travels via the command's STDIN, never in the script text: on failure\n\t\t// pulumi-command embeds the executed command verbatim in its error message, and\n\t\t// Pulumi does not scrub secrets from provider diagnostics — an inlined token prints\n\t\t// in plaintext exactly when a deploy fails. The `environment` map is no alternative:\n\t\t// an unknown secret there makes `pulumi preview` fail (the token is a resource\n\t\t// output, unknown on first preview). `|| true` keeps `set -e` alive when the stdin\n\t\t// payload has no trailing newline (read then exits 1 but still fills IC_TOK).\n\t\t// IC_SINCE is captured just before `railway up` as a createdAt fallback for id\n\t\t// resolution.\n\t\t// The capture is guarded with if/else because the whole script runs under\n\t\t// `set -e`: a bare `VAR=$(cmd); EXIT=$?` DIES AT THE ASSIGNMENT when cmd\n\t\t// fails, before the exit code is saved and before the output is re-emitted\n\t\t// — swallowing the CLI's error entirely (live incident: a failed production\n\t\t// `railway up` left zero diagnostics).\n\t\tconst cli = pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e \"process.stdout.write(String(Date.now()))\"); if IC_UP_OUT=$(RAILWAY_TOKEN=\"$IC_TOK\" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); then IC_UP_EXIT=0; else IC_UP_EXIT=$?; fi; printf '%s\\\\n' \"$IC_UP_OUT\"; if [ -n \"$INFRACRAFT_SKIP_DEPLOY_WAIT\" ]; then exit \"$IC_UP_EXIT\"; fi; IC_UP_OUT=\"$IC_UP_OUT\" IC_UP_EXIT=$IC_UP_EXIT IC_TOK=\"$IC_TOK\" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node \"${MONITOR_BIN}\"`;\n\n\t\t// `printf '%s'` (not a bare format string) so railpack values containing %\n\t\t// are literal; the JSON is single-quote-escaped the POSIX way (' -> '\\'').\n\t\tconst setup = args.railpackConfig\n\t\t\t? `printf '%s' '${JSON.stringify(args.railpackConfig).replace(/'/g, \"'\\\\''\")}' > railpack.json`\n\t\t\t: undefined;\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers: args.triggers,\n\t\t\t\texcludePaths: args.excludePaths,\n\t\t\t\tsetup,\n\t\t\t\tstdin: projectToken,\n\t\t\t},\n\t\t\t{ parent: this, ...pulumiOpts },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AA4CA,MAAM,0CACL,IAAI,IAAI,6EAA+C,CACxD;;;;;;;;;;;AAYA,IAAa,gBAAb,cAAmCA,eAAO,kBAAkB;CAI3D,YACC,MACA,MACA,MACC;EACD,MAAM,EACL,UACA,SACA,aACA,SACA,cACA,GAAG,eACA;EAEJ,MAAM,6BAA6B,MAAM,CAAC,GAAG,UAAU;EAuBvD,MAAM,MAAM,eAAO,WAAW,4KAA4K,QAAQ,GAAG,aAAa,QAAQ,GAAG,iBAAiB,YAAY,GAAG,gOAAgO,QAAQ,GAAG,UAAU,YAAY,GAAG,UAAU,QAAQ,GAAG,4BAA4B,YAAY;EAI9kB,MAAM,QAAQ,KAAK,iBAChB,gBAAgB,KAAK,UAAU,KAAK,cAAc,EAAE,QAAQ,MAAM,OAAO,EAAE,qBAC3E;EAEH,MAAM,EAAE,kBAAkBC,4CACzB;GACC;GACA;GACA,UAAU,KAAK;GACf,cAAc,KAAK;GACnB;GACA,OAAO;EACR,GACA;GAAE,QAAQ;GAAM,GAAG;EAAW,CAC/B;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
@@ -25,7 +25,7 @@ var RailwayDeploy = class extends pulumi.ComponentResource {
25
25
  constructor(name, args, opts) {
26
26
  const { provider, project, environment, service, projectToken, ...pulumiOpts } = opts;
27
27
  super("infracraft:railway:Deploy", name, {}, pulumiOpts);
28
- const cli = pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e "process.stdout.write(String(Date.now()))"); IC_UP_OUT=$(RAILWAY_TOKEN="$IC_TOK" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); IC_UP_EXIT=$?; printf '%s\\n' "$IC_UP_OUT"; if [ -n "$INFRACRAFT_SKIP_DEPLOY_WAIT" ]; then exit "$IC_UP_EXIT"; fi; IC_UP_OUT="$IC_UP_OUT" IC_UP_EXIT=$IC_UP_EXIT IC_TOK="$IC_TOK" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node "${MONITOR_BIN}"`;
28
+ const cli = pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e "process.stdout.write(String(Date.now()))"); if IC_UP_OUT=$(RAILWAY_TOKEN="$IC_TOK" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); then IC_UP_EXIT=0; else IC_UP_EXIT=$?; fi; printf '%s\\n' "$IC_UP_OUT"; if [ -n "$INFRACRAFT_SKIP_DEPLOY_WAIT" ]; then exit "$IC_UP_EXIT"; fi; IC_UP_OUT="$IC_UP_OUT" IC_UP_EXIT=$IC_UP_EXIT IC_TOK="$IC_TOK" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node "${MONITOR_BIN}"`;
29
29
  const setup = args.railpackConfig ? `printf '%s' '${JSON.stringify(args.railpackConfig).replace(/'/g, "'\\''")}' > railpack.json` : void 0;
30
30
  const { deploymentUrl } = createDeployCommand({
31
31
  name,
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.mjs","names":[],"sources":["../../src/railway/deploy.ts"],"sourcesContent":["// src/railway/deploy.ts (replace entire file)\nimport { fileURLToPath } from \"node:url\";\n\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand } from \"../commands/deploy\";\nimport type { RailwayEnvironment } from \"./environment\";\nimport type { RailwayProject } from \"./project\";\nimport type { RailwayProvider } from \"./provider\";\nimport { RailwayBuilder, type RailwayService } from \"./service\";\n\nexport interface RailwayDeployConfig {\n\tbuilder?: RailwayBuilder;\n\tstartCommand?: string;\n\tpreDeployCommand?: string;\n}\n\nexport interface RailwayDeployArgs {\n\t/** Redeploy triggers (e.g. source hashes, env hashes). */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** Paths excluded from the upload when running with `DeploySandbox` + `GitGuard`. */\n\texcludePaths?: string[];\n\t/** Railpack configuration written to `railpack.json` before deploy. */\n\trailpackConfig?: Record<string, unknown>;\n}\n\ntype RailwayDeployOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\tprovider: RailwayProvider;\n\tproject: RailwayProject;\n\tenvironment: RailwayEnvironment;\n\tservice: RailwayService;\n\t/** Environment-scoped Railway deploy token (provision via RailwayProjectToken). */\n\tprojectToken: pulumi.Input<string>;\n};\n\n/**\n * Absolute path to the runnable deploy monitor, resolved next to this module in `dist`.\n * `railway up` only uploads + triggers; this bin makes the Railway GraphQL API — not the\n * CLI's exit code — the source of truth for pass/fail, and dumps build + deploy logs on\n * failure. Its logic lives in the unit-tested `deployment-monitor` module.\n */\nconst MONITOR_BIN = fileURLToPath(\n\tnew URL(\"./bin/monitor-deployment.mjs\", import.meta.url),\n);\n\n/**\n * Deploys a Railway service and waits for a terminal status. Isolation/git are the\n * seam's job (list a `DeploySandbox` and optionally a `GitGuard` in `dependsOn`).\n *\n * @example\n * ```typescript\n * new RailwayDeploy(\"mesh\", { triggers: [sourceHash], railpackConfig: { apt: [\"libatomic1\"] } },\n * { provider, project, environment, service, projectToken: token.token, dependsOn: [sandbox, gitGuard] });\n * ```\n */\nexport class RailwayDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (Railway service URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: RailwayDeployArgs,\n\t\topts: RailwayDeployOptions,\n\t) {\n\t\tconst {\n\t\t\tprovider,\n\t\t\tproject,\n\t\t\tenvironment,\n\t\t\tservice,\n\t\t\tprojectToken,\n\t\t\t...pulumiOpts\n\t\t} = opts;\n\n\t\tsuper(\"infracraft:railway:Deploy\", name, {}, pulumiOpts);\n\n\t\t// `railway up --detach` uploads + triggers WITHOUT attaching to the build-log\n\t\t// stream — that long-lived stream is what intermittently times out and makes the\n\t\t// CLI exit non-zero even when the deploy actually succeeds. We capture its `--json`\n\t\t// output (for the exact deployment id) and exit code, re-emit it for visibility,\n\t\t// then hand off to the monitor bin which polls the Railway API to a terminal status.\n\t\t// The API — not the CLI exit code — decides pass/fail.\n\t\t//\n\t\t// The token travels via the command's STDIN, never in the script text: on failure\n\t\t// pulumi-command embeds the executed command verbatim in its error message, and\n\t\t// Pulumi does not scrub secrets from provider diagnostics — an inlined token prints\n\t\t// in plaintext exactly when a deploy fails. The `environment` map is no alternative:\n\t\t// an unknown secret there makes `pulumi preview` fail (the token is a resource\n\t\t// output, unknown on first preview). `|| true` keeps `set -e` alive when the stdin\n\t\t// payload has no trailing newline (read then exits 1 but still fills IC_TOK).\n\t\t// IC_SINCE is captured just before `railway up` as a createdAt fallback for id\n\t\t// resolution.\n\t\tconst cli = pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e \"process.stdout.write(String(Date.now()))\"); IC_UP_OUT=$(RAILWAY_TOKEN=\"$IC_TOK\" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); IC_UP_EXIT=$?; printf '%s\\\\n' \"$IC_UP_OUT\"; if [ -n \"$INFRACRAFT_SKIP_DEPLOY_WAIT\" ]; then exit \"$IC_UP_EXIT\"; fi; IC_UP_OUT=\"$IC_UP_OUT\" IC_UP_EXIT=$IC_UP_EXIT IC_TOK=\"$IC_TOK\" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node \"${MONITOR_BIN}\"`;\n\n\t\t// `printf '%s'` (not a bare format string) so railpack values containing %\n\t\t// are literal; the JSON is single-quote-escaped the POSIX way (' -> '\\'').\n\t\tconst setup = args.railpackConfig\n\t\t\t? `printf '%s' '${JSON.stringify(args.railpackConfig).replace(/'/g, \"'\\\\''\")}' > railpack.json`\n\t\t\t: undefined;\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers: args.triggers,\n\t\t\t\texcludePaths: args.excludePaths,\n\t\t\t\tsetup,\n\t\t\t\tstdin: projectToken,\n\t\t\t},\n\t\t\t{ parent: this, ...pulumiOpts },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AA4CA,MAAM,cAAc,cACnB,IAAI,IAAI,gCAAgC,OAAO,KAAK,GAAG,CACxD;;;;;;;;;;;AAYA,IAAa,gBAAb,cAAmC,OAAO,kBAAkB;CAI3D,YACC,MACA,MACA,MACC;EACD,MAAM,EACL,UACA,SACA,aACA,SACA,cACA,GAAG,eACA;EAEJ,MAAM,6BAA6B,MAAM,CAAC,GAAG,UAAU;EAkBvD,MAAM,MAAM,OAAO,WAAW,yKAAyK,QAAQ,GAAG,aAAa,QAAQ,GAAG,iBAAiB,YAAY,GAAG,oMAAoM,QAAQ,GAAG,UAAU,YAAY,GAAG,UAAU,QAAQ,GAAG,4BAA4B,YAAY;EAI/iB,MAAM,QAAQ,KAAK,iBAChB,gBAAgB,KAAK,UAAU,KAAK,cAAc,EAAE,QAAQ,MAAM,OAAO,EAAE,qBAC3E;EAEH,MAAM,EAAE,kBAAkB,oBACzB;GACC;GACA;GACA,UAAU,KAAK;GACf,cAAc,KAAK;GACnB;GACA,OAAO;EACR,GACA;GAAE,QAAQ;GAAM,GAAG;EAAW,CAC/B;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
1
+ {"version":3,"file":"deploy.mjs","names":[],"sources":["../../src/railway/deploy.ts"],"sourcesContent":["// src/railway/deploy.ts (replace entire file)\nimport { fileURLToPath } from \"node:url\";\n\nimport * as pulumi from \"@pulumi/pulumi\";\n\nimport { createDeployCommand } from \"../commands/deploy\";\nimport type { RailwayEnvironment } from \"./environment\";\nimport type { RailwayProject } from \"./project\";\nimport type { RailwayProvider } from \"./provider\";\nimport { RailwayBuilder, type RailwayService } from \"./service\";\n\nexport interface RailwayDeployConfig {\n\tbuilder?: RailwayBuilder;\n\tstartCommand?: string;\n\tpreDeployCommand?: string;\n}\n\nexport interface RailwayDeployArgs {\n\t/** Redeploy triggers (e.g. source hashes, env hashes). */\n\ttriggers: pulumi.Input<pulumi.Input<string>[]>;\n\t/** Paths excluded from the upload when running with `DeploySandbox` + `GitGuard`. */\n\texcludePaths?: string[];\n\t/** Railpack configuration written to `railpack.json` before deploy. */\n\trailpackConfig?: Record<string, unknown>;\n}\n\ntype RailwayDeployOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\tprovider: RailwayProvider;\n\tproject: RailwayProject;\n\tenvironment: RailwayEnvironment;\n\tservice: RailwayService;\n\t/** Environment-scoped Railway deploy token (provision via RailwayProjectToken). */\n\tprojectToken: pulumi.Input<string>;\n};\n\n/**\n * Absolute path to the runnable deploy monitor, resolved next to this module in `dist`.\n * `railway up` only uploads + triggers; this bin makes the Railway GraphQL API — not the\n * CLI's exit code — the source of truth for pass/fail, and dumps build + deploy logs on\n * failure. Its logic lives in the unit-tested `deployment-monitor` module.\n */\nconst MONITOR_BIN = fileURLToPath(\n\tnew URL(\"./bin/monitor-deployment.mjs\", import.meta.url),\n);\n\n/**\n * Deploys a Railway service and waits for a terminal status. Isolation/git are the\n * seam's job (list a `DeploySandbox` and optionally a `GitGuard` in `dependsOn`).\n *\n * @example\n * ```typescript\n * new RailwayDeploy(\"mesh\", { triggers: [sourceHash], railpackConfig: { apt: [\"libatomic1\"] } },\n * { provider, project, environment, service, projectToken: token.token, dependsOn: [sandbox, gitGuard] });\n * ```\n */\nexport class RailwayDeploy extends pulumi.ComponentResource {\n\t/** The deploy CLI's final stdout line (Railway service URL when emitted). */\n\tpublic readonly deploymentUrl: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: RailwayDeployArgs,\n\t\topts: RailwayDeployOptions,\n\t) {\n\t\tconst {\n\t\t\tprovider,\n\t\t\tproject,\n\t\t\tenvironment,\n\t\t\tservice,\n\t\t\tprojectToken,\n\t\t\t...pulumiOpts\n\t\t} = opts;\n\n\t\tsuper(\"infracraft:railway:Deploy\", name, {}, pulumiOpts);\n\n\t\t// `railway up --detach` uploads + triggers WITHOUT attaching to the build-log\n\t\t// stream — that long-lived stream is what intermittently times out and makes the\n\t\t// CLI exit non-zero even when the deploy actually succeeds. We capture its `--json`\n\t\t// output (for the exact deployment id) and exit code, re-emit it for visibility,\n\t\t// then hand off to the monitor bin which polls the Railway API to a terminal status.\n\t\t// The API — not the CLI exit code — decides pass/fail.\n\t\t//\n\t\t// The token travels via the command's STDIN, never in the script text: on failure\n\t\t// pulumi-command embeds the executed command verbatim in its error message, and\n\t\t// Pulumi does not scrub secrets from provider diagnostics — an inlined token prints\n\t\t// in plaintext exactly when a deploy fails. The `environment` map is no alternative:\n\t\t// an unknown secret there makes `pulumi preview` fail (the token is a resource\n\t\t// output, unknown on first preview). `|| true` keeps `set -e` alive when the stdin\n\t\t// payload has no trailing newline (read then exits 1 but still fills IC_TOK).\n\t\t// IC_SINCE is captured just before `railway up` as a createdAt fallback for id\n\t\t// resolution.\n\t\t// The capture is guarded with if/else because the whole script runs under\n\t\t// `set -e`: a bare `VAR=$(cmd); EXIT=$?` DIES AT THE ASSIGNMENT when cmd\n\t\t// fails, before the exit code is saved and before the output is re-emitted\n\t\t// — swallowing the CLI's error entirely (live incident: a failed production\n\t\t// `railway up` left zero diagnostics).\n\t\tconst cli = pulumi.interpolate`IFS= read -r IC_TOK || true; IC_SINCE=$(node -e \"process.stdout.write(String(Date.now()))\"); if IC_UP_OUT=$(RAILWAY_TOKEN=\"$IC_TOK\" railway up --detach --json --project ${project.id} --service ${service.id} --environment ${environment.id} 2>&1); then IC_UP_EXIT=0; else IC_UP_EXIT=$?; fi; printf '%s\\\\n' \"$IC_UP_OUT\"; if [ -n \"$INFRACRAFT_SKIP_DEPLOY_WAIT\" ]; then exit \"$IC_UP_EXIT\"; fi; IC_UP_OUT=\"$IC_UP_OUT\" IC_UP_EXIT=$IC_UP_EXIT IC_TOK=\"$IC_TOK\" IC_PROJ=${project.id} IC_ENV=${environment.id} IC_SVC=${service.id} IC_SINCE=$IC_SINCE node \"${MONITOR_BIN}\"`;\n\n\t\t// `printf '%s'` (not a bare format string) so railpack values containing %\n\t\t// are literal; the JSON is single-quote-escaped the POSIX way (' -> '\\'').\n\t\tconst setup = args.railpackConfig\n\t\t\t? `printf '%s' '${JSON.stringify(args.railpackConfig).replace(/'/g, \"'\\\\''\")}' > railpack.json`\n\t\t\t: undefined;\n\n\t\tconst { deploymentUrl } = createDeployCommand(\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tcli,\n\t\t\t\ttriggers: args.triggers,\n\t\t\t\texcludePaths: args.excludePaths,\n\t\t\t\tsetup,\n\t\t\t\tstdin: projectToken,\n\t\t\t},\n\t\t\t{ parent: this, ...pulumiOpts },\n\t\t);\n\n\t\tthis.deploymentUrl = deploymentUrl;\n\n\t\tthis.registerOutputs({ deploymentUrl: this.deploymentUrl });\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AA4CA,MAAM,cAAc,cACnB,IAAI,IAAI,gCAAgC,OAAO,KAAK,GAAG,CACxD;;;;;;;;;;;AAYA,IAAa,gBAAb,cAAmC,OAAO,kBAAkB;CAI3D,YACC,MACA,MACA,MACC;EACD,MAAM,EACL,UACA,SACA,aACA,SACA,cACA,GAAG,eACA;EAEJ,MAAM,6BAA6B,MAAM,CAAC,GAAG,UAAU;EAuBvD,MAAM,MAAM,OAAO,WAAW,4KAA4K,QAAQ,GAAG,aAAa,QAAQ,GAAG,iBAAiB,YAAY,GAAG,gOAAgO,QAAQ,GAAG,UAAU,YAAY,GAAG,UAAU,QAAQ,GAAG,4BAA4B,YAAY;EAI9kB,MAAM,QAAQ,KAAK,iBAChB,gBAAgB,KAAK,UAAU,KAAK,cAAc,EAAE,QAAQ,MAAM,OAAO,EAAE,qBAC3E;EAEH,MAAM,EAAE,kBAAkB,oBACzB;GACC;GACA;GACA,UAAU,KAAK;GACf,cAAc,KAAK;GACnB;GACA,OAAO;EACR,GACA;GAAE,QAAQ;GAAM,GAAG;EAAW,CAC/B;EAEA,KAAK,gBAAgB;EAErB,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;CAC3D;AACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infracraft/pulumi",
3
- "version": "1.28.0",
3
+ "version": "1.28.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Native Pulumi providers for Railway, Neon, Vercel, and Fly.io with adopt-or-create semantics and deploy orchestration. No Terraform bridge.",