openship 0.6.9 → 0.7.0
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/bare-3POKLHTW.js +29 -0
- package/dist/{chunk-UAWY6X7V.js → chunk-3KUW2UC6.js} +470 -59
- package/dist/{chunk-GNOMEMNI.js → chunk-3LWGDMJU.js} +1 -1
- package/dist/{chunk-ENKJ7XIF.js → chunk-5CFUYMPE.js} +11 -11
- package/dist/{chunk-NUT6HKK6.js → chunk-5D27WZBW.js} +5 -5
- package/dist/{chunk-NIYD7MD2.js → chunk-7MKZP4TW.js} +89 -45
- package/dist/{chunk-IAMOUDHY.js → chunk-AUBB5DLY.js} +24 -15
- package/dist/{chunk-7PEXM2UI.js → chunk-BOD2IQ3P.js} +6 -6
- package/dist/{chunk-D6HU4VUZ.js → chunk-CMGRMPRQ.js} +1 -1
- package/dist/{chunk-MUWVC5R4.js → chunk-DZBXOF5Q.js} +11 -8
- package/dist/{chunk-BO6CY4V2.js → chunk-GEHV7JBS.js} +47 -4
- package/dist/{chunk-R5DC5PEF.js → chunk-GYDROM4W.js} +39 -10
- package/dist/{chunk-TAZZZKYO.js → chunk-HBQWOJRP.js} +1 -1
- package/dist/{chunk-WEZFTL4V.js → chunk-IVRTIKNZ.js} +183 -0
- package/dist/{chunk-P7RCYELG.js → chunk-J2NDOB7D.js} +1 -1
- package/dist/{chunk-T6DVUX4F.js → chunk-J4SYG2LC.js} +14 -3
- package/dist/{chunk-VAI5VOOI.js → chunk-JAKVPLHT.js} +1 -1
- package/dist/{chunk-NPSRGIHV.js → chunk-JWW5YAFL.js} +5 -4
- package/dist/{chunk-FCGJN5Q5.js → chunk-KYTTPWRP.js} +9 -9
- package/dist/{chunk-7YBWXEM6.js → chunk-LL7M7GL4.js} +4 -4
- package/dist/{chunk-SK4FFCFR.js → chunk-MZYD3LFP.js} +1 -1
- package/dist/{chunk-6GU6JSK6.js → chunk-QNQFS37A.js} +3 -3
- package/dist/{chunk-T46BQOLY.js → chunk-RHHCAWW3.js} +3 -3
- package/dist/{chunk-5UXHT6ED.js → chunk-SPR7N2EK.js} +113 -20
- package/dist/{chunk-AHJYP7DG.js → chunk-SYQ3FOLE.js} +74 -17
- package/dist/{chunk-3MP6ACKM.js → chunk-TPGBT5UR.js} +185 -78
- package/dist/{chunk-634DDFT5.js → chunk-TT7P5ZZ3.js} +8 -8
- package/dist/{chunk-D3OEMXYP.js → chunk-XQC6KYZD.js} +12 -7
- package/dist/{chunk-X53JXRS4.js → chunk-YGA52DHX.js} +3 -3
- package/dist/{chunk-5DJOB7IX.js → chunk-ZFA3MZ5N.js} +3 -3
- package/dist/{cloud-REV3DPJH.js → cloud-RFZSO6P5.js} +19 -19
- package/dist/{detect-BBFT5GEU.js → detect-NXD3PYBM.js} +4 -4
- package/dist/{docker-EG3QSE6I.js → docker-U5APUZBI.js} +10 -10
- package/dist/{docker-edge-executor-E5TOTLMR.js → docker-edge-executor-HUQOWFQU.js} +7 -7
- package/dist/{edge-import-YJVJUGYC.js → edge-import-UXD52WQR.js} +26 -26
- package/dist/{edge-preflight-QUW4BM7N.js → edge-preflight-3PMJ5BWM.js} +13 -13
- package/dist/{ensure-container-edge-FOEFQ3PI.js → ensure-container-edge-GDPY7UJD.js} +11 -11
- package/dist/{executor-NTWDJ3DB.js → executor-XOVSO6QZ.js} +6 -6
- package/dist/{host-channel-preflight-OI2TRHSG.js → host-channel-preflight-T2QUDQXU.js} +26 -26
- package/dist/index.js +71 -49
- package/dist/{local-executor-OQ2GRN7K.js → local-executor-KR7BFCJP.js} +3 -3
- package/dist/{nginx-4U4C2XUS.js → nginx-JMLAS7YS.js} +9 -9
- package/dist/{openresty-lua-LLWT5XQW.js → openresty-lua-FJH3KEC4.js} +7 -7
- package/dist/{privilege-MNDVMDST.js → privilege-H2QTJ5TE.js} +5 -5
- package/dist/server/index.js +9627 -4439
- package/dist/server/lua/site_logger.lua +18 -1
- package/dist/server/migrations/0117_github_installation_workspace_scope.sql +24 -0
- package/dist/server/migrations/0118_git_sources.sql +66 -0
- package/dist/server/migrations/0119_backup_run_batch.sql +8 -0
- package/dist/server/migrations/0120_domain_primary_unique.sql +24 -0
- package/dist/server/migrations/0121_host_port_claim_overlap.sql +14 -0
- package/dist/server/migrations/meta/_journal.json +35 -0
- package/dist/{setup-IFIMPQZJ.js → setup-ERGE5XNW.js} +12 -12
- package/dist/{ssh-client-2XWZCMGI.js → ssh-client-WVLLOAYK.js} +2 -2
- package/dist/up-EFCE6KA6.js +61 -0
- package/package.json +1 -1
- package/dist/bare-FA66N7GC.js +0 -29
- package/dist/up-RC5ZQIAD.js +0 -61
|
@@ -5,7 +5,7 @@ const require = __ospCreateRequire(import.meta.url);
|
|
|
5
5
|
import {
|
|
6
6
|
getTarCreateEnv,
|
|
7
7
|
prepareSourceTarArgs
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JAKVPLHT.js";
|
|
9
9
|
import {
|
|
10
10
|
TRANSFER_EXCLUDES,
|
|
11
11
|
nodeBinDirs,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
packageManagerEnsureCommand,
|
|
14
14
|
safeErrorMessage,
|
|
15
15
|
shellQuote
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IVRTIKNZ.js";
|
|
17
17
|
|
|
18
18
|
// ../../packages/adapters/src/runtime/git-clone.ts
|
|
19
19
|
var sq = shellQuote;
|
|
@@ -75,18 +75,48 @@ function assembleGitClone(auth) {
|
|
|
75
75
|
);
|
|
76
76
|
}
|
|
77
77
|
if (auth.gitCredentialHelperPath) {
|
|
78
|
-
|
|
78
|
+
const base = invocation(
|
|
79
79
|
auth.repoUrl,
|
|
80
80
|
[
|
|
81
81
|
TERMINAL_PROMPT,
|
|
82
|
-
|
|
82
|
+
// An empty helper value resets helpers inherited from the host before
|
|
83
|
+
// adding the deployment-scoped relay. Without the reset, a server's
|
|
84
|
+
// stale/global helper can answer first and silently override the
|
|
85
|
+
// forwarded identity named in the deployment log.
|
|
86
|
+
["GIT_CONFIG_COUNT", "3", false],
|
|
83
87
|
["GIT_CONFIG_KEY_0", "credential.helper", false],
|
|
84
|
-
["GIT_CONFIG_VALUE_0",
|
|
85
|
-
["GIT_CONFIG_KEY_1", "credential.
|
|
86
|
-
["GIT_CONFIG_VALUE_1",
|
|
88
|
+
["GIT_CONFIG_VALUE_0", "", true],
|
|
89
|
+
["GIT_CONFIG_KEY_1", "credential.helper", false],
|
|
90
|
+
["GIT_CONFIG_VALUE_1", auth.gitCredentialHelperPath, true],
|
|
91
|
+
["GIT_CONFIG_KEY_2", "credential.useHttpPath", false],
|
|
92
|
+
["GIT_CONFIG_VALUE_2", "true", false]
|
|
87
93
|
],
|
|
88
94
|
false
|
|
89
95
|
);
|
|
96
|
+
let url;
|
|
97
|
+
try {
|
|
98
|
+
url = new URL(auth.repoUrl);
|
|
99
|
+
} catch {
|
|
100
|
+
throw new Error("Git credential forwarding requires an absolute HTTPS repository URL");
|
|
101
|
+
}
|
|
102
|
+
if (url.protocol !== "https:") {
|
|
103
|
+
throw new Error("Git credential forwarding requires an HTTPS repository URL");
|
|
104
|
+
}
|
|
105
|
+
const protocol = url.protocol.slice(0, -1);
|
|
106
|
+
const path = url.pathname.replace(/^\/+/, "");
|
|
107
|
+
const headerVar = "OPENSHIP_GIT_AUTH_HEADER";
|
|
108
|
+
const headerCommand = `${sq(auth.gitCredentialHelperPath)} auth-header ${sq(protocol)} ${sq(url.hostname)} ${sq(path)}`;
|
|
109
|
+
return {
|
|
110
|
+
...base,
|
|
111
|
+
// `auth-header` returns only the Basic header, never prints it to the
|
|
112
|
+
// build log, and keeps the token out of the command text and filesystem.
|
|
113
|
+
// The value exists only in the remote shell/git process for this command.
|
|
114
|
+
shellPrelude: `${headerVar}="$(${headerCommand})" && test -n "$${headerVar}"`,
|
|
115
|
+
// The argv representation above remains a valid challenge-based helper
|
|
116
|
+
// invocation for local spawn users. Remote shell users call
|
|
117
|
+
// gitShellCommand(), which adds the preemptive header as config slot 3.
|
|
118
|
+
gitEnv: `${base.gitEnv.replace("GIT_CONFIG_COUNT=3", "GIT_CONFIG_COUNT=4")} GIT_CONFIG_KEY_3=http.extraHeader GIT_CONFIG_VALUE_3="$${headerVar}"`
|
|
119
|
+
};
|
|
90
120
|
}
|
|
91
121
|
if (auth.ambient) {
|
|
92
122
|
if (auth.ambient.via === "ssh") {
|
|
@@ -112,6 +142,12 @@ function assembleGitClone(auth) {
|
|
|
112
142
|
true
|
|
113
143
|
);
|
|
114
144
|
}
|
|
145
|
+
function gitShellCommand(invocation2, args) {
|
|
146
|
+
const env = invocation2.gitEnv ? `${invocation2.gitEnv} ` : "";
|
|
147
|
+
const flags = invocation2.credFlag ? `${invocation2.credFlag} ` : "";
|
|
148
|
+
const command = `${env}git ${flags}${args}`;
|
|
149
|
+
return invocation2.shellPrelude ? `${invocation2.shellPrelude} && ${command}` : command;
|
|
150
|
+
}
|
|
115
151
|
|
|
116
152
|
// ../../packages/adapters/src/runtime/git-ssh-material.ts
|
|
117
153
|
import { mkdir, rm, writeFile } from "fs/promises";
|
|
@@ -253,31 +289,49 @@ async function runBuildPipeline(env, config, logger) {
|
|
|
253
289
|
config.gitSsh
|
|
254
290
|
);
|
|
255
291
|
}
|
|
256
|
-
const
|
|
292
|
+
const gitInvocation = assembleGitClone({
|
|
257
293
|
repoUrl: config.repoUrl,
|
|
258
294
|
gitToken: config.gitToken,
|
|
259
295
|
gitCredentialHelperPath: config.gitCredentialHelperPath,
|
|
260
296
|
ssh: sshMaterial,
|
|
261
297
|
ambient: config.gitAmbient
|
|
262
298
|
});
|
|
299
|
+
const { cloneUrl, credFlag: CRED } = gitInvocation;
|
|
263
300
|
try {
|
|
264
301
|
if (config.commitSha) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
302
|
+
await exec(
|
|
303
|
+
gitShellCommand(
|
|
304
|
+
gitInvocation,
|
|
305
|
+
`clone --progress --depth 50 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(env.projectDir)}`
|
|
306
|
+
)
|
|
307
|
+
);
|
|
308
|
+
const commitPresent = await exec(
|
|
309
|
+
`cd ${sq(env.projectDir)} && git ${CRED} cat-file -e ${sq(`${config.commitSha}^{commit}`)}`
|
|
310
|
+
).then(
|
|
311
|
+
() => true,
|
|
312
|
+
() => false
|
|
313
|
+
);
|
|
314
|
+
if (!commitPresent) {
|
|
270
315
|
logger.log(
|
|
271
|
-
`
|
|
316
|
+
`Commit ${config.commitSha} is not in the depth-50 clone; fetching full history before checkout.`,
|
|
272
317
|
"warn"
|
|
273
318
|
);
|
|
274
319
|
await exec(
|
|
275
|
-
`cd ${sq(env.projectDir)} && ${
|
|
320
|
+
`cd ${sq(env.projectDir)} && ${gitShellCommand(gitInvocation, "fetch --progress --unshallow")}`
|
|
276
321
|
);
|
|
277
322
|
}
|
|
323
|
+
await exec(
|
|
324
|
+
`cd ${sq(env.projectDir)} && ${gitShellCommand(
|
|
325
|
+
gitInvocation,
|
|
326
|
+
`-c advice.detachedHead=false checkout ${sq(config.commitSha)}`
|
|
327
|
+
)}`
|
|
328
|
+
);
|
|
278
329
|
} else {
|
|
279
330
|
await exec(
|
|
280
|
-
|
|
331
|
+
gitShellCommand(
|
|
332
|
+
gitInvocation,
|
|
333
|
+
`clone --progress --depth 1 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${sq(env.projectDir)}`
|
|
334
|
+
)
|
|
281
335
|
);
|
|
282
336
|
}
|
|
283
337
|
} finally {
|
|
@@ -342,7 +396,9 @@ function parseLogLevel(message) {
|
|
|
342
396
|
function detectBuildKillHint(output) {
|
|
343
397
|
if (!output) return null;
|
|
344
398
|
const tail = output.slice(-4096);
|
|
345
|
-
if (/\bsigkill\b|\bKilled\b|out of memory|JavaScript heap out of memory|Allocation failed/i.test(
|
|
399
|
+
if (/\bsigkill\b|\bKilled\b|out of memory|JavaScript heap out of memory|Allocation failed/i.test(
|
|
400
|
+
tail
|
|
401
|
+
)) {
|
|
346
402
|
return "Build process was killed - typically because the target ran out of memory during the build. Increase RAM on the target, add swap, or build locally and ship the dist.";
|
|
347
403
|
}
|
|
348
404
|
return null;
|
|
@@ -913,6 +969,7 @@ export {
|
|
|
913
969
|
sq,
|
|
914
970
|
injectGitToken,
|
|
915
971
|
assembleGitClone,
|
|
972
|
+
gitShellCommand,
|
|
916
973
|
materializeGitSsh,
|
|
917
974
|
shellGitSshWriter,
|
|
918
975
|
localGitSshWriter,
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
prepareSourceTree,
|
|
10
10
|
resolveDockerBuildArgs,
|
|
11
11
|
resolveServiceDockerfile
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QNQFS37A.js";
|
|
13
13
|
import {
|
|
14
14
|
isArtifactPathRef,
|
|
15
15
|
removeManagedArtifact
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-MZYD3LFP.js";
|
|
17
17
|
import {
|
|
18
18
|
BuildCancelledError,
|
|
19
19
|
BuildLogger,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
dockerBuildContextDirectory,
|
|
23
23
|
droppedRuntimeEnvMessage,
|
|
24
24
|
generateDockerfile,
|
|
25
|
+
gitShellCommand,
|
|
25
26
|
isExcludedDocRootEntry,
|
|
26
27
|
killProcessesUnderDir,
|
|
27
28
|
materializeGitSsh,
|
|
@@ -34,7 +35,7 @@ import {
|
|
|
34
35
|
sq,
|
|
35
36
|
staticBuilderOutputPath,
|
|
36
37
|
transferLocalDirectory
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-SYQ3FOLE.js";
|
|
38
39
|
import {
|
|
39
40
|
DOCKER_DIAL_STDIO_COMMAND,
|
|
40
41
|
attachDialStdioDiagnostics,
|
|
@@ -43,14 +44,14 @@ import {
|
|
|
43
44
|
execSshCommand,
|
|
44
45
|
openDockerDialStdioChannel,
|
|
45
46
|
openSshUnixSocket
|
|
46
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-HBQWOJRP.js";
|
|
47
48
|
import {
|
|
48
49
|
dirOf,
|
|
49
50
|
ensureOwnedDir
|
|
50
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-JWW5YAFL.js";
|
|
51
52
|
import {
|
|
52
53
|
OPENSHIP_LABEL
|
|
53
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-CMGRMPRQ.js";
|
|
54
55
|
import {
|
|
55
56
|
isRuntimeNotFoundError
|
|
56
57
|
} from "./chunk-N5YZMO33.js";
|
|
@@ -64,7 +65,7 @@ import {
|
|
|
64
65
|
registryForImage,
|
|
65
66
|
safeErrorMessage,
|
|
66
67
|
withTimeout
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-IVRTIKNZ.js";
|
|
68
69
|
import {
|
|
69
70
|
__commonJS,
|
|
70
71
|
__require,
|
|
@@ -4630,6 +4631,41 @@ import { createGzip } from "zlib";
|
|
|
4630
4631
|
import { PassThrough, Writable } from "stream";
|
|
4631
4632
|
import { relative, sep } from "path";
|
|
4632
4633
|
|
|
4634
|
+
// ../../packages/adapters/src/runtime/docker-container-info.ts
|
|
4635
|
+
function bindingPriority(ip) {
|
|
4636
|
+
const normalized = ip?.trim().replace(/^\[|\]$/g, "") ?? "";
|
|
4637
|
+
if (normalized === "127.0.0.1" || normalized === "::1") return 3;
|
|
4638
|
+
if (/^127(?:\.\d{1,3}){3}$/.test(normalized)) return 2;
|
|
4639
|
+
if (normalized && normalized !== "0.0.0.0" && normalized !== "::") return 1;
|
|
4640
|
+
return 0;
|
|
4641
|
+
}
|
|
4642
|
+
function dockerPublishedPortInfo(ports) {
|
|
4643
|
+
const selected = /* @__PURE__ */ new Map();
|
|
4644
|
+
for (const binding of ports) {
|
|
4645
|
+
if ((binding.type || "tcp").toLowerCase() !== "tcp") continue;
|
|
4646
|
+
if (!Number.isSafeInteger(binding.privatePort) || binding.privatePort < 1 || binding.privatePort > 65535) {
|
|
4647
|
+
continue;
|
|
4648
|
+
}
|
|
4649
|
+
const hostPort2 = binding.publicPort;
|
|
4650
|
+
if (typeof hostPort2 !== "number" || !Number.isSafeInteger(hostPort2) || hostPort2 < 1 || hostPort2 > 65535) {
|
|
4651
|
+
continue;
|
|
4652
|
+
}
|
|
4653
|
+
const priority = bindingPriority(binding.ip);
|
|
4654
|
+
const previous = selected.get(binding.privatePort);
|
|
4655
|
+
if (!previous || priority > previous.priority) {
|
|
4656
|
+
selected.set(binding.privatePort, { hostPort: hostPort2, priority });
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
const hostPortByContainerPort = Object.fromEntries(
|
|
4660
|
+
[...selected].map(([containerPort, binding]) => [containerPort, binding.hostPort])
|
|
4661
|
+
);
|
|
4662
|
+
const hostPort = selected.values().next().value?.hostPort;
|
|
4663
|
+
return {
|
|
4664
|
+
...hostPort !== void 0 ? { hostPort } : {},
|
|
4665
|
+
...selected.size > 0 ? { hostPortByContainerPort } : {}
|
|
4666
|
+
};
|
|
4667
|
+
}
|
|
4668
|
+
|
|
4633
4669
|
// ../../packages/adapters/src/runtime/docker-auth.ts
|
|
4634
4670
|
import { readFile } from "fs/promises";
|
|
4635
4671
|
import { homedir } from "os";
|
|
@@ -4805,11 +4841,13 @@ function bridgeSocket(socket, leftover) {
|
|
|
4805
4841
|
});
|
|
4806
4842
|
return out;
|
|
4807
4843
|
}
|
|
4808
|
-
function upgradeRequest(conn, path, body) {
|
|
4844
|
+
function upgradeRequest(conn, path, body, opts = {}) {
|
|
4809
4845
|
return new Promise((resolve, reject) => {
|
|
4810
4846
|
const socket = connect(conn);
|
|
4811
4847
|
let settled = false;
|
|
4812
4848
|
let head = Buffer.alloc(0);
|
|
4849
|
+
const protocol = opts.protocol ?? "tcp";
|
|
4850
|
+
const timeoutLabel = opts.timeoutLabel ?? "docker exec";
|
|
4813
4851
|
const fail = (err) => {
|
|
4814
4852
|
if (settled) return;
|
|
4815
4853
|
settled = true;
|
|
@@ -4818,7 +4856,7 @@ function upgradeRequest(conn, path, body) {
|
|
|
4818
4856
|
reject(err);
|
|
4819
4857
|
};
|
|
4820
4858
|
const timer = setTimeout(
|
|
4821
|
-
() => fail(new Error(
|
|
4859
|
+
() => fail(new Error(`${timeoutLabel} upgrade timed out after ${UPGRADE_TIMEOUT_MS}ms`)),
|
|
4822
4860
|
UPGRADE_TIMEOUT_MS
|
|
4823
4861
|
);
|
|
4824
4862
|
const onData = (chunk) => {
|
|
@@ -4827,7 +4865,8 @@ function upgradeRequest(conn, path, body) {
|
|
|
4827
4865
|
const text = head.toString("latin1");
|
|
4828
4866
|
const end = text.indexOf(HEADER_END);
|
|
4829
4867
|
if (end === -1) {
|
|
4830
|
-
if (head.length > 64 * 1024)
|
|
4868
|
+
if (head.length > 64 * 1024)
|
|
4869
|
+
fail(new Error(`${timeoutLabel} upgrade: response head too large`));
|
|
4831
4870
|
return;
|
|
4832
4871
|
}
|
|
4833
4872
|
const statusLine = text.slice(0, text.indexOf("\r\n"));
|
|
@@ -4848,14 +4887,17 @@ function upgradeRequest(conn, path, body) {
|
|
|
4848
4887
|
socket.on("data", onData);
|
|
4849
4888
|
socket.on("error", fail);
|
|
4850
4889
|
socket.on("close", onEarlyClose);
|
|
4890
|
+
const extraHeaders = Object.entries(opts.headers ?? {}).map(([name, value]) => `${name}: ${value}\r
|
|
4891
|
+
`).join("");
|
|
4892
|
+
const contentType = opts.contentType ? `Content-Type: ${opts.contentType}\r
|
|
4893
|
+
` : "";
|
|
4851
4894
|
socket.write(
|
|
4852
4895
|
`POST ${path} HTTP/1.1\r
|
|
4853
4896
|
Host: ${conn.socketPath ? "localhost" : conn.host ?? "localhost"}\r
|
|
4854
|
-
Content-
|
|
4855
|
-
Content-Length: ${Buffer.byteLength(body)}\r
|
|
4897
|
+
` + contentType + `Content-Length: ${Buffer.byteLength(body)}\r
|
|
4856
4898
|
Connection: Upgrade\r
|
|
4857
|
-
Upgrade:
|
|
4858
|
-
|
|
4899
|
+
Upgrade: ${protocol}\r
|
|
4900
|
+
` + extraHeaders + `\r
|
|
4859
4901
|
` + body
|
|
4860
4902
|
);
|
|
4861
4903
|
});
|
|
@@ -4864,7 +4906,8 @@ function startExecStream(conn, execId, opts) {
|
|
|
4864
4906
|
return upgradeRequest(
|
|
4865
4907
|
conn,
|
|
4866
4908
|
`/exec/${execId}/start`,
|
|
4867
|
-
JSON.stringify({ Detach: false, Tty: opts.tty })
|
|
4909
|
+
JSON.stringify({ Detach: false, Tty: opts.tty }),
|
|
4910
|
+
{ contentType: "application/json" }
|
|
4868
4911
|
);
|
|
4869
4912
|
}
|
|
4870
4913
|
function startAttachStream(conn, containerId, opts) {
|
|
@@ -4874,7 +4917,55 @@ function startAttachStream(conn, containerId, opts) {
|
|
|
4874
4917
|
stdout: opts.stdout ? "1" : "0",
|
|
4875
4918
|
stderr: opts.stderr ? "1" : "0"
|
|
4876
4919
|
});
|
|
4877
|
-
return upgradeRequest(conn, `/containers/${containerId}/attach?${q.toString()}`, ""
|
|
4920
|
+
return upgradeRequest(conn, `/containers/${containerId}/attach?${q.toString()}`, "", {
|
|
4921
|
+
contentType: "application/json"
|
|
4922
|
+
});
|
|
4923
|
+
}
|
|
4924
|
+
function startBuildKitSessionStream(conn, sessionId, sessionName) {
|
|
4925
|
+
if (!sessionId || /[\r\n]/.test(sessionId) || /[\r\n]/.test(sessionName)) {
|
|
4926
|
+
return Promise.reject(new Error("Invalid Docker BuildKit session identity"));
|
|
4927
|
+
}
|
|
4928
|
+
return upgradeRequest(conn, "/session", "", {
|
|
4929
|
+
protocol: "h2c",
|
|
4930
|
+
headers: {
|
|
4931
|
+
"X-Docker-Expose-Session-Uuid": sessionId,
|
|
4932
|
+
"X-Docker-Expose-Session-Name": sessionName
|
|
4933
|
+
},
|
|
4934
|
+
timeoutLabel: "Docker BuildKit session"
|
|
4935
|
+
});
|
|
4936
|
+
}
|
|
4937
|
+
var patchedBuildKitModems = /* @__PURE__ */ new WeakSet();
|
|
4938
|
+
function headerValue(headers, name) {
|
|
4939
|
+
if (!headers || typeof headers !== "object") return "";
|
|
4940
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
4941
|
+
if (key.toLowerCase() !== name.toLowerCase()) continue;
|
|
4942
|
+
if (Array.isArray(value)) return value.length > 0 ? String(value[0]) : "";
|
|
4943
|
+
return value == null ? "" : String(value);
|
|
4944
|
+
}
|
|
4945
|
+
return "";
|
|
4946
|
+
}
|
|
4947
|
+
function installDockerodeBuildKitSessionWorkaround(docker) {
|
|
4948
|
+
if (!docker.modem || typeof docker.modem !== "object") return;
|
|
4949
|
+
const modem = docker.modem;
|
|
4950
|
+
if (typeof modem.dial !== "function" || patchedBuildKitModems.has(modem)) return;
|
|
4951
|
+
const originalDial = modem.dial.bind(modem);
|
|
4952
|
+
modem.dial = (options, callback) => {
|
|
4953
|
+
const upgrade = headerValue(options.headers, "upgrade");
|
|
4954
|
+
if (options.path !== "/session" || options.hijack !== true || upgrade.toLowerCase() !== "h2c" || !callback) {
|
|
4955
|
+
return originalDial(options, callback);
|
|
4956
|
+
}
|
|
4957
|
+
const sessionId = headerValue(options.headers, "x-docker-expose-session-uuid");
|
|
4958
|
+
const sessionName = headerValue(options.headers, "x-docker-expose-session-name");
|
|
4959
|
+
void startBuildKitSessionStream(
|
|
4960
|
+
daemonConnectionFrom(docker),
|
|
4961
|
+
sessionId,
|
|
4962
|
+
sessionName || "openship"
|
|
4963
|
+
).then(
|
|
4964
|
+
(socket) => callback(null, socket),
|
|
4965
|
+
(error) => callback(error instanceof Error ? error : new Error(String(error)), null)
|
|
4966
|
+
);
|
|
4967
|
+
};
|
|
4968
|
+
patchedBuildKitModems.add(modem);
|
|
4878
4969
|
}
|
|
4879
4970
|
function daemonConnectionFrom(docker) {
|
|
4880
4971
|
const m = docker.modem ?? {};
|
|
@@ -5113,7 +5204,10 @@ function awaitFirstByte(upstream, ms) {
|
|
|
5113
5204
|
upstream.removeListener("close", onFail);
|
|
5114
5205
|
resolve(outcome);
|
|
5115
5206
|
};
|
|
5116
|
-
const onData = (chunk) =>
|
|
5207
|
+
const onData = (chunk) => {
|
|
5208
|
+
upstream.pause();
|
|
5209
|
+
finish({ kind: "data", chunk });
|
|
5210
|
+
};
|
|
5117
5211
|
const onFail = () => finish({ kind: "closed" });
|
|
5118
5212
|
const timer = setTimeout(() => finish({ kind: "silent" }), ms);
|
|
5119
5213
|
upstream.on("data", onData);
|
|
@@ -5373,7 +5467,9 @@ function createDockerSshBridge(opts) {
|
|
|
5373
5467
|
firstByte.kind === "closed" ? "channel closed before answering" : "channel opened but no data flowed"
|
|
5374
5468
|
);
|
|
5375
5469
|
} catch (err) {
|
|
5376
|
-
console.warn(
|
|
5470
|
+
console.warn(
|
|
5471
|
+
`[docker-ssh] bridge client failed (${opts.host ?? "?"}): ${safeErrorMessage(err)}`
|
|
5472
|
+
);
|
|
5377
5473
|
capture.fail(bridgeFailureReason(opts, safeErrorMessage(err)));
|
|
5378
5474
|
}
|
|
5379
5475
|
};
|
|
@@ -5386,7 +5482,9 @@ function createDockerSshBridge(opts) {
|
|
|
5386
5482
|
void bridgeClient(client);
|
|
5387
5483
|
});
|
|
5388
5484
|
server.on("error", (err) => {
|
|
5389
|
-
console.warn(
|
|
5485
|
+
console.warn(
|
|
5486
|
+
`[docker-ssh] bridge listener error (${opts.host ?? "?"}): ${safeErrorMessage(err)}`
|
|
5487
|
+
);
|
|
5390
5488
|
});
|
|
5391
5489
|
return {
|
|
5392
5490
|
start: () => new Promise((resolve, reject) => {
|
|
@@ -5852,38 +5950,28 @@ function extractNetworkInfo(data) {
|
|
|
5852
5950
|
break;
|
|
5853
5951
|
}
|
|
5854
5952
|
}
|
|
5855
|
-
const hostPortByContainerPort = {};
|
|
5856
|
-
let hostPort;
|
|
5857
5953
|
const liveBindings = data.NetworkSettings?.Ports ?? {};
|
|
5858
5954
|
const configuredBindings = data.HostConfig?.PortBindings ?? {};
|
|
5955
|
+
const publishedPorts = [];
|
|
5859
5956
|
for (const key of /* @__PURE__ */ new Set([...Object.keys(liveBindings), ...Object.keys(configuredBindings)])) {
|
|
5860
5957
|
const [containerRaw, protocol = "tcp"] = key.split("/");
|
|
5861
|
-
if (protocol.toLowerCase() !== "tcp") continue;
|
|
5862
5958
|
const containerPort = Number(containerRaw);
|
|
5863
|
-
if (!Number.isSafeInteger(containerPort) || containerPort < 1 || containerPort > 65535) {
|
|
5864
|
-
continue;
|
|
5865
|
-
}
|
|
5866
5959
|
const live = liveBindings[key];
|
|
5867
5960
|
const bindings = live && live.some((binding) => binding?.HostPort) ? live : configuredBindings[key];
|
|
5868
|
-
const
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
(candidate) => Boolean(candidate)
|
|
5876
|
-
).sort((left, right) => right.priority - left.priority || left.index - right.index);
|
|
5877
|
-
const selected = candidates[0]?.port;
|
|
5878
|
-
if (selected !== void 0) {
|
|
5879
|
-
hostPortByContainerPort[containerPort] = selected;
|
|
5880
|
-
hostPort ??= selected;
|
|
5961
|
+
for (const binding of bindings ?? []) {
|
|
5962
|
+
publishedPorts.push({
|
|
5963
|
+
privatePort: containerPort,
|
|
5964
|
+
publicPort: Number(binding?.HostPort),
|
|
5965
|
+
type: protocol,
|
|
5966
|
+
...binding?.HostIp ? { ip: binding.HostIp } : {}
|
|
5967
|
+
});
|
|
5881
5968
|
}
|
|
5882
5969
|
}
|
|
5970
|
+
const { hostPort, hostPortByContainerPort } = dockerPublishedPortInfo(publishedPorts);
|
|
5883
5971
|
return {
|
|
5884
5972
|
ip,
|
|
5885
5973
|
hostPort,
|
|
5886
|
-
...
|
|
5974
|
+
...hostPortByContainerPort ? { hostPortByContainerPort } : {}
|
|
5887
5975
|
};
|
|
5888
5976
|
}
|
|
5889
5977
|
function parseLoadedImageRef(output) {
|
|
@@ -5988,6 +6076,9 @@ var DockerRuntime = class _DockerRuntime {
|
|
|
5988
6076
|
static async create(opts, systemManager, provisionLock) {
|
|
5989
6077
|
const runtime = new _DockerRuntime(opts, systemManager, provisionLock);
|
|
5990
6078
|
runtime._docker = new Dockerode(await runtime.transport.establish());
|
|
6079
|
+
if (process.versions.bun) {
|
|
6080
|
+
installDockerodeBuildKitSessionWorkaround(runtime._docker);
|
|
6081
|
+
}
|
|
5991
6082
|
return runtime;
|
|
5992
6083
|
}
|
|
5993
6084
|
supports(cap) {
|
|
@@ -6338,48 +6429,64 @@ var DockerRuntime = class _DockerRuntime {
|
|
|
6338
6429
|
config.gitSsh
|
|
6339
6430
|
);
|
|
6340
6431
|
}
|
|
6341
|
-
const {
|
|
6342
|
-
cloneUrl,
|
|
6343
|
-
gitEnv: GIT_ENV,
|
|
6344
|
-
credFlag: CRED
|
|
6345
|
-
} = assembleGitClone({
|
|
6432
|
+
const gitInvocation = assembleGitClone({
|
|
6346
6433
|
repoUrl: config.repoUrl,
|
|
6347
6434
|
gitToken: config.gitToken,
|
|
6348
6435
|
gitCredentialHelperPath: config.gitCredentialHelperPath,
|
|
6349
6436
|
ssh: sshMaterial,
|
|
6350
6437
|
ambient: config.gitAmbient
|
|
6351
6438
|
});
|
|
6439
|
+
const { cloneUrl, credFlag: CRED } = gitInvocation;
|
|
6352
6440
|
const dir = sq(remoteContextDir);
|
|
6353
6441
|
const authLabel = config.gitSsh ? "ssh key" : useHelper ? "forwarded credentials" : config.gitAmbient ? `the server's own git credentials (${config.gitAmbient.via})` : "token";
|
|
6354
6442
|
log.log(`Cloning ${config.repoUrl} on the server \u2192 ${remoteContextDir} (${authLabel})...
|
|
6355
6443
|
`);
|
|
6356
6444
|
await executor.exec(`rm -rf ${dir} && mkdir -p ${dir}`);
|
|
6357
|
-
const run = async (cmd) => {
|
|
6445
|
+
const run = async (operation, cmd) => {
|
|
6358
6446
|
const { code } = await executor.streamExec(
|
|
6359
6447
|
cmd,
|
|
6360
6448
|
(entry) => log.log(entry.message, parseLogLevel(entry.message))
|
|
6361
6449
|
);
|
|
6362
|
-
if (code !== 0) throw new Error(`git
|
|
6450
|
+
if (code !== 0) throw new Error(`git ${operation} on server exited with code ${code}`);
|
|
6363
6451
|
};
|
|
6364
6452
|
try {
|
|
6365
6453
|
if (config.commitSha) {
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6454
|
+
await run(
|
|
6455
|
+
"clone",
|
|
6456
|
+
gitShellCommand(
|
|
6457
|
+
gitInvocation,
|
|
6458
|
+
`clone --progress --depth 50 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${dir}`
|
|
6459
|
+
)
|
|
6460
|
+
);
|
|
6461
|
+
const commitPresent = await executor.exec(`cd ${dir} && git ${CRED} cat-file -e ${sq(`${config.commitSha}^{commit}`)}`).then(
|
|
6462
|
+
() => true,
|
|
6463
|
+
() => false
|
|
6464
|
+
);
|
|
6465
|
+
if (!commitPresent) {
|
|
6371
6466
|
log.log(
|
|
6372
6467
|
`Commit ${config.commitSha} not in the shallow clone; unshallowing and retrying.
|
|
6373
6468
|
`,
|
|
6374
6469
|
"warn"
|
|
6375
6470
|
);
|
|
6376
6471
|
await run(
|
|
6377
|
-
|
|
6472
|
+
"fetch",
|
|
6473
|
+
`cd ${dir} && ${gitShellCommand(gitInvocation, "fetch --progress --unshallow")}`
|
|
6378
6474
|
);
|
|
6379
6475
|
}
|
|
6476
|
+
await run(
|
|
6477
|
+
"checkout",
|
|
6478
|
+
`cd ${dir} && ${gitShellCommand(
|
|
6479
|
+
gitInvocation,
|
|
6480
|
+
`-c advice.detachedHead=false checkout ${sq(config.commitSha)}`
|
|
6481
|
+
)}`
|
|
6482
|
+
);
|
|
6380
6483
|
} else {
|
|
6381
6484
|
await run(
|
|
6382
|
-
|
|
6485
|
+
"clone",
|
|
6486
|
+
gitShellCommand(
|
|
6487
|
+
gitInvocation,
|
|
6488
|
+
`clone --progress --depth 1 --branch ${sq(config.branch)} ${sq(cloneUrl)} ${dir}`
|
|
6489
|
+
)
|
|
6383
6490
|
);
|
|
6384
6491
|
}
|
|
6385
6492
|
await executor.exec(`rm -rf ${sq(`${remoteContextDir}/.git`)}`).catch(() => {
|
|
@@ -8725,12 +8832,6 @@ var DockerRuntime = class _DockerRuntime {
|
|
|
8725
8832
|
const log = onLog ?? (() => {
|
|
8726
8833
|
});
|
|
8727
8834
|
const containerName = `openship-${config.slug}-${config.serviceName}`;
|
|
8728
|
-
try {
|
|
8729
|
-
const existing = this.docker.getContainer(containerName);
|
|
8730
|
-
await gracefulStopForGrace(existing);
|
|
8731
|
-
await existing.remove({ force: true });
|
|
8732
|
-
} catch {
|
|
8733
|
-
}
|
|
8734
8835
|
const serviceEnv = splitRuntimeEnv(config.environment);
|
|
8735
8836
|
if (serviceEnv.dropped.length > 0) {
|
|
8736
8837
|
log({
|
|
@@ -8758,6 +8859,31 @@ var DockerRuntime = class _DockerRuntime {
|
|
|
8758
8859
|
const restartPolicy = resolveRestartPolicy(config.restart);
|
|
8759
8860
|
const healthcheck = toDockerHealthcheck(config.advanced?.healthcheck);
|
|
8760
8861
|
const stopConfig = toStopConfig(config.advanced);
|
|
8862
|
+
if (!config.imageAlreadyPrepared) {
|
|
8863
|
+
try {
|
|
8864
|
+
log({
|
|
8865
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8866
|
+
message: `Pulling image ${config.image}...
|
|
8867
|
+
`,
|
|
8868
|
+
level: "info"
|
|
8869
|
+
});
|
|
8870
|
+
await this.pullImage(config.image, { force: config.forcePull });
|
|
8871
|
+
} catch (err) {
|
|
8872
|
+
log({
|
|
8873
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8874
|
+
message: `Failed to pull ${config.image}: ${err}
|
|
8875
|
+
`,
|
|
8876
|
+
level: "error"
|
|
8877
|
+
});
|
|
8878
|
+
throw err;
|
|
8879
|
+
}
|
|
8880
|
+
}
|
|
8881
|
+
try {
|
|
8882
|
+
const existing = this.docker.getContainer(containerName);
|
|
8883
|
+
await gracefulStopForGrace(existing);
|
|
8884
|
+
await existing.remove({ force: true });
|
|
8885
|
+
} catch {
|
|
8886
|
+
}
|
|
8761
8887
|
log({
|
|
8762
8888
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8763
8889
|
message: `Creating service container ${containerName} from ${config.image}...
|
|
@@ -8787,25 +8913,6 @@ var DockerRuntime = class _DockerRuntime {
|
|
|
8787
8913
|
level: "info"
|
|
8788
8914
|
});
|
|
8789
8915
|
}
|
|
8790
|
-
if (!config.image.startsWith("openship/")) {
|
|
8791
|
-
try {
|
|
8792
|
-
log({
|
|
8793
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
-
message: `Pulling image ${config.image}...
|
|
8795
|
-
`,
|
|
8796
|
-
level: "info"
|
|
8797
|
-
});
|
|
8798
|
-
await this.pullImage(config.image, { force: config.forcePull });
|
|
8799
|
-
} catch (err) {
|
|
8800
|
-
log({
|
|
8801
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8802
|
-
message: `Failed to pull ${config.image}: ${err}
|
|
8803
|
-
`,
|
|
8804
|
-
level: "error"
|
|
8805
|
-
});
|
|
8806
|
-
throw err;
|
|
8807
|
-
}
|
|
8808
|
-
}
|
|
8809
8916
|
const container = await this.docker.createContainer({
|
|
8810
8917
|
name: containerName,
|
|
8811
8918
|
Image: config.image,
|
|
@@ -10,28 +10,28 @@ import {
|
|
|
10
10
|
readComposeEnvFile,
|
|
11
11
|
resolveLocalEnvironmentSync,
|
|
12
12
|
thisHost
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-SPR7N2EK.js";
|
|
14
14
|
import {
|
|
15
15
|
OS_DIR
|
|
16
16
|
} from "./chunk-ELGRMZOW.js";
|
|
17
17
|
import {
|
|
18
18
|
systemCatalog
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-7MKZP4TW.js";
|
|
20
20
|
import {
|
|
21
21
|
EDGE_CONTAINER_MOUNTS,
|
|
22
22
|
EDGE_HOST_STATE_DIR
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-BOD2IQ3P.js";
|
|
24
24
|
import {
|
|
25
25
|
DEFAULT_DOCKER_SOCKET_PATH,
|
|
26
26
|
resolveLocalDockerSocketPath
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-TPGBT5UR.js";
|
|
28
28
|
import {
|
|
29
29
|
LocalExecutor
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-J4SYG2LC.js";
|
|
31
31
|
import {
|
|
32
32
|
invalidateEdgeContainer,
|
|
33
33
|
sanitizeEdgeVhosts
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-YGA52DHX.js";
|
|
35
35
|
import {
|
|
36
36
|
DEFAULT_IMAGE_REGISTRY,
|
|
37
37
|
HOST_CHANNEL_BLOCKED,
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
hostFirewallRule,
|
|
52
52
|
hostFirewallRuleRemoval,
|
|
53
53
|
wrapText
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-IVRTIKNZ.js";
|
|
55
55
|
|
|
56
56
|
// src/lib/host-channel-preflight.ts
|
|
57
57
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
@@ -1627,7 +1627,7 @@ function operatorEnvPassthrough(managed, prev) {
|
|
|
1627
1627
|
}
|
|
1628
1628
|
var PRESERVED_ENV_HEADER = "# Preserved from your existing .env \u2014 set by you, not by `openship up` (#485).";
|
|
1629
1629
|
function resolveImageVersion(opts) {
|
|
1630
|
-
return opts.version?.trim() || process.env.OPENSHIP_VERSION?.trim() || (true ? "0.
|
|
1630
|
+
return opts.version?.trim() || process.env.OPENSHIP_VERSION?.trim() || (true ? "0.7.0" : "latest");
|
|
1631
1631
|
}
|
|
1632
1632
|
function managedEnvLines(opts, host, cfg, prev) {
|
|
1633
1633
|
const lines = [
|