-
Notifications
You must be signed in to change notification settings - Fork 27
/
daily-tags.sh
executable file
·283 lines (249 loc) · 11.5 KB
/
daily-tags.sh
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#!/bin/bash -ex
set -ex
substitute_vars () {
local value=$1
value=${value//!!FLPSUITE_LATEST!!/$flpsuite_latest}
value=${value//!!FLPSUITE_CURRENT!!/$flpsuite_current}
value=${value//!!ALIDIST_BRANCH!!/$ALIDIST_BRANCH}
LANG=C TZ=UTC date -d "@$START_TIMESTAMP" "+$value"
}
edit_package_tag () {
# Patch package definition (e.g. o2.sh) with a new tag and version, changing
# the defaults as well if necessary.
local package=${1:?edit_package_tag: package not provided} defaults=${2:?edit_package_tag: defaults not provided} tag=$3 version=$4
[ -n "$tag$version" ] || return 0
sed -E -i "${tag:+"s|^tag: .*$|tag: \"$tag\"|;"} ${version:+"s|^version: .*\$|version: \"$version\"|"}" "alidist/${package,,}.sh"
# Patch defaults definition (e.g. defaults-o2.sh)
# Process overrides by changing in-place the given defaults. This requires
# some YAML processing so we are better off with Python.
package=$package defaults=$defaults tag=$tag version=$version python3 <<\EOF
import os, yaml
f = "alidist/defaults-%s.sh" % os.environ["defaults"].lower()
with open(f, "r") as recipef:
meta, sep, rest = recipef.read().partition("\n---\n")
assert sep, "could not parse defaults recipe in %s" % f
d = yaml.safe_load(meta)
write = False
overrides = d.setdefault("overrides", {}).setdefault(os.environ["package"], {})
for key in ("tag", "version"):
if key in os.environ and key in overrides:
overrides[key] = os.environ[key]
write = True
if write:
with open(f, "w") as outf:
yaml.dump(d, outf); outf.write(sep); outf.write(rest)
EOF
}
# PACKAGES contains whitespace-separated package names to tag. Only the first is
# built, but every listed package's tag is edited in the resulting commit. This
# enables tagging e.g. O2 and O2Physics at the same time, with the same tag, and
# building O2Physics (which pulls in O2 as well).
main_pkg=${PACKAGES%% *}
# Check for required variables
: "${PACKAGES:?}" "${main_pkg:?}" "${NODE_NAME:?}"
: "${ALIDIST_SLUG:=alisw/alidist@master}" "${DEFAULTS:=release}"
# Determine branch from slug string: group/repo@ref
ALIDIST_BRANCH="${ALIDIST_SLUG##*@}"
ALIDIST_REPO="${ALIDIST_SLUG%@*}"
# Clean up old stuff
rm -rf alidist/
git config --global user.name 'ALICE Builder'
git config --global user.email [email protected]
PYTHON_USER_OPT=""
if [[ -z "$VIRTUAL_ENV" ]]; then
PYTHON_USER_OPT="--user"
fi
# Upgrade pip
python3 -m pip install ${PYTHON_USER_OPT} --upgrade pip
# Install the latest release if ALIBUILD_SLUG is not provided
python3 -m pip install ${PYTHON_USER_OPT} --upgrade "${ALIBUILD_SLUG:+git+https://github.com/}${ALIBUILD_SLUG:-alibuild}"
aliBuild analytics off
# The alidist branches are always named with a trailing .0 instead of the
# "normal" patch release number.
flpsuite_latest=$(git ls-remote "https://github.com/$ALIDIST_REPO" -- 'refs/heads/flp-suite-v*' |
cut -f2 | sort -V | sed -rn '$s,^refs/heads/(.*)\.[0-9]+$,\1.0,p')
# In case ali-flp is offline, don't fail if we don't need its info.
if echo "$ALIDIST_BRANCH $AUTOTAG_PATTERN $OVERRIDE_TAGS" | grep -qi 'flpsuite_current'; then
flpsuite_current=flp-suite-v$(curl -fSsLk https://ali-flp.cern.ch/suite_version)
flpsuite_current=${flpsuite_current%.*}.0
fi
if [ "$(date +%u)" = 1 ]; then # On Mondays (for Sunday night builds)
flpsuite_current=$flpsuite_latest
fi
ALIDIST_BRANCH=${ALIDIST_BRANCH//!!FLPSUITE_LATEST!!/$flpsuite_latest}
ALIDIST_BRANCH=${ALIDIST_BRANCH//!!FLPSUITE_CURRENT!!/$flpsuite_current}
if ! git clone -b "$ALIDIST_BRANCH" "https://github.com/$ALIDIST_REPO" alidist/; then
# We may have been given a commit hash as $ALIDIST_BRANCH, and we can't pass
# hashes to -b. Clone and checkout instead.
git clone "https://github.com/$ALIDIST_REPO" alidist/
(cd alidist && git checkout -f "$ALIDIST_BRANCH")
fi
# Switch the recipes for the packages specified in ALIDIST_OVERRIDE_PKGS
# to the version found in the alidist branch specified by ALIDIST_OVERRIDE_BRANCH
if [ -n "$ALIDIST_OVERRIDE_BRANCH" ]; then (
cd alidist
git checkout "$ALIDIST_OVERRIDE_BRANCH" -- \
$(echo "$ALIDIST_OVERRIDE_PKGS" |
tr ',[:upper:]' ' [:lower:]' |
xargs -rn1 echo | sed 's/$/.sh/')
); fi
# Apply explicit tag overrides after possibly checking out the recipe from
# ALIDIST_OVERRIDE_BRANCH to allow combining the two effects.
for tagspec in $OVERRIDE_TAGS; do
edit_package_tag "${tagspec%%=*}" "$DEFAULTS" "$(substitute_vars "${tagspec#*=}")" ''
done
for versionspec in $OVERRIDE_VERSIONS; do
edit_package_tag "${versionspec%%=*}" "$DEFAULTS" '' "$(substitute_vars "${versionspec#*=}")"
done
# Select build directory in order to prevent conflicts and allow for cleanups.
workarea=$(mktemp -d "$PWD/daily-tags.XXXXXXXXXX")
# NOMAD_CPU_CORES is of the form "0-2,7,12-14". Get the total number of
# assigned cores from that (i.e. 7 cores in the example). For some Nomad jobs,
# we manually set MAX_CORES, so only assign to it if it's not already set.
: "${MAX_CORES:=$(echo "$NOMAD_CPU_CORES" | tr , '\n' | awk -F- '/^./{num_cores += $2 ? 1 + $2 - $1 : 1} END{print num_cores}')}"
# Define aliBuild args once, so that we have (mostly) the same args for
# templating and the real build.
alibuild_args=(
--debug --work-dir "$workarea"
# JOBS is set by the Jenkins job, MAX_CORES is set by Nomad.
--jobs "${JOBS:-${MAX_CORES:-$(nproc)}}"
--reference-sources mirror
${ARCHITECTURE:+--architecture "$ARCHITECTURE"}
${ALIBUILD_DISABLE:+--disable "$ALIBUILD_DISABLE"}
${DEFAULTS:+--defaults "$DEFAULTS"}
build "$main_pkg"
)
# Assignments are specified as a multi-line string with one VAR=value pair per line.
while read -r assignment; do
if [ -n "$assignment" ]; then
alibuild_args+=(-e "$assignment")
fi
done <<< "$BUILD_ENV_VARS"
# Attach any user-specified comment to all top-level packages.
if [ -n "$BUILD_COMMENT" ] &&
# Make sure that this aliBuild supports --annotate.
aliBuild build --help | grep -q -- --annotate; then
for package in $PACKAGES; do
alibuild_args+=(--annotate "$package=$BUILD_COMMENT")
done
fi
# Process the pattern as a jinja2 template with aliBuild's templating plugin.
# Fetch the source repos now, so they're available for the "real" build later.
AUTOTAG_PATTERN=$(aliBuild --plugin templating --fetch-repos "${alibuild_args[@]}" << EOF
{%- set alidist_branch = "$ALIDIST_BRANCH" -%}
{%- set flpsuite_latest = "$flpsuite_latest" -%}
{%- set flpsuite_current = "$flpsuite_current" -%}
$AUTOTAG_PATTERN
EOF
)
# Finally, replace strftime formatting (%Y, %m, %d etc) in the pattern.
# We use the UTC timezone to avoid issues with DST changes.
AUTOTAG_TAG=$(LANG=C TZ=UTC date -d "@$START_TIMESTAMP" "+$AUTOTAG_PATTERN")
: "${AUTOTAG_TAG:?}" # make sure the tag isn't empty
[ "$TEST_TAG" = true ] && AUTOTAG_TAG=TEST-IGNORE-$AUTOTAG_TAG
if echo "$AUTOTAG_TAG" | grep -Fq '!!'; then
echo "Tag $AUTOTAG_TAG contains !!-placeholders! These will not be replaced; use Jinja2 syntax instead. Exiting." >&2
exit 1
fi
# The tag doesn't exist yet, so build using the branch first.
for package in $PACKAGES; do
edit_package_tag "$package" "$DEFAULTS" "rc/$AUTOTAG_TAG" "$AUTOTAG_OVERRIDE_VERSION"
done
(cd alidist && git diff) || :
for package in $PACKAGES; do (
rm -rf "${package,,}.git"
AUTOTAG_REMOTE=$(grep -E '^(source:|write_repo:)' "alidist/${package,,}.sh" | sort -r | head -n1 | cut -d: -f2- | xargs echo)
if [ -n "$AUTOTAG_REMOTE" ]; then
AUTOTAG_MIRROR=$MIRROR/${package,,}
echo "A Git tag will be created, upon success and if not existing, with the name $AUTOTAG_TAG"
echo "A Git branch will be created to pinpoint the build operation, with the name rc/$AUTOTAG_TAG"
[[ -d $AUTOTAG_MIRROR ]] || AUTOTAG_MIRROR=
mkdir "${package,,}.git"
cd "${package,,}.git"
git clone --bare ${AUTOTAG_MIRROR:+--reference=$AUTOTAG_MIRROR} "$AUTOTAG_REMOTE" .
AUTOTAG_HASH=$(git ls-remote origin "refs/tags/$AUTOTAG_TAG" | tail -1 | cut -f1)
if [ -n "$AUTOTAG_HASH" ]; then
echo "Tag $AUTOTAG_TAG exists already as $AUTOTAG_HASH, using it"
elif [ "$DO_NOT_CREATE_NEW_TAG" = true ]; then
# Tag does not exist, but we have requested this job to forcibly use an existing one.
# Will abort the job.
echo "Tag $AUTOTAG_TAG was not found, however we have been requested to not create a new one" \
"(DO_NOT_CREATE_NEW_TAG is true). Aborting with error"
exit 1
else
# Tag does not exist. Create release candidate branch, if not existing.
AUTOTAG_HASH=$(git ls-remote origin "refs/heads/rc/$AUTOTAG_TAG" | tail -1 | cut -f1)
if [ -n "$AUTOTAG_HASH" ] && [ "$REMOVE_RC_BRANCH_FIRST" = true ]; then
# Remove branch first if requested. Error is fatal.
git push origin ":refs/heads/rc/$AUTOTAG_TAG"
AUTOTAG_HASH=
fi
if [ -z "$AUTOTAG_HASH" ]; then
# Let's point it to HEAD
AUTOTAG_HASH=$(git ls-remote origin HEAD | tail -1 | cut -f1)
if [ -z "$AUTOTAG_HASH" ]; then
echo "FATAL: Cannot find any hash pointing to HEAD (repo's default branch)!" >&2
exit 1
fi
echo "Head of $AUTOTAG_REMOTE will be used, it's at $AUTOTAG_HASH"
fi
fi
# At this point, we have $AUTOTAG_HASH for sure. It might come from HEAD, an existing rc/* branch,
# or an existing tag. We always create a new branch out of it
git push origin "+$AUTOTAG_HASH:refs/heads/rc/$AUTOTAG_TAG"
fi
); done
: "${REMOTE_STORE:=b3://alibuild-repo::rw}"
case "$REMOTE_STORE" in
b3://*)
set +x # avoid leaking secrets
. /secrets/aws_bot_secrets
export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
set -x ;;
esac
aliBuild --remote-store "$REMOTE_STORE" "${alibuild_args[@]}" || {
builderr=$?
echo "Exiting with an error ($builderr), not tagging"
exit $builderr
}
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
# Now we tag, in case we should
for package in $PACKAGES; do
pushd "${package,,}.git" &> /dev/null || continue
if [ -n "$(git ls-remote origin "refs/tags/$AUTOTAG_TAG")" ]; then
echo "Not tagging: tag $AUTOTAG_TAG exists already"
else
# We previously pushed AUTOTAG_HASH to refs/heads/rc/$AUTOTAG_TAG.
# For some reason, +refs/remotes/origin/rc/$AUTOTAG_TAG:... doesn't work --
# even though we push above, the ref doesn't seem to be remembered locally.
autotag_hash=$(git ls-remote origin "refs/heads/rc/$AUTOTAG_TAG" | cut -f1)
[ -n "$autotag_hash" ]
git push origin "+$autotag_hash:refs/tags/$AUTOTAG_TAG"
fi
git push origin ":refs/heads/rc/$AUTOTAG_TAG" || : # error is not a big deal here
popd &> /dev/null
done
# Also tag the appropriate alidist
: "${PACKAGES_IN_ALIDIST_TAG:=$PACKAGES}"
# We normally want to build using the tag, and now it exists.
(cd alidist && git stash) # first, undo our temporary changes, which might include changes that shouldn't be committed
for package in $PACKAGES_IN_ALIDIST_TAG; do
edit_package_tag "$package" "$DEFAULTS" "$AUTOTAG_TAG" "$AUTOTAG_OVERRIDE_VERSION"
done
cd alidist
edited_files=("defaults-${DEFAULTS,,}.sh")
for edited_pkg in $PACKAGES_IN_ALIDIST_TAG; do
edited_files+=("${edited_pkg,,}.sh")
done
# If the file was modified, the output of git status will be non-empty.
if [ -n "$(git status --porcelain "${edited_files[@]}")" ]; then
git add "${edited_files[@]}"
git commit -m "Auto-update: ${edited_files[*]}"
fi
git push origin -f "HEAD:refs/tags/$main_pkg-$AUTOTAG_TAG"
if [ "$CREATE_ALIDIST_PULL_REQUEST" = true ]; then
# If ALIDIST_BRANCH doesn't exist or we can push to it, do it.
git push origin "HEAD:${ALIDIST_BRANCH:?}" ||
# Else, make a PR by pushing an rc/ branch. (An action in the repo handles this.)
git push origin -f "HEAD:refs/heads/rc/${ALIDIST_BRANCH:?}"
fi