openship 0.6.7 → 0.6.9

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 (67) hide show
  1. package/dist/bare-FA66N7GC.js +29 -0
  2. package/dist/{chunk-LHFXSC36.js → chunk-3MP6ACKM.js} +183 -87
  3. package/dist/{chunk-MEE6OZFP.js → chunk-5DJOB7IX.js} +3 -3
  4. package/dist/{chunk-VQM6JHJB.js → chunk-5UXHT6ED.js} +9 -9
  5. package/dist/{chunk-PPEBIY5F.js → chunk-634DDFT5.js} +35 -12
  6. package/dist/{chunk-XWHWTHEL.js → chunk-6GU6JSK6.js} +21 -2
  7. package/dist/{chunk-QHMDCYZ3.js → chunk-7PEXM2UI.js} +213 -45
  8. package/dist/{chunk-RDXT4BQB.js → chunk-7YBWXEM6.js} +4 -4
  9. package/dist/{chunk-H4FS5BED.js → chunk-AHJYP7DG.js} +13 -11
  10. package/dist/{chunk-VSTFHUCV.js → chunk-BO6CY4V2.js} +109 -23
  11. package/dist/{chunk-J3K6XABC.js → chunk-D3OEMXYP.js} +3 -3
  12. package/dist/{chunk-UWEV6XTS.js → chunk-D6HU4VUZ.js} +1 -1
  13. package/dist/{chunk-S6B2Z3OO.js → chunk-ENKJ7XIF.js} +21 -11
  14. package/dist/{chunk-DDFUESPJ.js → chunk-FCGJN5Q5.js} +9 -9
  15. package/dist/{chunk-BLEXTYRK.js → chunk-GNOMEMNI.js} +1 -1
  16. package/dist/{chunk-NRTJRNAE.js → chunk-IAMOUDHY.js} +138 -54
  17. package/dist/{chunk-CIJV43LH.js → chunk-MUWVC5R4.js} +161 -39
  18. package/dist/{chunk-ZPJ74LXE.js → chunk-NIYD7MD2.js} +197 -45
  19. package/dist/{chunk-FZ6QCF6B.js → chunk-NPSRGIHV.js} +2 -2
  20. package/dist/{chunk-2GWYYHOR.js → chunk-NRU2EBYZ.js} +2 -2
  21. package/dist/{chunk-J2XM3QSP.js → chunk-NUT6HKK6.js} +5 -5
  22. package/dist/{chunk-H3WT3A6R.js → chunk-P7RCYELG.js} +1 -1
  23. package/dist/{chunk-FYPFEDPZ.js → chunk-R5DC5PEF.js} +1 -1
  24. package/dist/{chunk-RXQBD4ZY.js → chunk-RHLNVZMS.js} +2 -2
  25. package/dist/{chunk-WU54BXFE.js → chunk-SK4FFCFR.js} +1 -1
  26. package/dist/{chunk-PVP4RGWT.js → chunk-T46BQOLY.js} +3 -3
  27. package/dist/{chunk-E2X26PXR.js → chunk-T6DVUX4F.js} +1 -1
  28. package/dist/{chunk-5T4UVOM3.js → chunk-TAZZZKYO.js} +1 -1
  29. package/dist/{chunk-GGIAIGUL.js → chunk-UAWY6X7V.js} +34 -12
  30. package/dist/{chunk-2ANV5ZQ5.js → chunk-VAI5VOOI.js} +1 -1
  31. package/dist/{chunk-2VSW6Q6C.js → chunk-WEZFTL4V.js} +655 -62
  32. package/dist/{chunk-GIPJNNI5.js → chunk-X53JXRS4.js} +3 -3
  33. package/dist/{cloud-KRTZ2IL5.js → cloud-2CRDKOWQ.js} +1 -1
  34. package/dist/cloud-REV3DPJH.js +42 -0
  35. package/dist/{detect-G4DR3U2N.js → detect-BBFT5GEU.js} +4 -4
  36. package/dist/{docker-YOVPCIB4.js → docker-EG3QSE6I.js} +10 -10
  37. package/dist/{docker-edge-executor-QFXD3337.js → docker-edge-executor-E5TOTLMR.js} +7 -7
  38. package/dist/edge-import-YJVJUGYC.js +56 -0
  39. package/dist/{edge-preflight-MXERVAMG.js → edge-preflight-QUW4BM7N.js} +13 -13
  40. package/dist/{ensure-container-edge-F4JUNQIK.js → ensure-container-edge-FOEFQ3PI.js} +13 -11
  41. package/dist/{executor-CVPAYYHR.js → executor-NTWDJ3DB.js} +6 -6
  42. package/dist/host-channel-preflight-OI2TRHSG.js +54 -0
  43. package/dist/index.js +158 -72
  44. package/dist/{local-executor-ODC6RANU.js → local-executor-OQ2GRN7K.js} +3 -3
  45. package/dist/{nginx-KLFF43TC.js → nginx-4U4C2XUS.js} +9 -9
  46. package/dist/{noop-NJ72F46T.js → noop-CLLJHCPL.js} +1 -1
  47. package/dist/{openresty-lua-VKWUV4GB.js → openresty-lua-LLWT5XQW.js} +7 -5
  48. package/dist/{privilege-7D3SSOL3.js → privilege-MNDVMDST.js} +5 -5
  49. package/dist/server/index.js +31801 -25560
  50. package/dist/server/migrations/0109_service_build_args.sql +9 -0
  51. package/dist/server/migrations/0110_service_deployment_host_ports.sql +18 -0
  52. package/dist/server/migrations/0111_host_port_claim.sql +381 -0
  53. package/dist/server/migrations/0112_backup_run_execution_lease.sql +12 -0
  54. package/dist/server/migrations/0113_docker_migration_execution_lease.sql +11 -0
  55. package/dist/server/migrations/0114_build_session_execution_lease_index.sql +6 -0
  56. package/dist/server/migrations/0115_orphan_target_key.sql +3 -0
  57. package/dist/server/migrations/0116_domain_ssl_challenge.sql +2 -0
  58. package/dist/server/migrations/meta/_journal.json +56 -0
  59. package/dist/{setup-I5AJC6NJ.js → setup-IFIMPQZJ.js} +12 -12
  60. package/dist/{ssh-client-625VWGKP.js → ssh-client-2XWZCMGI.js} +2 -2
  61. package/dist/up-RC5ZQIAD.js +61 -0
  62. package/package.json +1 -1
  63. package/dist/bare-7QD623QV.js +0 -29
  64. package/dist/cloud-KNNABE3O.js +0 -40
  65. package/dist/edge-import-CRFVSR6P.js +0 -56
  66. package/dist/host-channel-preflight-QTDNGLCK.js +0 -54
  67. package/dist/up-QXTOOVXC.js +0 -61
