@pablozaiden/devbox 0.1.4 → 0.1.5
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 +2 -0
- package/dist/devbox.js +62 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@ It does not modify the original `devcontainer.json`. Instead, it generates a der
|
|
|
12
12
|
- Publishes the same TCP port on host and container.
|
|
13
13
|
- Mounts the current directory into the container as the workspace.
|
|
14
14
|
- Shares a usable SSH agent socket with the container and copies `known_hosts` into the container.
|
|
15
|
+
- Seeds the container user's global Git `user.name` and `user.email` from the host when available.
|
|
15
16
|
- Runs the [`ssh-server-runner`](https://github.com/PabloZaiden/ssh-server-runner) one-liner inside the devcontainer.
|
|
16
17
|
- Persists the runner credentials on the mounted workspace as a local `.sshcred` file, and keeps SSH host keys in `.devbox-ssh-host-keys/`, so they survive `down` / `rebuild`.
|
|
17
18
|
|
|
@@ -108,6 +109,7 @@ cd examples/smoke-workspace
|
|
|
108
109
|
- When Docker Desktop host services are available, `devbox` can share the SSH agent without relying on a host-shell `SSH_AUTH_SOCK`.
|
|
109
110
|
- On Docker Desktop, `devbox` prefers the Docker-provided SSH agent socket over the host `SSH_AUTH_SOCK`, which avoids macOS launchd socket mount issues.
|
|
110
111
|
- `--allow-missing-ssh` starts the workspace without mounting an SSH agent and prints a warning instead of failing.
|
|
112
|
+
- When the host already has Git author identity configured, `devbox` copies it into the container user's global Git config if the container does not already define those values.
|
|
111
113
|
|
|
112
114
|
## Releasing to npm
|
|
113
115
|
|
package/dist/devbox.js
CHANGED
|
@@ -1350,6 +1350,25 @@ function buildAssertConfiguredSshAuthSockScript() {
|
|
|
1350
1350
|
].join(`
|
|
1351
1351
|
`);
|
|
1352
1352
|
}
|
|
1353
|
+
function buildConfigureGitIdentityScript(input) {
|
|
1354
|
+
const commands = [];
|
|
1355
|
+
if (input.gitUserName) {
|
|
1356
|
+
commands.push('current_git_user_name="$(git config --global --get user.name 2>/dev/null || true)"', 'if [ -z "$current_git_user_name" ]; then', ` git config --global user.name ${quoteShell(input.gitUserName)}`, "fi");
|
|
1357
|
+
}
|
|
1358
|
+
if (input.gitUserEmail) {
|
|
1359
|
+
commands.push('current_git_user_email="$(git config --global --get user.email 2>/dev/null || true)"', 'if [ -z "$current_git_user_email" ]; then', ` git config --global user.email ${quoteShell(input.gitUserEmail)}`, "fi");
|
|
1360
|
+
}
|
|
1361
|
+
if (commands.length === 0) {
|
|
1362
|
+
return null;
|
|
1363
|
+
}
|
|
1364
|
+
return [
|
|
1365
|
+
"if ! command -v git >/dev/null 2>&1; then",
|
|
1366
|
+
" exit 0",
|
|
1367
|
+
"fi",
|
|
1368
|
+
...commands
|
|
1369
|
+
].join(`
|
|
1370
|
+
`);
|
|
1371
|
+
}
|
|
1353
1372
|
function buildInteractiveShellScript() {
|
|
1354
1373
|
return [
|
|
1355
1374
|
"if command -v bash >/dev/null 2>&1; then",
|
|
@@ -1415,13 +1434,21 @@ async function ensureHostEnvironment(options) {
|
|
|
1415
1434
|
}
|
|
1416
1435
|
const hostEnvSshAuthSock = process.env.SSH_AUTH_SOCK?.trim() || undefined;
|
|
1417
1436
|
const hostEnvSockExists = hostEnvSshAuthSock ? await pathExists(hostEnvSshAuthSock) : false;
|
|
1418
|
-
const dockerDesktopHostServiceAvailable = await
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1437
|
+
const [dockerDesktopHostServiceAvailable, gitUserName, gitUserEmail] = await Promise.all([
|
|
1438
|
+
hasDockerDesktopHostService(),
|
|
1439
|
+
tryGetGitConfig(options.workspacePath, "user.name"),
|
|
1440
|
+
tryGetGitConfig(options.workspacePath, "user.email")
|
|
1441
|
+
]);
|
|
1442
|
+
return {
|
|
1443
|
+
...resolveSshAuthSockSource({
|
|
1444
|
+
hostEnvSshAuthSock,
|
|
1445
|
+
hostEnvSockExists,
|
|
1446
|
+
dockerDesktopHostServiceAvailable,
|
|
1447
|
+
allowMissingSsh: options.allowMissingSsh
|
|
1448
|
+
}),
|
|
1449
|
+
gitUserName,
|
|
1450
|
+
gitUserEmail
|
|
1451
|
+
};
|
|
1425
1452
|
}
|
|
1426
1453
|
async function ensureGeneratedConfigIgnored(workspacePath, generatedConfigPath) {
|
|
1427
1454
|
await ensurePathIgnored(workspacePath, generatedConfigPath);
|
|
@@ -1527,6 +1554,13 @@ async function copyKnownHosts(containerId) {
|
|
|
1527
1554
|
const script = `if [ -f ${quoteShell(KNOWN_HOSTS_TARGET)} ]; then umask 077 && mkdir -p ~/.ssh && cp ${quoteShell(KNOWN_HOSTS_TARGET)} ~/.ssh/known_hosts && chmod 600 ~/.ssh/known_hosts; fi`;
|
|
1528
1555
|
await devcontainerExec(containerId, script, { quiet: true });
|
|
1529
1556
|
}
|
|
1557
|
+
async function configureGitIdentity(containerId, gitUserName, gitUserEmail) {
|
|
1558
|
+
const script = buildConfigureGitIdentityScript({ gitUserName, gitUserEmail });
|
|
1559
|
+
if (!script) {
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
await devcontainerExec(containerId, script, { quiet: true });
|
|
1563
|
+
}
|
|
1530
1564
|
async function stopManagedSshd(containerId) {
|
|
1531
1565
|
await devcontainerExec(containerId, buildStopManagedSshdScript(), { quiet: true });
|
|
1532
1566
|
}
|
|
@@ -1652,6 +1686,22 @@ async function tryGetGitTopLevel(workspacePath) {
|
|
|
1652
1686
|
return null;
|
|
1653
1687
|
}
|
|
1654
1688
|
}
|
|
1689
|
+
async function tryGetGitConfig(workspacePath, key) {
|
|
1690
|
+
if (!isExecutableAvailable("git")) {
|
|
1691
|
+
return null;
|
|
1692
|
+
}
|
|
1693
|
+
const result = await execute(["git", "config", "--get", key], {
|
|
1694
|
+
cwd: workspacePath,
|
|
1695
|
+
stdoutMode: "capture",
|
|
1696
|
+
stderrMode: "capture",
|
|
1697
|
+
allowFailure: true
|
|
1698
|
+
});
|
|
1699
|
+
if (result.exitCode !== 0) {
|
|
1700
|
+
return null;
|
|
1701
|
+
}
|
|
1702
|
+
const trimmed = result.stdout.trim();
|
|
1703
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1704
|
+
}
|
|
1655
1705
|
async function findListeningPids(port) {
|
|
1656
1706
|
if (isExecutableAvailable("lsof")) {
|
|
1657
1707
|
const result = await execute(["lsof", "-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-t"], {
|
|
@@ -1863,7 +1913,7 @@ async function main() {
|
|
|
1863
1913
|
await handleUpLike(parsed.command, workspacePath, state, parsed.port, parsed.allowMissingSsh, parsed.devcontainerSubpath);
|
|
1864
1914
|
}
|
|
1865
1915
|
async function handleUpLike(command, workspacePath, state, explicitPort, allowMissingSsh, devcontainerSubpath) {
|
|
1866
|
-
const environment = await ensureHostEnvironment({ allowMissingSsh });
|
|
1916
|
+
const environment = await ensureHostEnvironment({ allowMissingSsh, workspacePath });
|
|
1867
1917
|
const port = resolvePort(command, explicitPort, state);
|
|
1868
1918
|
const knownHostsPath = await getKnownHostsPath();
|
|
1869
1919
|
const discovered = await discoverDevcontainerConfig(workspacePath, devcontainerSubpath);
|
|
@@ -1922,6 +1972,10 @@ async function handleUpLike(command, workspacePath, state, explicitPort, allowMi
|
|
|
1922
1972
|
await assertConfiguredSshAuthSockAvailable(upResult.containerId);
|
|
1923
1973
|
}
|
|
1924
1974
|
await copyKnownHosts(upResult.containerId);
|
|
1975
|
+
if (environment.gitUserName || environment.gitUserEmail) {
|
|
1976
|
+
console.log("Syncing Git author identity from the host into the devcontainer...");
|
|
1977
|
+
await configureGitIdentity(upResult.containerId, environment.gitUserName, environment.gitUserEmail);
|
|
1978
|
+
}
|
|
1925
1979
|
await stopManagedSshd(upResult.containerId);
|
|
1926
1980
|
await restoreRunnerHostKeys(upResult.containerId, remoteWorkspaceFolder);
|
|
1927
1981
|
console.log("Installing and starting the SSH server inside the container (first run can take a bit)...");
|