Skip to content

Commit 14a4445

Browse files
committed
Merge branch 'ps/ci-gitlab'
Add support for GitLab CI. * ps/ci-gitlab: ci: add support for GitLab CI ci: install test dependencies for linux-musl ci: squelch warnings when testing with unusable Git repo ci: unify setup of some environment variables ci: split out logic to set up failed test artifacts ci: group installation of Docker dependencies ci: make grouping setup more generic ci: reorder definitions for grouping functions
2 parents 712177e + 0e3b67e commit 14a4445

File tree

5 files changed

+233
-54
lines changed

5 files changed

+233
-54
lines changed

.gitlab-ci.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
default:
2+
timeout: 2h
3+
4+
workflow:
5+
rules:
6+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
7+
- if: $CI_COMMIT_TAG
8+
- if: $CI_COMMIT_REF_PROTECTED == "true"
9+
10+
test:
11+
image: $image
12+
before_script:
13+
- ./ci/install-docker-dependencies.sh
14+
script:
15+
- useradd builder --create-home
16+
- chown -R builder "${CI_PROJECT_DIR}"
17+
- sudo --preserve-env --set-home --user=builder ./ci/run-build-and-tests.sh
18+
after_script:
19+
- |
20+
if test "$CI_JOB_STATUS" != 'success'
21+
then
22+
sudo --preserve-env --set-home --user=builder ./ci/print-test-failures.sh
23+
fi
24+
parallel:
25+
matrix:
26+
- jobname: linux-sha256
27+
image: ubuntu:latest
28+
CC: clang
29+
- jobname: linux-gcc
30+
image: ubuntu:20.04
31+
CC: gcc
32+
CC_PACKAGE: gcc-8
33+
- jobname: linux-TEST-vars
34+
image: ubuntu:20.04
35+
CC: gcc
36+
CC_PACKAGE: gcc-8
37+
- jobname: linux-gcc-default
38+
image: ubuntu:latest
39+
CC: gcc
40+
- jobname: linux-leaks
41+
image: ubuntu:latest
42+
CC: gcc
43+
- jobname: linux-asan-ubsan
44+
image: ubuntu:latest
45+
CC: clang
46+
- jobname: pedantic
47+
image: fedora:latest
48+
- jobname: linux-musl
49+
image: alpine:latest
50+
artifacts:
51+
paths:
52+
- t/failed-test-artifacts
53+
when: on_failure

ci/install-docker-dependencies.sh

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# Install dependencies required to build and test Git inside container
44
#
55

