Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cdb1710
feature(amd64-ci): First attempt to provide Arm64 CI/dev images
greenc-FNAL Aug 25, 2026
7c0033a
feat(amd64-ci): More execution/revision progress
greenc-FNAL Sep 6, 2026
ad0eb9d
feat(ci): enable ARM64 builds and parameterize GCC/LLVM versions
greenc-FNAL Sep 22, 2026
ab7eaad
build(devcontainer): update base image and npm install command
greenc-FNAL Sep 29, 2026
520fcba
fix(devcontainer): Fix devcontainer build for arm64
greenc-FNAL Sep 29, 2026
aae5136
Latest image for test
greenc-FNAL Oct 1, 2026
49db730
Compatibiility with newer CMake versions
greenc-FNAL Oct 1, 2026
08d5b5b
Delay cleanup for easier debugging
greenc-FNAL Oct 1, 2026
ae651ac
Temporary tweaks to understand target issues
greenc-FNAL Oct 6, 2026
95d6d67
Fix TBB provider selection and related target issues
greenc-FNAL Oct 6, 2026
2d4b8a3
Add specific instructions for multi-arch build/push
greenc-FNAL Oct 7, 2026
d027039
First stage of Arm64 CI integration
greenc-FNAL Oct 7, 2026
87ac89c
ci(coverage): upload architecture-specific coverage reports
greenc-FNAL Oct 8, 2026
6f70c36
fix(ci): promote Phlex dependencies to Spack roots
greenc-FNAL Oct 9, 2026
ac2e349
fix(ci): correct podman commands in multi-arch manifest notes
greenc-FNAL Oct 9, 2026
951aaf2
feat(ci): add generate-image script for podman image builds
greenc-FNAL Oct 9, 2026
5177676
fix(build): repair invalid JSON syntax for CMP0218 policy default
greenc-FNAL Oct 9, 2026
096a47c
Remove unwanted planning/evidence files
greenc-FNAL Oct 12, 2026
b325da7
Update ci/packages.yaml
greenc-FNAL Oct 12, 2026
543dee3
chore: Address CodeRabbit review comments
greenc-FNAL Oct 12, 2026
67353b2
chore: More CodeRabbit review fixes
greenc-FNAL Oct 12, 2026
1791ce8
chore: More CodeRabbit review fixes
greenc-FNAL Oct 12, 2026
db4cfa8
fix(devcontainer): harden relay self-tests and use latest dev image
greenc-FNAL Oct 12, 2026
4657d45
chore: Remove more unwanted AI artifacts
greenc-FNAL Oct 14, 2026
2f4fc82
fix: Self-test must use loopback
greenc-FNAL Oct 14, 2026
1a9eb0a
fix: Remove remaining AI cruft after verifying preservation elsewhere
greenc-FNAL Oct 14, 2026
efe3095
fix: address remaining CodeRabbit review comments
greenc-FNAL Oct 14, 2026
dabeb3e
Institute test coverage mesurement for .devcontainer
greenc-FNAL Oct 14, 2026
efc0b0e
Update .devcontainer/kilo-env-self-test.sh
greenc-FNAL Oct 14, 2026
a22d70f
fix: Remaining CodeRabbit and CodeQL issues
greenc-FNAL Oct 14, 2026
301d056
fix: reformulate checksum handling
greenc-FNAL Oct 14, 2026
e5242ce
docs(devcontainer): clarify self-test execution
greenc-FNAL Oct 20, 2026
31b6d26
docs(cmake): document policy upper bound in cmake_minimum_required
greenc-FNAL Oct 20, 2026
ea7a699
Remove unintentionally-committed change
greenc-FNAL Oct 20, 2026
a3afd2a
Improve `cmake_minimum_required()` comment
greenc-FNAL Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
FROM ghcr.io/framework-r-d/phlex-dev:2026-07-23
ARG PHLEX_DEV_IMAGE=ghcr.io/framework-r-d/phlex-dev:latest
FROM ${PHLEX_DEV_IMAGE}

# Validate Python site-packages symlink.
# Invoke bash explicitly: the script uses bash features (pipefail, arrays,
Expand Down Expand Up @@ -103,7 +104,7 @@ INSTALL_DEV_UTILS

RUN bash <<'INSTALL_NPM_PACKAGES'
set -euo pipefail
npm update -g npm@^11.10.0
npm install -g npm@^11.10.0
npm config set allow-scripts=@kilocode/cli --location=user
npm config set min-release-age=3 --location=user
npm install -g @kilocode/cli
Expand All @@ -117,9 +118,12 @@ RUN printf '. /entrypoint.sh\n' >> /root/.bashrc
# allow GPG agent to function correctly when running as root.
RUN mkdir -p /run/user/0 && chmod 700 /run/user/0 && chown root:root /run/user/0

