mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-14 05:17:13 +02:00
`grep -q` exits on its first match, which closes the pipe under the still- writing `printf`. Under `pipefail` the killed writer, not the successful match, sets the exit status, so a large diff emitted `false` for an area that had changed. It is a race rather than a buffer threshold: it starts firing at around 1200 paths, well under the 64 KiB pipe buffer, and it kills the second `grep` in the build pipeline too. Both pipelines are now here-strings. The largest diff in this repo's history is 519 files, so this was latent, but a repo-wide sweep or a mass directory move reaches it. pipeline.yml and this script are now inputs to the go, js and i18n filters. A pipeline-only change previously skipped every suite that pipeline.yml defines, so a broken test command merged green and surfaced on master. Worse, a wrong gating expression is invisible in every run: `outputs.golang` instead of `outputs.go` reads as empty on master pushes too, and the suite disappears silently and permanently. This change adds 63 such expressions. Of 82 historical pipeline-only commits, 38 edited a job that is now gated, and the measured cost is about 12 extra full runs a year. The download-link workflow returned before looking for its own previous comment, so a PR that built binaries and then became docs-only kept advertising artifacts from a commit that is no longer the head. That branch was unreachable until this PR gated the build. It now deletes the stale comment. Deleting rather than rewording is deliberate: the comment is matched by its header, so a reworded body would either have to keep a header that contradicts it or start posting duplicates. The lookup is also paginated now; it saw only the first 30 comments.
67 lines
2.7 KiB
Bash
Executable file
67 lines
2.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Emits per-area change flags to $GITHUB_OUTPUT so the pipeline can skip work a
|
|
# pull request cannot affect:
|
|
#
|
|
# go - Go sources, module files, linter config, embedded resources
|
|
# js - anything under ui/
|
|
# i18n - translation files and their validation script
|
|
# build - anything that ends up in a binary, image or package (i.e. every
|
|
# change except the doc-only paths in $DOC_ONLY_RE)
|
|
#
|
|
# pipeline.yml and this script are inputs to every suite they gate: a wrong
|
|
# gating expression skips a suite green, in every run, with no other signal.
|
|
#
|
|
# Only pull requests are narrowed. Master pushes, tags and manual runs always get
|
|
# every flag, so a release can never be built from a partially validated tree.
|
|
#
|
|
# Flags gate STEPS, not jobs: a job-level skip propagates through the needs
|
|
# chain (actions/runner#491) and would take the release jobs down with it.
|
|
#
|
|
# Compares HEAD against $BASE_REF (default master). Requires full history
|
|
# (fetch-depth: 0 in CI).
|
|
set -uo pipefail
|
|
export LC_ALL=C
|
|
|
|
GO_RE='(\.go$|(^|/)go\.(mod|sum)$|^Makefile$|^\.golangci\.yml$|^resources/|^db/migrations/|^tests/|^\.github/workflows/(pipeline\.yml|detect-changes\.sh)$)'
|
|
JS_RE='(^ui/|^\.github/workflows/(pipeline\.yml|detect-changes\.sh)$)'
|
|
I18N_RE='(^resources/i18n/|^ui/src/i18n/en\.json$|^\.github/workflows/validate-translations\.sh$|^\.github/workflows/(pipeline\.yml|detect-changes\.sh)$)'
|
|
DOC_ONLY_RE='(\.md$|^LICENSE$|^\.git-blame-ignore-revs$|^\.gitignore$|^\.devcontainer/)'
|
|
|
|
emit() { printf '%s=%s\n' "$1" "$2" | tee -a "${GITHUB_OUTPUT:-/dev/null}"; }
|
|
|
|
if [ "${GITHUB_EVENT_NAME:-}" != "pull_request" ]; then
|
|
echo "Not a pull request — running everything."
|
|
for area in go js i18n build; do emit "$area" true; done
|
|
exit 0
|
|
fi
|
|
|
|
BASE_REF="${BASE_REF:-master}"
|
|
git fetch --no-tags --quiet origin "+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}" || true
|
|
# Guard the diff, not the fetch: checkout already created the ref, so a failed
|
|
# refresh is harmless, but an unresolvable ref would emit every flag as false.
|
|
if ! git rev-parse --verify --quiet "origin/${BASE_REF}" >/dev/null; then
|
|
printf '::error::Cannot resolve origin/%s. In CI, check out with fetch-depth: 0.\n' "$BASE_REF" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --no-renames: rename detection reports only the destination, so moving a file
|
|
# out of a gated area would drop the source path from every filter.
|
|
files="$(git diff --no-renames --name-only "origin/${BASE_REF}...HEAD")"
|
|
echo "Changed files:"
|
|
printf '%s\n' "$files" | sed 's/^/ /'
|
|
echo
|
|
|
|
flag() { # $1=name $2=regex
|
|
if grep -qE "$2" <<< "$files"; then emit "$1" true; else emit "$1" false; fi
|
|
}
|
|
|
|
flag go "$GO_RE"
|
|
flag js "$JS_RE"
|
|
flag i18n "$I18N_RE"
|
|
|
|
if [ -n "$(grep -vE "$DOC_ONLY_RE" <<< "$files")" ]; then
|
|
emit build true
|
|
else
|
|
emit build false
|
|
fi
|