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.
This commit is contained in:
2026-06-24 14:52:47 +02:00
parent 4854bda118
commit 7693ef8680
5 changed files with 230 additions and 16 deletions

168
docs/argocd-gitops.md Normal file
View File

@@ -0,0 +1,168 @@
# 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:
```text
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:
```bash
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:
```bash
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`:
```bash
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:
```bash
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:
```bash
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:
```bash
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.