Align k8s manifests with convention and add /metrics endpoint #3

Closed
opened 2026-03-02 08:27:20 +00:00 by forgejo_admin · 5 comments
Contributor

Type

Feature

Lineage

Standalone — discovered during platform onboarding of linkedin-scheduler-remote. Original issue scope was ~80% complete at time of filing; this rewrite reflects only the remaining delta.

Repo

forgejo_admin/linkedin-scheduler-remote

User Story

As a platform operator
I want linkedin-scheduler-remote's k8s manifests to follow the split-file convention and expose a /metrics endpoint
So that ArgoCD syncs are clean, ServiceMonitor scraping works, and the repo matches every other onboarded service

Context

linkedin-scheduler-remote was onboarded to the k3s cluster with a working CI pipeline (.woodpecker.yml), Dockerfile, Deployment, ServiceMonitor, and kustomization.yaml already on main. However, the Deployment manifest bundles Service and PVC inline (multi-document YAML), which breaks the one-resource-per-file convention used by every other onboarded service. Additionally, server.py has no /metrics endpoint, so the ServiceMonitor (scraping /metrics at 30s intervals) is hitting 404. Ruff config in pyproject.toml is already correct.

File Targets

Files the agent should modify or create:

  • k8s/deployment.yaml — remove the inline --- Service and PVC documents, leaving only the Deployment resource
  • k8s/service.yamlnew file, extracted Service (port 8000) from deployment.yaml
  • k8s/pvc.yamlnew file, extracted PVC (linkedin-mcp-data, 100Mi local-path) from deployment.yaml
  • k8s/kustomization.yaml — add service.yaml and pvc.yaml to the resources list
  • server.py — add a /metrics HTTP endpoint returning Prometheus-format metrics (at minimum: uptime, request count)

Files the agent should NOT touch:

  • .woodpecker.yml — CI pipeline is correct as-is
  • Dockerfile — container build is correct as-is
  • k8s/servicemonitor.yaml — already configured for /metrics:8000 at 30s
  • pyproject.toml — ruff config already present and correct

Acceptance Criteria

  • k8s/deployment.yaml contains only the Deployment resource (no --- separators, no Service, no PVC)
  • k8s/service.yaml exists with the Service resource (port 8000, selector app: linkedin-scheduler-remote)
  • k8s/pvc.yaml exists with the PVC resource (linkedin-mcp-data, 100Mi, local-path)
  • k8s/kustomization.yaml lists all four resources: deployment.yaml, service.yaml, pvc.yaml, servicemonitor.yaml
  • server.py exposes GET /metrics returning Prometheus text format (at minimum: uptime_seconds, http_requests_total)
  • When ArgoCD syncs, the ServiceMonitor successfully scrapes /metrics (no more 404)
  • When I push to main, Woodpecker CI passes ruff lint/format and builds/pushes the image to Harbor

Test Expectations

  • Manual: kubectl kustomize k8s/ renders four separate resources (Deployment, Service, PVC, ServiceMonitor)
  • Manual: curl http://localhost:8000/metrics returns Prometheus text format with at least one metric
  • CI: ruff lint and ruff format pass in Woodpecker pipeline
  • Run command: cd k8s && kubectl kustomize . to verify manifest correctness locally

Constraints

  • Follow the one-resource-per-file k8s convention used by all other onboarded services (notion-mcp-remote, basketball-api, etc.)
  • The /metrics endpoint must use Prometheus text exposition format (text/plain; version=0.0.4) — no external dependencies like prometheus_client required, a simple hand-rolled response is acceptable
  • Stale PR #4 (3-add-woodpecker-ci-pipeline-and-k8s-manif) is open and not mergeable. It was created against the original full-scope issue and includes files that already exist on main. The agent should close PR #4 and open a fresh PR scoped to only this delta work.
  • Do not rename .woodpecker.yml to .woodpecker.yaml — the existing filename is what Woodpecker CI reads

