-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild+push
More file actions
executable file
·187 lines (166 loc) · 6.69 KB
/
build+push
File metadata and controls
executable file
·187 lines (166 loc) · 6.69 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
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
#!/usr/bin/env sh
# Set good defaults to allow script to be run by hand. The three variables below
# will be overriden when run from within the workflow.
DOCKER_REPO=${DOCKER_REPO:-"gpsgate/csharpier"}
SOURCE_COMMIT=${SOURCE_COMMIT:-$(git log --no-decorate|grep '^commit'|head -n 1| awk '{print $2}')}
PLATFORMS=${PLATFORMS:-"linux/amd64"}
# Minimum version of csharpier to build for.
MINVER=${MINVER:-0.18.0}
# You shouldn't really need to have to modify the following variables.
GH_PROJECT=belav/csharpier
BUILDX_OPERATION=${BUILDX_OPERATION:-"--push"}; # Change to --load to build only.
OCINS="org.opencontainers.image"
SCRIPTDIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
ROOTDIR=${SCRIPTDIR}/..
DOCKERDIR=${ROOTDIR}/docker
# shellcheck disable=SC1091
. "$(dirname "$0")/reg-tags/image_api.sh"
_releases() {
# Ask GH for the list of releases matching the tag pattern, then fool the sort
# -V option to properly understand semantic versioning. Arrange for latest
# version to be at the top. See: https://stackoverflow.com/a/40391207
github_releases -r 'v?[0-9]+\.[0-9]+\.[0-9]+' "$1" |
sed '/-/!{s/$/_/}' |
sort -V |
sed 's/_$//'
}
# Returns the number of seconds since the epoch for the ISO8601 date passed as
# an argument. This will only recognise a subset of the standard, i.e. dates
# with milliseconds, microseconds, nanoseconds or none specified, and timezone
# only specified as diffs from UTC, e.g. 2019-09-09T08:40:39.505-07:00 or
# 2019-09-09T08:40:39.505214+00:00. The special Z timezone (i.e. UTC) is also
# recognised.
_iso8601() {
# Arrange for tzdiff to be the number of seconds for the timezone.
tz=$(printf %s\\n "$1"|sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]{3,9}))?([+-]([0-9]{2}):([0-9]{2})|Z)?/\9/')
tzdiff=0
if [ -n "$tz" ]; then
if [ "$tz" = "Z" ]; then
tzdiff=0
else
hrs=$(printf %s\\n "$tz" | sed -E 's/[+-]([0-9]{2}):([0-9]{2})/\1/')
mns=$(printf %s\\n "$tz" | sed -E 's/[+-]([0-9]{2}):([0-9]{2})/\2/')
hrs=${hrs##0}; mns=${mns##0}; # Strip leading 0s
sign=$(printf %s\\n "$tz" | sed -E 's/([+-])([0-9]{2}):([0-9]{2})/\1/')
secs=$((hrs*3600+mns*60))
if [ "$sign" = "-" ]; then
tzdiff=$secs
else
tzdiff=$((-secs))
fi
fi
fi
# Extract UTC date and time into something that date can understand, then
# add the number of seconds representing the timezone.
utc=$(printf %s\\n "$1"|sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]{3,9}))?([+-]([0-9]{2}):([0-9]{2})|Z)?/\1-\2-\3 \4:\5:\6/')
if [ "$(uname -s)" = "Darwin" ]; then
secs=$(date -u -j -f "%Y-%m-%d %H:%M:%S" "$utc" +"%s")
else
secs=$(date -u -d "$utc" +"%s")
fi
# shellcheck disable=SC2003 # antiquated but we want parenthesis for clarity
expr "$secs" + \( "$tzdiff" \)
}
# Return the UNIX timestamp of the docker image passed as argument. This
# downloads the image in all cases.
_docker_timestamp() {
# Remember if image was already present.
_present=0
if docker image inspect "$1" >/dev/null 2>&1; then
_present=1
fi
# Pull image in all cases, we want to have the latest known pushed image for
# that tag.
docker image pull --quiet "$1" >/dev/null || true
# Compute and print the timestamp of the image. 0 if the image does not exist.
_iso_date=$(docker image inspect --format '{{.Created}}' "$1")
if [ -z "$_iso_date" ]; then
printf %d\\n '0'
else
_iso8601 "$_iso_date"
fi
# Remove the image if it was not present before.
if [ "$_present" = "0" ]; then
docker image rm "$1" >/dev/null 2>&1
fi
}
# Return the UNIX timestamp of the commit reference(s) passed as argument.
_git_timestamp() { git show -s --format="%ct" "$@";}
# Print out list of files changed in the commit passed as argument, one per
# line.
_git_commit_files() {
git show --name-only --oneline "$@" | tail -n +2
}
# Given a list of files passed as arguments, print out the ones that are ignored
# by the .dockerignore file.
_dockerignored_files() {
git ls-files --ignored --cached --exclude-from="${ROOTDIR}/.dockerignore" -- "$@"
}
# Given a git sha reference, print out the files that are relevant to the
# building of the Docker image, i.e. that are NOT ignored by the .dockerignore
# file.
_dockerimage_sha_ref() {
while IFS= read -r file; do
if [ -n "$file" ] && [ -z "$(_dockerignored_files "$file")" ]; then
printf %s\\n "$file"
fi
done <<EOF
$(_git_commit_files "$@")
EOF
}
build_n_push() {
# Prepare arguments for docker buildx.
set -- \
--tag "${DOCKER_REPO}:$tag" \
--platform "$PLATFORMS" \
--build-arg CSHARPIER_VERSION="$tag" \
--label "${OCINS}.revision=$SOURCE_COMMIT" \
"$BUILDX_OPERATION"
# Add latest tag when relevant
if [ "$tag" = "$_latest" ]; then
set -- \
--tag "${DOCKER_REPO}:latest" \
"$@"
fi
if [ -n "$LABEL_AUTHOR" ]; then set -- --label "${OCINS}.authors=$LABEL_AUTHOR" "$@"; fi
if [ -n "$LABEL_DESCRIPTION" ]; then set -- --label "${OCINS}.description=$LABEL_DESCRIPTION" "$@"; fi
if [ -n "$LABEL_URL" ]; then set -- --label "${OCINS}.url=$LABEL_URL" "$@"; fi
if [ -n "$LABEL_TITLE" ]; then set -- --label "${OCINS}.title=$LABEL_TITLE" "$@"; fi
# Fix dotnet version, migrate to LTS 8.0 starting from 0.26.2. See:
# https://github.com/belav/csharpier/releases/tag/0.26.2
if [ "$(img_version "${tag#v}")" -ge "$(img_version "0.26.2")" ]; then
set -- \
--build-arg DOTNET_VERSION="8.0" \
"$@"
fi
# build (and push) according to arguments and at the right tags.
docker buildx build "$@" "$DOCKERDIR"
}
echo "============== Gettings latest releases for $GH_PROJECT at github"
_latest=
for tag in $(_releases "$GH_PROJECT"); do
# Latest is the first tag that we encounter.
if [ -z "$_latest" ]; then
_latest="$tag"
fi
if [ "$(img_version "${tag#v}")" -ge "$(img_version "$MINVER")" ]; then
img_date=$(_docker_timestamp "${DOCKER_REPO}:$tag")
if [ "$img_date" = "0" ]; then
echo "============== No image ${DOCKER_REPO}:$tag yet"
build_n_push "$@"
else
docker_files=$(_dockerimage_sha_ref "$SOURCE_COMMIT")
if [ -n "$docker_files" ]; then
git_date=$(_git_timestamp "$SOURCE_COMMIT")
if [ "$git_date" -ge "$img_date" ]; then
echo "============== Image ${DOCKER_REPO}:$tag older than $SOURCE_COMMIT"
build_n_push "$@"
else
echo "!!!!!!!!!!!!!! Image ${DOCKER_REPO}:$tag newer than ${SOURCE_COMMIT}, skipping"
fi
else
echo "!!!!!!!!!!!!!! No files relevant to the Docker image touched by commit ${SOURCE_COMMIT}, skipping"
fi
fi
fi
done