@@ -7,13 +7,13 @@ import {
7
7
  isContainerPortForwarder,
8
8
  managedDeploymentIdFromUnit,
9
9
  tryExec
10
- } from "./chunk-UWEV6XTS.js";
10
+ } from "./chunk-D6HU4VUZ.js";
11
11
  import {
12
12
  shellQuote
13
- } from "./chunk-2VSW6Q6C.js";
13
+ } from "./chunk-WEZFTL4V.js";
14
14
 
15
15
  // ../../packages/adapters/src/system/port-listen.ts
16
- var PROC_NET_TCP_CMD = "cat /proc/net/tcp 2>/dev/null; cat /proc/net/tcp6 2>/dev/null; true";
16
+ var PROC_NET_TCP_FILES = ["/proc/net/tcp", "/proc/net/tcp6"];
17
17
  var TCP_LISTEN = "0A";
18
18
  function parseListeningPorts(procText) {
19
19
  const ports = /* @__PURE__ */ new Set();
@@ -34,12 +34,15 @@ function parseListeningPorts(procText) {
34
34
  return ports;
35
35
  }
36
36
  async function probePortListeningOnce(executor, port) {
37
- try {
38
- const out = await executor.exec(PROC_NET_TCP_CMD, { timeout: 5e3 });
39
- return parseListeningPorts(out).has(port);
40
- } catch {
41
- return null;
37
+ const readable = [];
38
+ for (const file of PROC_NET_TCP_FILES) {
39
+ try {
40
+ readable.push(await executor.exec(`cat ${file} 2>/dev/null`, { timeout: 5e3 }));
41
+ } catch {
42
+ }
42
43
  }
44
+ if (readable.length === 0) return null;
45
+ return parseListeningPorts(readable.join("\n")).has(port);
43
46
  }
44
47
  function delay(ms) {
45
48
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -85,12 +88,14 @@ async function waitForPortFree(executor, port, opts = {}) {
85
88
 
86
89
  // ../../packages/adapters/src/runtime/port-conflict.ts
87
90
  async function resolveListenerOwner(executor, pid) {
88
- const cgroup = await tryExec(executor, `cat /proc/${pid}/cgroup 2>/dev/null || true`);
91
+ const cgroup = (await tryExec(executor, `cat /proc/${pid}/cgroup 2>/dev/null`))?.trim();
92
+ if (!cgroup) return { cgroupVerified: false };
93
+ const evidence = { cgroupVerified: true, processCgroup: cgroup };
89
94
  const containerId = containerIdFromCgroup(cgroup);
90
- if (containerId) return { containerId };
95
+ if (containerId) return { ...evidence, containerId };
91
96
  const systemdUnit = cgroup?.match(/(?:^|\/)([^/\n]+\.service)(?:$|\n|\/)/m)?.[1]?.trim();
92
97
  if (!systemdUnit || !/^[A-Za-z0-9@._:-]+\.service$/.test(systemdUnit)) {
93
- return {};
98
+ return evidence;
94
99
  }
95
100
  const description = await tryExec(
96
101
  executor,
@@ -98,6 +103,7 @@ async function resolveListenerOwner(executor, pid) {
98
103
  );
99
104
  const deploymentId = managedDeploymentIdFromUnit(systemdUnit);
100
105
  return {
106
+ ...evidence,
101
107
  systemdUnit,
102
108
  systemdDescription: description?.trim() || void 0,
103
109
  ...deploymentId ? { deploymentId, isManagedDeployment: true } : { isManagedDeployment: false }
@@ -108,25 +114,104 @@ async function resolveListener(executor, port) {
108
114
  executor,
109
115
  `ss -tlnp sport = :${port} 2>/dev/null | grep LISTEN || lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null || true`
110
116
  );
111
- if (out) {
112
- const ssMatch = out.match(/pid=(\d+)/);
113
- const lsofMatch = !ssMatch ? out.match(/^\s*(\d+)\s*$/m) : null;
114
- const pid = ssMatch ? parseInt(ssMatch[1], 10) : lsofMatch ? parseInt(lsofMatch[1], 10) : null;
115
- if (pid) return { pid, occupied: true };
117
+ const listenerPid = (output) => {
118
+ if (!output) return null;
119
+ const ssMatch = output.match(/pid=(\d+)/);
120
+ const lsofMatch = !ssMatch ? output.match(/^\s*(\d+)\s*$/m) : null;
121
+ const parsed = ssMatch?.[1] ?? lsofMatch?.[1];
122
+ if (!parsed) return null;
123
+ const pid2 = Number.parseInt(parsed, 10);
124
+ return Number.isSafeInteger(pid2) && pid2 > 0 ? pid2 : null;
125
+ };
126
+ const pid = listenerPid(out);
127
+ if (pid) return { pid, occupied: true, checked: true };
128
+ const observedListener = Boolean(out?.trim());
129
+ if (observedListener) {
130
+ const privilegedOut = await tryExec(
131
+ executor,
132
+ `sudo -n ss -tlnp sport = :${port} 2>/dev/null | grep LISTEN || sudo -n lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null || true`,
133
+ { timeout: 5e3 }
134
+ );
135
+ const privilegedPid = listenerPid(privilegedOut);
136
+ if (privilegedPid) return { pid: privilegedPid, occupied: true, checked: true };
116
137
  }
117
138
  const listening = await probePortListeningOnce(executor, port);
118
- return { pid: null, occupied: listening === true };
139
+ return {
140
+ pid: null,
141
+ occupied: observedListener || listening === true,
142
+ checked: observedListener || listening !== null
143
+ };
119
144
  }
120
- async function probeListeningPort(executor, port) {
145
+ function parseListenerPids(output) {
146
+ const lines = (output ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
147
+ if (lines.length === 0) return { observed: false, complete: true, pids: [] };
148
+ const pids = /* @__PURE__ */ new Set();
149
+ let complete = true;
150
+ for (const line of lines) {
151
+ const matches = [...line.matchAll(/pid=(\d+)/g)].map((match) => match[1]);
152
+ const bare = matches.length === 0 ? line.match(/^(\d+)$/)?.[1] : void 0;
153
+ const values = bare ? [bare] : matches;
154
+ if (values.length === 0) complete = false;
155
+ for (const value of values) {
156
+ const pid = Number.parseInt(value, 10);
157
+ if (Number.isSafeInteger(pid) && pid > 0) pids.add(pid);
158
+ else complete = false;
159
+ }
160
+ }
161
+ return { observed: true, complete, pids: [...pids] };
162
+ }
163
+ async function probeListeningPortOwners(executor, port) {
164
+ const command = `ss -tlnp sport = :${port} 2>/dev/null | grep LISTEN || lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null || true`;
165
+ const ordinary = parseListenerPids(await tryExec(executor, command));
166
+ let evidence = ordinary;
167
+ if (ordinary.observed && !ordinary.complete) {
168
+ const privileged = parseListenerPids(
169
+ await tryExec(
170
+ executor,
171
+ `sudo -n ss -tlnp sport = :${port} 2>/dev/null | grep LISTEN || sudo -n lsof -ti tcp:${port} -sTCP:LISTEN 2>/dev/null`,
172
+ { timeout: 5e3 }
173
+ )
174
+ );
175
+ if (privileged.observed && privileged.complete) evidence = privileged;
176
+ else {
177
+ evidence = {
178
+ observed: true,
179
+ complete: false,
180
+ pids: [.../* @__PURE__ */ new Set([...ordinary.pids, ...privileged.pids])]
181
+ };
182
+ }
183
+ }
184
+ if (!evidence.observed) {
185
+ const listening = await probePortListeningOnce(executor, port);
186
+ if (listening === null) return { occupants: [], checked: false, ownershipComplete: false };
187
+ if (!listening) return { occupants: [], checked: true, ownershipComplete: true };
188
+ return { occupants: [], checked: true, ownershipComplete: false };
189
+ }
190
+ const described = await Promise.all(
191
+ evidence.pids.map((pid) => describeProcess(executor, pid).catch(() => null))
192
+ );
193
+ const occupants = described.filter((row) => row !== null);
194
+ return {
195
+ occupants,
196
+ checked: true,
197
+ ownershipComplete: evidence.complete && occupants.length === evidence.pids.length
198
+ };
199
+ }
200
+ async function probeListeningPortState(executor, port) {
121
201
  try {
122
- const { pid, occupied } = await resolveListener(executor, port);
123
- if (!occupied) return null;
124
- if (pid === null) return { pid: null, command: "unknown listener" };
125
- return await describeProcess(executor, pid);
202
+ const { pid, occupied, checked } = await resolveListener(executor, port);
203
+ if (!checked || !occupied) return { occupant: null, checked };
204
+ if (pid === null) {
205
+ return { occupant: { pid: null, command: "unknown listener" }, checked: true };
206
+ }
207
+ return { occupant: await describeProcess(executor, pid), checked: true };
126
208
  } catch {
127
- return null;
209
+ return { occupant: null, checked: false };
128
210
  }
129
211
  }
212
+ async function probeListeningPort(executor, port) {
213
+ return (await probeListeningPortState(executor, port)).occupant;
214
+ }
130
215
  async function describeProcess(executor, pid) {
131
216
  let command = `PID ${pid}`;
132
217
  let rawCommand;
@@ -173,6 +258,7 @@ function portOccupantDetails(port, occupant, stopTarget) {
173
258
  export {
174
259
  waitForPortListening,
175
260
  waitForPortFree,
261
+ probeListeningPortOwners,
176
262
  probeListeningPort,
177
263
  describeProcess,
178
264
  portOccupantDetails
@@ -8,14 +8,14 @@ import {
8
8
  } from "./chunk-I3DPMTSF.js";
9
9
  import {
10
10
  LocalExecutor
11
- } from "./chunk-E2X26PXR.js";
11
+ } from "./chunk-T6DVUX4F.js";
12
12
  import {
13
13
  logEntry,
14
14
  sq
15
- } from "./chunk-H3WT3A6R.js";
15
+ } from "./chunk-P7RCYELG.js";
16
16
  import {
17
17
  edgeFailureReason
18
- } from "./chunk-GIPJNNI5.js";
18
+ } from "./chunk-X53JXRS4.js";
19
19
 
20
20
  // ../../packages/adapters/src/system/docker-edge-executor.ts
21
21
  import Dockerode from "dockerode";
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  safeErrorMessage,
12
12
  shellQuote
13
- } from "./chunk-2VSW6Q6C.js";
13
+ } from "./chunk-WEZFTL4V.js";
14
14
 
15
15
  // ../../packages/adapters/src/system/probe-exec.ts
16
16
  async function tryExec(executor, command, opts) {
@@ -7,11 +7,11 @@ import {
7
7
  resolveProjectDir,
8
8
  resolveStaticOutputPath,
9
9
  runLocalBuild
10
- } from "./chunk-MEE6OZFP.js";
10
+ } from "./chunk-5DJOB7IX.js";
11
11
  import {
12
12
  isArtifactPathRef,
13
13
  removeManagedArtifact
14
- } from "./chunk-WU54BXFE.js";
14
+ } from "./chunk-SK4FFCFR.js";
15
15
  import {
16
16
  BuildCancelledError,
17
17
  BuildLogger,
@@ -24,36 +24,36 @@ import {
24
24
  splitRuntimeEnv,
25
25
  sq,
26
26
  transferLocalDirectory
27
- } from "./chunk-H4FS5BED.js";
27
+ } from "./chunk-AHJYP7DG.js";
28
28
  import {
29
29
  LocalExecutor
30
- } from "./chunk-E2X26PXR.js";
30
+ } from "./chunk-T6DVUX4F.js";
31
31
  import {
32
32
  privilegedExecutor
33
- } from "./chunk-PVP4RGWT.js";
33
+ } from "./chunk-T46BQOLY.js";
34
34
  import {
35
35
  HOST_STATE_DIR,
36
36
  envOps,
37
37
  hostRefusal,
38
38
  opScript
39
- } from "./chunk-BLEXTYRK.js";
39
+ } from "./chunk-GNOMEMNI.js";
40
40
  import {
41
41
  ensureOwnedDir,
42
42
  resolveEnvironment
43
- } from "./chunk-FZ6QCF6B.js";
43
+ } from "./chunk-NPSRGIHV.js";
44
44
  import {
45
45
  sq as sq2,
46
46
  wrapLocalBuildCommand
47
- } from "./chunk-H3WT3A6R.js";
47
+ } from "./chunk-P7RCYELG.js";
48
48
  import {
49
49
  portOccupantDetails,
50
50
  probeListeningPort
51
- } from "./chunk-VSTFHUCV.js";
51
+ } from "./chunk-BO6CY4V2.js";
52
52
  import {
53
53
  managedDeploymentUnitName,
54
54
  probeExec,
55
55
  withReason
56
- } from "./chunk-UWEV6XTS.js";
56
+ } from "./chunk-D6HU4VUZ.js";
57
57
  import {
58
58
  formatDuration,
59
59
  isRemoteConnectionError,
@@ -73,7 +73,7 @@ import {
73
73
  refused,
74
74
  safeErrorMessage,
75
75
  shellQuote
76
- } from "./chunk-2VSW6Q6C.js";
76
+ } from "./chunk-WEZFTL4V.js";
77
77
 