Checklist

  • PR opened (new PR, after closing stale PR #4)
  • Tests pass (ruff lint + kustomize build)
  • No unrelated changes
  • project-pal-e — pal-e platform infrastructure
  • review-65-2026-03-27-v2 — scope review that identified the refinement gaps
### Type Feature ### Lineage Standalone — discovered during platform onboarding of linkedin-scheduler-remote. Original issue scope was ~80% complete at time of filing; this rewrite reflects only the remaining delta. ### Repo `forgejo_admin/linkedin-scheduler-remote` ### User Story As a platform operator I want linkedin-scheduler-remote's k8s manifests to follow the split-file convention and expose a /metrics endpoint So that ArgoCD syncs are clean, ServiceMonitor scraping works, and the repo matches every other onboarded service ### Context linkedin-scheduler-remote was onboarded to the k3s cluster with a working CI pipeline (.woodpecker.yml), Dockerfile, Deployment, ServiceMonitor, and kustomization.yaml already on main. However, the Deployment manifest bundles Service and PVC inline (multi-document YAML), which breaks the one-resource-per-file convention used by every other onboarded service. Additionally, server.py has no /metrics endpoint, so the ServiceMonitor (scraping /metrics at 30s intervals) is hitting 404. Ruff config in pyproject.toml is already correct. ### File Targets Files the agent should modify or create: - `k8s/deployment.yaml` — remove the inline `---` Service and PVC documents, leaving only the Deployment resource - `k8s/service.yaml` — **new file**, extracted Service (port 8000) from deployment.yaml - `k8s/pvc.yaml` — **new file**, extracted PVC (linkedin-mcp-data, 100Mi local-path) from deployment.yaml - `k8s/kustomization.yaml` — add `service.yaml` and `pvc.yaml` to the resources list - `server.py` — add a `/metrics` HTTP endpoint returning Prometheus-format metrics (at minimum: uptime, request count) Files the agent should NOT touch: - `.woodpecker.yml` — CI pipeline is correct as-is - `Dockerfile` — container build is correct as-is - `k8s/servicemonitor.yaml` — already configured for /metrics:8000 at 30s - `pyproject.toml` — ruff config already present and correct ### Acceptance Criteria - [ ] `k8s/deployment.yaml` contains only the Deployment resource (no `---` separators, no Service, no PVC) - [ ] `k8s/service.yaml` exists with the Service resource (port 8000, selector app: linkedin-scheduler-remote) - [ ] `k8s/pvc.yaml` exists with the PVC resource (linkedin-mcp-data, 100Mi, local-path) - [ ] `k8s/kustomization.yaml` lists all four resources: deployment.yaml, service.yaml, pvc.yaml, servicemonitor.yaml - [ ] `server.py` exposes `GET /metrics` returning Prometheus text format (at minimum: uptime_seconds, http_requests_total) - [ ] When ArgoCD syncs, the ServiceMonitor successfully scrapes /metrics (no more 404) - [ ] When I push to main, Woodpecker CI passes ruff lint/format and builds/pushes the image to Harbor ### Test Expectations - [ ] Manual: `kubectl kustomize k8s/` renders four separate resources (Deployment, Service, PVC, ServiceMonitor) - [ ] Manual: `curl http://localhost:8000/metrics` returns Prometheus text format with at least one metric - [ ] CI: ruff lint and ruff format pass in Woodpecker pipeline - Run command: `cd k8s && kubectl kustomize .` to verify manifest correctness locally ### Constraints - Follow the one-resource-per-file k8s convention used by all other onboarded services (notion-mcp-remote, basketball-api, etc.) - The /metrics endpoint must use Prometheus text exposition format (text/plain; version=0.0.4) — no external dependencies like prometheus_client required, a simple hand-rolled response is acceptable - **Stale PR #4** (`3-add-woodpecker-ci-pipeline-and-k8s-manif`) is open and not mergeable. It was created against the original full-scope issue and includes files that already exist on main. The agent should **close PR #4** and open a fresh PR scoped to only this delta work. - Do not rename `.woodpecker.yml` to `.woodpecker.yaml` — the existing filename is what Woodpecker CI reads ### Checklist - [ ] PR opened (new PR, after closing stale PR #4) - [ ] Tests pass (ruff lint + kustomize build) - [ ] No unrelated changes ### Related - `project-pal-e` — pal-e platform infrastructure - `review-65-2026-03-27-v2` — scope review that identified the refinement gaps
Author
Contributor

Scope Review: NEEDS_REFINEMENT

Review note: review-65-2026-03-27

Traceability is complete (story:superuser-onboard, arch:ci-pipeline, type:feature). Issue is open and correctly placed.

Issues found:

  • Scope is ~80% stale: .woodpecker.yml, Dockerfile, k8s/deployment.yaml (with Service+PVC inline), and k8s/servicemonitor.yaml already exist on main. The issue describes creating files that are already there.
  • Missing template sections: File Targets, Context, Constraints, Test Expectations (5/11 required sections missing)
  • Remaining delta is small: split inline Service/PVC into separate k8s files, update kustomization.yaml, add /metrics endpoint to server.py, verify ruff config in pyproject.toml
  • File naming mismatch: existing .woodpecker.yml vs pattern .woodpecker.yaml; existing Dockerfile vs issue's Dockerfile.k8s
  • No /metrics endpoint: server.py has no /metrics — the only substantive missing feature

Before moving to next_up: rewrite scope to reflect only the remaining delta, or consider closing and opening a smaller issue for the /metrics + file-split work.

## Scope Review: NEEDS_REFINEMENT Review note: `review-65-2026-03-27` Traceability is complete (story:superuser-onboard, arch:ci-pipeline, type:feature). Issue is open and correctly placed. **Issues found:** - **Scope is ~80% stale**: `.woodpecker.yml`, `Dockerfile`, `k8s/deployment.yaml` (with Service+PVC inline), and `k8s/servicemonitor.yaml` already exist on main. The issue describes creating files that are already there. - **Missing template sections**: File Targets, Context, Constraints, Test Expectations (5/11 required sections missing) - **Remaining delta is small**: split inline Service/PVC into separate k8s files, update kustomization.yaml, add /metrics endpoint to server.py, verify ruff config in pyproject.toml - **File naming mismatch**: existing `.woodpecker.yml` vs pattern `.woodpecker.yaml`; existing `Dockerfile` vs issue's `Dockerfile.k8s` - **No /metrics endpoint**: server.py has no /metrics — the only substantive missing feature Before moving to next_up: rewrite scope to reflect only the remaining delta, or consider closing and opening a smaller issue for the /metrics + file-split work.
Author
Contributor

Issue body updated per scope review corrections.

Issue body updated per scope review corrections.
Author
Contributor

Scope Review: NEEDS_REFINEMENT

Review note: review-65-2026-03-27-v2

Issue body was updated after prior review but still has 6 of 11 required feature template sections missing (Type, Lineage, Context, File Targets, Test Expectations, Constraints).

Issues found:

  • Missing 6 template sections per template-issue-feature
  • Deprecated ### Plan header instead of ### Lineage
  • No acceptance criterion for /metrics endpoint (the only substantive code change -- server.py has no /metrics, ServiceMonitor is 404ing)
  • Stale PR #4 exists -- agent needs guidance (close or build on it)
  • Title is misleading -- ~80% of work is done, only delta remains (split Service/PVC, update kustomization.yaml, add /metrics)

File targets all verified accurate. Traceability complete (story:superuser-onboard, arch:ci-pipeline). No decomposition needed. No blocking dependencies.

## Scope Review: NEEDS_REFINEMENT Review note: `review-65-2026-03-27-v2` Issue body was updated after prior review but still has 6 of 11 required feature template sections missing (Type, Lineage, Context, File Targets, Test Expectations, Constraints). **Issues found:** - Missing 6 template sections per `template-issue-feature` - Deprecated `### Plan` header instead of `### Lineage` - No acceptance criterion for /metrics endpoint (the only substantive code change -- server.py has no /metrics, ServiceMonitor is 404ing) - Stale PR #4 exists -- agent needs guidance (close or build on it) - Title is misleading -- ~80% of work is done, only delta remains (split Service/PVC, update kustomization.yaml, add /metrics) **File targets all verified accurate.** Traceability complete (story:superuser-onboard, arch:ci-pipeline). No decomposition needed. No blocking dependencies.
forgejo_admin changed title from Add Woodpecker CI pipeline and k8s manifests to Align k8s manifests with convention and add /metrics endpoint 2026-03-28 05:48:32 +00:00
Author
Contributor

Issue Refined per review-65-2026-03-27-v2

Title updated: "Add Woodpecker CI pipeline and k8s manifests" → "Align k8s manifests with convention and add /metrics endpoint" (reflects actual remaining delta, not the original full scope)

Body rewritten to include all 11 required sections from template-issue-feature:

  • Added ### Type (Feature)
  • Replaced deprecated ### Plan with ### Lineage
  • Added ### Context explaining why the remaining work matters
  • Added ### File Targets with explicit modify/create/do-not-touch lists (verified against main)
  • Added ### Test Expectations with kustomize and curl verification steps
  • Added ### Constraints including stale PR #4 guidance (close and open fresh PR)

Acceptance criteria expanded: Added /metrics AC (the only substantive code change — server.py currently has no /metrics, so ServiceMonitor is 404ing).

Verified against main:

  • server.py — no /metrics endpoint (confirmed)
  • k8s/deployment.yaml — contains inline Service + PVC (confirmed, needs split)
  • k8s/kustomization.yaml — only lists deployment.yaml + servicemonitor.yaml (confirmed)
  • pyproject.toml — ruff config already present (no work needed)
  • .woodpecker.yml — exists and correct (no work needed)
  • Dockerfile — exists and correct (no work needed)
## Issue Refined per review-65-2026-03-27-v2 **Title updated:** "Add Woodpecker CI pipeline and k8s manifests" → "Align k8s manifests with convention and add /metrics endpoint" (reflects actual remaining delta, not the original full scope) **Body rewritten** to include all 11 required sections from `template-issue-feature`: - Added `### Type` (Feature) - Replaced deprecated `### Plan` with `### Lineage` - Added `### Context` explaining why the remaining work matters - Added `### File Targets` with explicit modify/create/do-not-touch lists (verified against main) - Added `### Test Expectations` with kustomize and curl verification steps - Added `### Constraints` including stale PR #4 guidance (close and open fresh PR) **Acceptance criteria expanded:** Added /metrics AC (the only substantive code change — server.py currently has no /metrics, so ServiceMonitor is 404ing). **Verified against main:** - `server.py` — no /metrics endpoint (confirmed) - `k8s/deployment.yaml` — contains inline Service + PVC (confirmed, needs split) - `k8s/kustomization.yaml` — only lists deployment.yaml + servicemonitor.yaml (confirmed) - `pyproject.toml` — ruff config already present (no work needed) - `.woodpecker.yml` — exists and correct (no work needed) - `Dockerfile` — exists and correct (no work needed)
Author
Contributor

Scope Review: READY

Review note: review-65-2026-03-27-v3

Third review (v3) after full template rewrite. All 11 required sections from template-issue-feature are present and accurate. Traceability triangle complete (story:superuser-onboard, arch:ci-pipeline, Forgejo issue open). All 5 file targets verified against repo main branch — deployment.yaml confirmed multi-doc, service.yaml/pvc.yaml confirmed absent, server.py confirmed no /metrics endpoint. Blast radius is low (aligns with existing convention in notion-mcp-remote). No decomposition needed — estimated ~3 min agent pass.

Ticket is ready to move to next_up.

## Scope Review: READY Review note: `review-65-2026-03-27-v3` Third review (v3) after full template rewrite. All 11 required sections from `template-issue-feature` are present and accurate. Traceability triangle complete (story:superuser-onboard, arch:ci-pipeline, Forgejo issue open). All 5 file targets verified against repo main branch — deployment.yaml confirmed multi-doc, service.yaml/pvc.yaml confirmed absent, server.py confirmed no /metrics endpoint. Blast radius is low (aligns with existing convention in notion-mcp-remote). No decomposition needed — estimated ~3 min agent pass. Ticket is ready to move to next_up.
forgejo_admin 2026-03-28 05:58:26 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/linkedin-scheduler-remote#3
No description provided.