openship 0.4.8 → 0.6.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/README.md +27 -1
- package/dist/bare-FSUAM5V5.js +23 -0
- package/dist/{bowser-O3AEA6AN.js → bowser-HNOTPGJO.js} +2 -2
- package/dist/{chunk-5MZ624VX.js → chunk-2GWYYHOR.js} +1 -1
- package/dist/chunk-3FYIXVX5.js +8051 -0
- package/dist/{chunk-ILFETZOM.js → chunk-3LDWWY7U.js} +21 -1
- package/dist/{chunk-W73X43R7.js → chunk-3NQQXMDR.js} +3 -3
- package/dist/{chunk-OWED2GRM.js → chunk-42WQABXM.js} +2 -2
- package/dist/{chunk-TYVME3XD.js → chunk-6FH4AXVY.js} +20 -3
- package/dist/{chunk-OXWDY22G.js → chunk-6ODUBKUB.js} +3 -3
- package/dist/{chunk-DYPH4HCI.js → chunk-AO252K7Z.js} +1 -1
- package/dist/{chunk-XPPZ7B2J.js → chunk-B3CE2OMR.js} +14 -12
- package/dist/{chunk-IXCHURVK.js → chunk-DOD2BXHQ.js} +4 -4
- package/dist/{chunk-VWPEKOH6.js → chunk-DRK3MEDS.js} +3 -3
- package/dist/{chunk-V6AN6XLZ.js → chunk-EMXI4UCU.js} +125 -47
- package/dist/{chunk-GKHUSZCD.js → chunk-EP2TNALB.js} +2 -2
- package/dist/{chunk-SLTYVHU7.js → chunk-GUQ3QCJ7.js} +942 -519
- package/dist/chunk-I3DPMTSF.js +29 -0
- package/dist/{chunk-L2VOGB2X.js → chunk-IW2UKBVF.js} +3 -3
- package/dist/{chunk-VDMQJHPI.js → chunk-IXM5245F.js} +228 -13
- package/dist/{chunk-MZ2WEHHY.js → chunk-JIMUYEKN.js} +4 -4
- package/dist/chunk-OGY63DGD.js +705 -0
- package/dist/{chunk-O6ZZF52V.js → chunk-ONKEYSMY.js} +2 -2
- package/dist/{chunk-6APULWSU.js → chunk-OTLSJYAC.js} +1744 -118
- package/dist/{chunk-EI575GHN.js → chunk-PDW4L3NV.js} +3 -3
- package/dist/{chunk-5NYUCONN.js → chunk-PSZSKEPA.js} +33 -51
- package/dist/{chunk-KI2EY3WB.js → chunk-PXKCZB2I.js} +1 -1
- package/dist/{chunk-FXTBHTWY.js → chunk-QEH4QUBX.js} +649 -85
- package/dist/{chunk-6APIPIJY.js → chunk-QWHBRY2K.js} +5 -5
- package/dist/{chunk-6B5YCFFV.js → chunk-RVER2EOO.js} +5 -5
- package/dist/{chunk-Q2CIRAOK.js → chunk-RXQBD4ZY.js} +1 -1
- package/dist/{chunk-TGIINPVM.js → chunk-TWJCLD4W.js} +60 -10
- package/dist/{chunk-4Z5QO7N6.js → chunk-VDDMADOF.js} +3 -3
- package/dist/{chunk-BBHX7T4R.js → chunk-VE2YOK4I.js} +991 -254
- package/dist/{chunk-2D3I5G6P.js → chunk-VZ2ZHPS2.js} +73 -43
- package/dist/{chunk-AVIB7CT7.js → chunk-WNWQBB7F.js} +2 -2
- package/dist/{chunk-FRNAR33O.js → chunk-XZYFZ6A5.js} +3 -3
- package/dist/{chunk-RPHRPFEH.js → chunk-ZCFVHA25.js} +1 -1
- package/dist/{chunk-FPRHYBY2.js → chunk-ZFJXPCQP.js} +1 -1
- package/dist/{chunk-JYGD5WSN.js → chunk-ZWLDLTJP.js} +1 -1
- package/dist/cloud-E5M6VMCG.js +31 -0
- package/dist/{cloud-7QYOGF7F.js → cloud-KRTZ2IL5.js} +3 -3
- package/dist/{detect-AZLOHUFX.js → detect-ALF4GXRX.js} +7 -8
- package/dist/{dist-IQJ6H6UZ.js → dist-BM6NPWIH.js} +3 -3
- package/dist/{dist-es-X3B5QYKB.js → dist-es-2YRDXMUU.js} +6 -6
- package/dist/{dist-es-OSNJBLXB.js → dist-es-CCVZEFRZ.js} +5 -5
- package/dist/{dist-es-VNKHQVIB.js → dist-es-IOH6G4GM.js} +4 -4
- package/dist/{dist-es-RYHIPOTN.js → dist-es-JGBPABJI.js} +14 -14
- package/dist/{dist-es-JSTDUS7Q.js → dist-es-KWSMDPIP.js} +6 -6
- package/dist/{dist-es-5DY7K32L.js → dist-es-UYDDOVZ3.js} +6 -6
- package/dist/{dist-es-WV4AMOII.js → dist-es-XUOR4NQN.js} +8 -8
- package/dist/docker-QECQJ5P4.js +32 -0
- package/dist/docker-edge-executor-62N64MGS.js +17 -0
- package/dist/edge-import-CQWHN2Q3.js +48 -0
- package/dist/ensure-container-edge-MJVXJQG5.js +32 -0
- package/dist/{event-streams-EHRAKL75.js → event-streams-TR4GAC53.js} +4 -4
- package/dist/{executor-XJ6RP4Q2.js → executor-JELARVKC.js} +8 -8
- package/dist/index.js +1209 -560
- package/dist/{loadSso-46FQRIZS.js → loadSso-UGF4JMRK.js} +10 -10
- package/dist/{local-executor-V7U5VOZW.js → local-executor-WOFZD72X.js} +4 -4
- package/dist/nginx-AXGNWRKZ.js +31 -0
- package/dist/node-entry.js +4 -0
- package/dist/{noop-FMMFG2EZ.js → noop-NJ72F46T.js} +3 -3
- package/dist/openresty-lua-IE4P5YQX.js +81 -0
- package/dist/server/index.js +116248 -94749
- package/dist/server/lua/geo_country.lua +31 -6
- package/dist/server/lua/maxminddb.lua +403 -0
- package/dist/server/lua/mgmt_api.lua +431 -68
- package/dist/server/lua/pipe_log.lua +10 -4
- package/dist/server/lua/site_logger.lua +220 -12
- package/dist/server/migrations/0073_project_volumes_object_storage.sql +3 -0
- package/dist/server/migrations/0074_project_compose_path.sql +1 -0
- package/dist/server/migrations/0075_service_command_argv.sql +1 -0
- package/dist/server/migrations/0076_rollback_retention.sql +17 -0
- package/dist/server/migrations/0077_domain_redirect.sql +13 -0
- package/dist/server/migrations/0078_grant_source_scope.sql +30 -0
- package/dist/server/migrations/0079_project_readiness.sql +18 -0
- package/dist/server/migrations/0080_deployment_error_classification.sql +26 -0
- package/dist/server/migrations/0081_project_readiness_repair.sql +34 -0
- package/dist/server/migrations/0082_edge_target_verification.sql +39 -0
- package/dist/server/migrations/0083_service_incident.sql +84 -0
- package/dist/server/migrations/0084_analytics_daily_rollup.sql +72 -0
- package/dist/server/migrations/0085_resource_usage.sql +68 -0
- package/dist/server/migrations/0086_remote_infra_updates.sql +41 -0
- package/dist/server/migrations/0087_server_container_version_columns.sql +17 -0
- package/dist/server/migrations/0088_audit_source_and_settings.sql +27 -0
- package/dist/server/migrations/0089_auto_scan_infra.sql +7 -0
- package/dist/server/migrations/0090_project_collect_paths.sql +18 -0
- package/dist/server/migrations/0091_project_server_id.sql +26 -0
- package/dist/server/migrations/0092_project_internal_alias.sql +13 -0
- package/dist/server/migrations/0093_service_incident_org_index.sql +13 -0
- package/dist/server/migrations/0094_backup_restore_meta.sql +15 -0
- package/dist/server/migrations/0095_backup_restore_cancel.sql +19 -0
- package/dist/server/migrations/0096_backup_policy_retention_defaults.sql +20 -0
- package/dist/server/migrations/0097_update_status_upstream_only.sql +35 -0
- package/dist/server/migrations/meta/_journal.json +175 -0
- package/dist/setup-FA4PW4NU.js +21 -0
- package/dist/{signin-ITOPKKUB.js → signin-3M3UPB6K.js} +10 -10
- package/dist/{sso-oidc-NON2PD7Y.js → sso-oidc-3VDIYOEJ.js} +10 -10
- package/dist/{sts-HHFFSAY2.js → sts-B3WIYLXR.js} +9 -9
- package/package.json +6 -3
- package/dist/bare-JY5Y5ELU.js +0 -23
- package/dist/chunk-SJIFLLX4.js +0 -2931
- package/dist/chunk-VFINNTUL.js +0 -362
- package/dist/cloud-KYWY3RP4.js +0 -30
- package/dist/docker-LODK5Y2S.js +0 -16
- package/dist/docker-edge-executor-VHW3JPJS.js +0 -13
- package/dist/edge-import-ABUDKKJI.js +0 -45
- package/dist/ensure-container-edge-SW6HENSG.js +0 -31
- package/dist/nginx-3L4SIBJA.js +0 -24
- package/dist/openresty-lua-4WLGDSER.js +0 -42
- package/dist/setup-NU6T2PDU.js +0 -20
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
+
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
+
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
// ../../packages/adapters/src/system/edge-exec-error.ts
|
|
7
|
+
var EDGE_DOWN_MARKER = "the edge container is not running";
|
|
8
|
+
function isEdgeDownFailure(text) {
|
|
9
|
+
return /is restarting, wait until the container is running/i.test(text) || /container .* is not running/i.test(text) || /\bis not running\b/i.test(text) || /No such container/i.test(text) || /container .* is paused/i.test(text) || /invalid PID number/i.test(text);
|
|
10
|
+
}
|
|
11
|
+
function explainEdgeDown(opts) {
|
|
12
|
+
const { container, status, reason } = opts;
|
|
13
|
+
const state = status?.trim() ? ` (${status.trim()})` : "";
|
|
14
|
+
const crashLooping = status?.trim() === "restarting";
|
|
15
|
+
const consequence = crashLooping ? `it is crash-looping, so nothing that runs through the edge on this server can work \u2014 certificate issuance, config reloads and route changes all go through it` : `nothing that runs through the edge on this server can work until it is up \u2014 certificate issuance, config reloads and route changes all go through it`;
|
|
16
|
+
const cause = reason?.trim() ? `OpenResty is refusing to start: ${reason.trim().replace(/\s+/g, " ")}. Fix that, then \`docker start ${container}\` and retry.` : `Run \`docker logs --tail 40 ${container}\` on the server for the reason, then retry.`;
|
|
17
|
+
return `${EDGE_DOWN_MARKER} ("${container}")${state} \u2014 ${consequence}. ${cause}`;
|
|
18
|
+
}
|
|
19
|
+
function edgeDownExplanation(text) {
|
|
20
|
+
if (!text) return null;
|
|
21
|
+
const line = text.split("\n").map((l) => l.trim()).find((l) => l.includes(EDGE_DOWN_MARKER));
|
|
22
|
+
return line || null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
isEdgeDownFailure,
|
|
27
|
+
explainEdgeDown,
|
|
28
|
+
edgeDownExplanation
|
|
29
|
+
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
|
-
":" //# ; exec "$(command -v
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
3
|
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
4
|
const require = __ospCreateRequire(import.meta.url);
|
|
5
5
|
import {
|
|
6
6
|
formatDuration,
|
|
7
7
|
isRemoteConnectionError,
|
|
8
8
|
systemDebug
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZCFVHA25.js";
|
|
10
10
|
import {
|
|
11
11
|
safeErrorMessage
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OTLSJYAC.js";
|
|
13
13
|
|
|
14
14
|
// ../../packages/adapters/src/system/environment.ts
|
|
15
15
|
var profileCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
|
-
":" //# ; exec "$(command -v
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
3
|
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
4
|
const require = __ospCreateRequire(import.meta.url);
|
|
5
5
|
import {
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
resolveProjectDir,
|
|
8
8
|
resolveStaticOutputPath,
|
|
9
9
|
runLocalBuild
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JIMUYEKN.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveEnvironment
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-IW2UKBVF.js";
|
|
14
14
|
import {
|
|
15
15
|
BuildCancelledError,
|
|
16
16
|
BuildLogger,
|
|
@@ -19,32 +19,33 @@ import {
|
|
|
19
19
|
runBuildPipeline,
|
|
20
20
|
sq,
|
|
21
21
|
transferLocalDirectory
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-VDDMADOF.js";
|
|
23
23
|
import {
|
|
24
24
|
formatDuration,
|
|
25
25
|
isRemoteConnectionError,
|
|
26
26
|
isRetryableRemoteConnectionError,
|
|
27
27
|
systemDebug
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-ZCFVHA25.js";
|
|
29
29
|
import {
|
|
30
30
|
LocalExecutor
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6FH4AXVY.js";
|
|
32
|
+
import {
|
|
33
|
+
probeListeningPort
|
|
34
|
+
} from "./chunk-3LDWWY7U.js";
|
|
32
35
|
import {
|
|
33
36
|
sq as sq2,
|
|
34
37
|
wrapLocalBuildCommand
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import {
|
|
37
|
-
probeListeningPort
|
|
38
|
-
} from "./chunk-ILFETZOM.js";
|
|
38
|
+
} from "./chunk-ZFJXPCQP.js";
|
|
39
39
|
import {
|
|
40
40
|
DeployError,
|
|
41
41
|
LANGUAGES,
|
|
42
42
|
STACKS,
|
|
43
|
+
appVolumeTargets,
|
|
43
44
|
buildOutputTransferExcludes,
|
|
44
45
|
missingOutputDirectoryMessage,
|
|
45
46
|
packageManagerEnsureCommand,
|
|
46
47
|
safeErrorMessage
|
|
47
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-OTLSJYAC.js";
|
|
48
49
|
|
|
49
50
|
// ../../packages/adapters/src/system/remote-journal.ts
|
|
50
51
|
var OPSH_RUN_VERSION = 1;
|
|
@@ -996,6 +997,101 @@ async function installTools(executor, toolNames, onLog, requiredVersions) {
|
|
|
996
997
|
return results;
|
|
997
998
|
}
|
|
998
999
|
|
|
1000
|
+
// ../../packages/adapters/src/runtime/supervisor/usage.ts
|
|
1001
|
+
var SAMPLE_MS = 250;
|
|
1002
|
+
var ZERO_USAGE = {
|
|
1003
|
+
cpuPercent: 0,
|
|
1004
|
+
memoryMb: 0,
|
|
1005
|
+
diskMb: 0,
|
|
1006
|
+
networkRxBytes: 0,
|
|
1007
|
+
networkTxBytes: 0
|
|
1008
|
+
};
|
|
1009
|
+
function buildProbe(pid, cgroupCandidates) {
|
|
1010
|
+
const p = sq(String(pid));
|
|
1011
|
+
const cgList = cgroupCandidates.map(sq).join(" ");
|
|
1012
|
+
return [
|
|
1013
|
+
`P=${p}`,
|
|
1014
|
+
// Locate a readable cgroup v2 dir for this unit, if any.
|
|
1015
|
+
`CG=""`,
|
|
1016
|
+
`for c in ${cgList}; do if [ -r "$c/cpu.stat" ]; then CG="$c"; break; fi; done`,
|
|
1017
|
+
// ── cgroup v2 ──
|
|
1018
|
+
`if [ -n "$CG" ]; then`,
|
|
1019
|
+
` C1=$(awk '/^usage_usec/{print $2}' "$CG/cpu.stat" 2>/dev/null)`,
|
|
1020
|
+
` sleep ${(SAMPLE_MS / 1e3).toFixed(3)}`,
|
|
1021
|
+
` C2=$(awk '/^usage_usec/{print $2}' "$CG/cpu.stat" 2>/dev/null)`,
|
|
1022
|
+
` M=$(cat "$CG/memory.current" 2>/dev/null)`,
|
|
1023
|
+
// io.stat is "<maj:min> rbytes=N wbytes=N rios=N wios=N" per device — summed
|
|
1024
|
+
// across devices. Read and write are kept apart so the parser adds each once.
|
|
1025
|
+
` R=$(awk '{for(i=1;i<=NF;i++){split($i,kv,"=");if(kv[1]=="rbytes")r+=kv[2]}}END{print r+0}' "$CG/io.stat" 2>/dev/null)`,
|
|
1026
|
+
` W=$(awk '{for(i=1;i<=NF;i++){split($i,kv,"=");if(kv[1]=="wbytes")w+=kv[2]}}END{print w+0}' "$CG/io.stat" 2>/dev/null)`,
|
|
1027
|
+
` echo "cgroup \${C1:-0} \${C2:-0} \${M:-0} \${R:-0} \${W:-0}"`,
|
|
1028
|
+
// ── /proc/<pid> ──
|
|
1029
|
+
`elif [ -r "/proc/$P/stat" ]; then`,
|
|
1030
|
+
// utime (14) + stime (15) in clock ticks. comm can contain spaces, so cut
|
|
1031
|
+
// everything up to the closing paren before counting fields.
|
|
1032
|
+
` T=$(getconf CLK_TCK 2>/dev/null || echo 100)`,
|
|
1033
|
+
` C1=$(sed 's/.*) //' "/proc/$P/stat" 2>/dev/null | awk -v t="$T" '{print int((($12+$13)/t)*1000000)}')`,
|
|
1034
|
+
` sleep ${(SAMPLE_MS / 1e3).toFixed(3)}`,
|
|
1035
|
+
` C2=$(sed 's/.*) //' "/proc/$P/stat" 2>/dev/null | awk -v t="$T" '{print int((($12+$13)/t)*1000000)}')`,
|
|
1036
|
+
` M=$(awk '/^VmRSS:/{print $2*1024}' "/proc/$P/status" 2>/dev/null)`,
|
|
1037
|
+
` R=$(awk '/^read_bytes:/{print $2}' "/proc/$P/io" 2>/dev/null)`,
|
|
1038
|
+
` W=$(awk '/^write_bytes:/{print $2}' "/proc/$P/io" 2>/dev/null)`,
|
|
1039
|
+
` echo "proc \${C1:-0} \${C2:-0} \${M:-0} \${R:-0} \${W:-0}"`,
|
|
1040
|
+
// ── ps (macOS / no procfs) ──
|
|
1041
|
+
`else`,
|
|
1042
|
+
// ps %cpu is a LIFETIME average, not a rate — reported as-is and flagged by the
|
|
1043
|
+
// `ps` source so the parser doesn't pretend it's an instantaneous sample.
|
|
1044
|
+
` X=$(ps -o rss=,%cpu= -p "$P" 2>/dev/null | awk '{print ($1*1024)" "$2}')`,
|
|
1045
|
+
` echo "ps \${X:-0 0}"`,
|
|
1046
|
+
`fi`
|
|
1047
|
+
].join("; ");
|
|
1048
|
+
}
|
|
1049
|
+
function parseProbe(out) {
|
|
1050
|
+
const parts = out.trim().split(/\s+/);
|
|
1051
|
+
const source = parts[0];
|
|
1052
|
+
const n = (i) => {
|
|
1053
|
+
const v = Number(parts[i]);
|
|
1054
|
+
return Number.isFinite(v) && v >= 0 ? v : 0;
|
|
1055
|
+
};
|
|
1056
|
+
let cpuPercent;
|
|
1057
|
+
let memoryMb;
|
|
1058
|
+
let diskMb = 0;
|
|
1059
|
+
if (source === "ps") {
|
|
1060
|
+
if (parts.length < 3) return { ...ZERO_USAGE, source: "none" };
|
|
1061
|
+
memoryMb = n(1) / (1024 * 1024);
|
|
1062
|
+
cpuPercent = n(2);
|
|
1063
|
+
} else if (source === "cgroup" || source === "proc") {
|
|
1064
|
+
if (parts.length < 6) return { ...ZERO_USAGE, source: "none" };
|
|
1065
|
+
const deltaUsec = Math.max(0, n(2) - n(1));
|
|
1066
|
+
cpuPercent = deltaUsec / (SAMPLE_MS * 1e3) * 100;
|
|
1067
|
+
memoryMb = n(3) / (1024 * 1024);
|
|
1068
|
+
diskMb = (n(4) + n(5)) / (1024 * 1024);
|
|
1069
|
+
} else {
|
|
1070
|
+
return { ...ZERO_USAGE, source: "none" };
|
|
1071
|
+
}
|
|
1072
|
+
return {
|
|
1073
|
+
cpuPercent: Math.round(cpuPercent * 100) / 100,
|
|
1074
|
+
memoryMb: Math.round(memoryMb * 100) / 100,
|
|
1075
|
+
diskMb: Math.round(diskMb * 100) / 100,
|
|
1076
|
+
// Per-process network accounting needs eBPF or a per-unit netns, neither of
|
|
1077
|
+
// which a bare deploy has. Zero here means "not measured", and the dashboard
|
|
1078
|
+
// shows network only for container runtimes.
|
|
1079
|
+
networkRxBytes: 0,
|
|
1080
|
+
networkTxBytes: 0,
|
|
1081
|
+
source
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
async function sampleBareUsage(executor, pid, cgroupCandidates = []) {
|
|
1085
|
+
if (!Number.isInteger(pid) || pid <= 0) return { ...ZERO_USAGE };
|
|
1086
|
+
try {
|
|
1087
|
+
const out = await executor.exec(buildProbe(pid, cgroupCandidates));
|
|
1088
|
+
const { source: _source, ...usage } = parseProbe(out);
|
|
1089
|
+
return usage;
|
|
1090
|
+
} catch {
|
|
1091
|
+
return { ...ZERO_USAGE };
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
999
1095
|
// ../../packages/adapters/src/runtime/supervisor/systemd.ts
|
|
1000
1096
|
var UNIT_PREFIX = "openship";
|
|
1001
1097
|
function escapeSystemdEnvValue(value) {
|
|
@@ -1146,6 +1242,33 @@ ${hint}` : "Process exited immediately after start (no output captured)";
|
|
|
1146
1242
|
return false;
|
|
1147
1243
|
}
|
|
1148
1244
|
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Usage for the unit. Prefers the unit's cgroup, which accounts for the whole
|
|
1247
|
+
* process tree — a `npm start` that forks the real server would otherwise report
|
|
1248
|
+
* only the wrapper's near-zero usage.
|
|
1249
|
+
*
|
|
1250
|
+
* `MainPID` is fetched as the fallback identity (and as the liveness check) for a
|
|
1251
|
+
* host without a readable cgroup; the probe picks the tier itself. `--value` is
|
|
1252
|
+
* used so a stopped unit yields "0" rather than a `MainPID=0` line to parse.
|
|
1253
|
+
*/
|
|
1254
|
+
async getUsage(deploymentId) {
|
|
1255
|
+
const unitName = this.unitName(deploymentId);
|
|
1256
|
+
try {
|
|
1257
|
+
const out = await this.executor.exec(
|
|
1258
|
+
`systemctl show ${sq(unitName)} -p MainPID --value 2>/dev/null || true`
|
|
1259
|
+
);
|
|
1260
|
+
const pid = Number.parseInt(out.trim(), 10);
|
|
1261
|
+
if (!Number.isFinite(pid) || pid <= 0) return { ...ZERO_USAGE };
|
|
1262
|
+
return sampleBareUsage(this.executor, pid, [
|
|
1263
|
+
// Where systemd places a unit started from /etc/systemd/system. The delegate
|
|
1264
|
+
// path appears when the unit sets Delegate=yes; harmless to probe either way.
|
|
1265
|
+
`/sys/fs/cgroup/system.slice/${unitName}`,
|
|
1266
|
+
`/sys/fs/cgroup/system.slice/${unitName}/init.scope`
|
|
1267
|
+
]);
|
|
1268
|
+
} catch {
|
|
1269
|
+
return { ...ZERO_USAGE };
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1149
1272
|
async getLogs(deploymentId, tail) {
|
|
1150
1273
|
const unitName = this.unitName(deploymentId);
|
|
1151
1274
|
const tailArg = tail ? `-n ${tail}` : `-n 200`;
|
|
@@ -1325,6 +1448,19 @@ ${hint}` : "Process exited immediately after spawn (no output captured)";
|
|
|
1325
1448
|
if (!pid) return false;
|
|
1326
1449
|
return this.isAlive(pid);
|
|
1327
1450
|
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Usage for the tracked process.
|
|
1453
|
+
*
|
|
1454
|
+
* No cgroup candidates: nohup does not create one (that's the documented
|
|
1455
|
+
* limitation above), so the probe uses /proc on Linux and `ps` on macOS. Both
|
|
1456
|
+
* measure the LEADER only — a start command that forks will under-report, which
|
|
1457
|
+
* is the same tradeoff as this supervisor's lack of restart and reboot handling.
|
|
1458
|
+
*/
|
|
1459
|
+
async getUsage(deploymentId) {
|
|
1460
|
+
const pid = await this.readPid(deploymentId);
|
|
1461
|
+
if (!pid) return { ...ZERO_USAGE };
|
|
1462
|
+
return sampleBareUsage(this.executor, pid);
|
|
1463
|
+
}
|
|
1328
1464
|
async getLogs(deploymentId, tail) {
|
|
1329
1465
|
const logPath = this.logFile(deploymentId);
|
|
1330
1466
|
try {
|
|
@@ -1385,6 +1521,10 @@ async function probeSystemd(executor) {
|
|
|
1385
1521
|
}
|
|
1386
1522
|
|
|
1387
1523
|
// ../../packages/adapters/src/runtime/bare.ts
|
|
1524
|
+
function parentPath(path) {
|
|
1525
|
+
const idx = path.replace(/\/+$/, "").lastIndexOf("/");
|
|
1526
|
+
return idx > 0 ? path.slice(0, idx) : "/";
|
|
1527
|
+
}
|
|
1388
1528
|
var DEFAULT_WORK_DIR = "/opt/openship";
|
|
1389
1529
|
var DEFAULT_BUILD_TIMEOUT = 10 * 60 * 1e3;
|
|
1390
1530
|
var STATIC_RELEASE_BASE = "/opt/openship/static";
|
|
@@ -1399,8 +1539,17 @@ var BareRuntime = class {
|
|
|
1399
1539
|
"destroy",
|
|
1400
1540
|
"runtimeLogs",
|
|
1401
1541
|
"streamLogs",
|
|
1542
|
+
// Real measurements now (cgroup → /proc → ps, via the supervisor), so this can
|
|
1543
|
+
// finally be declared. It was absent while getUsage returned a zeros stub — but
|
|
1544
|
+
// nothing checked, so callers rendered those zeros as data. Anything reading
|
|
1545
|
+
// usage should gate on supports("usage") rather than trust the numbers.
|
|
1546
|
+
// Network is the one gap: per-process rx/tx needs eBPF or a netns, so it stays 0.
|
|
1547
|
+
"usage",
|
|
1402
1548
|
"containerIp",
|
|
1403
1549
|
"rollback",
|
|
1550
|
+
// The release dir + supervisor unit survive a redeploy, so restoring a
|
|
1551
|
+
// past release really is an in-place unit swap (see makeActive).
|
|
1552
|
+
"unitRestore",
|
|
1404
1553
|
"inContainerExec"
|
|
1405
1554
|
]);
|
|
1406
1555
|
workDir;
|
|
@@ -1466,6 +1615,60 @@ var BareRuntime = class {
|
|
|
1466
1615
|
releaseDir(deploymentId) {
|
|
1467
1616
|
return `${this.workDir}/releases/${deploymentId}`;
|
|
1468
1617
|
}
|
|
1618
|
+
/** Per-project directory holding the paths that must survive a release swap.
|
|
1619
|
+
* The `shared/` half of the Capistrano layout `releases/` already implements. */
|
|
1620
|
+
sharedDir(projectId) {
|
|
1621
|
+
return `${this.workDir}/shared/${projectId}`;
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Repoint the release's persistent paths at `shared/`, so a redeploy doesn't
|
|
1625
|
+
* take the app's data with the old release.
|
|
1626
|
+
*
|
|
1627
|
+
* Docker gets this from a volume; bare has no mount to hang it on, so the
|
|
1628
|
+
* equivalent is the deploy convention: keep the state outside the release tree
|
|
1629
|
+
* and symlink it in. The first release that ships the path SEEDS the shared
|
|
1630
|
+
* copy from it — frameworks ship a skeleton there (Laravel's `storage/` has
|
|
1631
|
+
* `framework/cache`, `framework/sessions`, …) and an app handed an empty
|
|
1632
|
+
* directory instead would fail on write.
|
|
1633
|
+
*
|
|
1634
|
+
* Best-effort per path: a box without the shared dir writable is a storage
|
|
1635
|
+
* problem to report, not a reason to fail an otherwise good release.
|
|
1636
|
+
*/
|
|
1637
|
+
async linkPersistentPaths(releaseDir, projectId, volumes, log) {
|
|
1638
|
+
const targets = appVolumeTargets(volumes ?? []);
|
|
1639
|
+
if (targets.length === 0) return;
|
|
1640
|
+
const shared = this.sharedDir(projectId);
|
|
1641
|
+
for (const relative of targets) {
|
|
1642
|
+
const sharedPath = `${shared}/${relative}`;
|
|
1643
|
+
const releasePath = `${releaseDir}/${relative}`;
|
|
1644
|
+
try {
|
|
1645
|
+
if (!await this.executor.exists(sharedPath)) {
|
|
1646
|
+
await this.executor.mkdir(parentPath(sharedPath));
|
|
1647
|
+
if (await this.executor.exists(releasePath)) {
|
|
1648
|
+
await this.executor.exec(`cp -a ${sq(releasePath)} ${sq(sharedPath)}`);
|
|
1649
|
+
} else {
|
|
1650
|
+
await this.executor.mkdir(sharedPath);
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
await this.executor.rm(releasePath);
|
|
1654
|
+
await this.executor.mkdir(parentPath(releasePath));
|
|
1655
|
+
await this.executor.exec(`ln -sfn ${sq(sharedPath)} ${sq(releasePath)}`);
|
|
1656
|
+
log?.({
|
|
1657
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1658
|
+
message: `Persistent path ${relative} \u2192 ${sharedPath}
|
|
1659
|
+
`,
|
|
1660
|
+
level: "info"
|
|
1661
|
+
});
|
|
1662
|
+
} catch (err) {
|
|
1663
|
+
log?.({
|
|
1664
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1665
|
+
message: `Could not persist ${relative}: ${safeErrorMessage(err)}
|
|
1666
|
+
`,
|
|
1667
|
+
level: "warn"
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1469
1672
|
async promoteBuildArtifact(artifactPath, deploymentId, previousDeploymentId) {
|
|
1470
1673
|
const releaseDir = this.releaseDir(deploymentId);
|
|
1471
1674
|
if (artifactPath === releaseDir) return releaseDir;
|
|
@@ -1727,6 +1930,7 @@ var BareRuntime = class {
|
|
|
1727
1930
|
config.deploymentId,
|
|
1728
1931
|
config.previousDeploymentId
|
|
1729
1932
|
) : stagedDir;
|
|
1933
|
+
await this.linkPersistentPaths(workDir, config.projectId, config.volumes, _onLog);
|
|
1730
1934
|
const sv = await this.supervisor();
|
|
1731
1935
|
const env = {
|
|
1732
1936
|
...Object.fromEntries(
|
|
@@ -1887,8 +2091,19 @@ var BareRuntime = class {
|
|
|
1887
2091
|
const sv = await this.supervisor();
|
|
1888
2092
|
return sv.streamLogs(containerId, onLog, opts);
|
|
1889
2093
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
2094
|
+
/**
|
|
2095
|
+
* CPU / memory / disk-IO for the deployment's process.
|
|
2096
|
+
*
|
|
2097
|
+
* `containerId` is the DEPLOYMENT id here, not a docker container id — that's the
|
|
2098
|
+
* bare runtime's convention throughout (it's what the supervisor keys units and
|
|
2099
|
+
* PID files on).
|
|
2100
|
+
*
|
|
2101
|
+
* The supervisor owns the measurement because the identity differs: systemd has a
|
|
2102
|
+
* unit and a cgroup, nohup has a PID file. Both land on the same probe.
|
|
2103
|
+
*/
|
|
2104
|
+
async getUsage(containerId) {
|
|
2105
|
+
const sv = await this.supervisor();
|
|
2106
|
+
return sv.getUsage(containerId);
|
|
1892
2107
|
}
|
|
1893
2108
|
// ── Network ────────────────────────────────────────────────────────────
|
|
1894
2109
|
async getContainerIp(_containerId) {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
|
-
":" //# ; exec "$(command -v
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
3
|
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
4
|
const require = __ospCreateRequire(import.meta.url);
|
|
5
5
|
import {
|
|
6
6
|
detectBuildKillHint,
|
|
7
7
|
runBuildPipeline,
|
|
8
8
|
transferLocalDirectory
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VDDMADOF.js";
|
|
10
10
|
import {
|
|
11
11
|
LocalExecutor
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6FH4AXVY.js";
|
|
13
13
|
import {
|
|
14
14
|
wrapLocalBuildCommand
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ZFJXPCQP.js";
|
|
16
16
|
|
|
17
17
|
// ../../packages/adapters/src/runtime/local-build.ts
|
|
18
18
|
var LOCAL_BUILD_DIR = "/tmp/openship/.builds";
|