@@ -1195,6 +1195,127 @@ jobs:
11951195 echo "Publishing $SOURCE → $TARGET"
11961196 docker buildx imagetools create -t $TARGET $SOURCE
11971197
1198+ # ==========================================================================
1199+ # CI STATUS - Single required check for branch protection
1200+ # ==========================================================================
1201+ # This job aggregates the results of all CI jobs and provides a single
1202+ # status check for branch protection rules.
1203+ #
1204+ # To configure optional checks:
1205+ # 1. Go to Settings → Secrets and variables → Actions → Variables
1206+ # 2. Create a repository variable named OPTIONAL_CHECKS
1207+ # 3. Set its value to a comma-separated list of job names that should be optional
1208+ # Example: "test-e2e,test-zapier,helm-chart-lint"
1209+ #
1210+ # Jobs listed in OPTIONAL_CHECKS can fail without blocking the PR.
1211+ # Jobs NOT listed are required and must pass (or be skipped due to path filtering).
1212+ # ==========================================================================
1213+
1214+ ci-status :
1215+ name : CI Status
1216+ runs-on : ubuntu-latest
1217+ if : always()
1218+ needs :
1219+ # Lint jobs (can be skipped based on path changes)
1220+ - backend-lint
1221+ - frontend-lint
1222+ - dockerfile-lint
1223+ - helm-chart-lint
1224+ # Test jobs (can be skipped based on path changes)
1225+ - backend-check-startup
1226+ - test-backend
1227+ - test-frontend
1228+ - test-zapier
1229+ - check-mjml-compiled
1230+ # E2E tests (can be skipped based on path changes)
1231+ - test-e2e
1232+ - collect-e2e-reports
1233+ # Coverage (depends on test-backend)
1234+ - collect-coverage
1235+ steps :
1236+ - name : Evaluate CI results
1237+ env :
1238+ OPTIONAL_CHECKS : ${{ vars.OPTIONAL_CHECKS || '' }}
1239+ RESULTS : |
1240+ backend-lint=${{ needs.backend-lint.result }}
1241+ frontend-lint=${{ needs.frontend-lint.result }}
1242+ dockerfile-lint=${{ needs.dockerfile-lint.result }}
1243+ helm-chart-lint=${{ needs.helm-chart-lint.result }}
1244+ backend-check-startup=${{ needs.backend-check-startup.result }}
1245+ test-backend=${{ needs.test-backend.result }}
1246+ test-frontend=${{ needs.test-frontend.result }}
1247+ test-zapier=${{ needs.test-zapier.result }}
1248+ check-mjml-compiled=${{ needs.check-mjml-compiled.result }}
1249+ test-e2e=${{ needs.test-e2e.result }}
1250+ collect-e2e-reports=${{ needs.collect-e2e-reports.result }}
1251+ collect-coverage=${{ needs.collect-coverage.result }}
1252+ run : |
1253+ echo "=================================="
1254+ echo "CI Status Check"
1255+ echo "=================================="
1256+ echo ""
1257+ echo "Optional checks (from OPTIONAL_CHECKS variable):"
1258+ echo " ${OPTIONAL_CHECKS:-"(none configured)"}"
1259+ echo ""
1260+ echo "Job results:"
1261+ echo "$RESULTS" | grep -v '^$'
1262+ echo ""
1263+ echo "=================================="
1264+
1265+ # Convert OPTIONAL_CHECKS to an array for easier lookup
1266+ IFS=',' read -ra OPTIONAL_ARRAY <<< "$OPTIONAL_CHECKS"
1267+
1268+ is_optional() {
1269+ local job_name="$1"
1270+ for optional in "${OPTIONAL_ARRAY[@]}"; do
1271+ # Trim whitespace
1272+ optional=$(echo "$optional" | xargs)
1273+ if [[ "$job_name" == "$optional" ]]; then
1274+ return 0
1275+ fi
1276+ done
1277+ return 1
1278+ }
1279+
1280+ has_failure=false
1281+
1282+ while IFS='=' read -r job_name result; do
1283+ # Skip empty lines
1284+ [[ -z "$job_name" ]] && continue
1285+
1286+ # Trim whitespace
1287+ job_name=$(echo "$job_name" | xargs)
1288+ result=$(echo "$result" | xargs)
1289+
1290+ if is_optional "$job_name"; then
1291+ if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
1292+ echo "⚠️ $job_name: $result (optional - ignored)"
1293+ else
1294+ echo "✅ $job_name: $result (optional)"
1295+ fi
1296+ else
1297+ if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
1298+ echo "❌ $job_name: $result (required)"
1299+ has_failure=true
1300+ elif [[ "$result" == "skipped" ]]; then
1301+ echo "⏭️ $job_name: $result (skipped due to path filter)"
1302+ else
1303+ echo "✅ $job_name: $result"
1304+ fi
1305+ fi
1306+ done <<< "$RESULTS"
1307+
1308+ echo ""
1309+ echo "=================================="
1310+
1311+ if [[ "$has_failure" == "true" ]]; then
1312+ echo "❌ CI failed: one or more required checks failed"
1313+ exit 1
1314+ else
1315+ echo "✅ CI passed: all required checks passed (or were skipped)"
1316+ exit 0
1317+ fi
1318+
11981319 trigger-saas-build :
11991320 name : Trigger SaaS GitLab Pipeline
12001321 runs-on : ubuntu-latest
0 commit comments