Merge v4-beta to v4 (2026-05-22)#165
Open
dbolotin wants to merge 11 commits into
Open
Conversation
- docker-compose.yaml: replace user: root with user: $PL_UID:$PL_GID (resolved at action-launch time via id -u / id -g). - Add tmpfs /pl-home and HOME=/pl-home so child processes have a writable home without host pollution. - action.yaml: export PL_UID and PL_GID before docker compose up. Switch internal sub-action references from @v4 to @v4-beta to match beta-branch convention; merge-beta.sh restores @v4 at promotion time. Motivation: enable exec.builder writable: false tests in platforma PR #1648 — they require OS file-mode enforcement which root bypasses.
pl entrypoint run-pl.sh runs `id --user --name` under `set -o errexit`. With user: $PL_UID:$PL_GID and no matching entry, the entrypoint aborts immediately. Generate a minimal passwd+group file pair containing root and a synthetic pl user for the resolved UID/GID, then bind-mount them read-only into the container.
pl runs as non-root and cannot mkdir /packages at image root. /storage is bind-mounted from a runner-owned host path and is already writable by the resolved UID/GID.
When platforma runs as non-root and minio stays root, minio writes .minio.sys/tmp/.trash/*.bkp files that the runner cannot remove during cleanup. Switching minio to the same UID/GID keeps every file in PL_MAIN_ROOT owned by the runner — rm -rf cleanup works without sudo.
When platforma runs as non-root and minio stays root, minio writes .minio.sys/tmp/.trash/*.bkp files that the runner cannot remove during cleanup. Switching minio to the same UID/GID keeps every file in PL_MAIN_ROOT owned by the runner — rm -rf cleanup works without sudo.
Comment on lines
3
to
9
| services: | ||
| minio: | ||
| image: quay.io/minio/minio | ||
| # Run as the runner UID/GID — keeps all files in PL_MAIN_ROOT owned by | ||
| # one user so cleanup (rm -rf) works without sudo. | ||
| user: "${PL_UID}:${PL_GID}" | ||
| command: server /data/minio --address "0.0.0.0:9000" --console-address "0.0.0.0:9001" |
There was a problem hiding this comment.
MinIO running as non-root without
/etc/passwd injection
The minio service now runs as ${PL_UID}:${PL_GID} but doesn't have /etc/passwd or /etc/group bind-mounted. If MinIO's startup or any entrypoint script calls id --user --name (or similar), it will fail for the same reason that prompted the passwd injection for the platforma service. This may be intentional if MinIO is known not to need user-name resolution, but it's worth verifying. Has MinIO been confirmed to not require /etc/passwd username resolution when running as a non-default UID?
Prompt To Fix With AI
This is a comment left during a code review.
Path: actions/docker/pl-compose/docker-compose.yaml
Line: 3-9
Comment:
**MinIO running as non-root without `/etc/passwd` injection**
The `minio` service now runs as `${PL_UID}:${PL_GID}` but doesn't have `/etc/passwd` or `/etc/group` bind-mounted. If MinIO's startup or any entrypoint script calls `id --user --name` (or similar), it will fail for the same reason that prompted the passwd injection for the `platforma` service. This may be intentional if MinIO is known not to need user-name resolution, but it's worth verifying. Has MinIO been confirmed to not require `/etc/passwd` username resolution when running as a non-default UID?
How can I resolve this? If you propose a fix, please make it concise.Extract require-latest, the pnpm-workspace/lock drift guard, and the scan-pnpm-repo Trivy scan from build-test-publish into separate preflight and security-scan jobs. Both are non-blocking on PRs and blocking on the default branch and in the merge queue, mirroring the existing check-changesets pattern. build-test-publish gates publish on both via needs + if.
scan-pnpm-repo discovers images via dist/artifacts/*.json which is only populated by the build step. A pre-build security-scan job silently passes in auto-discovery mode (scan_npm_package returns 0 when no images are found and _require_docker=false), making the Trivy gate a no-op. Restore scan-pnpm-repo as a step in build-test-publish after the build. preflight (require-latest + lockfile drift) is unaffected since those checks have no artifact dependency.
…re-latest Surface publish-time gates as PR-visible jobs
The previous single 'preflight' job collapsed both checks under one PR status row, and when require-latest failed the pnpm-lock-sync step was skipped (job-level continue-on-error does not propagate to step ordering inside the job). Split into 'preflight-require-latest' and 'preflight-pnpm-lock-sync' so each surfaces as its own PR-visible check, each carries its own job-level continue-on-error, and a failure in one no longer hides the other. Downstream needs: in pre-calculated-build, build-test-publish, and notify slack release updated to depend on both new jobs. Follow-up to #164.
preflight: split into require-latest and pnpm-lock-sync jobs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge v4-beta into v4
Greptile Summary
This PR switches the Platforma and MinIO containers from running as
rootto running as the GitHub Actions runner's UID/GID, and synthesizes minimal/etc/passwdand/etc/groupfiles so the Platforma entrypoint'sid --user --namecall succeeds. It also relocates--packages-dirfrom the standalone/packagespath to/storage/packages(within the bound storage volume) and adds a tmpfs/pl-homewithHOMEset accordingly.user: \"${PL_UID}:${PL_GID}\"sourced fromid -u/id -gin the launch step; a synthetic passwd+group file is bind-mounted into theplatformacontainer to satisfy entrypoint username lookups.--packages-diris moved from/packagesto/storage/packages, consolidating all mutable state inside the already-boundmain-rootvolume.docker compose logs/downdoes not declarePL_UID,PL_GID,PL_PASSWD_PATH, orPL_GROUP_PATH, so Docker Compose will receive empty values for those variables when parsing the compose file during teardown.Confidence Score: 3/5
The launch path looks correct, but the teardown post-step is missing the newly added env vars, which is likely to break log collection and container shutdown on every run.
The new env vars (PL_UID, PL_GID, PL_PASSWD_PATH, PL_GROUP_PATH) are set only in the launch step's inline shell, not in the GitHub Actions env: block of the post-step. Docker Compose will substitute empty strings when parsing the compose file during teardown, producing an invalid user: ":" directive and empty-source volume mounts, likely preventing docker compose logs and docker compose down from executing cleanly.
The post-step env: block in actions/docker/pl-compose/action.yaml (around line 152) needs the four new variables added.
Important Files Changed
Sequence Diagram
sequenceDiagram participant GHA as GitHub Actions Runner participant Shell as launch-pl step participant Compose as Docker Compose participant MinIO as minio (UID:GID) participant PL as platforma (UID:GID) GHA->>Shell: run launch step Shell->>Shell: "export PL_UID=$(id -u), PL_GID=$(id -g)" Shell->>Shell: mkdir .users/ and write passwd+group files Shell->>Shell: export PL_PASSWD_PATH, PL_GROUP_PATH Shell->>Compose: docker compose up Compose->>MinIO: "start with user=PL_UID:PL_GID" Compose->>PL: "start with user=PL_UID:PL_GID" Compose->>PL: bind-mount /etc/passwd (synthetic) Compose->>PL: bind-mount /etc/group (synthetic) Note over PL: id --user --name resolves to pl PL->>PL: "run with --packages-dir=/storage/packages" Note over GHA,PL: Post-step (teardown) GHA->>Compose: docker compose logs/down (PL_UID/GID/PASSWD/GROUP not in env) Note over Compose: user: colon and empty volume paths may cause config parse errorComments Outside Diff (1)
actions/docker/pl-compose/action.yaml, line 152-176 (link)The post-step that runs
docker compose logs,docker compose images, anddocker compose downdoesn't includePL_UID,PL_GID,PL_PASSWD_PATH, orPL_GROUP_PATH. Docker Compose will substitute empty strings for these, producinguser: ":"(invalid) and volume mounts with empty source paths. This is likely to cause compose config-parsing errors, which would prevent logs from being collected and leave theplatformcontainers running after the job ends.Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "pl-compose: run minio as runner UID/GID ..." | Re-trigger Greptile