fix: pi container repo mount target and npm update permissions
- Add Alembic migration to update built-in pi-agent manifest:
* repo mount target from /workspace to ~/{{WORKSPACE_NAME}}
* keep /workspace as compatibility symlink via working_dir
* update startup chown target to $HOME/$WORKSPACE_NAME
- Pass REPO_NAME and WORKSPACE_NAME to compile_compose from instance_service
- Substitute {{WORKSPACE_NAME}} in manifest mount targets and expose it as
a container env var so the entrypoint can create the /workspace symlink
- Generate entrypoint workspace symlink from runtime WORKSPACE_NAME env var
- Install npm_global packages into {home_dir}/.npm-global with PATH so the
non-root container user can update global packages
- Update manifest compiler unit tests for the new behavior
Quality gates:
- pytest tests/unit: 207 passed
- ruff: clean on changed files
- mypy: clean on changed files
- alembic heads: single head
This commit is contained in:
@@ -92,7 +92,8 @@ class TestCompileDockerfileHomeDirectory:
|
||||
}
|
||||
dockerfile = compile_dockerfile(manifest)
|
||||
|
||||
assert "ln -sfn /home/custom/{{WORKSPACE_NAME}} /workspace" in dockerfile
|
||||
assert "mkdir -p /home/custom" in dockerfile
|
||||
assert "ln -sfn" in dockerfile
|
||||
|
||||
def test_runtime_working_dir_overrides_home_workdir(self) -> None:
|
||||
manifest = {
|
||||
@@ -168,6 +169,30 @@ class TestCompileComposeHomeDirectory:
|
||||
assert "/host/repos/my-app:/opt/code:ro" in compose
|
||||
assert "/home/custom/my-app" not in compose
|
||||
|
||||
def test_workspace_name_substituted_in_mount_target(self) -> None:
|
||||
manifest = {
|
||||
"base_image": "ubuntu:24.04",
|
||||
"interface_type": "terminal",
|
||||
"home_directory": "/home/custom",
|
||||
"user": {"name": "dev", "uid": 1000, "gid": 1000},
|
||||
"mounts": [
|
||||
{"source_type": "repo", "target": "~/{{WORKSPACE_NAME}}"}
|
||||
],
|
||||
}
|
||||
variables = {
|
||||
"IMAGE_TAG": "test:latest",
|
||||
"INSTANCE_NAME": "test-instance",
|
||||
"REPO_PATH": "/host/repos/my-app",
|
||||
"WORKSPACE_NAME": "my-app",
|
||||
"TOOL_PORT": 0,
|
||||
"EXTRA_ENV": {},
|
||||
"EXTRA_VOLUMES": [],
|
||||
}
|
||||
compose = compile_compose(manifest, variables)
|
||||
|
||||
assert "/host/repos/my-app:/home/custom/my-app" in compose
|
||||
assert "WORKSPACE_NAME: my-app" in compose
|
||||
|
||||
def test_working_dir_expands_home(self) -> None:
|
||||
manifest = {
|
||||
"base_image": "ubuntu:24.04",
|
||||
@@ -190,6 +215,23 @@ class TestCompileComposeHomeDirectory:
|
||||
assert "working_dir: /home/custom/code" in compose
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_compile_dockerfile_uses_user_npm_prefix() -> None:
|
||||
"""npm global packages must be installed into a user-writable prefix."""
|
||||
manifest = {
|
||||
"base_image": "ubuntu:24.04",
|
||||
"interface_type": "terminal",
|
||||
"home_directory": "/home/custom",
|
||||
"user": {"name": "dev", "uid": 1000, "gid": 1000},
|
||||
"packages": {"npm_global": ["@scope/pkg"]},
|
||||
}
|
||||
dockerfile = compile_dockerfile(manifest)
|
||||
|
||||
assert "npm install -g --prefix /home/custom/.npm-global" in dockerfile
|
||||
assert "/home/custom/.npm-global/bin:$PATH" in dockerfile
|
||||
assert "ENV PATH=/home/custom/.npm-global/bin:$PATH" in dockerfile
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestCompileEntrypoint:
|
||||
"""Tests for the generated permission-fixing entrypoint."""
|
||||
@@ -206,6 +248,7 @@ class TestCompileEntrypoint:
|
||||
assert 'mkdir -p "$HOME_DIR"' in entrypoint
|
||||
assert 'mkdir -p "$WORKSPACE_TARGET"' in entrypoint
|
||||
assert 'ln -sfn "$WORKSPACE_TARGET" /workspace' in entrypoint
|
||||
assert 'WORKSPACE_NAME="${WORKSPACE_NAME:-workspace}"' in entrypoint
|
||||
|
||||
def test_entrypoint_fixes_mount_owners(self) -> None:
|
||||
manifest = {
|
||||
|
||||
Reference in New Issue
Block a user