ci(fxhnt): single-trigger sensor + in-workflow git-diff mode decision
This commit is contained in:
57
infra/argo/fxhnt-build-sensor.yaml
Normal file
57
infra/argo/fxhnt-build-sensor.yaml
Normal file
@@ -0,0 +1,57 @@
|
||||
# Argo Events Sensor — hears the shared Gitea webhook for pushes to gitadmin/fxhnt master, and submits the
|
||||
# fxhnt-cockpit WorkflowTemplate (ns foxhunt). Structurally identical to build-msp-portal (single dependency,
|
||||
# single trigger) — the build-vs-deploy decision is made INSIDE the workflow via `git diff` (decide-mode step in
|
||||
# fxhnt-cockpit-workflowtemplate.yaml), not via a sensor-side path filter. See
|
||||
# docs/superpowers/plans/2026-07-21-fxhnt-cicd-pipeline.md Task 3 design note: the Sensor CRD here has an open
|
||||
# schema, so trigger-level path-filter negation can't be reliably validated — keeping the sensor simple is the
|
||||
# robust choice.
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Sensor
|
||||
metadata:
|
||||
name: build-fxhnt
|
||||
namespace: argo-events
|
||||
labels: { app.kubernetes.io/instance: build-pipeline }
|
||||
spec:
|
||||
dependencies:
|
||||
- name: push-to-master
|
||||
eventSourceName: gitea-webhook
|
||||
eventName: push
|
||||
filters:
|
||||
dataLogicalOperator: and
|
||||
data:
|
||||
- path: body.ref
|
||||
type: string
|
||||
comparator: "="
|
||||
value: ["refs/heads/master"]
|
||||
- path: body.pusher.username
|
||||
type: string
|
||||
comparator: "!="
|
||||
value: ["argocd-image-updater"]
|
||||
template:
|
||||
serviceAccountName: argo-events-sa
|
||||
triggers:
|
||||
- template:
|
||||
name: submit-build
|
||||
argoWorkflow:
|
||||
operation: submit
|
||||
source:
|
||||
resource:
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Workflow
|
||||
metadata:
|
||||
generateName: build-fxhnt-
|
||||
namespace: foxhunt
|
||||
spec:
|
||||
workflowTemplateRef:
|
||||
name: fxhnt-cockpit
|
||||
arguments:
|
||||
parameters:
|
||||
- name: commit-sha
|
||||
value: ""
|
||||
- name: mode
|
||||
value: auto
|
||||
parameters:
|
||||
- src:
|
||||
dependencyName: push-to-master
|
||||
dataKey: body.after
|
||||
dest: spec.arguments.parameters.0.value
|
||||
@@ -24,15 +24,68 @@ spec:
|
||||
arguments:
|
||||
parameters:
|
||||
- { name: commit-sha, value: HEAD }
|
||||
- { name: mode, value: build } # "build" = kaniko rebuild + deploy; "deploy" = skip build, just apply + rollout restart (git-sync re-pulls code). The sensor routes src-only pushes to "deploy".
|
||||
- { name: mode, value: auto } # "auto" = decide-mode git-diffs commit-sha~1..commit-sha to pick build/deploy; "build" = force kaniko rebuild + deploy; "deploy" = force skip build, just apply + rollout restart (git-sync re-pulls code). A human can still force build/deploy via `argo submit -p mode=...`.
|
||||
templates:
|
||||
- name: pipeline
|
||||
dag:
|
||||
tasks:
|
||||
# decide-mode: when mode=auto, git-diffs the pushed commit against its parent to pick build vs deploy
|
||||
# (dep/Dockerfile changes -> build; anything else, or a missing parent, -> build/deploy per script logic
|
||||
# below). When mode is forced (build|deploy), decide-mode just echoes it back unchanged.
|
||||
- { name: decide-mode, template: decide-mode }
|
||||
# Skip the ~5min kaniko build for code-only pushes (mode=deploy) — git-sync re-pulls src/ on the
|
||||
# rollout restart, so only dep/Dockerfile changes need a new image (mode=build).
|
||||
- { name: build, template: kaniko-build, when: "{{workflow.parameters.mode}} == build" }
|
||||
- { name: deploy, template: kubectl-deploy, depends: "build.Succeeded || build.Skipped" }
|
||||
- { name: build, template: kaniko-build, depends: decide-mode, when: "{{tasks.decide-mode.outputs.parameters.mode}} == build" }
|
||||
- { name: deploy, template: kubectl-deploy, depends: "decide-mode && (build.Succeeded || build.Skipped)" }
|
||||
|
||||
# --- decide-mode: resolve "auto" to build|deploy via git diff of the pushed commit vs its parent ---
|
||||
- name: decide-mode
|
||||
metadata:
|
||||
labels: { app.kubernetes.io/part-of: argo-workflows }
|
||||
nodeSelector: { k8s.scaleway.com/pool-name: large, topology.kubernetes.io/zone: fr-par-2 }
|
||||
tolerations: [{ effect: NoSchedule, key: node.cilium.io/agent-not-ready, operator: Exists }]
|
||||
outputs:
|
||||
parameters:
|
||||
- name: mode
|
||||
valueFrom: { path: /tmp/mode }
|
||||
container:
|
||||
image: alpine/git:latest
|
||||
command: [/bin/sh, -c]
|
||||
args:
|
||||
- |
|
||||
set -e
|
||||
mkdir -p /root/.ssh
|
||||
cp /etc/git-ssh/ssh-privatekey /root/.ssh/id_ed25519
|
||||
chmod 600 /root/.ssh/id_ed25519
|
||||
printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > /root/.ssh/config
|
||||
git clone --filter=blob:none \
|
||||
"ssh://git@gitea-sshd.foxhunt.svc.cluster.local:22/gitadmin/fxhnt.git" /workspace/src
|
||||
cd /workspace/src && git checkout "{{workflow.parameters.commit-sha}}"
|
||||
|
||||
if [ "{{workflow.parameters.mode}}" != "auto" ]; then
|
||||
echo -n "{{workflow.parameters.mode}}" > /tmp/mode
|
||||
else
|
||||
SHA="{{workflow.parameters.commit-sha}}"
|
||||
RESOLVED="$(git rev-parse "$SHA")"
|
||||
if CHANGED=$(git diff --name-only "${RESOLVED}~1" "${RESOLVED}" 2>/dev/null); then
|
||||
# diff succeeded (parent exists): build only if a dep/Dockerfile file changed, else deploy.
|
||||
if echo "$CHANGED" | grep -qE '^pyproject\.toml$|^infra/docker/fxhnt\.Dockerfile$'; then
|
||||
echo -n build > /tmp/mode
|
||||
else
|
||||
echo -n deploy > /tmp/mode
|
||||
fi
|
||||
else
|
||||
# diff failed (no parent -- first commit / shallow history): default to build (safe, never wrong).
|
||||
echo -n build > /tmp/mode
|
||||
fi
|
||||
fi
|
||||
cat /tmp/mode
|
||||
volumeMounts:
|
||||
- { name: git-ssh-key, mountPath: /etc/git-ssh, readOnly: true }
|
||||
- { name: workspace, mountPath: /workspace }
|
||||
volumes:
|
||||
- { name: workspace, emptyDir: {} }
|
||||
- { name: git-ssh-key, secret: { secretName: argo-git-ssh-key, defaultMode: 256 } }
|
||||
|
||||
# --- build: Kaniko builds infra/docker/fxhnt.Dockerfile -> internal registry ---
|
||||
- name: kaniko-build
|
||||
|
||||
Reference in New Issue
Block a user