Files
issue-core/docs/argocd-gitops.md
tegwick 7693ef8680 Accept non-UUID triggering_event_id and add GitOps runbook
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.
2026-06-24 14:52:47 +02:00

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-core ArgoCD Application.
  • External Secrets Operator and a ClusterSecretStore named openbao.
  • 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-runtime
  • ConfigMap/issue-core-backends
  • Deployment/issue-core
  • Service/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 Synced and Healthy.
  • ExternalSecret/issue-core-runtime reports Ready.
  • Secret/issue-core-runtime exists with two data keys.
  • Deployment/issue-core has one available replica.
  • Service/issue-core exposes port 8765.

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_KEY into the activity-core worker.
  • Keep cron-triggered emissions explicit: triggering_event_id may be a stable non-empty scheduler key such as scheduled; 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.