2026-09-16 10:34:38 +02:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# Guard the trap in .gitea/workflows.
|
|
|
|
|
#
|
|
|
|
|
# Gitea uses .gitea/workflows IF IT EXISTS, and falls back to .github/workflows
|
|
|
|
|
# only when it does not. It never merges them. So a workflow that lives only in
|
|
|
|
|
# .github/ simply does not run on Gitea — no error, no run to click on. It
|
|
|
|
|
# looks exactly like a runner that has not picked the job up, so you wait, and
|
|
|
|
|
# waiting never fixes it.
|
|
|
|
|
#
|
|
|
|
|
# Workflows that must behave identically on both forges are therefore kept
|
|
|
|
|
# byte-identical in both roots, and this script fails when they drift or when
|
|
|
|
|
# one appears in only one root without a stated reason.
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
cd "$(dirname "$0")/.."
|
2026-09-17 00:37:30 +02:00
|
|
|
. ci/lib.sh
|
2026-09-16 10:34:38 +02:00
|
|
|
|
|
|
|
|
# Workflows that are deliberately single-forge, and why.
|
|
|
|
|
declare -A only_on=(
|
|
|
|
|
["auto-merge.yml"]="github: it drives the GitHub merge API. Gitea merges the owner's green PRs itself."
|
|
|
|
|
["release.yml"]="both, but different: each publishes to the forge it runs on, and Gitea is where the update feed lives."
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
fail=0
|
|
|
|
|
|
|
|
|
|
for root in .github .gitea; do
|
|
|
|
|
[ -d "$root/workflows" ] || { echo "$root/workflows is missing."; fail=1; }
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
for f in .github/workflows/*.yml .gitea/workflows/*.yml; do
|
|
|
|
|
[ -e "$f" ] || continue
|
|
|
|
|
name=$(basename "$f")
|
|
|
|
|
gh=".github/workflows/$name"
|
|
|
|
|
gt=".gitea/workflows/$name"
|
|
|
|
|
|
|
|
|
|
case "${only_on[$name]:-}" in
|
|
|
|
|
github:*)
|
|
|
|
|
[ -f "$gt" ] && { echo "$name is marked GitHub-only but exists in .gitea/workflows too."; fail=1; }
|
|
|
|
|
continue
|
|
|
|
|
;;
|
|
|
|
|
both,*|"both, "*)
|
|
|
|
|
# Present in both, intentionally different. Both copies must exist.
|
|
|
|
|
{ [ -f "$gh" ] && [ -f "$gt" ]; } \
|
|
|
|
|
|| { echo "$name is expected in both roots, but one copy is missing."; fail=1; }
|
|
|
|
|
continue
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
if [ ! -f "$gh" ] || [ ! -f "$gt" ]; then
|
|
|
|
|
echo "$name exists in only one workflow root and is not listed in ci/workflows-in-sync.sh."
|
|
|
|
|
echo " A workflow missing from .gitea/workflows does not run on Gitea, silently."
|
|
|
|
|
fail=1
|
|
|
|
|
continue
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ! cmp -s "$gh" "$gt"; then
|
|
|
|
|
echo "$name has drifted between the two roots:"
|
|
|
|
|
diff -u "$gh" "$gt" || true
|
|
|
|
|
fail=1
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Measured on Gitea 1.27.2: a workflow-level `concurrency:` block produced no
|
|
|
|
|
# run at all — not a failed one, not a cancelled one. It may have been fixed
|
|
|
|
|
# since, but the cost of keeping the rule is nil and the cost of rediscovering
|
|
|
|
|
# it is an afternoon of blaming the runner.
|
|
|
|
|
if grep -rn '^concurrency:' .gitea/workflows/ 2>/dev/null; then
|
|
|
|
|
echo "A workflow-level concurrency: block can stop a Gitea workflow from running at all."
|
|
|
|
|
fail=1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# A workflow that does not parse produces no run — the same symptom as every
|
|
|
|
|
# other trap in this file. ci.yml cannot catch its own syntax error this way,
|
|
|
|
|
# but release.yml and compat.yml can be caught here rather than on the tag.
|
2026-09-17 00:37:30 +02:00
|
|
|
#
|
|
|
|
|
# 🔴 This used to skip with a note when PyYAML was missing, and still printed
|
|
|
|
|
# "Workflows: in sync." at the end. PyYAML is missing in exactly one place —
|
|
|
|
|
# the GITEA RUNNER (measured: `import yaml` raises ModuleNotFoundError on
|
|
|
|
|
# gitea/runner-images:ubuntu-latest) — which is the one forge where an
|
|
|
|
|
# unparseable workflow produces no run and no error to click on. So the check
|
|
|
|
|
# was switched off precisely where it was needed, and said "in sync" anyway.
|
|
|
|
|
#
|
|
|
|
|
# ci_python_yaml falls back to a container, so there is no skip path left: if
|
|
|
|
|
# the workflows cannot be parsed, that is a failure, not a note.
|
|
|
|
|
ci_python_yaml ci/check-workflows.py .github/workflows/*.yml .gitea/workflows/*.yml \
|
|
|
|
|
|| fail=1
|
2026-09-16 10:34:38 +02:00
|
|
|
|
|
|
|
|
[ "$fail" = 0 ] || exit 1
|
|
|
|
|
echo "Workflows: in sync."
|