Skip to content

Integrate Wildside with Nile Valley previews#358

Open
leynos wants to merge 17 commits into
mainfrom
backend-nile-valley-integration
Open

Integrate Wildside with Nile Valley previews#358
leynos wants to merge 17 commits into
mainfrom
backend-nile-valley-integration

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented May 20, 2026

Summary

Integrates Wildside with Nile Valley preview and GitOps workflows by delivering the approved execution plan in docs/execplans/backend-nile-valley-integration.md.

Implemented:

  • Domain-owned health observation semantics and Actix Web /health/live and /health/ready adapters.
  • Non-root multi-stage backend container image with stable /health/live health check defaults.
  • Nile Valley-aligned Helm chart support for ingress, config, secrets, ExternalSecret, service accounts, and local values.
  • Cyclopts/uv local k3d preview workflow with Makefile lifecycle targets.
  • User, developer, architecture, repository, design, contents, roadmap, and execplan documentation updates.

Review walkthrough

  • Start with docs/execplans/backend-nile-valley-integration.md for the approved plan, final progress, decisions, validation evidence, and residual environment limitations.
  • Review backend/src/domain/health.rs, backend/src/domain/ports/health_observer.rs, and backend/src/inbound/http/health.rs for the health boundary.
  • Review deploy/docker/backend.Dockerfile, .dockerignore, and deploy/charts/wildside/ for packaging and deployment changes.
  • Review scripts/local_k8s.py and scripts/local_k8s/ for the local preview helper.
  • Review docs/local-k8s-preview-design.md and docs/users-guide.md for the user-facing and design documentation.

Validation

Passed:

  • make check-fmt
  • make lint
  • make test
  • make fmt
  • make markdownlint
  • make nixie
  • helm lint deploy/charts/wildside
  • helm template deploy/charts/wildside --kube-version 1.31.0
  • local values and ExternalSecret Helm render checks
  • local preview CLI help and Python unit tests
  • coderabbit review --agent after each major milestone and final closeout, all with zero findings

Environment-limited checks:

  • Docker image build could not run because Docker is not installed in this environment.
  • Full k3d preview lifecycle could not run because k3d and kubectl are not installed in this environment.

Both blockers are recorded in the execplan and covered by CLI preflight checks.

References

Document the approved-gate plan for hardening Wildside's health server,
container image, Helm chart, and local k3d preview workflow before any
implementation work begins.

Capture the current repository discoveries, Corbusier and Nile Valley prior
art, validation strategy, and the CodeRabbit rate-limit blocker from the
planning milestone.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

Review Change Stack

Walkthrough

Domain health model moves liveness and readiness behind a HealthObserver trait. HTTP adapter becomes a type alias to ProcessHealth. Container image switches to Debian with updated health check defaults. Helm chart gains ExternalSecret support and multi-host ingress configuration. New Python orchestration tooling manages local k3d cluster setup and Helm releases. Comprehensive documentation and BDD tests validate health contract and integration.

Changes

Backend Health Contract and Local Kubernetes Preview

