diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 7efee44..098af34 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -495,7 +495,7 @@ jobs: if: needs.build-and-push.result == 'success' run: | cd infra/apps/overlays/dev - kustomize edit set image ghcr.io/cartsnitch/cartsnitch=git.farh.net/cartsnitch/cartsnitch:${{ steps.frontend_tag.outputs.tag }} + kustomize edit set image ghcr.io/cartsnitch/app=git.farh.net/cartsnitch/cartsnitch:${{ steps.frontend_tag.outputs.tag }} - name: Determine image tag for receiptwitness id: receiptwitness_tag @@ -577,6 +577,16 @@ jobs: if [ "${REVIEW_HTTP}" -lt 200 ] || [ "${REVIEW_HTTP}" -ge 300 ]; then echo "::notice::Failed to request reviewers for cartsnitch/infra PR #${PR_NUM} (HTTP ${REVIEW_HTTP}); continuing" fi + # CAR-1216: the in-job merge attempt is a best-effort fast-path only. + # `cartsnitch/infra` main requires a human approving review (immutable + # branch protection); the CI bot (`CI_GITEA_TOKEN`) can never self- + # approve, so this merge call structurally cannot succeed in the + # general case. Any non-merged outcome (approvals pending, checks + # pending, any other Gitea message) is the GitOps approval gate, not + # a CI failure — the PR is already opened and `cs_savannah` is + # requested as reviewer above. Surface the response as a notice and + # exit success. The only hard-fail (`exit 1`) in this step remains + # the empty-`PR_NUM` check (PR could not be created at all). MERGE_RESP=$(curl -sS -X POST \ -H "Authorization: token ${CI_GITEA_TOKEN}" \ -H "Content-Type: application/json" \ @@ -585,17 +595,9 @@ jobs: MERGED=$(echo "$MERGE_RESP" | jq -r '.merged // false') if [ "$MERGED" = "true" ]; then echo "PR #${PR_NUM} merged into cartsnitch/infra main" - elif echo "$MERGE_RESP" | grep -qi 'does not have enough approvals'; then - # GitOps approval gate: the PR is correctly opened and surfaces in - # the CTO queue via the reviewers request above. Treat as success - # (exit 0) so the deploy job does not hard-fail on the approvals - # requirement that only a human maintainer can satisfy. - echo "::notice::infra PR #${PR_NUM} opened and awaiting CTO (cs_savannah) approve+merge — GitOps approval gate, not a failure" - exit 0 else - echo "::error::Auto-merge of cartsnitch/infra PR #${PR_NUM} failed: $MERGE_RESP" - echo "::error::Reassign to cs_savannah (authorized merger for cartsnitch/infra main) for backstop merge." - exit 1 + echo "::notice::infra PR #${PR_NUM} opened and awaiting CTO (cs_savannah) approve+merge — GitOps approval gate, not a failure: $MERGE_RESP" + exit 0 fi deploy-uat: @@ -639,7 +641,7 @@ jobs: if: needs.build-and-push.result == 'success' run: | cd infra/apps/overlays/uat - kustomize edit set image ghcr.io/cartsnitch/cartsnitch=git.farh.net/cartsnitch/cartsnitch:${{ steps.frontend_tag.outputs.tag }} + kustomize edit set image ghcr.io/cartsnitch/app=git.farh.net/cartsnitch/cartsnitch:${{ steps.frontend_tag.outputs.tag }} - name: Determine image tag for receiptwitness id: receiptwitness_tag @@ -721,6 +723,16 @@ jobs: if [ "${REVIEW_HTTP}" -lt 200 ] || [ "${REVIEW_HTTP}" -ge 300 ]; then echo "::notice::Failed to request reviewers for cartsnitch/infra PR #${PR_NUM} (HTTP ${REVIEW_HTTP}); continuing" fi + # CAR-1216: the in-job merge attempt is a best-effort fast-path only. + # `cartsnitch/infra` main requires a human approving review (immutable + # branch protection); the CI bot (`CI_GITEA_TOKEN`) can never self- + # approve, so this merge call structurally cannot succeed in the + # general case. Any non-merged outcome (approvals pending, checks + # pending, any other Gitea message) is the GitOps approval gate, not + # a CI failure — the PR is already opened and `cs_savannah` is + # requested as reviewer above. Surface the response as a notice and + # exit success. The only hard-fail (`exit 1`) in this step remains + # the empty-`PR_NUM` check (PR could not be created at all). MERGE_RESP=$(curl -sS -X POST \ -H "Authorization: token ${CI_GITEA_TOKEN}" \ -H "Content-Type: application/json" \ @@ -729,15 +741,7 @@ jobs: MERGED=$(echo "$MERGE_RESP" | jq -r '.merged // false') if [ "$MERGED" = "true" ]; then echo "PR #${PR_NUM} merged into cartsnitch/infra main" - elif echo "$MERGE_RESP" | grep -qi 'does not have enough approvals'; then - # GitOps approval gate: the PR is correctly opened and surfaces in - # the CTO queue via the reviewers request above. Treat as success - # (exit 0) so the deploy job does not hard-fail on the approvals - # requirement that only a human maintainer can satisfy. - echo "::notice::infra PR #${PR_NUM} opened and awaiting CTO (cs_savannah) approve+merge — GitOps approval gate, not a failure" - exit 0 else - echo "::error::Auto-merge of cartsnitch/infra PR #${PR_NUM} failed: $MERGE_RESP" - echo "::error::Reassign to cs_savannah (authorized merger for cartsnitch/infra main) for backstop merge." - exit 1 + echo "::notice::infra PR #${PR_NUM} opened and awaiting CTO (cs_savannah) approve+merge — GitOps approval gate, not a failure: $MERGE_RESP" + exit 0 fi diff --git a/auth/Dockerfile b/auth/Dockerfile index 0b88089..388fd9d 100644 --- a/auth/Dockerfile +++ b/auth/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22-alpine AS builder +FROM node:22-alpine@sha256:8ea2348b068a9544dae7317b4f3aafcdc032df1647bb7d768a05a5cad1a7683f AS builder RUN apk update && apk upgrade --no-cache WORKDIR /app COPY package.json package-lock.json* ./ @@ -7,7 +7,7 @@ COPY tsconfig.json ./ COPY src/ src/ RUN npm run build -FROM node:22-alpine +FROM node:22-alpine@sha256:8ea2348b068a9544dae7317b4f3aafcdc032df1647bb7d768a05a5cad1a7683f RUN apk update && apk upgrade --no-cache WORKDIR /app ENV NODE_ENV=production