Skip to content

Commit 98042cd

Browse files
committed
implement filtering in bash
1 parent d05087a commit 98042cd

File tree

7 files changed

+264
-109
lines changed

7 files changed

+264
-109
lines changed

buildkite/Makefile

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,9 @@ format:
2525
find ./src/ -name "*.dhall" -print0 | xargs -I{} -0 -n1 bash -c 'echo "{}" && dhall --ascii format --inplace {} || exit 255'
2626
$(MAKE) convert_ifs_to_backticks
2727

28-
check_filter:
29-
# Ensure Jobs.dhall is generated before proceeding
30-
(cd ../ && ./buildkite/scripts/generate-jobs.sh > ./buildkite/src/gen/Jobs.dhall)
31-
python3 ./unit-tests/parse_triage.py
32-
# Clean up
33-
git checkout -- ./src/gen/Jobs.dhall
34-
3528
dump_pipelines:
3629
$(eval TMP := $(shell mktemp -d))
37-
scripts/dhall/dump_dhall_to_pipelines.sh src/Jobs "$(TMP)"
30+
./buildkite/scripts/dhall/dump_dhall_to_pipelines.sh ./buildkite/src "$(TMP)"
3831

3932
check_deps: dump_pipelines
4033
python3 scripts/dhall/checker.py --root "$(TMP)" deps
@@ -48,4 +41,4 @@ check_dups: dump_pipelines
4841
check_names: dump_pipelines
4942
python3 scripts/dhall/checker.py --root "$(TMP)" names
5043

51-
all: check_syntax lint format check_deps check_dirty check_dups check_names check_filter
44+
all: check_syntax lint format check_deps check_dirty check_dups check_names

buildkite/scripts/dhall/dump_dhall_to_pipelines.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#!/bin/bash
22

3+
# Check for required arguments
4+
if [ "$#" -ne 2 ]; then
5+
echo "Usage: $0 <dhall_root_dir> <output_dir>"
6+
exit 1
7+
fi
8+
39
ROOT=$1
410
OUTPUT=$2
511

12+
13+
614
mkdir -p "$OUTPUT"
715

816
shopt -s globstar nullglob
@@ -11,13 +19,16 @@ echo "Dumping pipelines from '$ROOT' to '$OUTPUT'"
1119

1220
COUNTER=0
1321

14-
for file in "$ROOT"/**/*.dhall
22+
for file in "$ROOT"/Jobs/**/*.dhall
1523
do
1624
filename=$(basename "$file")
1725
filename="${filename%.*}"
1826

1927
dhall-to-yaml --quoted --file "$file" > "$OUTPUT"/"$filename".yml
2028

29+
dhall-to-yaml <<< "let SelectFiles = $ROOT/Lib/SelectFiles.dhall in SelectFiles.compile (./$file).spec.dirtyWhen " > "$OUTPUT"/"$filename".dirtywhen
30+
31+
2132
COUNTER=$((COUNTER+1))
2233
done
2334