Layer / File(s) Summary
Domain health model and port definition
backend/src/domain/health.rs, backend/src/domain/mod.rs, backend/src/domain/ports/health_observer.rs, backend/src/domain/ports/mod.rs
New HealthStatus and HealthObservation value types; ProcessHealth implements HealthObserver trait using atomic readiness/liveness state with Acquire/Release semantics; trait defines observe_liveness and observe_readiness operations for the inbound adapter to call.
HTTP health endpoint refactoring
backend/src/inbound/http/health.rs, backend/src/lib.rs, backend/src/tests.rs
HealthState becomes a type alias to domain ProcessHealth. Endpoints call observe_readiness/observe_liveness; probe_response helper serialises JSON with status and per-probe checks. Re-exports updated to expose ProcessHealth publicly. Tests import HealthObserver and use new observation API.
Integration testing: health probes
backend/tests/features/health_probes.feature, backend/tests/health_probes_bdd.rs
BDD feature file with four scenarios covering readiness/liveness status transitions. Rust test harness with rstest steps, HTTP request/response capture, snapshot validation via insta.
Container image hardening
deploy/docker/backend.Dockerfile
Migrated from Alpine/musl to Debian/bookworm. Rust version bumped to 1.90.0. Build dependencies and runtime packages updated. Health check endpoint changed to /health/live with 127.0.0.1 binding and stricter curl flags. APP_UID/APP_GID made configurable.
Helm chart helpers and secret management
deploy/charts/wildside/templates/_helpers.tpl
New helpers: serviceAccountName (conditional account creation), effectiveSecretName (deriving secret name from existingSecretName or externalSecret config). validateSecrets strengthened with regex validation for environment variable names, empty-key rejection, and optional Secret key existence checking.
Helm chart manifests
deploy/charts/wildside/templates/serviceaccount.yaml, deploy/charts/wildside/templates/externalsecret.yaml, deploy/charts/wildside/templates/deployment.yaml, deploy/charts/wildside/templates/ingress.yaml
New ServiceAccount template conditional on .Values.serviceAccount.create. New ExternalSecret template for external-secrets.io integration. Deployment template updated to use effectiveSecretName helper and conditionally compute config/session-secret checksums. Ingress template refactored to support per-host/per-path configuration from hosts array with fallback to hostname.
Helm values and schema
deploy/charts/wildside/values.yaml, deploy/charts/wildside/values.local.yaml, deploy/charts/wildside/values.schema.json
values.yaml extended with ingress.hosts, ingress.tls, validateExistingSecret, externalSecret, and serviceAccount blocks. New values.local.yaml for local k3d configuration with traefik ingress and relaxed secret validation. values.schema.json substantially updated with probe definitions, ingress structures, externalSecret conditional validation, and removed top-level secretEnvFromKeys/existingSecretName coupling.
Local k3d preview: foundation modules
scripts/local_k8s/__init__.py, scripts/local_k8s/validation.py, scripts/local_k8s/config.py, scripts/local_k8s/commands.py
Package foundation: LocalK8sError custom exception; validate_port for TCP port parsing with range checks; require_tools for executable availability checking; PreviewConfig dataclass with from_env() constructor for reading WILDSIDE_ environment variables; CommandResult and run() for plumbum-based subprocess execution with optional working directory switching.
Local k3d preview: cluster and Kubernetes operations
scripts/local_k8s/k3d.py, scripts/local_k8s/k8s.py, scripts/local_k8s/deployment.py
k3d cluster lifecycle: ensure_cluster, delete_cluster, import_image, print_cluster_status with cluster existence checking via k3d cluster list --output json parsing. Kubernetes namespace ensurement and workload status printing. deploy_preview orchestrates preflight checks, cluster/namespace creation, optional image build, image import, Helm upgrade with dynamic image repository/tag derivation, and status output.
Local k3d preview: CLI and Makefile integration
scripts/local_k8s.py, Makefile
Cyclopts CLI with up, down, status, logs subcommands. _run() wrapper converts LocalK8sError to SystemExit. Four new Makefile targets (local-k8s-up/down/status/logs) invoking the Python script with corresponding subcommands.
Local k3d preview: Python unit tests
scripts/local_k8s/unittests/test_validation.py, scripts/local_k8s/unittests/test_deployment.py, scripts/local_k8s/unittests/test_k8s.py
Test coverage for validate_port (default fallback, valid ports 1–65535, invalid ranges), require_tools (missing executable detection), image_repository_and_tag parsing, and deployment preflight tool requirement logic; k8s helper test verifies Helm fullname usage for Service lookup.
Documentation: design and guidance
docs/local-k8s-preview-design.md, docs/execplans/backend-nile-valley-integration.md, docs/developers-guide.md, docs/users-guide.md, docs/repository-structure.md, docs/wildside-backend-architecture.md, docs/contents.md, docs/backend-roadmap.md
Comprehensive design documents: local-k8s-preview-design.md detailing health contract, container, Helm, and CLI specifications; backend-nile-valley-integration.md with execution plan, milestones, test strategy, and retrospective. Developers guide section on local Kubernetes preview. Users guide covering health endpoint semantics and preview setup. Architecture clarification on domain-owned ports. Roadmap entry 7.1 for deployment coordination.
Build infrastructure
.dockerignore, package.json
Docker build context optimised to exclude Git metadata, Node/TypeScript caches, Terraform, build outputs, and frontend artefacts. Dependency version bump: qs 6.14.2 → 6.15.2.

Suggested labels

Roadmap, Issue

"🏗️ Health contracts harden into stone,
k3d clusters hum for local test and tone,
Helm charts learn secrets' name,
and docs record the integration's fame."

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch backend-nile-valley-integration

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 20, 2026

Reviewer's Guide

Adds a detailed ExecPlan document describing the future integration of the Wildside backend with Nile Valley previews and GitOps workflows, including health semantics refactors, container and Helm hardening, local k3d orchestration, and documentation updates, but does not change any implementation code yet.

Flow diagram for local k3d preview workflow (local_k8s up)

