]>
Commit | Line | Data |
---|---|---|
657343a6 LS |
1 | # Library of functions shared by all CI scripts |
2 | ||
dab73aeb JS |
3 | if test true != "$GITHUB_ACTIONS" |
4 | then | |
5 | begin_group () { :; } | |
6 | end_group () { :; } | |
7 | ||
8 | group () { | |
9 | shift | |
10 | "$@" | |
11 | } | |
12 | set -x | |
13 | else | |
14 | begin_group () { | |
15 | need_to_end_group=t | |
16 | echo "::group::$1" >&2 | |
17 | set -x | |
18 | } | |
19 | ||
20 | end_group () { | |
21 | test -n "$need_to_end_group" || return 0 | |
22 | set +x | |
23 | need_to_end_group= | |
24 | echo '::endgroup::' >&2 | |
25 | } | |
26 | trap end_group EXIT | |
27 | ||
28 | group () { | |
29 | set +x | |
30 | begin_group "$1" | |
31 | shift | |
cadcafc3 JS |
32 | # work around `dash` not supporting `set -o pipefail` |
33 | ( | |
34 | "$@" 2>&1 | |
35 | echo $? >exit.status | |
36 | ) | | |
37 | sed 's/^\(\([^ ]*\):\([0-9]*\):\([0-9]*:\) \)\(error\|warning\): /::\5 file=\2,line=\3::\1/' | |
38 | res=$(cat exit.status) | |
39 | rm exit.status | |
dab73aeb JS |
40 | end_group |
41 | return $res | |
42 | } | |
43 | ||
44 | begin_group "CI setup" | |
45 | fi | |
46 | ||
47 | # Set 'exit on error' for all CI scripts to let the caller know that | |
48 | # something went wrong. | |
49 | # | |
50 | # We already enabled tracing executed commands earlier. This helps by showing | |
51 | # how # environment variables are set and and dependencies are installed. | |
52 | set -e | |
53 | ||
09f5e974 LS |
54 | skip_branch_tip_with_tag () { |
55 | # Sometimes, a branch is pushed at the same time the tag that points | |
56 | # at the same commit as the tip of the branch is pushed, and building | |
57 | # both at the same time is a waste. | |
58 | # | |
4096a98d JS |
59 | # When the build is triggered by a push to a tag, $CI_BRANCH will |
60 | # have that tagname, e.g. v2.14.0. Let's see if $CI_BRANCH is | |
61 | # exactly at a tag, and if so, if it is different from $CI_BRANCH. | |
62 | # That way, we can tell if we are building the tip of a branch that | |
63 | # is tagged and we can skip the build because we won't be skipping a | |
64 | # build of a tag. | |
09f5e974 | 65 | |
4096a98d JS |
66 | if TAG=$(git describe --exact-match "$CI_BRANCH" 2>/dev/null) && |
67 | test "$TAG" != "$CI_BRANCH" | |
09f5e974 | 68 | then |
4096a98d | 69 | echo "$(tput setaf 2)Tip of $CI_BRANCH is exactly at $TAG$(tput sgr0)" |
09f5e974 LS |
70 | exit 0 |
71 | fi | |
72 | } | |
73 | ||
9cc2c76f SG |
74 | # Save some info about the current commit's tree, so we can skip the build |
75 | # job if we encounter the same tree again and can provide a useful info | |
76 | # message. | |
77 | save_good_tree () { | |
b011fabd | 78 | echo "$(git rev-parse $CI_COMMIT^{tree}) $CI_COMMIT $CI_JOB_NUMBER $CI_JOB_ID" >>"$good_trees_file" |
9cc2c76f SG |
79 | # limit the file size |
80 | tail -1000 "$good_trees_file" >"$good_trees_file".tmp | |
81 | mv "$good_trees_file".tmp "$good_trees_file" | |
82 | } | |
83 | ||
84 | # Skip the build job if the same tree has already been built and tested | |
85 | # successfully before (e.g. because the branch got rebased, changing only | |
86 | # the commit messages). | |
87 | skip_good_tree () { | |
4a6e4b96 | 88 | if test true = "$GITHUB_ACTIONS" |
c46ebc24 SG |
89 | then |
90 | return | |
91 | fi | |
92 | ||
b011fabd | 93 | if ! good_tree_info="$(grep "^$(git rev-parse $CI_COMMIT^{tree}) " "$good_trees_file")" |
9cc2c76f SG |
94 | then |
95 | # Haven't seen this tree yet, or no cached good trees file yet. | |
96 | # Continue the build job. | |
97 | return | |
98 | fi | |
99 | ||
100 | echo "$good_tree_info" | { | |
101 | read tree prev_good_commit prev_good_job_number prev_good_job_id | |
102 | ||
b011fabd | 103 | if test "$CI_JOB_ID" = "$prev_good_job_id" |
9cc2c76f SG |
104 | then |
105 | cat <<-EOF | |
b011fabd | 106 | $(tput setaf 2)Skipping build job for commit $CI_COMMIT.$(tput sgr0) |
9cc2c76f SG |
107 | This commit has already been built and tested successfully by this build job. |
108 | To force a re-build delete the branch's cache and then hit 'Restart job'. | |
109 | EOF | |
110 | else | |
111 | cat <<-EOF | |
b011fabd | 112 | $(tput setaf 2)Skipping build job for commit $CI_COMMIT.$(tput sgr0) |
9cc2c76f | 113 | This commit's tree has already been built and tested successfully in build job $prev_good_job_number for commit $prev_good_commit. |
4a6e4b96 | 114 | The log of that build job is available at $SYSTEM_TASKDEFINITIONSURI$SYSTEM_TEAMPROJECT/_build/results?buildId=$prev_good_job_id |
9cc2c76f SG |
115 | To force a re-build delete the branch's cache and then hit 'Restart job'. |
116 | EOF | |
117 | fi | |
118 | } | |
119 | ||
120 | exit 0 | |
121 | } | |
122 | ||
863d6ceb | 123 | check_unignored_build_artifacts () { |
b92cb86e SG |
124 | ! git ls-files --other --exclude-standard --error-unmatch \ |
125 | -- ':/*' 2>/dev/null || | |
126 | { | |
127 | echo "$(tput setaf 1)error: found unignored build artifacts$(tput sgr0)" | |
128 | false | |
129 | } | |
130 | } | |
131 | ||
08dccc8f JS |
132 | handle_failed_tests () { |
133 | return 1 | |
134 | } | |
135 | ||
855c158e ĐTCD |
136 | # GitHub Action doesn't set TERM, which is required by tput |
137 | export TERM=${TERM:-dumb} | |
138 | ||
a8c51f77 JH |
139 | # Clear MAKEFLAGS that may come from the outside world. |
140 | export MAKEFLAGS= | |
141 | ||
4a6e4b96 | 142 | if test -n "$SYSTEM_COLLECTIONURI" || test -n "$SYSTEM_TASKDEFINITIONSURI" |
6141a2ed JS |
143 | then |
144 | CI_TYPE=azure-pipelines | |
145 | # We are running in Azure Pipelines | |
146 | CI_BRANCH="$BUILD_SOURCEBRANCH" | |
147 | CI_COMMIT="$BUILD_SOURCEVERSION" | |
148 | CI_JOB_ID="$BUILD_BUILDID" | |
149 | CI_JOB_NUMBER="$BUILD_BUILDNUMBER" | |
150 | CI_OS_NAME="$(echo "$AGENT_OS" | tr A-Z a-z)" | |
151 | test darwin != "$CI_OS_NAME" || CI_OS_NAME=osx | |
152 | CI_REPO_SLUG="$(expr "$BUILD_REPOSITORY_URI" : '.*/\([^/]*/[^/]*\)$')" | |
153 | CC="${CC:-gcc}" | |
154 | ||
155 | # use a subdirectory of the cache dir (because the file share is shared | |
156 | # among *all* phases) | |
157 | cache_dir="$HOME/test-cache/$SYSTEM_PHASENAME" | |
158 | ||
6141a2ed JS |
159 | export GIT_PROVE_OPTS="--timer --jobs 10 --state=failed,slow,save" |
160 | export GIT_TEST_OPTS="--verbose-log -x --write-junit-xml" | |
a8c51f77 | 161 | MAKEFLAGS="$MAKEFLAGS --jobs=10" |
a87e427e JS |
162 | test windows_nt != "$CI_OS_NAME" || |
163 | GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS" | |
a3f2eec8 JS |
164 | elif test true = "$GITHUB_ACTIONS" |
165 | then | |
166 | CI_TYPE=github-actions | |
167 | CI_BRANCH="$GITHUB_REF" | |
168 | CI_COMMIT="$GITHUB_SHA" | |
169 | CI_OS_NAME="$(echo "$RUNNER_OS" | tr A-Z a-z)" | |
170 | test macos != "$CI_OS_NAME" || CI_OS_NAME=osx | |
171 | CI_REPO_SLUG="$GITHUB_REPOSITORY" | |
172 | CI_JOB_ID="$GITHUB_RUN_ID" | |
3506cae0 | 173 | CC="${CC_PACKAGE:-${CC:-gcc}}" |
4463ce75 | 174 | DONT_SKIP_TAGS=t |
08dccc8f JS |
175 | handle_failed_tests () { |
176 | mkdir -p t/failed-test-artifacts | |
177 | echo "FAILED_TEST_ARTIFACTS=t/failed-test-artifacts" >>$GITHUB_ENV | |
178 | ||
179 | for test_exit in t/test-results/*.exit | |
180 | do | |
181 | test 0 != "$(cat "$test_exit")" || continue | |
182 | ||
183 | test_name="${test_exit%.exit}" | |
184 | test_name="${test_name##*/}" | |
185 | printf "\\e[33m\\e[1m=== Failed test: ${test_name} ===\\e[m\\n" | |
5aeb1457 JS |
186 | echo "The full logs are in the 'print test failures' step below." |
187 | echo "See also the 'failed-tests-*' artifacts attached to this run." | |
0068c82a | 188 | cat "t/test-results/$test_name.markup" |
08dccc8f JS |
189 | |
190 | trash_dir="t/trash directory.$test_name" | |
191 | cp "t/test-results/$test_name.out" t/failed-test-artifacts/ | |
192 | tar czf t/failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir" | |
193 | done | |
194 | return 1 | |
195 | } | |
a3f2eec8 JS |
196 | |
197 | cache_dir="$HOME/none" | |
198 | ||
199 | export GIT_PROVE_OPTS="--timer --jobs 10" | |
0068c82a | 200 | export GIT_TEST_OPTS="--verbose-log -x --github-workflow-markup" |
a3f2eec8 JS |
201 | MAKEFLAGS="$MAKEFLAGS --jobs=10" |
202 | test windows != "$CI_OS_NAME" || | |
203 | GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS" | |
b011fabd JS |
204 | else |
205 | echo "Could not identify CI type" >&2 | |
5127e8cf | 206 | env >&2 |
b011fabd JS |
207 | exit 1 |
208 | fi | |
4096a98d | 209 | |
b2cbaa09 SG |
210 | good_trees_file="$cache_dir/good-trees" |
211 | ||
212 | mkdir -p "$cache_dir" | |
b4a2fdc9 | 213 | |
4463ce75 | 214 | test -n "${DONT_SKIP_TAGS-}" || |
09f5e974 | 215 | skip_branch_tip_with_tag |
9cc2c76f | 216 | skip_good_tree |
83d1efe5 | 217 | |
bf427a94 SG |
218 | if test -z "$jobname" |
219 | then | |
b011fabd | 220 | jobname="$CI_OS_NAME-$CC" |
bf427a94 SG |
221 | fi |
222 | ||
e3371e92 SG |
223 | export DEVELOPER=1 |
224 | export DEFAULT_TEST_TARGET=prove | |
a85efb59 | 225 | export GIT_TEST_CLONE_2GB=true |
ef60e9f7 | 226 | export SKIP_DASHED_BUILT_INS=YesPlease |
e3371e92 | 227 | |
707d2f2f | 228 | case "$runs_on_pool" in |
0178420b | 229 | ubuntu-*) |
707d2f2f ÆAB |
230 | if test "$jobname" = "linux-gcc-default" |
231 | then | |
232 | break | |
233 | fi | |
234 | ||
0d3507f3 JX |
235 | PYTHON_PACKAGE=python2 |
236 | if test "$jobname" = linux-gcc | |
2c8921db | 237 | then |
0d3507f3 | 238 | PYTHON_PACKAGE=python3 |
2c8921db | 239 | fi |
0d3507f3 | 240 | MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE" |
2c8921db | 241 | |
39602906 | 242 | export GIT_TEST_HTTPD=true |
a1157b76 | 243 | |
e3371e92 | 244 | # The Linux build installs the defined dependency versions below. |
37a2e353 SG |
245 | # The OS X build installs much more recent versions, whichever |
246 | # were recorded in the Homebrew database upon creating the OS X | |
247 | # image. | |
248 | # Keep that in mind when you encounter a broken OS X build! | |
e3371e92 SG |
249 | export LINUX_GIT_LFS_VERSION="1.5.2" |
250 | ||
88e00b70 SG |
251 | P4_PATH="$HOME/custom/p4" |
252 | GIT_LFS_PATH="$HOME/custom/git-lfs" | |
83d1efe5 SG |
253 | export PATH="$GIT_LFS_PATH:$P4_PATH:$PATH" |
254 | ;; | |
d1119225 | 255 | macos-*) |
2c8921db SG |
256 | if [ "$jobname" = osx-gcc ] |
257 | then | |
6bb40ed2 SG |
258 | MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python3)" |
259 | else | |
260 | MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python2)" | |
35898ad2 | 261 | MAKEFLAGS="$MAKEFLAGS APPLE_COMMON_CRYPTO_SHA1=Yes" |
2c8921db | 262 | fi |
e3371e92 | 263 | ;; |
707d2f2f ÆAB |
264 | esac |
265 | ||
266 | case "$jobname" in | |
c08bb260 | 267 | linux32) |
d2fae19e SG |
268 | CC=gcc |
269 | ;; | |
e0f8690d ĐTCD |
270 | linux-musl) |
271 | CC=gcc | |
272 | MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3 USE_LIBPCRE2=Yes" | |
273 | MAKEFLAGS="$MAKEFLAGS NO_REGEX=Yes ICONV_OMITS_BOM=Yes" | |
482c962d | 274 | MAKEFLAGS="$MAKEFLAGS GIT_TEST_UTF8_LOCALE=C.UTF-8" |
e0f8690d | 275 | ;; |
956d2e46 ÆAB |
276 | linux-leaks) |
277 | export SANITIZE=leak | |
278 | export GIT_TEST_PASSING_SANITIZE_LEAK=true | |
c24feabc | 279 | export GIT_TEST_SANITIZE_LEAK_LOG=true |
956d2e46 | 280 | ;; |
ec691526 JK |
281 | linux-asan-ubsan) |
282 | export SANITIZE=address,undefined | |
6ba91362 JS |
283 | export NO_SVN_TESTS=LetsSaveSomeTime |
284 | MAKEFLAGS="$MAKEFLAGS NO_PYTHON=YepBecauseP4FlakesTooOften" | |
1c0962c0 | 285 | ;; |
956d2e46 ÆAB |
286 | esac |
287 | ||
a8c51f77 | 288 | MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}" |
dab73aeb JS |
289 | |
290 | end_group | |
291 | set -x |