Introduce Dockerfile, entrypoint, and k8s/railiance manifests for the ArgoCD GitOps pilot (ISSUE-WP-0003). Rename the Gitea PyPI build arg to GITEA_PYPI_INDEX_URL so pip still resolves dependencies from PyPI.
9.9 KiB
id, type, title, domain, repo, status, owner, topic_slug, created, updated, state_hub_workstream_id
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| ISSUE-WP-0003 | workplan | Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot) | custodian | issue-core | active | claude | custodian | 2026-06-19 | 2026-06-19 |
Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot)
issue-core is the authoritative task-lifecycle manager and the REST ingestion
target for activity-core's IssueSink. Deployment artifacts (Dockerfile,
docker-entrypoint.sh, k8s/railiance/) are now in-repo; the image builds
locally and /healthz returns 200. The railiance01 cluster still has no
issue-core namespace or workload — nothing is deployed until T01 push and
T02 ArgoCD bootstrap complete.
This workplan stands up issue-core as a first-class in-cluster service on
railiance01 via ArgoCD GitOps — making issue-core the cluster's first
declarative Application and turning on the idle GitOps capability.
Current state (verified 2026-06-19)
- Deployment artifacts in-repo:
Dockerfile,docker-entrypoint.sh, andk8s/railiance/(Kustomize: ExternalSecret, ConfigMap, Deployment, Service). Image builds locally;docker run+GET /healthzreturns 200. Image not yet pushed togitea.coulomb.social/coulomb/issue-core:0.2.0. - Dockerfile fix (2026-06-19): build arg renamed
GITEA_PYPI_INDEX_URL—ARG PIP_INDEX_URLleaked into the build env and pip used Gitea as the sole index, so dependencies likeclickwere not found. - railiance01 cluster: no
issue-corenamespace; no issue-core Deployment/Service/Pod in any namespace. - Dangling reference:
activity-core/k8s/railiance/20-runtime.yamlsetsISSUE_CORE_URL: http://issue-core.issue-core.svc.cluster.local:8010— a service that does not exist, on the wrong port (issue-core serves 8765) — withISSUE_SINK_TYPE: "null"so emission is disabled. It is a placeholder. - Packaging precursor is done:
ISSUE-WP-0002publishedissue-core==0.2.0to the Coulomb Gitea PyPI index. - ArgoCD is installed but unused: all 7 components healthy (~290d), but
0 Applications, 0 ApplicationSets, 0 registered git repos, only the stock
defaultAppProject. Nokind: Applicationmanifests exist in any infra repo. - Existing deploy pattern is imperative (the path we are replacing for
this service): local
docker build→k3s ctr images import(side-load, no registry) →rsyncmanifests →kubectl apply(seeactivity-core/k8s/railiance/README.md).
Decisions
- Deployment method = ArgoCD GitOps (operator decision 2026-06-19). issue-core is the pilot Application; the imperative side-load pattern is not used for this service.
- ArgoCD bootstrap owned by
railiance-platform(operator decision 2026-06-19). Platform owns repo registration, AppProject/app-of-apps conventions, and the External-Secrets/OpenBao plumbing. issue-core only contributes itsApplicationmanifest + workload manifests into the agreed GitOps source. T02 is therefore a cross-repo dependency, not issue-core work — see handoff to railiance-platform. - Backend = cluster Gitea (markitect) (operator decision 2026-06-19). Ingested tasks route to the existing Gitea backend; no new Postgres/PVC.
- Secret management = OpenBao.
ISSUE_CORE_API_KEYis a shared ingestion key injected from OpenBao on both issue-core and the activity-core worker. ops-warden does not vend it (see~/ops-warden/wiki/playbooks/activity-core-issue-sink.md). Coordinate the canonical path withrailiance-platform(issue-core-ingestion-api-key). - Image delivery = container registry, not side-load. GitOps requires a pullable image tag in a registry the cluster can reach (the Coulomb Gitea container registry); side-loading defeats declarative reproducibility.
Open questions
- GitOps source repo. Resolved by
railiance-platformas part of the bootstrap (T02 dependency): where issue-core'sApplication+ manifests are expected to live (its ownissue-core/k8s/vs. a platform GitOps repo) and the AppProject/app-of-apps convention to follow. - Registry path & pull secret. Confirm the Coulomb Gitea container registry
path and the cluster pull-secret posture (tracked in
railiance-forgecontainer-registry docs andrailiance-apps-WP-0004I03).
Container image published to a pullable registry
id: ISSUE-WP-0003-T01
status: in_progress
priority: high
Goal. A reproducible, registry-hosted image ArgoCD-managed pods can pull.
- Add
Dockerfileinstallingissue-core[api]>=0.2,<0.3from the Gitea PyPI index (with explicit PyPI primary index). Entrypoint rendersbackends.jsonthenissue serve --host 0.0.0.0 --port 8765. - Local build succeeds;
docker run+GET /healthzreturns 200. - Build and push to the Coulomb Gitea container registry (confirm path
per Open questions); tag
0.2.0. - Configure the cluster pull secret so
issue-corenamespace pods can pull. - Verify:
POST /issues/smoke; pushed tag pullable from the cluster.
ArgoCD bootstrap (railiance-platform dependency) + issue-core Application
id: ISSUE-WP-0003-T02
status: wait
priority: high
Owner split. ArgoCD bootstrap is railiance-platform's (operator
decision 2026-06-19): repo registration in ArgoCD, AppProject/app-of-apps
convention, and the agreed GitOps source layout. This task is wait on that
handoff. issue-core's part is to contribute the Application manifest +
workload manifests into the layout platform defines.
- (railiance-platform) Register the GitOps source repo (repository Secret + creds); define AppProject for cluster services; publish the source-repo/path convention and sync policy.
- (issue-core) Once the convention is known: author the
issue-coreArgoCDApplicationmanifest (source repo/path/revision → destinationissue-corenamespace) per the platform layout. - Verify:
kubectl get applications -n argocdshowsissue-coreSynced/Healthy; ArgoCD reconciles a trivial manifest change.
Kubernetes manifests (namespace, Deployment, Service) in GitOps source
id: ISSUE-WP-0003-T03
status: in_progress
priority: high
Goal. Declarative manifests in the GitOps source repo, synced by T02.
k8s/railiance/Kustomize bundle (namespace via ArgoCDCreateNamespace=true).- Deployment: registry image tag
0.2.0; port 8765;/healthzprobes; resource requests/limits; env from ExternalSecret (T04) and ConfigMap (T05). - Service: ClusterIP on 8765 as
issue-core.issue-core.svc.cluster.local. - Verify: ArgoCD syncs the manifests; Pod Ready;
/healthz200 from a debug pod (blocked on T01 push + T02 bootstrap + T04 secrets).
OpenBao secret: ISSUE_CORE_API_KEY
id: ISSUE-WP-0003-T04
status: todo
priority: high
Goal. The shared ingestion key delivered to both sides from OpenBao.
- Provision
ISSUE_CORE_API_KEYin OpenBao at the canonical path (coordinate withrailiance-platform; catalog idissue-core-ingestion-api-key). - Deliver into the issue-core Deployment (T03) and the activity-core worker (T06) with the same value (External Secrets / Bao injector — match the cluster's established mechanism).
- Never write the value to Git, manifests, State Hub, or logs.
- Verify: both pods resolve a non-empty key; auth round-trip (401 without, 201 with).
In-cluster backend config (cluster Gitea / markitect)
id: ISSUE-WP-0003-T05
status: in_progress
priority: medium
Goal. issue-core's backends.json inside the cluster points default at
the cluster Gitea (markitect) backend.
- ConfigMap
issue-core-backendswith in-cluster Gitea URL (gitea-http.default.svc.cluster.local:3000); token sentinel__FROM_ENV__. docker-entrypoint.shrenders~/.config/issue-tracker/backends.jsonfromBACKENDS_TEMPLATE+GITEA_BACKEND_TOKENat startup.- Verify: a
POST /issues/creates a real Gitea issue and returnsissue_url(blocked on T04 secrets + in-cluster deployment).
Wire activity-core to the live service
id: ISSUE-WP-0003-T06
status: todo
priority: high
Goal. activity-core emits to the live issue-core Service.
- Fix
activity-core/k8s/railiance/20-runtime.yaml:ISSUE_CORE_URLport8010 -> 8765; flipISSUE_SINK_TYPEnull -> restonce issue-core is Ready. - Inject
ISSUE_CORE_API_KEYinto the activity-core worker from the same OpenBao secret (T04). - Contract gap: issue-core requires
triggering_event_idas a UUID; activity-core cron paths may send non-UUID keys (e.g."scheduled"). Event-driven emission with real event UUIDs works (thestr()guard inissue_sink.py, commit f05c56e, handles UUID objects). Align schemas before enablingrestfor cron-triggered rules. - Verify: an activity-core run emits a task that lands in cluster Gitea via issue-core.
End-to-end verification + GitOps runbook
id: ISSUE-WP-0003-T07
status: todo
priority: medium
Goal. Confirm the deployed service is healthy and document the new path.
- ArgoCD Application Synced/Healthy; issue-core Pod Ready; Service reachable cluster-internal.
- activity-core → issue-core emission returns 201 and creates a Gitea issue.
- Document the GitOps runbook (image build/push, ArgoCD sync, secret rotation,
rollback) in
docs/. - Emit an
add_progress_eventmilestone to the hub on completion.
See also
ISSUE-WP-0002— Gitea PyPI publication (packaging precursor, finished).railiance-apps-WP-0004I03 — issue-core packaging/image enablement notes.railiance-forge— Gitea container registry docs.activity-core/docs/issue-core-emission-boundary.md— emission contract.activity-core/k8s/railiance/README.md— the imperative pattern being superseded for this service.~/ops-warden/wiki/playbooks/activity-core-issue-sink.md— key routing.