Skip to content

fix: restore build and Kubernetes conformance for core v0.3.0 (#7) - #8

Merged
antoinetoussaint-byte merged 4 commits into
mainfrom
issue-7-chore-fix-test-failures-before-release
Aug 18, 2026
Merged

fix: restore build and Kubernetes conformance for core v0.3.0 (#7)#8
antoinetoussaint-byte merged 4 commits into
mainfrom
issue-7-chore-fix-test-failures-before-release

Conversation

@antoinetoussaint-byte

@antoinetoussaint-byteantoinetoussaint-byte commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Closes#7.

Summary

  • The core v0.3.0 upgrade left the test suite red at several layers; each fix (compile → conformance → container runtime → CI tooling → generated-service tests) uncovered the next. This PR takes CI from a non-compiling package to fully green (ci / build and ci / test).
  • The upgrade also surfaced two real, previously-masked bugs that would hit actual Linux users: a deploy manifest that Kubernetes rejects, and generated services whose tests hang forever.

Changes

  • Build: pass the RuntimeContext argument now required by network.GenerateNetworkMappings (main_test.go).
  • Kubernetes conformance: harden deployment.yaml.tmpl for the EPHEMERAL_LOCAL_APPLY_V1 and restricted profiles (pod/container securityContext, resource bounds, probes, terminationGracePeriodSeconds, automountServiceAccountToken, digest-pinned image, secretKeyRef secrets); label the Namespace app.kubernetes.io/managed-by: codefly; elide the inline Secret under restricted profiles.
  • Deployability: pin the workload to numeric UID 1000 (Deployment runAsUser + Dockerfile adduser -u 1000) — runAsNonRoot with a non-numeric image user is rejected by the kubelet at admission. Give the read-only container writable scratch: bounded emptyDir at /tmp + HOME=/tmp.
  • Container runtime: run the runtime container as the invoking host user (WithUser). As root, uv sync wrote uv.lock/venv into the bind mount as root, so a second Init on a non-root host (Linux CI) failed hashing uv.lock with "permission denied". A dedicated host-owned UV_CACHE_DIR mount keeps uv's cache writable for that user.
  • Generated service tests: guard codefly.init() in the generated main.py and make the generated admin test hermetic. codefly-sdk's manifest lookup walks parents without stopping at /, so it spins forever when service.codefly.yaml is absent — exactly what core's snapshot-based test runner creates. This hung runtime.Test indefinitely.
  • CI: install uv via the shared workflow's setup-run hook; the Python runtime's Test step drives uv on the host.

Risks

  • readOnlyRootFilesystem: true is now enforced (required by the conformance contract). /tmp is writable via the bounded emptyDir and HOME points there; a service that writes elsewhere on the root FS would need its own volume.
  • The generated main.py no longer calls codefly.init() unconditionally at import — it only initializes when the manifest is reachable, relying on CODEFLY__* env vars otherwise (how the runtime already supplies config).

Test plan

  • go build ./..., go vet ./..., go mod tidy -diff clean
  • Unit + conformance: TestDeploymentTemplates (all three profiles), composition, transport-neutrality — pass; regression asserts on runAsUser, /tmp mount + bound, and HOME
  • TestCreateToRunDocker full lifecycle (create → run → run-again → in-container pytest) passes locally (66s) and on CI
  • ci / build and ci / test green on GitHub Actions

Restore the build and Kubernetes conformance after the core v0.3.0 upgrade:
- Pass the RuntimeContext argument now required by
network.GenerateNetworkMappings in the create-to-run test.
- Harden the deployment template to satisfy the
KUBERNETES_OUTPUT_PROFILE_EPHEMERAL_LOCAL_APPLY_V1 and restricted
conformance profiles: pod/container securityContext, resource bounds,
liveness/readiness/startup probes, terminationGracePeriodSeconds and
automountServiceAccountToken, digest-pinned image, and secretKeyRef-based
secret injection under restricted profiles.
- Pin the workload to numeric UID 1000 (deployment runAsUser + Dockerfile
adduser). Kubernetes' runAsNonRoot admission check rejects a container
whose image user is a non-numeric name, so runAsNonRoot alone would leave
every deployed pod stuck in CreateContainerConfigError.
- Give the read-only container writable scratch: mount a bounded emptyDir
(sizeLimit 1Gi) at /tmp and set HOME=/tmp so ~/.cache writes land there
instead of failing against readOnlyRootFilesystem.
- Label the owned Namespace with app.kubernetes.io/managed-by: codefly and
elide the inline Secret under restricted profiles.
- Assert the rendered deployment pins runAsUser, mounts and bounds /tmp, and
redirects HOME, so these runtime requirements can't regress silently past
static conformance.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byteforce-pushed the issue-7-chore-fix-test-failures-before-release branch from 0cbe910 to cd9da84CompareAugust 18, 2026 14:07
TestCreateToRunDocker failed on Linux CI (but not macOS) on its second
Init: the dependency cache hashes code/uv.lock and got "permission denied".
Root cause: the container ran as root, so `uv sync` wrote uv.lock into the
bind-mounted source (and populated the venv) as root. On a host where the
invoking user isn't root — Linux CI — the next Init could no longer read the
root-owned uv.lock to hash it. Docker Desktop's UID remapping masked this on
macOS.
Run the container as the invoking host user (uid:gid) so everything it writes
into bind mounts is host-owned. uv's download cache defaults to $HOME/.cache,
which that user can't write inside the image, so mount a dedicated host-owned
cache dir and point UV_CACHE_DIR at it.
Also assert init.Status is READY in the create-to-run test: Init reports
failures through the response status, not the returned error, so the previous
require.NoError let a failed Init through and surfaced as a confusing
empty-network-mappings error later.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byteforce-pushed the issue-7-chore-fix-test-failures-before-release branch from 327c3c2 to dd6c66aCompareAugust 18, 2026 18:55
The container-mode lifecycle test drives the Python runtime's Test step,
which runs `uv` on the host to sync dependencies and run pytest. The runner
doesn't ship uv, so `go test ./...` failed with `exec: "uv": executable file
not found in $PATH`. Install it via the shared workflow's setup-run hook.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#7)
The generated service's pytest hung indefinitely under the Python runtime's
Test step. codefly-sdk's init() walks parent directories for
service.codefly.yaml without stopping at the filesystem root, so it spins
forever when the manifest isn't found — which is exactly the case core's test
runner creates by executing pytest against an isolated source snapshot (the
snapshot holds code/, not the service-root manifest). Importing src.main ran
init() at module load and wedged collection.
- Guard the manifest lookup in main.py with a bounded search; init() only runs
when service.codefly.yaml is actually reachable, and runtime config
otherwise flows through CODEFLY__* env vars.
- Make the admin test hermetic: seed the CODEFLY__* values it needs (setdefault
preserves real runtime values) and drop the codefly.init("..") walk that
would spin in the snapshot.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byte merged commit b39ce10 into mainAug 18, 2026
2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore: fix test failures before release

1 participant

@antoinetoussaint-byte