COPY gitignore-global /root/.gitignore-global
COPY .devcontainer/gitignore-global /root/.gitignore-global
RUN git config --global core.excludesfile '/root/.gitignore-global'

# Install Kilo environment script that sets KILO_CONFIG_CONTENT globally
COPY kilo-env.sh /etc/profile.d/kilo-env.sh
RUN chmod +x /etc/profile.d/kilo-env.sh
# Keep runtime fixes current without rebuilding the expensive Spack base image.
COPY ci/entrypoint.sh /entrypoint.sh
COPY .devcontainer/kilo-env.sh /etc/profile.d/kilo-env.sh
COPY .devcontainer/kilo-env-self-test.sh /usr/local/lib/phlex/kilo-env-self-test.sh
RUN chmod +x /etc/profile.d/kilo-env.sh /usr/local/lib/phlex/kilo-env-self-test.sh
21 changes: 21 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Native macOS Devcontainer

The initializer generates the gitignored `docker-compose.host.yml` before VS Code resolves Compose. On Apple Silicon it requires a running rootless arm64 Podman VM and a locally available Linux/arm64 image, `localhost/phlex-dev:latest` by default. Set `PHLEX_DEV_IMAGE` in the environment launching VS Code to select another image reference. A multi-arch tag or manifest is supported when Podman can resolve its Linux/arm64 member from local storage; the generated Compose service explicitly selects `linux/arm64`. The initializer does not query remote manifests or pull automatically: for a registry image, explicitly run `podman pull --platform linux/arm64 <image-reference>` first. A manifest listing an arm64 member is not sufficient unless that member is available locally. Linux retains the Dockerfile's `ghcr.io/framework-r-d/phlex-dev:latest` default and the engine's native platform selection.

macOS uses pasta networking. Ordinary development does not mount the Podman engine socket or disable SELinux container labeling. Host Kilo configuration and auth inputs are read-only; auth is copied into the container-private data volume when first created.

## Optional Nested Podman

For future in-container `act` use, fully quit VS Code Insiders first, then launch a fresh process from the repository root:

```bash
PHLEX_ENABLE_NESTED_PODMAN=1 code-insiders .
```

Run **Dev Containers: Rebuild and Reopen in Container**. The initializer then mounts the VM's rootless Unix socket at `/tmp/podman.sock`, sets `DOCKER_HOST` and `CONTAINER_HOST`, and adds `security_opt: ["label=disable"]`. This explicitly reduces isolation: the devcontainer can control all containers and resources managed by the VM's rootless engine. The read-only bind mount does not make API operations read-only. No TCP API or macOS Unix-socket relay is used.

To restore the default boundary, quit Insiders, launch it without `PHLEX_ENABLE_NESTED_PODMAN`, and rebuild the devcontainer. Do not edit the generated override; initialization replaces it on each launch.

## Self-tests

