Integrate G15 submodules with Debian 13 packaging and devcontainer
This commit is contained in:
commit
795db7924b
28 files changed
+714
No files matched your search
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
for command in devcontainer docker node; do
|
||||
command -v "$command" >/dev/null || { echo "Required command missing: $command" >&2; exit 1; }
|
||||
done
|
||||
workspace=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
devcontainer up --workspace-folder "$workspace" > "$tmp/up.json"
|
||||
container=$(node -e '
|
||||
const result = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
||||
if (result.outcome !== "success" || !result.containerId) throw Error("CLI startup failed");
|
||||
process.stdout.write(result.containerId);
|
||||
' "$tmp/up.json")
|
||||
docker inspect "$container" > "$tmp/inspect.json"
|
||||
node - "$tmp/inspect.json" "$workspace" <<'NODE'
|
||||
const fs = require('fs');
|
||||
const assert = require('assert/strict');
|
||||
const [container] = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
||||
const host = container.HostConfig;
|
||||
const expected = [];
|
||||
const products = new Set(['c222', 'c225', 'c227', 'c22b', 'c22d', 'c22e']);
|
||||
for (const entry of fs.readdirSync('/sys/bus/usb/devices')) {
|
||||
const base = `/sys/bus/usb/devices/${entry}`;
|
||||
const read = name => fs.readFileSync(`${base}/${name}`, 'utf8').trim();
|
||||
try {
|
||||
if (read('idVendor') !== '046d' || !products.has(read('idProduct'))) continue;
|
||||
const bus = read('busnum'), number = read('devnum');
|
||||
assert.match(bus, /^\d{1,3}$/);
|
||||
assert.match(number, /^\d{1,3}$/);
|
||||
const node = `/dev/bus/usb/${String(Number(bus)).padStart(3, '0')}/${String(Number(number)).padStart(3, '0')}`;
|
||||
if (fs.statSync(node).isCharacterDevice()) expected.push(node);
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') throw error;
|
||||
}
|
||||
}
|
||||
assert.equal(container.State.Running, true, 'container must be running');
|
||||
assert.equal(host.Privileged, false, 'privileged mode forbidden');
|
||||
assert.notEqual(host.NetworkMode, 'host', 'host networking forbidden');
|
||||
assert.deepEqual(host.DeviceCgroupRules || [], [], 'device cgroup overrides forbidden');
|
||||
assert.deepEqual(host.DeviceRequests || [], [], 'additional device requests forbidden');
|
||||
const devices = host.Devices || [];
|
||||
assert.deepEqual(devices.map(device => device.PathOnHost).sort(), expected.sort(),
|
||||
'USB mappings must match current host allowlist; reconnects may require container recreation');
|
||||
for (const device of devices) {
|
||||
assert.equal(device.PathInContainer, device.PathOnHost, 'device remapping forbidden');
|
||||
assert.equal(device.CgroupPermissions, 'rw', 'only rw device access allowed');
|
||||
}
|
||||
// Only the checkout bind and the CLI's optional editor volume are permitted.
|
||||
assert(container.Mounts.some(mount => mount.Type === 'bind' &&
|
||||
mount.Source === process.argv[3] && mount.Destination === '/work'), 'workspace bind missing');
|
||||
for (const mount of container.Mounts) {
|
||||
assert((mount.Type === 'bind' && mount.Source === process.argv[3] && mount.Destination === '/work') ||
|
||||
(mount.Type === 'volume' && mount.Name === 'vscode' && mount.Destination === '/vscode'),
|
||||
`unexpected mount: ${mount.Source} -> ${mount.Destination}`);
|
||||
}
|
||||
console.log(`PASS: real Docker configuration; ${devices.length} exact allowed USB mapping(s)`);
|
||||
NODE
|
||||
# Expand PWD inside the container, not on the host.
|
||||
# shellcheck disable=SC2016
|
||||
devcontainer exec --workspace-folder "$workspace" bash -c \
|
||||
'set -euo pipefail; test "$PWD" = /work; test -f .devcontainer/devcontainer.json; test ! -e /dev/uinput; printf "PASS: CLI exec and no /dev/uinput; no keyboard I/O performed\n"'
|
||||
Reference in new issue
Block a user