-
Notifications
You must be signed in to change notification settings - Fork 183
95 lines (84 loc) · 3.04 KB
/
detect-changes.yml
File metadata and controls
95 lines (84 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
name: Detect changed files
# Outputs the list of files changed in a PR, one per line, wrapped
# with ^ and $ anchors (e.g. ^ui/src/App.tsx$). Jobs match with
# contains() using anchors for precise substring matching:
# '^scripts/' — full tree under a root directory
# '.go$' — file extension (won't match .gotmpl)
# '^go.mod$' — exact root file
#
# Empty output (push events, API failure, 3000+ files) is falsy,
# so jobs prefix with: !needs.detect-changes.outputs.files ||
# to default to "run" when the file list is unavailable.
#
# Optional run_all input: patterns that affect all jobs. If any
# changed file matches, output stays empty so all jobs run.
on:
workflow_call:
inputs:
run_all:
description: >
Newline-separated list of patterns (same ^/$ anchored
format as the output). If any changed file matches any
of these, output is empty and all jobs run.
type: string
required: false
default: ''
outputs:
files:
description: >
Newline-separated list of changed filenames, or empty
string on push/failure (falsy, so jobs default to run).
value: ${{ jobs.detect.outputs.files }}
jobs:
detect:
runs-on: ubuntu-latest
outputs:
files: ${{ steps.list.outputs.files }}
steps:
- name: List changed files
id: list
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
RUN_ALL: ${{ inputs.run_all }}
WORKFLOW_FILE_PATH: ".github/workflows/detect-changes.yml"
shell: bash
run: |
set -eo pipefail
if [[ -z "${PR_NUMBER}" ]]; then
echo "Not a PR" >&2
exit 0
fi
if ! output="$(gh api "repos/${GH_REPO}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename')"; then
echo "::warning::GitHub API call failed" >&2
exit 0
fi
mapfile -t files < <(echo -n "${output}")
echo "Changed files (${#files[@]}):" >&2
printf ' %s\n' "${files[@]}" >&2
if [[ ${#files[@]} -ge 3000 ]]; then
echo "::warning::PR has 3000+ changed files" >&2
exit 0
fi
anchored=$(printf '^%s$\n' "${files[@]}")
if echo "${anchored}" | grep -qF "^${WORKFLOW_FILE_PATH}$"; then
echo "detect-changes.yml modified, running all jobs" >&2
exit 0
fi
if [[ -n "${RUN_ALL}" ]]; then
while IFS= read -r pattern; do
[[ -z "$pattern" ]] && continue
if echo "${anchored}" | grep -qF "$pattern"; then
echo "run_all: matched '${pattern}', running all jobs" >&2
exit 0
fi
done <<< "${RUN_ALL}"
fi
if [[ ${#files[@]} -gt 0 ]]; then
{
echo "files<<EOF"
printf '^%s$\n' "${files[@]}"
echo "EOF"
} >> "${GITHUB_OUTPUT}"
fi