name: Promotion Gate description: Enforce which source branches may merge into which target branches inputs: rules: description: | One rule per line: "target:allowed1,allowed2,...". Targets not listed are unrestricted. Allowed entries may use a trailing glob, e.g. `hotfix-*`. Leave empty (default) to skip entirely. default: "" runs: using: composite steps: - name: Check merge source is allowed for target branch shell: sh env: BASE: ${{ gitea.event.pull_request.base.ref }} HEAD: ${{ gitea.event.pull_request.head.ref }} RULES: ${{ inputs.rules }} run: | if [ -z "$RULES" ]; then echo "No promotion rules configured — skipping." exit 0 fi rc=0 found=0 oldIFS=$IFS IFS=' ' set -f set -- $RULES set +f IFS=$oldIFS for line in "$@"; do if [ -z "$line" ]; then continue fi target=${line%%:*} allowed=${line#*:} if [ "$target" = "$line" ]; then continue fi if [ "$BASE" = "$target" ]; then found=1 matched=0 innerIFS=$IFS IFS=',' for pat in $allowed; do IFS=$innerIFS case "$HEAD" in $pat) matched=1 ;; esac IFS=',' done IFS=$innerIFS if [ "$matched" -eq 1 ]; then echo "Allowed: '$HEAD' -> '$BASE' (matches: $allowed)" else echo "::error::$BASE only accepts merges from: $allowed — got '$HEAD'" rc=1 fi fi done if [ "$found" -eq 0 ]; then echo "No promotion-source restriction configured for base '$BASE'" fi exit $rc