6+
. ${0%/*}/lib.sh
7+
8+
begin_group "Install dependencies"
9+
610
case "$jobname" in
711
linux32)
812
linux32 --32bit i386 sh -c '
@@ -12,11 +16,26 @@ linux32)
1216
'
1317
;;
1418
linux-musl)
15-
apk add --update build-base curl-dev openssl-dev expat-dev gettext \
16-
pcre2-dev python3 musl-libintl perl-utils ncurses >/dev/null
19+
apk add --update shadow sudo build-base curl-dev openssl-dev expat-dev gettext \
20+
pcre2-dev python3 musl-libintl perl-utils ncurses \
21+
apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \
22+
bash cvs gnupg perl-cgi perl-dbd-sqlite >/dev/null
23+
;;
24+
linux-*)
25+
# Required so that apt doesn't wait for user input on certain packages.
26+
export DEBIAN_FRONTEND=noninteractive
27+
28+
apt update -q &&
29+
apt install -q -y sudo git make language-pack-is libsvn-perl apache2 libssl-dev \
30+
libcurl4-openssl-dev libexpat-dev tcl tk gettext zlib1g-dev \
31+
perl-modules liberror-perl libauthen-sasl-perl libemail-valid-perl \
32+
libdbd-sqlite3-perl libio-socket-ssl-perl libnet-smtp-ssl-perl ${CC_PACKAGE:-${CC:-gcc}} \
33+
apache2 cvs cvsps gnupg libcgi-pm-perl subversion
1734
;;
1835
pedantic)
1936
dnf -yq update >/dev/null &&
2037
dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null
2138
;;
2239
esac
40+
41+
end_group "Install dependencies"

ci/lib.sh

Lines changed: 138 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
# Library of functions shared by all CI scripts
22

3-
if test true != "$GITHUB_ACTIONS"
3+
if test true = "$GITHUB_ACTIONS"
44
then
5-
begin_group () { :; }
6-
end_group () { :; }
7-
8-
group () {
9-
shift
10-
"$@"
11-
}
12-
set -x
13-
else
145
begin_group () {
156
need_to_end_group=t
167
echo "::group::$1" >&2
@@ -23,27 +14,50 @@ else
2314
need_to_end_group=
2415
echo '::endgroup::' >&2
2516
}
26-
trap end_group EXIT
17+
elif test true = "$GITLAB_CI"
18+
then
19+
begin_group () {
20+
need_to_end_group=t
21+
printf "\e[0Ksection_start:$(date +%s):$(echo "$1" | tr ' ' _)\r\e[0K$1\n"
22+
trap "end_group '$1'" EXIT
23+
set -x
24+
}
2725

28-
group () {
26+
end_group () {
27+
test -n "$need_to_end_group" || return 0
2928
set +x
30-
begin_group "$1"
31-
shift
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
40-
end_group
41-
return $res
29+
need_to_end_group=
30+
printf "\e[0Ksection_end:$(date +%s):$(echo "$1" | tr ' ' _)\r\e[0K\n"
31+
trap - EXIT
4232
}
33+
else
34+
begin_group () { :; }
35+
end_group () { :; }
4336

44-
begin_group "CI setup"
37+
set -x
4538
fi
4639

40+
group () {
41+
group="$1"
42+
shift
43+
begin_group "$group"
44+
45+
# work around `dash` not supporting `set -o pipefail`
46+
(
47+
"$@" 2>&1
48+
echo $? >exit.status
49+
) |
50+
sed 's/^\(\([^ ]*\):\([0-9]*\):\([0-9]*:\) \)\(error\|warning\): /::\5 file=\2,line=\3::\1/'
51+
res=$(cat exit.status)
52+
rm exit.status
53+
54+
end_group "$group"
55+
return $res
56+
}
57+
58+
begin_group "CI setup"
59+
trap "end_group 'CI setup'" EXIT
60+
4761
# Set 'exit on error' for all CI scripts to let the caller know that
4862
# something went wrong.
4963
#
@@ -71,10 +85,32 @@ skip_branch_tip_with_tag () {
7185
fi
7286
}
7387

88+
# Check whether we can use the path passed via the first argument as Git
89+
# repository.
90+
is_usable_git_repository () {
91+
# We require Git in our PATH, otherwise we cannot access repositories
92+
# at all.
93+
if ! command -v git >/dev/null
94+
then
95+
return 1
96+
fi
97+
98+
# And the target directory needs to be a proper Git repository.
99+
if ! git -C "$1" rev-parse 2>/dev/null
100+
then
101+
return 1
102+
fi
103+
}
104+
74105
# Save some info about the current commit's tree, so we can skip the build
75106
# job if we encounter the same tree again and can provide a useful info
76107
# message.
77108
save_good_tree () {
109+
if ! is_usable_git_repository .
110+
then
111+
return
112+
fi
113+
78114
echo "$(git rev-parse $CI_COMMIT^{tree}) $CI_COMMIT $CI_JOB_NUMBER $CI_JOB_ID" >>"$good_trees_file"
79115
# limit the file size
80116
tail -1000 "$good_trees_file" >"$good_trees_file".tmp
@@ -90,6 +126,11 @@ skip_good_tree () {
90126
return
91127
fi
92128

129+
if ! is_usable_git_repository .
130+
then
131+
return
132+
fi
133+
93134
if ! good_tree_info="$(grep "^$(git rev-parse $CI_COMMIT^{tree}) " "$good_trees_file")"
94135
then
95136
# Haven't seen this tree yet, or no cached good trees file yet.
@@ -121,6 +162,11 @@ skip_good_tree () {
121162
}
122163

123164
check_unignored_build_artifacts () {
165+
if ! is_usable_git_repository .
166+
then
167+
return
168+
fi
169+
124170
! git ls-files --other --exclude-standard --error-unmatch \
125171
-- ':/*' 2>/dev/null ||
126172
{
@@ -133,6 +179,26 @@ handle_failed_tests () {
133179
return 1
134180
}
135181

182+
create_failed_test_artifacts () {
183+
mkdir -p t/failed-test-artifacts
184+
185+
for test_exit in t/test-results/*.exit
186+
do
187+
test 0 != "$(cat "$test_exit")" || continue
188+
189+
test_name="${test_exit%.exit}"
190+
test_name="${test_name##*/}"
191+
printf "\\e[33m\\e[1m=== Failed test: ${test_name} ===\\e[m\\n"
192+
echo "The full logs are in the 'print test failures' step below."
193+
echo "See also the 'failed-tests-*' artifacts attached to this run."
194+
cat "t/test-results/$test_name.markup"
195+
196+
trash_dir="t/trash directory.$test_name"
197+
cp "t/test-results/$test_name.out" t/failed-test-artifacts/
198+
tar czf t/failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir"
199+
done
200+
}
201+
136202
# GitHub Action doesn't set TERM, which is required by tput
137203
export TERM=${TERM:-dumb}
138204

