diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 81500a2..4156cb6 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -57,15 +57,35 @@ jobs: service="${{ matrix.service }}" svc_dir="$(echo "$service" | tr '-' '_')" - if git rev-parse --verify HEAD^ >/dev/null 2>&1; then - CHANGED_FILES="$(git diff --name-only HEAD^ HEAD)" + # A push can carry more than one commit (e.g. a fast-forward + # merge or a mirror sync). Diffing only HEAD^..HEAD silently + # ignores every commit before the last one in the push, so a + # multi-commit push whose final commit is a no-op (docs, + # .gitignore, ...) skips rebuilding services even though an + # earlier commit in the same push touched their code. Prefer + # the pre-push SHA the trigger event actually gives us and + # diff/scan the whole pushed range; only fall back to + # HEAD^..HEAD when that's unavailable (e.g. manual re-run). + BEFORE_SHA="${{ github.event.before }}" + if [ -n "$BEFORE_SHA" ] && [ "$BEFORE_SHA" != "0000000000000000000000000000000000000000" ] \ + && git rev-parse --verify "${BEFORE_SHA}^{commit}" >/dev/null 2>&1; then + RANGE="${BEFORE_SHA}..HEAD" + elif git rev-parse --verify HEAD^ >/dev/null 2>&1; then + RANGE="HEAD^..HEAD" + else + RANGE="" + fi + + if [ -n "$RANGE" ]; then + CHANGED_FILES="$(git diff --name-only $RANGE)" + COMMIT_MSGS="$(git log --pretty=%B $RANGE | tr '\n' ' ')" else CHANGED_FILES="$(git ls-files)" + COMMIT_MSGS="$(git log -1 --pretty=%B | tr '\n' ' ')" fi - LAST_COMMIT_MSG="$(git log -1 --pretty=%B | tr '\n' ' ')" build=false - if echo "$LAST_COMMIT_MSG" | grep -Eiq 'trigger build|force build|rebuild all'; then + if echo "$COMMIT_MSGS" | grep -Eiq 'trigger build|force build|rebuild all'; then build=true elif echo "$CHANGED_FILES" | grep -Eq '^(\.forgejo/workflows/|Dockerfile|Cargo\.toml|Cargo\.lock|crates/|scripts/)'; then build=true