CI / CI (pull_request) Successful in 2m11s
Replaces ArgoCD Image Updater with a webhook-driven approach.
When Forgejo fires X-Gitea-Event: package (action: created, type: container):
1. Extract image owner+name+version from payload
2. Look up in static promotion table (10 images \u2192 ArgoCD apps)
3. Fetch digest from Forgejo registry v2 API (Basic auth, REGISTRY_PAT)
4. Read-modify-write ArgoCD Application CR via k8s API (in-cluster SA token)
- kustomize: JSON Patch /spec/sources[N]/kustomize/images
- helm: JSON Patch /spec/source/helm/parameters (runner.image.*)
5. Send Gotify notification with promotion result
Key design:
- Raw http.Client only \u2014 no client-go dependency
- context.Context propagated through all outbound calls
- Retry up to 3x on 409 Conflict (concurrent poimen-toolkit promotions)
- Request ID per invocation for log correlation
- Promotion table covers: api-gw, portfolio, poimen (3 sources), poimen-toolkit (2 images), forgejo-runner-{golang,node,rust}
RBAC: ClusterRole image-promoter (get+patch applications.argoproj.io) bound to api-gateway SA
NetworkPolicy: egress to cicd:3000 (registry) + default:443 (k8s API)
Deployment: REGISTRY_PAT from forgejo-registry-pat secret
13 tests in promoter_test.go, all pass
Closes #54
169 lines
4.1 KiB
YAML
169 lines
4.1 KiB
YAML
apiVersion: networking.k8s.io/v1
|
|
kind: NetworkPolicy
|
|
metadata:
|
|
name: api-gateway
|
|
namespace: api
|
|
labels:
|
|
app: api-gateway
|
|
spec:
|
|
podSelector:
|
|
matchLabels:
|
|
app: api-gateway
|
|
policyTypes:
|
|
- Ingress
|
|
- Egress
|
|
ingress:
|
|
# Allow from ingress-nginx controller (from ingress-nginx namespace)
|
|
- from:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
name: ingress-nginx
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow from Prometheus scraping (if in monitoring namespace)
|
|
- from:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
name: monitoring
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow from poimen namespace (orchestrator & worker pods)
|
|
# Enable Poimen workflows to call the LLM API gateway
|
|
- from:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: poimen
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow from portfolio namespace (riotpiao.com chat terminal)
|
|
- from:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: portfolio
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow from paperless namespace (paperless-ai document auto-tagging)
|
|
- from:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: paperless
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
egress:
|
|
# Allow DNS
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: kube-system
|
|
ports:
|
|
- protocol: UDP
|
|
port: 53
|
|
- protocol: TCP
|
|
port: 53
|
|
# Allow to upstreams (LLM services in llm-serving namespace)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: llm-serving
|
|
ports:
|
|
- protocol: TCP
|
|
port: 80
|
|
- protocol: TCP
|
|
port: 8000
|
|
- protocol: TCP
|
|
port: 8001
|
|
# Allow to other upstreams if needed (embeddings, reranker, etc.)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: llm-serving
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow to atlas (riotpiao-backend) for /cluster/* routes
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: atlas
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow to IAM (Authentik) for JWKS fetch + API
|
|
# Authentik pod listens on 9000 (http) and 9443 (https)
|
|
# Service translates 80→9000, 443→9443
|
|
# NetworkPolicy matches destination pod port, not service port
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: iam
|
|
ports:
|
|
- protocol: TCP
|
|
port: 9000
|
|
- protocol: TCP
|
|
port: 9443
|
|
# Allow to SQS (queue management service)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: sqs
|
|
ports:
|
|
- protocol: TCP
|
|
port: 9090
|
|
# Allow to Temporal (workflow engine gRPC)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: temporal
|
|
ports:
|
|
- protocol: TCP
|
|
port: 7233
|
|
# Allow to Poimen (memory/semantic search)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: poimen
|
|
ports:
|
|
- protocol: TCP
|
|
port: 8080
|
|
# Allow to Gotify (push notifications)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: notifications
|
|
ports:
|
|
- protocol: TCP
|
|
port: 80
|
|
# Allow to MinIO (S3-compatible storage)
|
|
# Service `minio` listens on port 80 (targetPort 9000).
|
|
# Headless `minio-cluster-hl` is 9000. Allow both.
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: storage
|
|
ports:
|
|
- protocol: TCP
|
|
port: 80
|
|
- protocol: TCP
|
|
port: 9000
|
|
# Allow to Forgejo registry v2 API (image digest lookup for promotion)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: cicd
|
|
ports:
|
|
- protocol: TCP
|
|
port: 3000
|
|
# Allow to kubernetes API server (ArgoCD Application patching via in-cluster SA)
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: default
|
|
ports:
|
|
- protocol: TCP
|
|
port: 443
|