Broaden POST /issues/ so triggering_event_id is any non-empty traceability string, enabling cron/scheduled activity-core emissions with stable keys like "scheduled" while event-driven paths still send UUIDs. Document the railiance01 ArgoCD deployment path in docs/argocd-gitops.md and update ISSUE-WP-0003 task status to reflect repo-side progress.
5.7 KiB
ArgoCD GitOps deployment - railiance01
This runbook captures the issue-core side of the railiance01 GitOps pilot. It keeps secrets out of Git and leaves platform-owned bootstrap steps in railiance-platform.
Source layout
- Workload bundle:
issue-core/k8s/railiance/ - Image:
gitea.coulomb.social/coulomb/issue-core:0.2.0 - Container port and Service port:
8765 - Cluster Service URL:
http://issue-core.issue-core.svc.cluster.local:8765 - Tenant Application:
railiance-platform/argocd/applications/issue-core.application.yaml
The Application should point at this repo's k8s/railiance path and use
CreateNamespace=true for the issue-core namespace. The namespace itself is
therefore intentionally not duplicated in this bundle.
Platform gates
The following pieces are owned by railiance-platform before the workload can be fully reconciled:
- ArgoCD repository credentials and the project/app-of-apps convention.
- The
issue-coreArgoCDApplication. - External Secrets Operator and a
ClusterSecretStorenamedopenbao. - OpenBao entries for the issue-core runtime Secret.
Until those gates exist, kubectl kustomize k8s/railiance can render locally,
but the live ExternalSecret and Deployment are expected to wait.
Secret contract
Kubernetes Secret name: issue-core-runtime
Current issue-core manifest path, pending railiance-platform confirmation:
platform/workloads/issue-core/issue-core/issue-core-runtime
Credential route catalog id issue-core-ingestion-api-key is owned by
railiance-platform/OpenBao and is still marked draft/path TBD in the local
ops-warden catalog reviewed 2026-06-18. Confirm the canonical path before
provisioning the live Secret.
Required properties:
ISSUE_CORE_API_KEY- shared ingestion key used by issue-core and activity-core.GITEA_BACKEND_TOKEN- token for creating issues in cluster Gitea.
Never write either value to Git, State Hub, workplans, logs, or chat. Record only non-secret evidence such as Secret key count, ExternalSecret readiness, HTTP status codes, and created issue URLs.
Build and publish
Use the published package as the image input. For a reproducible release image, pin the package version to the image tag:
docker build --build-arg ISSUE_CORE_VERSION="==0.2.0" -t gitea.coulomb.social/coulomb/issue-core:0.2.0 .
docker push gitea.coulomb.social/coulomb/issue-core:0.2.0
The Coulomb Gitea package is public-pullable for this image, so the workload
does not use an imagePullSecret.
Pre-sync validation
From the issue-core repo:
kubectl kustomize k8s/railiance
The rendered resources should be:
ExternalSecret/issue-core-runtimeConfigMap/issue-core-backendsDeployment/issue-coreService/issue-core
Sync verification
After railiance-platform syncs the tenant Application:
kubectl get application issue-core -n argocd
kubectl -n issue-core get externalsecret issue-core-runtime
kubectl -n issue-core get secret issue-core-runtime
kubectl -n issue-core get deploy,pod,svc
Expected non-secret evidence:
- ArgoCD Application reports
SyncedandHealthy. ExternalSecret/issue-core-runtimereports Ready.Secret/issue-core-runtimeexists with two data keys.Deployment/issue-corehas one available replica.Service/issue-coreexposes port8765.
Health check from inside the cluster:
kubectl -n issue-core run issue-core-health --rm -i --restart=Never --image=curlimages/curl:8.8.0 -- http://issue-core:8765/healthz
Ingestion smoke
Run the authenticated smoke from a short-lived Job so the API key is mounted from the Kubernetes Secret without printing it:
kubectl -n issue-core delete job issue-core-smoke --ignore-not-found
kubectl -n issue-core apply -f - <<'YAML'
apiVersion: batch/v1
kind: Job
metadata:
name: issue-core-smoke
spec:
ttlSecondsAfterFinished: 600
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: smoke
image: curlimages/curl:8.8.0
env:
- name: ISSUE_CORE_API_KEY
valueFrom:
secretKeyRef:
name: issue-core-runtime
key: ISSUE_CORE_API_KEY
command: ["/bin/sh", "-ceu"]
args:
- |
curl -fsS -X POST "http://issue-core:8765/issues/" -H "Authorization: Bearer ${ISSUE_CORE_API_KEY}" -H "Content-Type: application/json" --data '{"title":"issue-core railiance01 smoke","description":"GitOps smoke created by the issue-core deployment runbook.","target_repo":"coulomb/markitect_project","priority":"low","labels":["smoke","issue-core"],"source_type":"rule","source_id":"issue-core-gitops-smoke","triggering_event_id":"scheduled","activity_definition_id":"issue-core-gitops-smoke"}'
YAML
kubectl -n issue-core wait --for=condition=complete job/issue-core-smoke --timeout=90s
kubectl -n issue-core logs job/issue-core-smoke
Acceptance evidence is HTTP 201 plus a response body containing issue_id,
backend: "gitea", and an issue_url for cluster Gitea.
Cleanup:
kubectl -n issue-core delete job issue-core-smoke
Activity-core handoff
After issue-core is Ready and the shared ISSUE_CORE_API_KEY is available to
activity-core from the same approved OpenBao source:
- Set
ISSUE_CORE_URL=http://issue-core.issue-core.svc.cluster.local:8765. - Set
ISSUE_SINK_TYPE=rest. - Inject the same
ISSUE_CORE_API_KEYinto the activity-core worker. - Keep cron-triggered emissions explicit:
triggering_event_idmay be a stable non-empty scheduler key such asscheduled; event-driven emissions should continue to send the event UUID.
Verify by running an activity-core emission and confirming that issue-core returns HTTP 201 and creates a Gitea issue.