From 9980dafc6d980daa7679ddbe1f80cea5be11a794 Mon Sep 17 00:00:00 2001 From: Dave Kowalski Date: Sun, 16 Aug 2026 06:22:32 +0000 Subject: [PATCH 1/2] fix: skip direct push when an open PR already targets the same image:tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before committing and pushing, query the Gitea API for open PRs in the apps repo. If any open PR modifies the same kustomization.yaml path and its diff contains the target tag, exit 0 — the PR is the intended review gate and the direct push would bypass it. Fails open on API errors so an outage does not block all deploys. Fixes bug-nxhza9j2atqk --- README.md | 7 ++++++- action.yaml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ded8ab..8ccec50 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,12 @@ the GitOps target so ArgoCD can sync it. 3. Run `kustomize build .` to validate the manifests still render. **Fails the workflow if validation breaks** — apps repo is left untouched. 4. If no diff (apps repo already on this tag): exit 0 silently. -5. Otherwise commit + push to `main`. On push rejection (concurrent CI race), +5. Query the Gitea API for open PRs in the apps repo. If any open PR modifies + the same `kustomization.yaml` and its patch contains the target tag, exit 0 + — the PR is the intended control gate and the direct push is skipped. Fails + open on API errors (push proceeds) to avoid blocking deploys during an + outage. +6. Otherwise commit + push to `main`. On push rejection (concurrent CI race), `git pull --rebase` and retry up to 3 times with linear backoff. ## Notes diff --git a/action.yaml b/action.yaml index 5fdf517..9a0b97c 100644 --- a/action.yaml +++ b/action.yaml @@ -67,6 +67,37 @@ runs: exit 0 fi + # Detect an open PR already targeting the same image:tag in the same + # kustomization.yaml. If one is open, defer to it so the review gate + # is the actual control path — not a race with the direct push. + GITEA_HOST="${APPS_REPO%%/*}" + GITEA_REPO_PATH="${APPS_REPO#*/}" + GITEA_API="https://${GITEA_HOST}/api/v1" + KUSTOMIZATION_FILE="${PATH_IN_REPO}/kustomization.yaml" + + BLOCKING_PR="" + PR_NUMS=$(curl -sf -H "Authorization: token ${TOKEN}" \ + "${GITEA_API}/repos/${GITEA_REPO_PATH}/pulls?state=open&limit=50" \ + | jq -r '.[].number' 2>/dev/null || true) + + for pr_num in $PR_NUMS; do + FILES_JSON=$(curl -sf -H "Authorization: token ${TOKEN}" \ + "${GITEA_API}/repos/${GITEA_REPO_PATH}/pulls/${pr_num}/files" || echo "[]") + if echo "$FILES_JSON" | jq -e \ + --arg f "$KUSTOMIZATION_FILE" \ + --arg t "$TAG" \ + 'any(.[]; .filename == $f and (.patch // "" | contains($t)))' \ + > /dev/null 2>&1; then + BLOCKING_PR="$pr_num" + break + fi + done + + if [ -n "$BLOCKING_PR" ]; then + echo "PR #${BLOCKING_PR} is open and already targets ${NAME}:${TAG} in ${KUSTOMIZATION_FILE}; deferring to PR" + exit 0 + fi + git -C "$WORK" add "${PATH_IN_REPO}/kustomization.yaml" git -C "$WORK" commit -m "$MSG" -- 2.54.0 From 64a9e90138003ffce1ee242d87dc2febf188792d Mon Sep 17 00:00:00 2001 From: Dave Kowalski Date: Sun, 16 Aug 2026 06:28:26 +0000 Subject: [PATCH 2/2] ci: add validate workflow to enable Hub review fan-out --- .gitea/workflows/validate.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .gitea/workflows/validate.yml diff --git a/.gitea/workflows/validate.yml b/.gitea/workflows/validate.yml new file mode 100644 index 0000000..b972fca --- /dev/null +++ b/.gitea/workflows/validate.yml @@ -0,0 +1,18 @@ +name: validate +on: + push: + branches: [main] + pull_request: +jobs: + validate: + runs-on: fritzlab + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - name: check action.yaml exists and has required fields + run: | + set -euo pipefail + test -f action.yaml || { echo "FATAL: action.yaml missing"; exit 1; } + grep -q "^name:" action.yaml + grep -q "^runs:" action.yaml + echo "action.yaml OK" -- 2.54.0