`kilo-env-self-test.sh` and `ensure-repos.sh` execute their own unit tests when the `--self-test` option is provided. Fixture listeners, assertions, and test cases are loaded by sourcing the appropriate `*-self-test.sh` file, and the tests executed in lieu of each script executing its production code.
84 changes: 84 additions & 0 deletions .devcontainer/configure-host.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Persist host choices for Compose; initializeCommand exports cannot reach VS Code."""

from __future__ import annotations

import json
import os
import platform
import subprocess
import tempfile
from pathlib import Path


def host_service(system: str, home: Path) -> dict:
"""Use VM paths on macOS, never Unix sockets on the macOS shared filesystem."""
service: dict = {"volumes": []}
image = os.environ.get("PHLEX_DEV_IMAGE")
if system == "Darwin":
info = subprocess.check_output(
[
"podman",
"info",
"--format",
"{{.Host.Arch}} {{.Host.Security.Rootless}} {{.Host.RemoteSocket.Path}}",
],
text=True,
).split()
if len(info) != 3 or info[:2] != ["arm64", "true"]:
raise ValueError(
"macOS development requires a running native arm64 rootless Podman VM"
)
socket = info[2].removeprefix("unix://")
if not socket.startswith("/run/user/") or not socket.endswith("/podman/podman.sock"):
raise ValueError(f"Unexpected rootless VM socket: {socket}")
image = image or "localhost/phlex-dev:latest"
# Podman resolves local manifest lists to their native-platform member.
image_platform = subprocess.check_output(
["podman", "image", "inspect", "--format", "{{.Os}}/{{.Architecture}}", image],
text=True,
).strip()
if image_platform != "linux/arm64":
raise ValueError(
f"{image} does not resolve to a local linux/arm64 image; "
"build natively or explicitly pull its linux/arm64 member first"
)
service["platform"] = "linux/arm64"
service["network_mode"] = "pasta"
if os.environ.get("PHLEX_ENABLE_NESTED_PODMAN") == "1":
# Explicitly opt in to engine control and reduced SELinux isolation.
service["volumes"].append(f"{socket}:/tmp/podman.sock:ro")
service["security_opt"] = ["label=disable"]
else:
proxy_socket = home / ".podman-proxy/podman.sock"
if proxy_socket.exists():
service["volumes"].append(f"{proxy_socket}:/tmp/podman.sock:Z")
if service["volumes"]:
service["environment"] = {
"DOCKER_HOST": "unix:///tmp/podman.sock",
"CONTAINER_HOST": "unix:///tmp/podman.sock",
}
if image:
service["build"] = {"args": {"PHLEX_DEV_IMAGE": image}}
auth = home / ".local/share/kilo/auth.json"
if auth.is_file():
service["volumes"].append(f"{auth}:/run/phlex-host-auth.json:ro,Z")
return service


def main() -> None:
"""Atomically replace the generated, gitignored Compose override."""
target = Path(__file__).with_name("docker-compose.host.yml")
service = host_service(platform.system(), Path.home())
# JSON is also YAML, and safely quotes paths containing spaces or punctuation.
fd, temporary = tempfile.mkstemp(prefix=".compose-host-", dir=target.parent)
try:
with os.fdopen(fd, "w") as output:
output.write(json.dumps({"services": {"phlex-dev": service}}, indent=2) + "\n")
os.replace(temporary, target)
finally:
Path(temporary).unlink(missing_ok=True)


if __name__ == "__main__":
main()
6 changes: 4 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"name": "Phlex CI Dev Container",
"dockerComposeFile": "docker-compose.yml",
"dockerComposeFile": [
"docker-compose.yml",
"docker-compose.host.yml"
],
"service": "phlex-dev",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"remoteUser": "root",
Expand All @@ -25,7 +28,6 @@
"C_Cpp.default.cStandard": "c17",
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
"C_Cpp.default.cppStandard": "c++23",
"C_Cpp.default.intelliSenseMode": "linux-gcc-x64",
"files.watcherExclude": {
"**/.venv/**": true,
"**/py_virtual_env/**": true
Expand Down
12 changes: 5 additions & 7 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,25 @@ version: "3.8"
services:
phlex-dev:
build:
context: .
dockerfile: Dockerfile
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspaces/phlex:Z
- ../../phlex-coding-guidelines:/workspaces/phlex-coding-guidelines:Z
- ../../phlex-design:/workspaces/phlex-design:Z
- ../../phlex-examples:/workspaces/phlex-examples:Z
- ../../phlex-spack-recipes:/workspaces/phlex-spack-recipes:Z
- ${HOME}/.config/gh:/root/.config/gh:ro,Z
- ${HOME}/.config/kilo:/root/.config/kilo:Z
- ${HOME}/.config/kilo:/root/.config/kilo:ro,Z
- ${PHLEX_RELAY_STATE_DIR:-${HOME}/.phlex-devcontainer-tmp/relays}:/run/phlex-host-relays:ro,Z
- ${HOME}/.gnupg:/root/.gnupg:ro,Z
- ${HOME}/.podman-proxy/podman.sock:/tmp/podman.sock:Z
- phlex-kilo-data:/root/.local/share/kilo:Z
- ${HOME}/.local/share/kilo/auth.json:/root/.local/share/kilo/auth.json:ro,Z
- phlex-vscode-user-data:/root/.vscode-server-insiders/data/User:Z
environment:
- CMAKE_GENERATOR=Ninja
- GH_CONFIG_DIR=/root/.config/gh
- DOCKER_HOST=unix:///tmp/podman.sock
- CONTAINER_HOST=unix:///tmp/podman.sock
- GNUPGHOME=/root/.gnupg
- PHLEX_DEFAULT_COMPILER=${PHLEX_DEFAULT_COMPILER:-clang}
user: root
tty: true
stdin_open: true
Expand Down
Loading
Loading