@@ -156,11 +222,8 @@ then
156222
# among *all* phases)
157223
cache_dir="$HOME/test-cache/$SYSTEM_PHASENAME"
158224

159-
export GIT_PROVE_OPTS="--timer --jobs 10 --state=failed,slow,save"
160-
export GIT_TEST_OPTS="--verbose-log -x --write-junit-xml"
161-
MAKEFLAGS="$MAKEFLAGS --jobs=10"
162-
test windows_nt != "$CI_OS_NAME" ||
163-
GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS"
225+
GIT_TEST_OPTS="--write-junit-xml"
226+
JOBS=10
164227
elif test true = "$GITHUB_ACTIONS"
165228
then
166229
CI_TYPE=github-actions
@@ -173,40 +236,63 @@ then
173236
CC="${CC_PACKAGE:-${CC:-gcc}}"
174237
DONT_SKIP_TAGS=t
175238
handle_failed_tests () {
176-
mkdir -p t/failed-test-artifacts
177239
echo "FAILED_TEST_ARTIFACTS=t/failed-test-artifacts" >>$GITHUB_ENV
240+
create_failed_test_artifacts
241+
return 1
242+
}
178243

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"
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."
188-
cat "t/test-results/$test_name.markup"
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
244+
cache_dir="$HOME/none"
245+
246+
GIT_TEST_OPTS="--github-workflow-markup"
247+
JOBS=10
248+
elif test true = "$GITLAB_CI"
249+
then
250+
CI_TYPE=gitlab-ci
251+
CI_BRANCH="$CI_COMMIT_REF_NAME"
252+
CI_COMMIT="$CI_COMMIT_SHA"
253+
case "$CI_JOB_IMAGE" in
254+
macos-*)
255+
CI_OS_NAME=osx;;
256+
alpine:*|fedora:*|ubuntu:*)
257+
CI_OS_NAME=linux;;
258+
*)
259+
echo "Could not identify OS image" >&2
260+
env >&2
261+
exit 1
262+
;;
263+
esac
264+
CI_REPO_SLUG="$CI_PROJECT_PATH"
265+
CI_JOB_ID="$CI_JOB_ID"
266+
CC="${CC_PACKAGE:-${CC:-gcc}}"
267+
DONT_SKIP_TAGS=t
268+
handle_failed_tests () {
269+
create_failed_test_artifacts
194270
return 1
195271
}
196272

197273
cache_dir="$HOME/none"
198274

199-
export GIT_PROVE_OPTS="--timer --jobs 10"
200-
export GIT_TEST_OPTS="--verbose-log -x --github-workflow-markup"
201-
MAKEFLAGS="$MAKEFLAGS --jobs=10"
202-
test windows != "$CI_OS_NAME" ||
203-
GIT_TEST_OPTS="--no-chain-lint --no-bin-wrappers $GIT_TEST_OPTS"
275+
runs_on_pool=$(echo "$CI_JOB_IMAGE" | tr : -)
276+
JOBS=$(nproc)
204277
else
205278
echo "Could not identify CI type" >&2
206279
env >&2
207280
exit 1
208281
fi
209282

283+
MAKEFLAGS="$MAKEFLAGS --jobs=$JOBS"
284+
GIT_PROVE_OPTS="--timer --jobs $JOBS --state=failed,slow,save"
285+
286+
GIT_TEST_OPTS="$GIT_TEST_OPTS --verbose-log -x"
287+
case "$CI_OS_NAME" in
288+
windows|windows_nt)
289+
GIT_TEST_OPTS="$GIT_TEST_OPTS --no-chain-lint --no-bin-wrappers"
290+
;;
291+
esac
292+
293+
export GIT_TEST_OPTS
294+
export GIT_PROVE_OPTS
295+
210296
good_trees_file="$cache_dir/good-trees"
211297

212298
mkdir -p "$cache_dir"
@@ -285,5 +371,5 @@ esac
285371

286372
MAKEFLAGS="$MAKEFLAGS CC=${CC:-cc}"
287373

288-
end_group
374+
end_group "CI setup"
289375
set -x

ci/print-test-failures.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ do
5151
tar czf failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir"
5252
continue
5353
;;
54+
gitlab-ci)
55+
mkdir -p failed-test-artifacts
56+
cp "${TEST_EXIT%.exit}.out" failed-test-artifacts/
57+
tar czf failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir"
58+
continue
59+
;;
5460
*)
5561
echo "Unhandled CI type: $CI_TYPE" >&2
5662
exit 1

0 commit comments

Comments
 (0)