flowchart LR
  A["Developer runs
make local-k8s-up"] --> B["uv run scripts/local_k8s.py up"]
  B --> C["Validate tools: k3d, kubectl, Helm, Docker"]
  C -->|ok| D["Create or reuse k3d cluster
(loopback ingress port)"]
  D --> E["Docker build backend image
from deploy/docker/backend.Dockerfile"]
  E --> F["Import image into k3d cluster"]
  F --> G["helm upgrade --install wildside
using deploy/charts/wildside"]
  G --> H["Wildside Pod exposes
/health/live and /health/ready"]
  C -->|missing tool| X["Fail with preflight error
and exit"]
Loading

File-Level Changes

Change Details Files
Introduce a comprehensive execution plan for integrating Wildside with Nile Valley previews and GitOps workflows.
  • Describe current backend/runtime, Docker, and Helm chart surfaces and gaps with Nile Valley expectations.
  • Define constraints, tolerances, risks, prior art, and skills to be used during implementation.
  • Lay out milestone-by-milestone implementation steps covering domain health refactor, container hardening, Helm alignment, local k3d orchestration, documentation updates, and final gating.
  • Specify a test strategy spanning Rust domain and adapter tests, rstest-bdd behaviour tests, Python helper tests, and optional E2E preview runs.
  • Track planned work via Progress, Surprises & Discoveries, Decision Log, and Outcomes & Retrospective sections to be updated as implementation proceeds.
docs/execplans/backend-nile-valley-integration.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-delta-analysis[bot]

This comment was marked as outdated.

leynos added 2 commits May 21, 2026 14:19
Add a domain-owned process health model and observation port so HTTP
health routes map domain state instead of owning liveness and readiness
semantics.

Cover the health contract with focused `rstest` unit tests and an
`rstest-bdd` feature for externally observable probe responses.
Update the Nile Valley integration ExecPlan with the committed health
milestone, gate results, and CodeRabbit outcome before starting the next
implementation milestone.
codescene-delta-analysis[bot]

This comment was marked as outdated.

leynos added 2 commits May 21, 2026 14:33
Update the backend Dockerfile to use an edition-2024-capable Rust
builder, a non-root Debian slim runtime, explicit runtime libraries,
and a stable `/health/live` liveness probe.

Add a root `.dockerignore` to keep local build and dependency artefacts
out of container contexts, and record the local Docker CLI validation
blocker in the execution plan.
Update the execution plan with the committed container image hardening
milestone and the successful CodeRabbit review result before starting the
Helm chart work.
codescene-delta-analysis[bot]

This comment was marked as outdated.

leynos added 6 commits May 21, 2026 14:46
Add ExternalSecret rendering, service account support, local preview
values, hostless ingress handling, and schema coverage for deployment
values used by Nile Valley overlays.

Keep live Secret lookup validation opt-in so GitOps and offline renders
work without a cluster, while startup and liveness probes use
`/health/live` consistently.
Update the execution plan with the committed Helm chart alignment
milestone and the successful CodeRabbit review result before starting the
local preview workflow.
Add a Cyclopts and `uv` based local Kubernetes CLI for creating,
inspecting, logging, and tearing down a Wildside k3d preview.

Wire Makefile targets to the CLI, add local validation helpers, and
record the missing local `k3d` and `kubectl` environment blocker in the
execution plan.
Record the local k3d preview commit and CodeRabbit review outcome in
the execution plan before moving to the documentation milestone.
Add the local k3d preview design and user-facing server guide, then link
the workflow from developer, architecture, repository, contents, and
roadmap documentation.

Record the documentation validation evidence in the execution plan and
mark the Nile Valley preview integration roadmap item complete.
Record final validation, milestone review outcomes, residual local tool
limitations, and implementation results in the Nile Valley integration
execution plan.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 21, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

scripts/local_k8s/deployment.py

Comment on file

    """Split a Docker image reference into Helm repository and tag values."""

    repository, separator, tag = image_name.rpartition(":")
    if not separator or "/" in tag or not repository or not tag:

❌ New issue: Complex Conditional
image_repository_and_tag has 1 complex conditionals with 3 branches, threshold = 2

@coderabbitai

This comment was marked as resolved.

Move the local preview image reference validation condition behind a
named helper so the parser satisfies CodeScene�s complex conditional
threshold without changing behaviour.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 22, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

Code Duplication

backend/tests/health_probes_bdd.rs:

What lead to degradation?

The module contains 2 functions with similar structure: HealthProbeWorld.request_liveness,HealthProbeWorld.request_readiness

Why does this problem occur?

Duplicated code often leads to code that's harder to change since the same logical change has to be done in multiple functions. More duplication gives lower code health.

How to fix it?

A certain degree of duplicated code might be acceptable. The problems start when it is the same behavior that is duplicated across the functions in the module, ie. a violation of the Don't Repeat Yourself (DRY) principle. DRY violations lead to code that is changed together in predictable patterns, which is both expensive and risky. DRY violations can be identified using CodeScene's X-Ray analysis to detect clusters of change coupled functions with high code similarity. Read More
Once you have identified the similarities across functions, look to extract and encapsulate the concept that varies into its own function(s). These shared abstractions can then be re-used, which minimizes the amount of duplication and simplifies change.

@coderabbitai

This comment was marked as resolved.

Share the Actix test request setup between readiness and liveness probe
steps so the BDD world avoids duplicated request code without changing
scenario behaviour.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Return a stable JSON health envelope from liveness and readiness probes
and cover both pass and fail states with `insta` JSON snapshots. This
protects the operator-facing response contract while keeping the domain
health policy behind the existing health observer port.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Update the pnpm override for `qs` to 6.15.2 so the transitive
`style-dictionary` dependency path uses the patched release for
GHSA-q8mj-m7cp-5q26.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos marked this pull request as ready for review May 25, 2026 19:37
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 2500000 diff characters.

Please try again later or upgrade to continue using Sourcery

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc93169661

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/local_k8s/k8s.py Outdated
],
)
print(pods.stdout.strip() or "pods: none")
services = run("kubectl", ["-n", config.namespace, "get", "service", config.release_name, "--ignore-not-found"])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve service name from Helm fullname during status checks

print_kubernetes_status fetches the Service by config.release_name, but the chart names the Service with include "wildside.fullname" (see templates/service.yaml), which becomes <release>-wildside for non-default release names. In that common override case (WILDSIDE_HELM_RELEASE not equal to chart name), local_k8s status will incorrectly report service: none even though the release is healthy, which makes status output misleading and harder to trust for troubleshooting.

Useful? React with 👍 / 👎.

Comment thread scripts/local_k8s/deployment.py Outdated
def deploy_preview(config: PreviewConfig, *, skip_build: bool) -> None:
"""Build the image and install or upgrade the Wildside Helm release."""

require_tools(("docker", "helm", "k3d", "kubectl"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip Docker preflight when --skip-build is requested

deploy_preview always requires docker before it checks skip_build. As a result, local_k8s up --skip-build still fails immediately on machines without Docker even though no build is attempted, defeating the purpose of the flag for prebuilt images and blocking a documented workflow variant.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.dockerignore:
- Line 3: Remove or replace the incorrect literal `.node_modules` entry in
.dockerignore: delete the `.node_modules` line (the literal name matches
nothing) since `**/node_modules` already covers standard node_modules folders,
or if you intended to ignore a hidden folder specifically, change it to an
explicit pattern that matches that target; update the `.node_modules` entry
accordingly so only the correct node_modules patterns remain.

In `@deploy/charts/wildside/values.schema.json`:
- Around line 157-159: Tighten the externalSecret.data item schema in
deploy/charts/wildside/values.schema.json so the array cannot contain
empty/unshaped objects: replace the current "data": { "type": "array", "items":
{ "type": "object" } } with an item schema that mirrors
external-secrets.io/v1beta1 spec.data[] (e.g. items: { "type":"object",
"properties": { "secretKey": { "type":"string" }, "remoteRef": {
"type":"object", "properties": { "key": { "type":"string" }, "property": {
"type":"string" }, "propertyRegex": { "type":"string" }, "version": {
"type":"string" } }, "required":["key"], "additionalProperties": false } },
"required":["secretKey","remoteRef"], "additionalProperties": false }) so
templates/externalsecret.yaml rendering of .Values.externalSecret.data will
reject {}/malformed entries.

In `@docs/execplans/backend-nile-valley-integration.md`:
- Around line 721-723: Edit the rationale paragraph in the users-guide rationale
and replace the incorrect noun phrase "a global users guide" with the corrected
phrase "a global user guide" so the sentence reads "...the repository does not
currently have a global user guide covering server and deployment behaviour.";
search for the exact phrase "a global users guide" in the document to locate the
spot to update.

In `@docs/repository-structure.md`:
- Around line 488-493: Rewrap the Markdown paragraph that mentions the
developer-local k3d preview helper so no line exceeds 80 columns: break the long
line containing "`scripts/local_k8s.py` and `scripts/local_k8s/*`" (and the
clause about importing the backend image and installing the Wildside chart with
`deploy/charts/wildside/values.local.yaml`) into shorter lines so the paragraph
conforms to the 80-column limit while preserving wording and inline code
segments.

In `@package.json`:
- Line 55: In package.json, add the "qs": "6.15.2" entry into the top-level
"overrides" object (not just under "pnpm.overrides") so npm and pnpm override
parity is maintained; update the overrides block to include the same version pin
as the existing "pnpm.overrides" entry and add a short comment or adjacent
package.json field (e.g., "overridesNotes" or update package.json README)
documenting that qs@6.15.2 is the first patched version for the GitHub advisory
fixing the DoS affecting >=6.11.1 <=6.15.1 so reviewers can see the security
rationale.

In `@scripts/local_k8s.py`:
- Around line 23-27: The _run function currently accepts func: object and
silently no-ops if func isn't callable; change its signature to a strict
callable type (e.g., typing.Callable[[], None] or Callable[..., Any]) and remove
the callable() guard so the code directly calls func() and lets type checkers
and runtime errors surface invalid call sites; update imports to include
Callable and keep the existing LocalK8sError except block and invocation of
func() inside the try.

In `@scripts/local_k8s/__init__.py`:
- Line 1: Replace the single-line docstring with a short triple-quoted module
docstring for scripts.local_k8s that explains the package purpose (local
Kubernetes preview helpers for Wildside), lists provided utilities/entry points
(how to invoke CLI entry points or functions used to start the preview), and
shows a minimal usage example and invocation pattern (e.g., example CLI call or
calling main() if present); make sure it follows coding guidelines by describing
purpose, utility, and usage including an example invocation.

In `@scripts/local_k8s/commands.py`:
- Line 1: Update the module docstring and the public docstrings for
CommandResult and run to NumPy style: replace the short module string with a
NumPy-structured summary including Purpose, Usage (brief example), and Notes;
expand the CommandResult class docstring to include a short Summary, Attributes
(document fields like returncode, stdout, stderr, succeeded), and Examples;
expand the run function docstring to NumPy sections: Summary, Parameters
(document parameters and types), Returns (describe returned CommandResult),
Raises (exceptions raised), and Examples; ensure the symbol names CommandResult
and run are referenced and that types and example usage are present in each
docstring.

In `@scripts/local_k8s/k3d.py`:
- Around line 63-66: The code currently calls json.loads(result.stdout or "[]")
and will let json.JSONDecodeError propagate; wrap the parse in a try/except that
catches json.JSONDecodeError and raises LocalK8sError (including the original
exception message/context) so callers get a stable local-preview error; update
the block around json.loads, keep the subsequent type check for list and the
final any(...) check (referencing json.loads, LocalK8sError, and cluster_name)
and ensure the raised LocalK8sError preserves the original error text.

In `@scripts/local_k8s/k8s.py`:
- Around line 10-21: The short one-line docstrings for the public functions
ensure_namespace and print_kubernetes_status must be replaced with full
NumPy-style docstrings: for each function add a Parameters section documenting
the config parameter (type PreviewConfig and brief description), a Returns
section stating None, and a Raises section if the function can propagate
exceptions (e.g., from require_tools or run) — update the docstrings for
ensure_namespace and print_kubernetes_status accordingly to follow the numpy
style guide.

In `@scripts/local_k8s/unittests/test_validation.py`:
- Around line 20-23: The test test_validate_port_rejects_invalid_values
currently only asserts the exception type; update it to assert the error message
using a regex by passing the match parameter to pytest.raises (or by capturing
the exception and asserting re.search) so the message contract from
validate_port is verified for each raw_value; reference the validate_port
function and the test name test_validate_port_rejects_invalid_values when making
the change and ensure the regex covers the expected phrasing (e.g., mentions
invalid port or the given raw_value) for each input.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 07548c6b-a8aa-4ea7-a0d4-77f52c9dbf2d

📥 Commits

Reviewing files that changed from the base of the PR and between b23476f and bc93169.

⛔ Files ignored due to path filters (5)
  • backend/tests/snapshots/health_probes_bdd__health_probe_health_live_200.snap is excluded by !**/*.snap
  • backend/tests/snapshots/health_probes_bdd__health_probe_health_live_503.snap is excluded by !**/*.snap
  • backend/tests/snapshots/health_probes_bdd__health_probe_health_ready_200.snap is excluded by !**/*.snap
  • backend/tests/snapshots/health_probes_bdd__health_probe_health_ready_503.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (38)
  • .dockerignore
  • Makefile
  • backend/src/domain/health.rs
  • backend/src/domain/mod.rs
  • backend/src/domain/ports/health_observer.rs
  • backend/src/domain/ports/mod.rs
  • backend/src/inbound/http/health.rs
  • backend/src/lib.rs
  • backend/src/tests.rs
  • backend/tests/features/health_probes.feature
  • backend/tests/health_probes_bdd.rs
  • deploy/charts/wildside/templates/_helpers.tpl
  • deploy/charts/wildside/templates/deployment.yaml
  • deploy/charts/wildside/templates/externalsecret.yaml
  • deploy/charts/wildside/templates/ingress.yaml
  • deploy/charts/wildside/templates/serviceaccount.yaml
  • deploy/charts/wildside/values.local.yaml
  • deploy/charts/wildside/values.schema.json
  • deploy/charts/wildside/values.yaml
  • deploy/docker/backend.Dockerfile
  • docs/backend-roadmap.md
  • docs/contents.md
  • docs/developers-guide.md
  • docs/execplans/backend-nile-valley-integration.md
  • docs/local-k8s-preview-design.md
  • docs/repository-structure.md
  • docs/users-guide.md
  • docs/wildside-backend-architecture.md
  • package.json
  • scripts/local_k8s.py
  • scripts/local_k8s/__init__.py
  • scripts/local_k8s/commands.py
  • scripts/local_k8s/config.py
  • scripts/local_k8s/deployment.py
  • scripts/local_k8s/k3d.py
  • scripts/local_k8s/k8s.py
  • scripts/local_k8s/unittests/test_validation.py
  • scripts/local_k8s/validation.py

Comment thread .dockerignore
@@ -0,0 +1,12 @@
.git
.gitignore
.node_modules
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for any .node_modules directory in the repository
fd -HI -t d '^\.node_modules$' .

Repository: leynos/wildside

Length of output: 41


Fix the .dockerignore dependency ignore pattern.

  • Replace or remove the .node_modules entry on .dockerignore line 3: it only matches a literal root folder named .node_modules (none exists), while **/node_modules on line 8 already ignores the standard node_modules directory everywhere in the build context.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.dockerignore at line 3, Remove or replace the incorrect literal
`.node_modules` entry in .dockerignore: delete the `.node_modules` line (the
literal name matches nothing) since `**/node_modules` already covers standard
node_modules folders, or if you intended to ignore a hidden folder specifically,
change it to an explicit pattern that matches that target; update the
`.node_modules` entry accordingly so only the correct node_modules patterns
remain.

Comment on lines +157 to +159
"data": { "type": "array", "items": { "type": "object" } }
},
"required": ["enabled", "refreshInterval", "secretStoreRef", "data"],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate where externalSecret.data is defined in values schema
rg -n '"data"\s*:\s*\{|\bexternalSecret\b' deploy/charts/wildside/values.schema.json

# Print the specific region around the reported lines (~157-159)
sed -n '130,190p' deploy/charts/wildside/values.schema.json

# Find how externalSecret.data is consumed in templates
rg -n "externalSecret\.data|spec\.data|toYaml \.Values\.externalSecret\.data|remoteRef|secretKey" deploy/charts/wildside/templates

# Show the externalsecret template section that renders spec.data
rg -n "spec:\s*$|data:" deploy/charts/wildside/templates/externalsecret.yaml || true
sed -n '1,220p' deploy/charts/wildside/templates/externalsecret.yaml

Repository: leynos/wildside

Length of output: 3991


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect externalsecret template in full (small file)
sed -n '1,220p' deploy/charts/wildside/templates/externalsecret.yaml

# Inspect helper logic that mentions $secretKey and $data/$stringData
sed -n '1,160p' deploy/charts/wildside/templates/_helpers.tpl

# Inspect deployment template where secretKeyRef is built from $sec
sed -n '60,140p' deploy/charts/wildside/templates/deployment.yaml

# Search for where externalSecret.data is shaped/expected (remoteRef/secretKey/keys)
rg -n --context 2 "externalSecret\.data|remoteRef|secretKey" deploy/charts/wildside/templates

Repository: leynos/wildside

Length of output: 9929


Tighten externalSecret.data item validation in deploy/charts/wildside/values.schema.json

deploy/charts/wildside/templates/externalsecret.yaml renders spec.data verbatim from externalSecret.data (toYaml .Values.externalSecret.data), while the schema currently allows empty/unshaped objects:

        "data": { "type": "array", "items": { "type": "object" } }
      },
      "required": ["enabled", "refreshInterval", "secretStoreRef", "data"],

Reject malformed entries by defining an item schema for each element (use required fields matching external-secrets.io/v1beta1 spec.data[], and set additionalProperties: false, so {} is invalid).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/charts/wildside/values.schema.json` around lines 157 - 159, Tighten
the externalSecret.data item schema in deploy/charts/wildside/values.schema.json
so the array cannot contain empty/unshaped objects: replace the current "data":
{ "type": "array", "items": { "type": "object" } } with an item schema that
mirrors external-secrets.io/v1beta1 spec.data[] (e.g. items: { "type":"object",
"properties": { "secretKey": { "type":"string" }, "remoteRef": {
"type":"object", "properties": { "key": { "type":"string" }, "property": {
"type":"string" }, "propertyRegex": { "type":"string" }, "version": {
"type":"string" } }, "required":["key"], "additionalProperties": false } },
"required":["secretKey","remoteRef"], "additionalProperties": false }) so
templates/externalsecret.yaml rendering of .Values.externalSecret.data will
reject {}/malformed entries.

Comment on lines +721 to +723
Rationale: the user explicitly requested that file, and the repository does
not currently have a global users guide covering server and deployment
behaviour.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the noun phrase in the users-guide rationale.

Replace “a global users guide” with “a global user guide”.

Triage: [type:grammar] [type:docstyle]

As per coding guidelines: "Follow documentation style guide conventions for clear and consistent documentation".

🧰 Tools
🪛 LanguageTool

[grammar] ~722-~722: The plural noun “users” cannot be used with the article “a”. Did you mean “a global user” or “global users”?
Context: ...he repository does not currently have a global users guide covering server and deployment ...

(A_NNS)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/execplans/backend-nile-valley-integration.md` around lines 721 - 723,
Edit the rationale paragraph in the users-guide rationale and replace the
incorrect noun phrase "a global users guide" with the corrected phrase "a global
user guide" so the sentence reads "...the repository does not currently have a
global user guide covering server and deployment behaviour."; search for the
exact phrase "a global users guide" in the document to locate the spot to
update.

Comment on lines +488 to +493
This repository also provides a developer-local k3d preview helper:
`scripts/local_k8s.py` and `scripts/local_k8s/*`. The helper builds the
backend image, imports it into a local `k3d` cluster, and installs the Wildside
chart with `deploy/charts/wildside/values.local.yaml`. It validates the
application packaging contract; Nile Valley remains the owner of shared
cluster and GitOps automation.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Rewrap line 490 to comply with 80-column limit.

Line 490 exceeds the 80-column wrapping requirement for Markdown paragraphs.

Triage: [type:docstyle]

📏 Proposed rewrap
 This repository also provides a developer-local k3d preview helper:
-`scripts/local_k8s.py` and `scripts/local_k8s/*`. The helper builds the
-backend image, imports it into a local `k3d` cluster, and installs the Wildside
-chart with `deploy/charts/wildside/values.local.yaml`. It validates the
+`scripts/local_k8s.py` and `scripts/local_k8s/*`. The helper builds the backend
+image, imports it into a local `k3d` cluster, and installs the Wildside chart
+with `deploy/charts/wildside/values.local.yaml`. It validates the
 application packaging contract; Nile Valley remains the owner of shared
 cluster and GitOps automation.

As per coding guidelines, Markdown paragraphs must be wrapped at 80 columns.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/repository-structure.md` around lines 488 - 493, Rewrap the Markdown
paragraph that mentions the developer-local k3d preview helper so no line
exceeds 80 columns: break the long line containing "`scripts/local_k8s.py` and
`scripts/local_k8s/*`" (and the clause about importing the backend image and
installing the Wildside chart with `deploy/charts/wildside/values.local.yaml`)
into shorter lines so the paragraph conforms to the 80-column limit while
preserving wording and inline code segments.

Comment thread package.json
"lodash-es": "4.18.1",
"pino": "9.13.1",
"qs": "6.14.2",
"qs": "6.15.2",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify override parity
node ./scripts/check-overrides-parity.mjs

Repository: leynos/wildside

Length of output: 128


🏁 Script executed:

#!/bin/bash
# Check for qs security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 10, ecosystem: NPM, package: "qs") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Repository: leynos/wildside

Length of output: 2376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate qs and overrides blocks in package.json
FILE="package.json"
echo "== Locations of \"qs\" in $FILE =="
rg -n '"qs"\s*:' "$FILE" || true

echo
echo "== Extract around first match (approx) =="
# Print a small window around the first match
line=$(rg -n '"qs"\s*:' "$FILE" | head -n1 | cut -d: -f1)
start=$((line-20))
end=$((line+20))
sed -n "${start},${end}p" "$FILE" | cat -n

echo
echo "== Show overrides sections (limited) =="
# Show any overrides-related sections
rg -n '"overrides"\s*:' "$FILE" || true
rg -n '"pnpm"\s*:' "$FILE" || true

# Print a broader region around "overrides" keys
for l in $(rg -n '"overrides"\s*:' "$FILE" | cut -d: -f1); do
  start=$((l-10)); end=$((l+80));
  echo "--- overrides region around line $l ---"
  sed -n "${start},${end}p" "$FILE" | nl -ba
done

Repository: leynos/wildside

Length of output: 1641


Mirror the qs override into root overrides and link 6.15.2 to the security fix.

      "qs": "6.15.2",
  • Add qs to the top-level overrides block too: it currently exists only under pnpm.overrides, while root overrides does not include qs, so npm/pnpm override parity is not maintained for this package.
  • Document that qs@6.15.2 is the first patched version for the GitHub MODERATE remotely triggerable DoS advisory affecting >= 6.11.1, <= 6.15.1.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 55, In package.json, add the "qs": "6.15.2" entry into
the top-level "overrides" object (not just under "pnpm.overrides") so npm and
pnpm override parity is maintained; update the overrides block to include the
same version pin as the existing "pnpm.overrides" entry and add a short comment
or adjacent package.json field (e.g., "overridesNotes" or update package.json
README) documenting that qs@6.15.2 is the first patched version for the GitHub
advisory fixing the DoS affecting >=6.11.1 <=6.15.1 so reviewers can see the
security rationale.

@@ -0,0 +1 @@
"""Local Kubernetes preview helpers for Wildside."""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Expand the module docstring to include purpose, utility, and usage.

Replace the single-line package docstring with a short module overview that states
what the package provides and how entry points are invoked.

As per coding guidelines, "Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/local_k8s/__init__.py` at line 1, Replace the single-line docstring
with a short triple-quoted module docstring for scripts.local_k8s that explains
the package purpose (local Kubernetes preview helpers for Wildside), lists
provided utilities/entry points (how to invoke CLI entry points or functions
used to start the preview), and shows a minimal usage example and invocation
pattern (e.g., example CLI call or calling main() if present); make sure it
follows coding guidelines by describing purpose, utility, and usage including an
example invocation.

@@ -0,0 +1,34 @@
"""Command execution primitives for the local preview workflow."""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Replace public docstrings with NumPy-structured docstrings.

Expand Line 15 (CommandResult) and Line 22 (run) to full NumPy sections, and enrich the module docstring at Line 1 with utility/usage context.

🛠️ Proposed docstring update
-"""Command execution primitives for the local preview workflow."""
+"""Command execution primitives for the local preview workflow.
+
+This module runs local tooling commands and normalizes execution failures into
+`LocalK8sError` for CLI workflows.
+"""
@@
 `@dataclass`(frozen=True, slots=True)
 class CommandResult:
-    """Captured stdout and stderr from an external command."""
+    """Captured external command output.
+
+    Attributes
+    ----------
+    stdout
+        Captured standard output stream.
+    stderr
+        Captured standard error stream.
+    """
@@
 def run(command: str, args: Sequence[str], *, cwd: str | None = None) -> CommandResult:
-    """Run a command and raise a local preview error on failure."""
+    """Run a local command and capture output.
+
+    Parameters
+    ----------
+    command
+        Executable name on `PATH`.
+    args
+        Positional arguments passed to the executable.
+    cwd
+        Working directory for execution. Use the current directory when unset.
+
+    Returns
+    -------
+    CommandResult
+        Captured command stdout and stderr streams.
+
+    Raises
+    ------
+    LocalK8sError
+        Raised when process execution fails.
+    """

As per coding guidelines: "Docstrings must follow the numpy style guide... full structured docs for all public interfaces."

Also applies to: 15-24

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/local_k8s/commands.py` at line 1, Update the module docstring and the
public docstrings for CommandResult and run to NumPy style: replace the short
module string with a NumPy-structured summary including Purpose, Usage (brief
example), and Notes; expand the CommandResult class docstring to include a short
Summary, Attributes (document fields like returncode, stdout, stderr,
succeeded), and Examples; expand the run function docstring to NumPy sections:
Summary, Parameters (document parameters and types), Returns (describe returned
CommandResult), Raises (exceptions raised), and Examples; ensure the symbol
names CommandResult and run are referenced and that types and example usage are
present in each docstring.

Comment thread scripts/local_k8s/k3d.py
Comment on lines +63 to +66
clusters = json.loads(result.stdout or "[]")
if not isinstance(clusters, list):
raise LocalK8sError("unexpected k3d cluster list JSON shape")
return any(isinstance(cluster, dict) and cluster.get("name") == cluster_name for cluster in clusters)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wrap JSON parse failures in LocalK8sError.

Handle invalid k3d JSON output and raise a stable local-preview error instead of leaking
json.JSONDecodeError.

Proposed fix
 def _cluster_exists(cluster_name: str) -> bool:
     result = run("k3d", ["cluster", "list", "--output", "json"])
-    clusters = json.loads(result.stdout or "[]")
+    try:
+        clusters = json.loads(result.stdout or "[]")
+    except json.JSONDecodeError as exc:
+        message = "unexpected k3d cluster list JSON payload"
+        raise LocalK8sError(message) from exc
     if not isinstance(clusters, list):
         raise LocalK8sError("unexpected k3d cluster list JSON shape")
     return any(isinstance(cluster, dict) and cluster.get("name") == cluster_name for cluster in clusters)
🧰 Tools
🪛 Ruff (0.15.14)

[warning] 65-65: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/local_k8s/k3d.py` around lines 63 - 66, The code currently calls
json.loads(result.stdout or "[]") and will let json.JSONDecodeError propagate;
wrap the parse in a try/except that catches json.JSONDecodeError and raises
LocalK8sError (including the original exception message/context) so callers get
a stable local-preview error; update the block around json.loads, keep the
subsequent type check for list and the final any(...) check (referencing
json.loads, LocalK8sError, and cluster_name) and ensure the raised LocalK8sError
preserves the original error text.

Comment thread scripts/local_k8s/k8s.py
Comment on lines +10 to +21
def ensure_namespace(config: PreviewConfig) -> None:
"""Create the preview namespace when it does not already exist."""

require_tools(("kubectl",))
result = run("kubectl", ["get", "namespace", config.namespace, "--ignore-not-found"])
if result.stdout.strip():
return
run("kubectl", ["create", "namespace", config.namespace])


def print_kubernetes_status(config: PreviewConfig) -> None:
"""Print namespace, service, and pod status for the preview release."""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use full NumPy docstrings for public functions.

Replace the single-line docstrings on Line 11 and Line 21 with structured NumPy sections (Parameters, Returns, and Raises where relevant).

🛠️ Proposed docstring update
 def ensure_namespace(config: PreviewConfig) -> None:
-    """Create the preview namespace when it does not already exist."""
+    """Create the preview namespace when absent.
+
+    Parameters
+    ----------
+    config
+        Preview configuration carrying the target namespace.
+
+    Returns
+    -------
+    None
+        This function mutates cluster state only when the namespace is missing.
+
+    Raises
+    ------
+    LocalK8sError
+        Raised when `kubectl` is unavailable or command execution fails.
+    """
@@
 def print_kubernetes_status(config: PreviewConfig) -> None:
-    """Print namespace, service, and pod status for the preview release."""
+    """Print Kubernetes status for the preview release.
+
+    Parameters
+    ----------
+    config
+        Preview configuration containing namespace and Helm release name.
+
+    Returns
+    -------
+    None
+        Status is printed to standard output.
+
+    Raises
+    ------
+    LocalK8sError
+        Raised when `kubectl` is unavailable or command execution fails.
+    """

As per coding guidelines: "Docstrings must follow the numpy style guide... full structured docs for all public interfaces."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/local_k8s/k8s.py` around lines 10 - 21, The short one-line docstrings
for the public functions ensure_namespace and print_kubernetes_status must be
replaced with full NumPy-style docstrings: for each function add a Parameters
section documenting the config parameter (type PreviewConfig and brief
description), a Returns section stating None, and a Raises section if the
function can propagate exceptions (e.g., from require_tools or run) — update the
docstrings for ensure_namespace and print_kubernetes_status accordingly to
follow the numpy style guide.

Comment on lines +20 to +23
@pytest.mark.parametrize("raw_value", ["0", "65536", "not-a-port"])
def test_validate_port_rejects_invalid_values(raw_value: str) -> None:
with pytest.raises(LocalK8sError):
validate_port(raw_value, default=8088, name="WILDSIDE_K3D_PORT")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP 'pytest\.raises\(\s*LocalK8sError\s*\)' scripts/local_k8s/unittests/test_validation.py

Repository: leynos/wildside

Length of output: 101


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n --hidden --no-ignore -S "def validate_port|validate_port\(" scripts/local_k8s
rg -n --hidden --no-ignore -S "class LocalK8sError|LocalK8sError\(" scripts/local_k8s

Repository: leynos/wildside

Length of output: 1402


🏁 Script executed:

#!/bin/bash
set -euo pipefail
nl -ba scripts/local_k8s/unittests/test_validation.py | sed -n '1,120p'

Repository: leynos/wildside

Length of output: 102


🏁 Script executed:

#!/bin/bash
set -euo pipefail
cat -n scripts/local_k8s/unittests/test_validation.py | sed -n '1,120p'

Repository: leynos/wildside

Length of output: 2195


🏁 Script executed:

#!/bin/bash
set -euo pipefail
cat -n scripts/local_k8s/validation.py | sed -n '1,120p'

Repository: leynos/wildside

Length of output: 1622


Constrain invalid-port exception assertions with regex.

Assert the invalid-port error-message contract for each input; the test currently checks only the exception type.

Patch
-@pytest.mark.parametrize("raw_value", ["0", "65536", "not-a-port"])
-def test_validate_port_rejects_invalid_values(raw_value: str) -> None:
-    with pytest.raises(LocalK8sError):
+@pytest.mark.parametrize(
+    ("raw_value", "message_pattern"),
+    [
+        ("0", r"must be between 1 and 65535"),
+        ("65536", r"must be between 1 and 65535"),
+        ("not-a-port", r"must be an integer TCP port"),
+    ],
+)
+def test_validate_port_rejects_invalid_values(raw_value: str, message_pattern: str) -> None:
+    with pytest.raises(LocalK8sError, match=message_pattern):
         validate_port(raw_value, default=8088, name="WILDSIDE_K3D_PORT")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/local_k8s/unittests/test_validation.py` around lines 20 - 23, The
test test_validate_port_rejects_invalid_values currently only asserts the
exception type; update it to assert the error message using a regex by passing
the match parameter to pytest.raises (or by capturing the exception and
asserting re.search) so the message contract from validate_port is verified for
each raw_value; reference the validate_port function and the test name
test_validate_port_rejects_invalid_values when making the change and ensure the
regex covers the expected phrasing (e.g., mentions invalid port or the given
raw_value) for each input.

Resolve the Helm fullname used for the Wildside Service before running
the status lookup. This keeps `local_k8s status` accurate when
`WILDSIDE_HELM_RELEASE` is set to a non-default release name.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Make the local k3d deployment preflight match the selected build mode.
`local_k8s up --skip-build` now checks only Helm, k3d, and kubectl,
while the image-building path still requires Docker.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant