-
Notifications
You must be signed in to change notification settings - Fork 4
/
functions.sh
227 lines (208 loc) · 7.46 KB
/
functions.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
#!/bin/bash
function current_branch_name() {
git rev-parse --abbrev-ref HEAD
}
function get_num_parents() {
sha=$1
parents=$(git cat-file -p $sha | grep parent | wc -l)
echo $parents
}
# Given a range, produce the list of file paths changed
function changed_paths_in_range() {
compare_range=$1
# diff-filter=d excludes deleted files
git diff --name-only --diff-filter=d $compare_range
}
# Check if DEPLOY_BRANCH is set and current branch can be tested
function check_deploy_branch() {
if [[ "$DEPLOY_BRANCH" == "" ]]; then
echo "Error: DEPLOY_BRANCH is empty"
echo "Please ensure DEPLOY_BRANCH is set to the name of the git branch that should be considered for deploying, typically 'master'";
exit 1;
else
echo "Using Deploy branch as $DEPLOY_BRANCH..."
fi
current_branch=$(current_branch_name)
if [[ "$current_branch" == "$DEPLOY_BRANCH" ]]; then
# Current branch is the deploy branch, we must have a merge commit to test/build
num_parents=$(get_num_parents "HEAD")
if [[ "$num_parents" -lt "2" ]]; then
echo "Error: Current branch is the deploy branch ($DEPLOY_BRANCH), but HEAD is not a merge commit. Build failed." && exit 1
fi
fi
}
# If the current branch is the deploy branch, return a range representing
# the two parents of the HEAD's merge commit. If not, return a range comparing
# the current HEAD with the deploy_branch
function get_compare_range() {
current_branch=$(current_branch_name)
if [[ "$current_branch" == "$DEPLOY_BRANCH" ]]; then
# On the deploy branch (e.g. master)
# check_deploy_branch should have verified it is a merge commit
range_start="HEAD^1" # alias for first parent
range_end="HEAD^2" # alias for second parent
else
# Not on the deploy branch (e.g. master)
# When not on the deploy branch, always compare with the deploy branch
# Circle resets master to the tested commit, so we have to use origin/master
range_start="origin/$DEPLOY_BRANCH"
range_end="HEAD"
fi
echo "$range_start $range_end"
}
# Given a docker repo owner, image name, and version, produce a local docker build command
function build_docker_cmd() {
owner=$1
tool=$2
version=$3
echo "docker build -f $tool/$version/Dockerfile" -t "$owner/$tool:$version" "$tool/$version"
}
# Given a docker repo owner, image name, and version, produce a docker push command
function push_docker_cmd() {
owner=$1
tool=$2
version=$3
echo "docker push $owner/$tool:$version";
}
# Given a docker repo owner, image name, and version, produce a docker pull command
function pull_docker_cmd() {
owner=$1
tool=$2
version=$3
echo "docker pull $owner/$tool:$version";
}
# Given a docker repo owner, image name, source and dest tags produce a docker tag command
function tag_docker_cmd() {
owner=$1
tool=$2
src=$3
tag=$4
echo "docker tag $owner/$tool:$src $owner/$tool:$tag"
}
# Given a docker repo owner, image name, and version, produce a command that returns the image id if it exists locally
function docker_image_id_cmd() {
owner=$1
tool=$2
tag=$3
echo "docker images $owner/$tool:$tag -q"
}
# Given a docker repo owner, image name, and version, check if it exists locally and pull if necessary
function ensure_local_image() {
owner=$1
tool=$2
version=$3
local_image_id=$($(docker_image_id_cmd $owner $tool $version))
if [[ "$local_image_id" == "" ]]; then
echo "Image $owner/$tool:$version does not exist locally for tagging, pulling..."
$(pull_docker_cmd $owner $tool $version)
fi
}
# Given
# 1. a Docker repo owner (e.g. "dukegcb") and
# 2. a list of relative paths to Dockerfiles (e.g. "fastqc/0.11.4/Dockerfile bwa/0.7.12/Dockerfile",
# issue a docker build command and tag any versions with a latest symlink
function build_images() {
echo "Building changed Dockerfiles..."; echo
owner="$1"
changed_paths="$2"
# Check for Dockerfile changes first
for changed_path in $changed_paths; do
IFS='/' read -r -a f <<< "$changed_path"
tool="${f[0]}"
version="${f[1]}"
filename="${f[2]}"
if [[ "$filename" == "Dockerfile" && "$version" != "latest" ]]; then
attempted_build="1"
echo "Building $owner/$tool:$version..."
$(build_docker_cmd $owner $tool $version)
# Check if there's a symlink $tool/latest pointing to THIS version
if [[ "$tool/latest/Dockerfile" -ef "$tool/$version/Dockerfile" ]]; then
echo "Tagging $owner/$tool:$version as $owner/$tool:latest"
$(tag_docker_cmd $owner $tool $version "latest")
fi
fi
done;
# After building all Dockerfiles, check for any changes to latest
echo "Updating latest tags..."; echo
for changed_path in $changed_paths; do
IFS='/' read -r -a f <<< "$changed_path"
tool="${f[0]}"
version="${f[1]}"
filename="${f[2]}"
if [[ -L "$changed_path" && "$filename" == "" && "$version" == "latest" ]]; then
attempted_build="1"
# The changed file is a symlink called latest, e.g. "fastqc/latest"
# Determine the version it's pointing to
dest_version=$(readlink $changed_path)
# In order to tag to version, it must exist locally. If it wasn't built in previous loop,
# need to pull it
ensure_local_image $owner $tool $dest_version
echo "Tagging $owner/$tool:$dest_version as $owner/$tool:latest"
$(tag_docker_cmd $owner $tool $dest_version "latest")
fi
done;
if [[ "$attempted_build" == "" ]]; then
echo "No changes to Dockerfiles or latest symlinks detected, nothing to build";
fi
}
# Given
# 1. a Docker repo owner (e.g. "dukegcb") and
# 2. a list of relative paths to Dockerfiles (e.g. "fastqc/0.11.4/Dockerfile bwa/0.7.12/Dockerfile",
# issue a docker push command for the images built by build_images
function push_images() {
owner="$1"
changed_paths="$2"
for changed_path in $changed_paths; do
IFS='/' read -r -a f <<< "$changed_path"
tool="${f[0]}"
version="${f[1]}"
filename="${f[2]}"
if [[ "$filename" == "Dockerfile" && "$version" != "latest" ]]; then
attempted_push="1"
echo "Pushing $owner/$tool:$version..."
$(push_docker_cmd $owner $tool $version)
# Check if there's a symlink $tool/latest pointing to THIS version
if [[ "$tool/latest/Dockerfile" -ef "$tool/$version/Dockerfile" ]]; then
echo "Pushing $owner/$tool:latest..."
$(push_docker_cmd $owner $tool "latest")
fi
fi
done;
# After pushing all Dockerfiles, check for any changes to latest and push those
echo "Pushing latest tags..."; echo
for changed_path in $changed_paths; do
IFS='/' read -r -a f <<< "$changed_path"
tool="${f[0]}"
version="${f[1]}"
filename="${f[2]}"
if [[ -L "$changed_path" && "$filename" == "" && "$version" == "latest" ]]; then
attempted_push="1"
# The changed file is a symlink called latest, e.g. "fastqc/latest"
# Determine the version it's pointing to
echo "Pushing $owner/$tool:latest..."
$(push_docker_cmd $owner $tool "latest")
fi
done;
if [[ "$attempted_push" == "" ]]; then
echo "No changes to Dockerfiles or latest symlinks detected, nothing to push";
fi
}
function print_changed() {
range="$1"
paths="$2"
echo "Changed files in ($range)"
echo
for changed_path in $paths; do
echo " $changed_path"
done
echo
}
function check_org() {
if [[ "$DOCKERHUB_ORG" == "" ]]; then
echo "Error: DOCKERHUB_ORG is empty"
echo "Please ensure DOCKERHUB_ORG is set to the name of the Docker Hub organization";
exit 1;
else
echo "Using Docker Hub org as $DOCKERHUB_ORG..."
fi
}