buildkite/scripts/monorepo.sh

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/bin/bash
2+
3+
# Usage:
4+
# monorepo.sh --scopes <scopes> --tags <tags> --filter-mode <filter_mode> --selection <selection> --jobs <jobs>
5+
6+
set -euo pipefail
7+
8+
# Default values
9+
SCOPES=""
10+
TAGS=""
11+
FILTER_MODE=""
12+
SELECTION=""
13+
JOBS=""
14+
GIT_DIFF_FILE=""
15+
DRY_RUN=false
16+
17+
# Parse CLI arguments
18+
while [[ $# -gt 0 ]]; do
19+
key="$1"
20+
case $key in
21+
--scopes)
22+
SCOPES="$2"
23+
shift; shift
24+
;;
25+
--tags)
26+
TAGS="$2"
27+
shift; shift
28+
;;
29+
--filter-mode)
30+
FILTER_MODE="$2"
31+
shift; shift
32+
;;
33+
--selection)
34+
SELECTION="$2"
35+
shift; shift
36+
;;
37+
--jobs)
38+
JOBS="$2"
39+
shift; shift
40+
;;
41+
--git-diff-file)
42+
GIT_DIFF_FILE="$2"
43+
shift; shift
44+
;;
45+
--dry-run)
46+
DRY_RUN=true
47+
shift
48+
;;
49+
--debug)
50+
set -x
51+
shift
52+
;;
53+
*)
54+
echo "Unknown option: $1"
55+
exit 1
56+
;;
57+
esac
58+
done
59+
60+
61+
# Require all arguments
62+
if [[ -z "$SCOPES" || -z "$TAGS" || -z "$FILTER_MODE" || -z "$SELECTION" || -z "$JOBS" || -z "$GIT_DIFF_FILE" ]]; then
63+
echo "Error: All arguments --scopes, --tags, --filter-mode, --selection, --jobs, and --git-diff-file are required."
64+
exit 1
65+
fi
66+
67+
# Check if yq is installed, if not install it
68+
if ! command -v yq &> /dev/null; then
69+
echo "yq not found, installing..."
70+
if command -v apt-get &> /dev/null; then
71+
sudo apt-get update && sudo apt-get install -y wget
72+
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
73+
sudo chmod +x /usr/local/bin/yq
74+
else
75+
echo "Error: yq is not installed and automatic installation is not supported on this system. Please install yq manually."
76+
exit 1
77+
fi
78+
fi
79+
80+
IFS=',' read -r -a DESIRED_TAGS <<< "$TAGS"
81+
IFS=',' read -r -a DESIRED_SCOPES <<< "$SCOPES"
82+
83+
# Set filter flag based on FILTER_MODE
84+
FILTER_ANY=false
85+
FILTER_ALL=false
86+
if [[ "$FILTER_MODE" == "any" ]]; then
87+
FILTER_ANY=true
88+
elif [[ "$FILTER_MODE" == "all" ]]; then
89+
FILTER_ALL=true
90+
else
91+
echo "Error: --filter-mode must be 'any' or 'all'."
92+
exit 1
93+
fi
94+
95+
# Validate SELECTION value
96+
97+
# Set selection flags
98+
SELECTION_TRIAGED=false
99+
SELECTION_FULL=false
100+
if [[ "$SELECTION" == "triaged" ]]; then
101+
SELECTION_TRIAGED=true
102+
elif [[ "$SELECTION" == "full" ]]; then
103+
SELECTION_FULL=true
104+
else
105+
echo "Error: --selection must be 'triaged' or 'full'."
106+
exit 1
107+
fi
108+
# Find all files in jobs and use yq to get .pipeline.spec.tags
109+
110+
has_matching_tags() {
111+
local tags="$1"
112+
local filter_any="$2"
113+
local filter_all="$3"
114+
shift 3
115+
local desired_tags=("$@")
116+
117+
local match_count=0
118+
119+
120+
121+
122+
for want in "${desired_tags[@]}"; do
123+
124+
if WANT="$want" \
125+
yq -e '.[] | select((downcase) == (env(WANT) | downcase))' \
126+
<<< "$tags" \
127+
>/dev/null 2>&1
128+
then
129+
match_count=$((match_count+1))
130+
fi
131+
done
132+
133+
if $filter_any && [[ $match_count -ge 1 ]]; then
134+
echo 1
135+
elif $filter_all && [[ $match_count -eq ${#desired_tags[@]} ]]; then
136+
echo 1
137+
else
138+
echo 0
139+
fi
140+
}
141+
142+
scope_matches() {
143+
local scope="$1"
144+
shift
145+
local desired_scopes=("$@")
146+
local match_count=0
147+
148+
for want in "${desired_scopes[@]}"; do
149+
# yq v4 NIE ma --arg, więc używamy env(WANT)
150+
if WANT="$want" \
151+
yq -e '.[] | select((downcase) == (env(WANT) | downcase))' \
152+
<<< "$scope" \
153+
>/dev/null 2>&1
154+
then
155+
match_count=$((match_count+1))
156+
break
157+
fi
158+
done
159+
160+
echo $(( match_count == 1 ? 1 : 0 ))
161+
}
162+
163+
select_job() {
164+
local selection_full="$1"
165+
local selection_triaged="$2"
166+
local file="$3"
167+
local job_name="$4"
168+
local git_diff_file="$5"
169+
170+
if [[ "$selection_full" == true ]]; then
171+
echo 1
172+
elif [[ "$selection_triaged" == true ]]; then
173+
dirtyWhen=$(cat "${file%.yml}.dirtywhen")
174+
# Remove quotes from beginning and end of string
175+
dirtyWhen="${dirtyWhen%\"}"
176+
dirtyWhen="${dirtyWhen#\"}"
177+
if cat "$git_diff_file" | grep -E "$dirtyWhen" > /dev/null; then
178+
echo 1
179+
else
180+
echo 0
181+
fi
182+
fi
183+
}
184+
185+
find "$JOBS" -type f -name "*.yml" | while read -r file; do
186+
tags=$(yq .spec.tags "$file")
187+
scope=$(yq .spec.scope "$file")
188+
job_name=$(yq -r .spec.name "$file")
189+
190+
tag_match=$(has_matching_tags "$tags" "$FILTER_ANY" "$FILTER_ALL" "${DESIRED_TAGS[@]}")
191+
192+
scope_match=$(scope_matches "$scope" "${DESIRED_SCOPES[@]}")
193+
194+
if [[ $tag_match -ne 1 ]]; then
195+
echo "🏷️🚫 $job_name rejected job due to tags mismatch: $file" >&2
196+
continue
197+
fi
198+
if [[ $scope_match -ne 1 ]]; then
199+
echo "🔭🚫 $job_name rejected job due to scope mismatch: $file" >&2
200+
continue
201+
fi
202+
203+
job_selected=$(select_job "$SELECTION_FULL" "$SELECTION_TRIAGED" "$file" "$job_name" "$GIT_DIFF_FILE")
204+
205+
if [[ $job_selected -ne 1 ]]; then
206+
echo "🧹🚫 $job_name rejected job as it does not fall into dirty when: $file" >&2
207+
continue
208+
fi
209+
210+
echo "✅ Including job $job_name in build "
211+
212+
if [[ "$DRY_RUN" == true ]]; then
213+
printf " -> 🛑 Dry run enabled, skipping upload for job: %s\n" "$job_name"
214+
else
215+
job_path=$(yq -r .spec.path "$file")
216+
217+
dhall-to-yaml --quoted <<< "(./buildkite/src/Jobs/$job_path/$job_name.dhall).pipeline" | buildkite-agent pipeline upload
218+
printf " -> ✅ Uploaded job: %s\n" "$job_name"
219+
fi
220+
221+
done
222+

buildkite/src/Command/Base.dhall

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ let targetToAgent =
133133
, Perf = toMap { size = "performance" }
134134
, Multi = toMap { size = "generic-multi" }
135135
, Arm64 = toMap { size = "arm64-static" }
136+
, Dev = toMap { size = "development-0" }
136137
}
137138
target
138139

buildkite/src/Jobs/Lint/Dhall.dhall

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let dump_pipelines_cmd =
2121
Cmd.Docker::{
2222
, image = (../../Constants/ContainerImages.dhall).toolchainBase
2323
}
24-
"buildkite/scripts/dhall/dump_dhall_to_pipelines.sh buildkite/src/Jobs _pipelines"
24+
"buildkite/scripts/dhall/dump_dhall_to_pipelines.sh ./buildkite/src/ _pipelines"
2525

2626
in Pipeline.build
2727
Pipeline.Config::{

0 commit comments

Comments
 (0)