@rainbow-robotics/muscat-plugin-kit 1.3.6-dev.6 → 1.3.6-dev.8
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/cli/README.md +3 -8
- package/cli/bin/muscat-pk.mjs +0 -5
- package/cli/bundle-templates.mjs +1 -6
- package/cli/docker/Dockerfile.cpp +6 -28
- package/cli/docker/Dockerfile.dev +0 -32
- package/cli/docker/Dockerfile.python +0 -19
- package/cli/src/bridge.mjs +12 -45
- package/cli/src/build.mjs +79 -48
- package/cli/src/cpp.mjs +5 -11
- package/cli/src/dev.mjs +2 -7
- package/cli/src/devBack.mjs +40 -97
- package/cli/src/host_agent.py +83 -143
- package/cli/src/manifest.mjs +0 -11
- package/cli/src/mcp.mjs +54 -398
- package/cli/src/new.mjs +3 -13
- package/cli/src/ports.mjs +7 -21
- package/cli/src/python.mjs +20 -16
- package/cli/src/ros2.mjs +8 -16
- package/cli/src/sdk.mjs +21 -23
- package/cli/src/templates-embedded.mjs +4 -0
- package/cli/src/type.mjs +10 -44
- package/cli/src/uninstall.mjs +20 -3
- package/cli/src/update.mjs +8 -14
- package/cli/src/util.mjs +9 -70
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBRangeDateInput.stories.tsx +1 -13
- package/cli/storybook-dist/_stories-src/RBInput/RBSelectBox.stories.tsx +1 -98
- package/cli/storybook-dist/assets/{Color-YHDXOIA2-C5ttlJWI.js → Color-YHDXOIA2-Du8dJ-nM.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-CCfiEyzU.js → Docs--Fm8069p.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-B3AV-YvP.js → Docs-Cb72AJnj.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-BN206lKl.js → Docs-LdjYwuG4.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-BqH2prGO.js → Docs-Sy5RDbtH.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-DhncK7Aw.js → Docs-guGflRzZ.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-CGN1_Ua8.js → Docs-pwGqGTV_.js} +1 -1
- package/cli/storybook-dist/assets/{DocsRenderer-CFRXHY34-D-w8Kq64.js → DocsRenderer-CFRXHY34-YGBLQ4BD.js} +1 -1
- package/cli/storybook-dist/assets/{NxAvatar.stories-oCcYtLwq.js → NxAvatar.stories-C1d4n8cq.js} +1 -1
- package/cli/storybook-dist/assets/{NxButton.stories-C5jUScIj.js → NxButton.stories-gCBoZdMq.js} +1 -1
- package/cli/storybook-dist/assets/{NxIcons.stories-DeqrVzVs.js → NxIcons.stories-Dg42riT5.js} +1 -1
- package/cli/storybook-dist/assets/{NxNumberInput.stories-gjsEulIN.js → NxNumberInput.stories-DB-vLM2J.js} +1 -1
- package/cli/storybook-dist/assets/{NxPagination.stories-BK6uSWIa.js → NxPagination.stories-CS8iMIak.js} +1 -1
- package/cli/storybook-dist/assets/{NxPointerHoldButton.stories-BDD5CvSZ.js → NxPointerHoldButton.stories-D66BopeS.js} +1 -1
- package/cli/storybook-dist/assets/{NxRangeInput.stories-C_nW26_x.js → NxRangeInput.stories-CZxddsJ2.js} +3 -3
- package/cli/storybook-dist/assets/{NxSelectBox.stories-DqLfKU9H.js → NxSelectBox.stories-CmezGGrm.js} +1 -1
- package/cli/storybook-dist/assets/{NxSlideRange.stories-CQjHA8yv.js → NxSlideRange.stories-CGAFMITi.js} +1 -1
- package/cli/storybook-dist/assets/{NxSwitch.stories-BMHCiPoL.js → NxSwitch.stories-B3QInkXX.js} +1 -1
- package/cli/storybook-dist/assets/{NxTextArea.stories-k7r1WVQh.js → NxTextArea.stories-BgJcgZNe.js} +1 -1
- package/cli/storybook-dist/assets/{NxTextInput.stories-Cqfe1I32.js → NxTextInput.stories-CwMQwI9L.js} +1 -1
- package/cli/storybook-dist/assets/{RBAccordion.stories-CJ3Ttuja.js → RBAccordion.stories-BuBVNzJT.js} +1 -1
- package/cli/storybook-dist/assets/{RBAccordionGroup.stories-BThv7tM0.js → RBAccordionGroup.stories-Crdb6kFF.js} +1 -1
- package/cli/storybook-dist/assets/{RBAlert.stories-CSMP8Vun.js → RBAlert.stories-CqXgUvA2.js} +1 -1
- package/cli/storybook-dist/assets/{RBBadge.stories-cBMA2R6F.js → RBBadge.stories-BCw_ksML.js} +1 -1
- package/cli/storybook-dist/assets/{RBBattery.stories-BKVOskqs.js → RBBattery.stories-0id4XYoc.js} +1 -1
- package/cli/storybook-dist/assets/{RBCard.stories-BTOfK0HC.js → RBCard.stories-CgpG-7Lk.js} +1 -1
- package/cli/storybook-dist/assets/{RBCheckBox.stories-DyE912wG.js → RBCheckBox.stories-BG02BoGX.js} +1 -1
- package/cli/storybook-dist/assets/{RBCheckIconButton.stories-0sLFU0kM.js → RBCheckIconButton.stories-vrjD4GQ4.js} +1 -1
- package/cli/storybook-dist/assets/{RBCheckLabelButton.stories-c8VecClE.js → RBCheckLabelButton.stories-POba8lU-.js} +1 -1
- package/cli/storybook-dist/assets/{RBChipTab.stories-CQ9Uav5_.js → RBChipTab.stories-XWJbFrHF.js} +1 -1
- package/cli/storybook-dist/assets/{RBChipsBoxTab.stories-Ap4NlhAZ.js → RBChipsBoxTab.stories-BdU0Dzdp.js} +1 -1
- package/cli/storybook-dist/assets/{RBColorIcons.stories-BPPXjif2.js → RBColorIcons.stories-C_0dCNXG.js} +1 -1
- package/cli/storybook-dist/assets/{RBCommand.stories-PDpYOKlm.js → RBCommand.stories-Dvrko5No.js} +1 -1
- package/cli/storybook-dist/assets/{RBConfirm.stories-BEWvMAYP.js → RBConfirm.stories-CkTn0sHa.js} +1 -1
- package/cli/storybook-dist/assets/{RBDateInput.stories-DLdyNnVF.js → RBDateInput.stories-BH3D08cs.js} +1 -1
- package/cli/storybook-dist/assets/{RBDialog.stories-HsawMNOb.js → RBDialog.stories-C2nNX9fl.js} +1 -1
- package/cli/storybook-dist/assets/{RBDivider.stories-dlWwOxik.js → RBDivider.stories-D-GrJ0QZ.js} +1 -1
- package/cli/storybook-dist/assets/{RBDrawer.stories-C87iqGk0.js → RBDrawer.stories-XLOnLOnh.js} +1 -1
- package/cli/storybook-dist/assets/{RBDropdownMenu.stories-B8EQhA0z.js → RBDropdownMenu.stories-BjBSeoV2.js} +1 -1
- package/cli/storybook-dist/assets/{RBEmptyView.stories-SzpIhNDw.js → RBEmptyView.stories-C6U2zKNE.js} +1 -1
- package/cli/storybook-dist/assets/{RBIconButton.stories-BQ0nM1gb.js → RBIconButton.stories-MCJq5Hta.js} +1 -1
- package/cli/storybook-dist/assets/{RBIcons.stories-C19g5M5z.js → RBIcons.stories-DxOCiCe0.js} +1 -1
- package/cli/storybook-dist/assets/{RBInlineLabelButton.stories-DbgI4-1P.js → RBInlineLabelButton.stories-BVZi1aEs.js} +1 -1
- package/cli/storybook-dist/assets/{RBJoyStick.stories-smF-vpGL.js → RBJoyStick.stories-BDThbEek.js} +1 -1
- package/cli/storybook-dist/assets/{RBLabelButton.stories-s53klwDv.js → RBLabelButton.stories-CaPEKUS6.js} +1 -1
- package/cli/storybook-dist/assets/{RBLight.stories-BnzkoR51.js → RBLight.stories-CihQzyEL.js} +1 -1
- package/cli/storybook-dist/assets/{RBMenubar.stories-CW014klu.js → RBMenubar.stories-J852XVFh.js} +1 -1
- package/cli/storybook-dist/assets/{RBMultiRangeInput.stories-qa4tH_4Y.js → RBMultiRangeInput.stories-DXyX0cOZ.js} +1 -1
- package/cli/storybook-dist/assets/{RBPagination.stories-YoQNUpQH.js → RBPagination.stories-C9_49ymO.js} +1 -1
- package/cli/storybook-dist/assets/{RBPopover.stories-Bhpi0OaH.js → RBPopover.stories-DxLE912-.js} +1 -1
- package/cli/storybook-dist/assets/{RBPrompt.stories-iQM5iAka.js → RBPrompt.stories-DlsfGqWb.js} +1 -1
- package/cli/storybook-dist/assets/{RBRadioBox.stories-BGyq4rzx.js → RBRadioBox.stories-hb5cNWW1.js} +1 -1
- package/cli/storybook-dist/assets/{RBRadioButton.stories-DF6BcUcJ.js → RBRadioButton.stories-CSuOgeN-.js} +1 -1
- package/cli/storybook-dist/assets/RBRangeDateInput.stories-KRg2glX8.js +15 -0
- package/cli/storybook-dist/assets/{RBResizable.stories-DSVHvwjp.js → RBResizable.stories-BetjF9vG.js} +1 -1
- package/cli/storybook-dist/assets/RBSelectBox.stories-ILLQQ8M8.js +6 -0
- package/cli/storybook-dist/assets/{RBSheet.stories-CAK9hb-p.js → RBSheet.stories-D3QbcMKq.js} +1 -1
- package/cli/storybook-dist/assets/{RBSideNumberInput.stories-DUymnH-9.js → RBSideNumberInput.stories-DcTh0IjM.js} +1 -1
- package/cli/storybook-dist/assets/{RBSlider.stories-BwlDh9--.js → RBSlider.stories-B59We7ei.js} +1 -1
- package/cli/storybook-dist/assets/{RBSpinner.stories-VOlkuP6t.js → RBSpinner.stories-9u3_ETbi.js} +1 -1
- package/cli/storybook-dist/assets/{RBSwitch.stories-BiW2dQnT.js → RBSwitch.stories-DrVm1WGX.js} +1 -1
- package/cli/storybook-dist/assets/{RBTab.stories-DFKVsy0C.js → RBTab.stories-D8Dm7cRW.js} +1 -1
- package/cli/storybook-dist/assets/{RBTable.stories-BWG0ZSYI.js → RBTable.stories-dRdZ8g1j.js} +1 -1
- package/cli/storybook-dist/assets/{RBTableRow.stories-JVTD83Mh.js → RBTableRow.stories-rZeoGwHZ.js} +1 -1
- package/cli/storybook-dist/assets/{RBTabs.stories-D-aN385u.js → RBTabs.stories-STRV2lgO.js} +1 -1
- package/cli/storybook-dist/assets/{RBTextArea.stories-Dx5xkmZS.js → RBTextArea.stories-CfgUbrbJ.js} +1 -1
- package/cli/storybook-dist/assets/{RBTextField.stories-DmVciExd.js → RBTextField.stories-B5t8-Y97.js} +1 -1
- package/cli/storybook-dist/assets/{RBTextInput.stories-CCf0VGEv.js → RBTextInput.stories-Bf1edN6l.js} +1 -1
- package/cli/storybook-dist/assets/{RBToast.stories-DT0DGn05.js → RBToast.stories-Cnm8JwQ6.js} +1 -1
- package/cli/storybook-dist/assets/{RBToggle.stories-Ce_q3EtP.js → RBToggle.stories-B0OCo6zd.js} +1 -1
- package/cli/storybook-dist/assets/{RBToggleGroup.stories-CN40YHsR.js → RBToggleGroup.stories-GdYO2Fxg.js} +1 -1
- package/cli/storybook-dist/assets/{RBTooltip.stories-L7btDEpA.js → RBTooltip.stories-DXJTCScO.js} +1 -1
- package/cli/storybook-dist/assets/SideNumberInput-CrF-a1Nr.js +1114 -0
- package/cli/storybook-dist/assets/browserUtils-CxJ5gea3.js +1 -0
- package/cli/storybook-dist/assets/{entry-preview-D_nGAXUk.js → entry-preview-DSRwIaVJ.js} +1 -1
- package/cli/storybook-dist/assets/{iframe-23VS_ZeI.js → iframe-Cj53Wn3d.js} +2 -2
- package/cli/storybook-dist/assets/{index-ClAc6FBW.js → index-C1OzuK6-.js} +1 -1
- package/cli/storybook-dist/assets/{index-Ckae_HWe.js → index-CkHtLEe8.js} +3 -3
- package/cli/storybook-dist/assets/preview-CEfMaO1t.css +1 -0
- package/cli/storybook-dist/assets/{preview-BVJwlGUF.js → preview-CILRoSnB.js} +1 -1
- package/cli/storybook-dist/assets/{preview-CD0LINug.js → preview-CgOtgtCD.js} +2 -2
- package/cli/storybook-dist/assets/preview-D_2um8Sd.js +3 -0
- package/cli/storybook-dist/assets/react-resizable-panels.browser-CtORL3tG.js +102 -0
- package/cli/storybook-dist/iframe.html +1 -1
- package/cli/storybook-dist/index.html +1 -1
- package/cli/storybook-dist/index.json +1 -1
- package/cli/storybook-dist/project.json +1 -1
- package/cli/templates/common/README.md +7 -211
- package/cli/templates/common/py/main.py +2 -29
- package/cli/templates/common/requirements.txt +3 -3
- package/cli/templates/cpp/cpp/CMakeLists.txt +7 -6
- package/cli/templates/cpp/cpp/main.cpp +10 -57
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/CMakeLists.txt +0 -4
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/src/node.cpp +4 -5
- package/package.json +3 -3
- package/cli/storybook-dist/assets/RBRangeDateInput.stories-COOQ_HNF.js +0 -15
- package/cli/storybook-dist/assets/RBSelectBox.stories-BookV8Sm.js +0 -74
- package/cli/storybook-dist/assets/SideNumberInput-B5_xLK8z.js +0 -1109
- package/cli/storybook-dist/assets/browserUtils-CQM9Za7e.js +0 -1
- package/cli/storybook-dist/assets/preview-P8yWWsME.js +0 -3
- package/cli/storybook-dist/assets/preview-zuAvMksL.css +0 -1
- package/cli/storybook-dist/assets/react-resizable-panels.browser-CYcsrUgg.js +0 -120
- package/cli/templates/readme-cpp/README.md +0 -993
package/cli/src/ports.mjs
CHANGED
|
@@ -4,15 +4,7 @@ import { usesHostNetwork } from "./zenohDev.mjs";
|
|
|
4
4
|
|
|
5
5
|
export const PLUGIN_PORT_MIN = 28600;
|
|
6
6
|
export const PLUGIN_PORT_MAX = 28999;
|
|
7
|
-
export const
|
|
8
|
-
export const INTERNAL_DEV_PORTS = new Set([10000, ...MEDIA_PORTS]);
|
|
9
|
-
|
|
10
|
-
export function mediaPortFlags() {
|
|
11
|
-
return [
|
|
12
|
-
"-p", "127.0.0.1:8554:8554", "-p", "127.0.0.1:8889:8889",
|
|
13
|
-
"-p", "127.0.0.1:8189:8189/udp", "-p", "127.0.0.1:8189:8189/tcp",
|
|
14
|
-
];
|
|
15
|
-
}
|
|
7
|
+
export const INTERNAL_DEV_PORTS = new Set([10000]);
|
|
16
8
|
export const RESERVED_BACKEND_PORTS = new Map([
|
|
17
9
|
[502, "Modbus TCP"],
|
|
18
10
|
[4840, "OPC-UA"],
|
|
@@ -126,21 +118,14 @@ export function publishPortFlags(ranges = []) {
|
|
|
126
118
|
return ranges.flatMap((port) => ["-p", `127.0.0.1:${port}:${port}`]);
|
|
127
119
|
}
|
|
128
120
|
|
|
129
|
-
// Skips OS-assigned loopback listeners (127.0.0.1:0, e.g. the SDK's Zenoh session).
|
|
130
121
|
function listeningTcpPorts(container) {
|
|
131
122
|
const script = `
|
|
132
|
-
read -r eph_lo eph_hi < /proc/sys/net/ipv4/ip_local_port_range 2>/dev/null || { eph_lo=32768; eph_hi=60999; }
|
|
133
123
|
for f in /proc/net/tcp /proc/net/tcp6; do
|
|
134
124
|
[ -r "$f" ] || continue
|
|
135
125
|
tail -n +2 "$f" | while read -r sl local_address rem_address st rest; do
|
|
136
126
|
[ "$st" = "0A" ] || continue
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
case "$hex_ip" in
|
|
140
|
-
0100007F|00000000000000000000000001000000)
|
|
141
|
-
[ "$port" -ge "$eph_lo" ] && [ "$port" -le "$eph_hi" ] && continue ;;
|
|
142
|
-
esac
|
|
143
|
-
echo "$port"
|
|
127
|
+
hex_port="\${local_address##*:}"
|
|
128
|
+
printf "%d\\n" "0x$hex_port"
|
|
144
129
|
done
|
|
145
130
|
done | sort -n -u
|
|
146
131
|
`;
|
|
@@ -156,9 +141,10 @@ done | sort -n -u
|
|
|
156
141
|
}
|
|
157
142
|
|
|
158
143
|
export function startPortContractMonitor({ container, ranges, log, intervalMs = 1000, allow = [] }) {
|
|
159
|
-
// Under --network host
|
|
160
|
-
// host/robot service port, not just the plugin's —
|
|
161
|
-
|
|
144
|
+
// Under --network host the container shares the host's netns, so
|
|
145
|
+
// /proc/net/tcp shows every host/robot service port, not just the plugin's —
|
|
146
|
+
// the contract can't be enforced. Skip it (no isolated ports to police).
|
|
147
|
+
if (usesHostNetwork()) return () => false;
|
|
162
148
|
const declared = ranges ?? [];
|
|
163
149
|
// muscat-pk's own dev plumbing shares this netns — not the plugin's doing.
|
|
164
150
|
const ignored = new Set([...INTERNAL_DEV_PORTS, ...allow.map(Number).filter(Number.isInteger)]);
|
package/cli/src/python.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Shared Python Docker helpers (Ubuntu 24.04 + Python 3.12 — matches the robot).
|
|
2
2
|
// Used by dev:back (hot-reload) and build (lock + wheel vendor).
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { existsSync
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
5
|
import { dirname, resolve } from "node:path";
|
|
6
|
-
import { canSkipImageBuild,
|
|
6
|
+
import { canSkipImageBuild, dockerUserFlags, hasBin, log, pruneMuskatImages, resolveDockerfile } from "./util.mjs";
|
|
7
7
|
|
|
8
8
|
export const PYTHON_DEV_IMAGE = "muscat-pk-python-dev";
|
|
9
9
|
|
|
@@ -15,17 +15,16 @@ export function assertDockerReady() {
|
|
|
15
15
|
|
|
16
16
|
/** Build the dev image from the kit's bundled Dockerfile (Docker layer-caches). */
|
|
17
17
|
export async function ensureImage(image = PYTHON_DEV_IMAGE, { platform = null } = {}) {
|
|
18
|
-
|
|
19
|
-
const key = imageKey(dockerfile);
|
|
20
|
-
if (canSkipImageBuild(image, key)) {
|
|
18
|
+
if (canSkipImageBuild(image)) {
|
|
21
19
|
log.step(`${image} already built — skipping docker build`);
|
|
22
20
|
return;
|
|
23
21
|
}
|
|
22
|
+
const dockerfile = await resolveDockerfile("Dockerfile.python");
|
|
24
23
|
log.step(`docker build -t ${image}${platform ? ` (${platform})` : ""} (first run is slow, then cached)…`);
|
|
25
24
|
const platformFlags = platform ? ["--platform", platform] : [];
|
|
26
25
|
const r = spawnSync(
|
|
27
26
|
"docker",
|
|
28
|
-
["build", ...platformFlags,
|
|
27
|
+
["build", ...platformFlags, "-t", image, "-f", dockerfile, dirname(dockerfile)],
|
|
29
28
|
{ stdio: "inherit" },
|
|
30
29
|
);
|
|
31
30
|
if (r.status !== 0) throw new Error("docker build failed.");
|
|
@@ -66,11 +65,7 @@ export async function lockAndVendor(pluginRoot, archs = ["amd64", "arm64"]) {
|
|
|
66
65
|
|
|
67
66
|
await ensureImage();
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
// pre-releases too; uv rejects those transitive pre-releases unless allowed.
|
|
71
|
-
const reqText = readFileSync(resolve(pluginRoot, "requirements.txt"), "utf8");
|
|
72
|
-
const prerelease = /==\s*\S*\d(a|b|rc|\.dev)\d*\s*$/im.test(reqText) ? " --prerelease=allow" : "";
|
|
73
|
-
log.step(`generating lock (uv pip compile${prerelease})…`);
|
|
68
|
+
log.step("generating lock (uv pip compile)…");
|
|
74
69
|
const lockResult = spawnSync(
|
|
75
70
|
"docker",
|
|
76
71
|
[
|
|
@@ -79,16 +74,17 @@ export async function lockAndVendor(pluginRoot, archs = ["amd64", "arm64"]) {
|
|
|
79
74
|
"-v", `${pluginRoot}:/plugin`,
|
|
80
75
|
PYTHON_DEV_IMAGE,
|
|
81
76
|
"bash", "-c",
|
|
82
|
-
"set -e && cd /plugin && mkdir -p dist && uv pip compile requirements.txt --python-version 3.12 -o dist/requirements.lock"
|
|
77
|
+
"set -e && cd /plugin && mkdir -p dist && uv pip compile requirements.txt --python-version 3.12 -o dist/requirements.lock",
|
|
83
78
|
],
|
|
84
79
|
{ stdio: "inherit" },
|
|
85
80
|
);
|
|
86
81
|
if (lockResult.status !== 0) throw new Error("lock generation failed (uv pip compile)");
|
|
87
82
|
log.ok("dist/requirements.lock ready");
|
|
88
83
|
|
|
84
|
+
const failed = [];
|
|
89
85
|
for (const arch of archs) {
|
|
90
86
|
const pipPlatforms = PIP_PLATFORM[arch];
|
|
91
|
-
if (!pipPlatforms)
|
|
87
|
+
if (!pipPlatforms) { log.warn(`unknown arch '${arch}' — skipped`); continue; }
|
|
92
88
|
log.step(`vendoring wheels for ${arch}…`);
|
|
93
89
|
const r = spawnSync(
|
|
94
90
|
"docker",
|
|
@@ -106,8 +102,16 @@ export async function lockAndVendor(pluginRoot, archs = ["amd64", "arm64"]) {
|
|
|
106
102
|
],
|
|
107
103
|
{ stdio: "inherit" },
|
|
108
104
|
);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
if (r.status !== 0) {
|
|
106
|
+
log.warn(`wheel vendoring failed for ${arch}`);
|
|
107
|
+
failed.push(arch);
|
|
108
|
+
} else {
|
|
109
|
+
log.ok(`dist/wheels/ ready (${arch})`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (failed.length === archs.length) {
|
|
114
|
+
throw new Error(`wheel vendoring failed for all archs: ${failed.join(", ")}`);
|
|
112
115
|
}
|
|
116
|
+
return failed;
|
|
113
117
|
}
|
package/cli/src/ros2.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { existsSync, readdirSync } from "node:fs";
|
|
5
5
|
import { dirname, resolve } from "node:path";
|
|
6
|
-
import { canSkipImageBuild,
|
|
6
|
+
import { canSkipImageBuild, hasBin, log, pruneMuskatImages, resolveDockerfile } from "./util.mjs";
|
|
7
7
|
|
|
8
8
|
export const ROS2_DEV_IMAGE = "muscat-pk-ros2-dev";
|
|
9
9
|
|
|
@@ -30,19 +30,16 @@ export const ARCH_DOCKER_PLATFORM = {
|
|
|
30
30
|
|
|
31
31
|
/** Build the dev image from the kit's bundled Dockerfile (Docker layer-caches). */
|
|
32
32
|
export async function ensureImage(image = ROS2_DEV_IMAGE, { platform = null } = {}) {
|
|
33
|
-
|
|
34
|
-
const sdkVer = process.env.MUSCAT_PK_RB_SDK_VERSION;
|
|
35
|
-
const key = imageKey(dockerfile, sdkVer ?? "");
|
|
36
|
-
if (canSkipImageBuild(image, key)) {
|
|
33
|
+
if (canSkipImageBuild(image)) {
|
|
37
34
|
log.step(`${image} already built — skipping docker build`);
|
|
38
35
|
return;
|
|
39
36
|
}
|
|
37
|
+
const dockerfile = await resolveDockerfile("Dockerfile.dev");
|
|
40
38
|
log.step(`docker build -t ${image}${platform ? ` (${platform})` : ""} (first run is slow, then cached)…`);
|
|
41
39
|
const platformFlags = platform ? ["--platform", platform] : [];
|
|
42
|
-
const buildArgs = [...(sdkVer ? ["--build-arg", `RB_SDK_VERSION=${sdkVer}`] : []), ...imageKeyLabel(key)];
|
|
43
40
|
const r = spawnSync(
|
|
44
41
|
"docker",
|
|
45
|
-
["build", ...platformFlags,
|
|
42
|
+
["build", ...platformFlags, "-t", image, "-f", dockerfile, dirname(dockerfile)],
|
|
46
43
|
{ stdio: "inherit" },
|
|
47
44
|
);
|
|
48
45
|
if (r.status !== 0) throw new Error("docker build failed.");
|
|
@@ -74,16 +71,12 @@ export function colconBuild(root, { image = ROS2_DEV_IMAGE, symlink = false, arc
|
|
|
74
71
|
installBase = "../dist/ros2_ws/install";
|
|
75
72
|
}
|
|
76
73
|
const flag = symlink ? "--symlink-install" : "";
|
|
77
|
-
const buildBase = symlink ? "build" : arch ? `build-${arch}` : "build-dist";
|
|
78
74
|
const script = [
|
|
79
75
|
"pip install -r requirements.txt --break-system-packages --ignore-installed -q || true",
|
|
80
76
|
"cd ros2_ws",
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`colcon build ${flag} --build-base ${buildBase} --install-base ${installBase}`.replace(" ", " ") +
|
|
85
|
-
(arch ? ` --cmake-args '-DCMAKE_INSTALL_RPATH=$ORIGIN/..'` : ""),
|
|
86
|
-
...(arch ? [`for d in ${installBase}/*/lib; do if readelf -d $(find "$d" -mindepth 2 -type f -executable) 2>/dev/null | grep -q librb_sdk; then cp -a $(dpkg -L rainbow-rb-sdk | grep -E '/librb_sdk[.]so[.][0-9]') "$d"/; fi; done`] : []),
|
|
77
|
+
// ponytail: rm only on cross-arch; same-arch dev rebuilds keep the cache
|
|
78
|
+
...(arch ? ["rm -rf build"] : []),
|
|
79
|
+
`colcon build ${flag} --install-base ${installBase}`.trim(),
|
|
87
80
|
].join(" && ");
|
|
88
81
|
const label = arch
|
|
89
82
|
? `colcon build (${arch}) → dist/ros2_ws/install-${arch}/…`
|
|
@@ -94,8 +87,7 @@ export function colconBuild(root, { image = ROS2_DEV_IMAGE, symlink = false, arc
|
|
|
94
87
|
const platformFlags = dockerPlatform ? ["--platform", dockerPlatform] : [];
|
|
95
88
|
const r = spawnSync(
|
|
96
89
|
"docker",
|
|
97
|
-
|
|
98
|
-
["run", "--rm", ...platformFlags, ...dockerUserFlags(), "-e", "PIP_ROOT_USER_ACTION=ignore", "-v", `${root}:/plugin`, "-w", "/plugin", actualImage, "bash", "-lc", script],
|
|
90
|
+
["run", "--rm", ...platformFlags, "-e", "PIP_ROOT_USER_ACTION=ignore", "-v", `${root}:/plugin`, "-w", "/plugin", actualImage, "bash", "-lc", script],
|
|
99
91
|
{ cwd: root, stdio: "inherit" },
|
|
100
92
|
);
|
|
101
93
|
if (r.status !== 0) throw new Error(`colcon build failed${arch ? ` (${arch})` : ""}.`);
|
package/cli/src/sdk.mjs
CHANGED
|
@@ -6,24 +6,24 @@
|
|
|
6
6
|
// the new version immediately; this is best-effort only.
|
|
7
7
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { resolve } from "node:path";
|
|
9
|
-
import {
|
|
9
|
+
import { spawnSync } from "node:child_process";
|
|
10
|
+
import { findPluginRoot, log, venvPython } from "./util.mjs";
|
|
10
11
|
|
|
11
12
|
const PKG = "rainbow-rb-sdk";
|
|
12
13
|
|
|
13
|
-
async function
|
|
14
|
+
async function fetchVersions() {
|
|
14
15
|
try {
|
|
15
16
|
const res = await fetch(`https://pypi.org/pypi/${PKG}/json`);
|
|
16
|
-
|
|
17
|
+
if (!res.ok) return [];
|
|
18
|
+
const data = await res.json();
|
|
19
|
+
return Object.keys(data.releases || {}).sort((a, b) =>
|
|
20
|
+
b.localeCompare(a, undefined, { numeric: true }),
|
|
21
|
+
);
|
|
17
22
|
} catch {
|
|
18
|
-
return
|
|
23
|
+
return [];
|
|
19
24
|
}
|
|
20
25
|
}
|
|
21
26
|
|
|
22
|
-
async function fetchVersions() {
|
|
23
|
-
const data = await fetchPypi();
|
|
24
|
-
return Object.keys(data?.releases || {}).sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
27
|
export async function runSdk(args = []) {
|
|
28
28
|
const sub = args[0];
|
|
29
29
|
const root = findPluginRoot();
|
|
@@ -42,25 +42,23 @@ export async function runSdk(args = []) {
|
|
|
42
42
|
if (sub === "update") {
|
|
43
43
|
let version = args[1];
|
|
44
44
|
if (!version) {
|
|
45
|
-
|
|
46
|
-
version =
|
|
47
|
-
if (!version) throw new Error("could not fetch the latest version (offline?). Pass one: muscat-pk sdk update <version>");
|
|
45
|
+
const versions = await fetchVersions();
|
|
46
|
+
version = versions[0] || "latest";
|
|
48
47
|
}
|
|
49
|
-
// rainbow-rb-* pin each other exactly — bump them together.
|
|
50
48
|
let content = existsSync(reqs) ? readFileSync(reqs, "utf8") : "";
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
content = (content ? content.trimEnd() + "\n" : "") +
|
|
56
|
-
bumped.push(PKG);
|
|
49
|
+
const line = `${PKG}==${version}`;
|
|
50
|
+
if (new RegExp(`^${PKG}==`, "m").test(content)) {
|
|
51
|
+
content = content.replace(new RegExp(`^${PKG}==.*$`, "m"), line);
|
|
52
|
+
} else {
|
|
53
|
+
content = (content ? content.trimEnd() + "\n" : "") + line + "\n";
|
|
57
54
|
}
|
|
58
55
|
writeFileSync(reqs, content);
|
|
59
|
-
log.ok(`requirements.txt → ${
|
|
56
|
+
log.ok(`requirements.txt → ${line}`);
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
const py = venvPython(resolve(root, ".venv"));
|
|
59
|
+
if (existsSync(py)) {
|
|
60
|
+
log.step("pip install -r requirements.txt (.venv, for your editor)…");
|
|
61
|
+
spawnSync(py, ["-m", "pip", "install", "-q", "-r", reqs], { cwd: root, stdio: "inherit" });
|
|
64
62
|
} else {
|
|
65
63
|
log.info("Installed automatically on the next `muscat-pk dev` / `dev:back` (Docker container).");
|
|
66
64
|
}
|