fix: skip direct push when an open PR already targets the same image:tag

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
This commit is contained in:
dev
2026-08-16 06:22:32 +00:00
parent 511259e830
commit 9980dafc6d
2 changed files with 37 additions and 1 deletions
+6 -1
View File
@@ -47,7 +47,12 @@ the GitOps target so ArgoCD can sync it.
3. Run `kustomize build .` to validate the manifests still render. **Fails the 3. Run `kustomize build .` to validate the manifests still render. **Fails the
workflow if validation breaks** — apps repo is left untouched. workflow if validation breaks** — apps repo is left untouched.
4. If no diff (apps repo already on this tag): exit 0 silently. 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. `git pull --rebase` and retry up to 3 times with linear backoff.
## Notes ## Notes
+31
View File
@@ -67,6 +67,37 @@ runs:
exit 0 exit 0
fi 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" add "${PATH_IN_REPO}/kustomization.yaml"
git -C "$WORK" commit -m "$MSG" git -C "$WORK" commit -m "$MSG"