78
78
  // ../../packages/adapters/src/system/remote-journal.ts
79
79
  var OPSH_RUN_VERSION = 1;
@@ -1608,6 +1608,16 @@ var BareRuntime = class {
1608
1608
  async inContainerExecutor() {
1609
1609
  return this.executor;
1610
1610
  }
1611
+ /**
1612
+ * Resolve a retained application release for an env-only refresh.
1613
+ * Deployment ids originate in our database, but reject path-shaped input at
1614
+ * this boundary so an imported/corrupt row cannot escape releases/.
1615
+ */
1616
+ async retainedReleaseArtifact(deploymentId) {
1617
+ if (!deploymentId || deploymentId.includes("/") || deploymentId.includes("\\")) return null;
1618
+ const path = this.releaseDir(deploymentId);
1619
+ return await this.executor.exists(path).catch(() => false) ? path : null;
1620
+ }
1611
1621
  /** Get or lazily initialise the process supervisor. */
1612
1622
  async supervisor() {
1613
1623
  if (this._supervisor) return this._supervisor;
@@ -28,7 +28,7 @@ import {
28
28
  resolvePorts,
29
29
  sourceBuildDir,
30
30
  verifyHostChannel
31
- } from "./chunk-PPEBIY5F.js";
31
+ } from "./chunk-634DDFT5.js";
32
32
  import {
33
33
  bootstrapAdmin,
34
34
  importMigratedSites,
@@ -36,18 +36,18 @@ import {
36
36
  internalPost,
37
37
  mintBareInternalToken,
38
38
  waitHealthy
39
- } from "./chunk-RDXT4BQB.js";
39
+ } from "./chunk-7YBWXEM6.js";
40
40
  import {
41
41
  startUnitHint,
42
42
  thisHost
43
- } from "./chunk-VQM6JHJB.js";
43
+ } from "./chunk-5UXHT6ED.js";
44
44
  import {
45
45
  completeHostEdge,
46
46
  markStoppedProxyImported,
47
47
  planAndApplyHostEdge,
48
48
  previewHostEdge,
49
49
  rollbackHostEdge
50
- } from "./chunk-J2XM3QSP.js";
50
+ } from "./chunk-NUT6HKK6.js";
51
51
  import {
52
52
  AUTH_SECRET_FILE,
53
53
  DATA_DIR,
@@ -58,17 +58,17 @@ import {
58
58
  } from "./chunk-ELGRMZOW.js";
59
59
  import {
60
60
  LocalExecutor
61
- } from "./chunk-E2X26PXR.js";
61
+ } from "./chunk-T6DVUX4F.js";
62
62
  import {
63
63
  edgeCrashReason,
64
64
  edgeIsBroken
65
- } from "./chunk-GIPJNNI5.js";
65
+ } from "./chunk-X53JXRS4.js";
66
66
  import {
67
67
  EDGE_CONTAINER_NAME
68
- } from "./chunk-UWEV6XTS.js";
68
+ } from "./chunk-D6HU4VUZ.js";
69
69
  import {
70
70
  isValidEmail
71
- } from "./chunk-2VSW6Q6C.js";
71
+ } from "./chunk-WEZFTL4V.js";
72
72
 
73
73
  // src/commands/up.ts
74
74
  import { Command } from "commander";
@@ -1564,7 +1564,7 @@ async function runForeground(opts, source) {
1564
1564
  const uiSpinner = ora("Preparing the dashboard\u2026").start();
1565
1565
  try {
1566
1566
  const bundle = await ensureDashboard({
1567
- tag: source ? "local" : opts.uiVersion || `v${"0.6.7"}`,
1567
+ tag: source ? "local" : opts.uiVersion || `v${"0.6.9"}`,
1568
1568
  onProgress: (received, total) => {
1569
1569
  if (total) {
1570
1570
  uiSpinner.text = `Downloading dashboard\u2026 ${Math.round(received / total * 100)}%`;
@@ -9,7 +9,7 @@ import {
9
9
  firewallPersists,
10
10
  refused,
11
11
  shellQuote
12
- } from "./chunk-2VSW6Q6C.js";
12
+ } from "./chunk-WEZFTL4V.js";
13
13
 
14
14
  // ../../packages/adapters/src/system/environment-ops.ts
15
15
  function opScript(steps) {