Browse code

Adding Jenkins CI script to sources

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2015/12/07 11:52:24
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,241 @@
0
+# Jenkins CI script for Windows to Linux CI.
1
+# Heavily modified by John Howard (@jhowardmsft) December 2015 to try to make it more reliable.
2
+set +x
3
+SCRIPT_VER="4-Jan-2016 15:19 PST"
4
+
5
+# TODO to make (even) more resilient: 
6
+#  - Check if jq is installed
7
+#  - Make sure bash is v4.3 or later. Can't do until all Azure nodes on the latest version
8
+#  - Make sure we are not running as local system. Can't do until all Azure nodes are updated.
9
+#  - Error if docker versions are not equal. Can't do until all Azure nodes are updated
10
+#  - Error if go versions are not equal. Can't do until all Azure nodes are updated.
11
+#  - Error if running 32-bit posix tools. Probably can take from bash --version and check contains "x86_64"
12
+#  - Warn if the CI directory cannot be deleted afterwards. Otherwise turdlets are left behind
13
+#  - Use %systemdrive% ($SYSTEMDRIVE) rather than hard code to c: for TEMP
14
+#  - Consider cross builing the Windows binary and copy across. That's a bit of a heavy lift. Only reason
15
+#    for doing that is that it mirrors the actual release process for docker.exe which is cross-built.
16
+#    However, should absolutely not be a problem if built natively, so nit-picking.
17
+#  - Tidy up of images and containers. Either here, or in the teardown script.
18
+
19
+ec=0
20
+echo INFO: Started at `date`. Script version $SCRIPT_VER
21
+
22
+# get the ip
23
+ip="${DOCKER_HOST#*://}"
24
+ip="${ip%%:*}"
25
+
26
+# make sure it is the right DOCKER_HOST. No, this is not a typo, it really
27
+# is at port 2357. This is the daemon which is running on the Linux host.
28
+# The way CI works is to launch a second daemon, docker-in-docker, which
29
+# listens on port 2375 and is built from sources matching the PR. That's the
30
+# one which is tested against.
31
+export DOCKER_HOST="tcp://$ip:2357"
32
+
33
+# Save for use by make.sh and scripts it invokes
34
+export MAIN_DOCKER_HOST="$DOCKER_HOST"
35
+
36
+
37
+# Verify we can get the remote node to respond to _ping
38
+if [ $ec -eq 0 ]; then
39
+	reply=`curl -s http://$ip:2357/_ping`
40
+	if [ "$reply" != "OK" ]; then
41
+		ec=1
42
+		echo "ERROR: Failed to get OK response from Linux node at $ip:2357. It may be down."
43
+		echo "       Try re-running this CI job, or ask on #docker-dev or #docker-maintainers"
44
+		echo "       to see if the node is up and running."
45
+		echo
46
+		echo "Regular ping output for remote host below. It should reply. If not, it needs restarting."
47
+		ping $ip
48
+	else
49
+		echo "INFO: The Linux nodes outer daemon replied to a ping. Good!"
50
+	fi 
51
+fi
52
+
53
+# Get the version from the remote node. Note this may fail if jq is not installed.
54
+# That's probably worth checking to make sure, just in case.
55
+if [ $ec -eq 0 ]; then
56
+	remoteVersion=`curl -s http://$ip:2357/version | jq -c '.Version'`
57
+	echo "INFO: Remote daemon is running docker version $remoteVersion"
58
+fi
59
+
60
+# Compare versions. We should really fail if result is no 1. Output at end of script.
61
+if [ $ec -eq 0 ]; then
62
+	uniques=`docker version | grep Version | /usr/bin/sort -u | wc -l`
63
+fi
64
+
65
+# Make sure we are in repo
66
+if [ $ec -eq 0 ]; then
67
+	if [ ! -d hack ]; then
68
+		echo "ERROR: Are you sure this is being launched from a the root of docker repository?"
69
+		echo "       If this is a Windows CI machine, it should be c:\jenkins\gopath\src\github.com\docker\docker."
70
+                echo "       Current directory is `pwd`"
71
+		ec=1
72
+	fi
73
+fi
74
+
75
+# Get the commit has and verify we have something
76
+if [ $ec -eq 0 ]; then
77
+	export COMMITHASH=$(git rev-parse --short HEAD)
78
+	echo INFO: Commmit hash is $COMMITHASH
79
+	if [ -z $COMMITHASH ]; then
80
+		echo "ERROR: Failed to get commit hash. Are you sure this is a docker repository?"
81
+		ec=1
82
+	fi
83
+fi
84
+
85
+# Redirect to a temporary location. Check is here for local runs from Jenkins machines just in case not
86
+# in the right directory where the repo is cloned. We also redirect TEMP to not use the environment
87
+# TEMP as when running as a standard user (not local system), it otherwise exposes a bug in posix tar which
88
+# will cause CI to fail from Windows to Linux. Obviously it's not best practice to ever run as local system...
89
+if [ $ec -eq 0 ]; then
90
+	export TEMP=/c/CI/CI-$COMMITHASH
91
+	export TMP=$TMP
92
+	/usr/bin/mkdir -p $TEMP  # Make sure Linux mkdir for -p
93
+fi
94
+
95
+# Tidy up time
96
+if [ $ec -eq 0 ]; then
97
+	echo INFO: Deleting pre-existing containers and images...
98
+	# Force remove all containers based on a previously built image with this commit
99
+	! docker rm -f $(docker ps -aq --filter "ancestor=docker:$COMMITHASH") &>/dev/null
100
+
101
+	# Force remove any container with this commithash as a name
102
+	! docker rm -f $(docker ps -aq --filter "name=docker-$COMMITHASH") &>/dev/null
103
+
104
+	# Force remove the image if it exists
105
+	! docker rmi -f "docker-$COMMITHASH" &>/dev/null
106
+	
107
+	# This SHOULD never happen, but just in case, also blow away any containers
108
+	# that might be around. 
109
+	! if [ ! `docker ps -aq | wc -l` -eq 0 ]; then
110
+		echo WARN: There were some leftover containers. Cleaning them up.
111
+		! docker rm -f $(docker ps -aq)
112
+	fi
113
+fi
114
+
115
+# Provide the docker version for debugging purposes. If these fail, game over. 
116
+# as the Linux box isn't responding for some reason.
117
+if [ $ec -eq 0 ]; then
118
+	echo INFO: Docker version and info of the outer daemon on the Linux node
119
+	echo
120
+	docker version
121
+	ec=$?
122
+	if [ 0 -ne $ec ]; then
123
+		echo "ERROR: The main linux daemon does not appear to be running. Has the Linux node crashed?"
124
+	fi
125
+	echo
126
+fi
127
+
128
+# Same as above, but docker info
129
+if [ $ec -eq 0 ]; then
130
+	echo
131
+	docker info
132
+	ec=$?
133
+	if [ 0 -ne $ec ]; then
134
+		echo "ERROR: The main linux daemon does not appear to be running. Has the Linux node crashed?"
135
+	fi
136
+	echo
137
+fi
138
+
139
+# build the daemon image
140
+if [ $ec -eq 0 ]; then
141
+	echo "INFO: Running docker build on Linux host at $DOCKER_HOST"
142
+	set -x
143
+	docker build --rm --force-rm -t "docker:$COMMITHASH" .
144
+	ec=$?
145
+	set +x
146
+	if [ 0 -ne $ec ]; then
147
+		echo "ERROR: docker build failed"
148
+	fi
149
+fi
150
+
151
+# Start the docker-in-docker daemon from the image we just built
152
+if [ $ec -eq 0 ]; then
153
+	echo "INFO: Starting build of a Linux daemon to test against, and starting it..."
154
+	set -x
155
+	docker run --pid host --privileged -d --name "docker-$COMMITHASH" --net host "docker:$COMMITHASH" bash -c 'echo "INFO: Compiling" && date && hack/make.sh binary && echo "INFO: Compile complete" && date && cp bundles/$(cat VERSION)/binary/docker /bin/docker && echo "INFO: Starting daemon" && exec docker daemon -D -H tcp://0.0.0.0:2375'
156
+	ec=$?
157
+	set +x
158
+	if [ 0 -ne $ec ]; then
159
+	    	echo "ERROR: Failed to compile and start the linux daemon"
160
+	fi
161
+fi
162
+
163
+# Build locally.
164
+if [ $ec -eq 0 ]; then
165
+	echo "INFO: Starting local build of Windows binary..."
166
+	set -x
167
+	export TIMEOUT="120m"
168
+	export DOCKER_HOST="tcp://$ip:2375"
169
+	export DOCKER_TEST_HOST="tcp://$ip:2375"
170
+	unset DOCKER_CLIENTONLY
171
+	export DOCKER_REMOTE_DAEMON=1
172
+	hack/make.sh binary 
173
+	ec=$?
174
+	set +x
175
+	if [ 0 -ne $ec ]; then
176
+	    echo "ERROR: Build of binary on Windows failed"
177
+	fi
178
+fi
179
+
180
+# Make a local copy of the built binary and ensure that is first in our path
181
+if [ $ec -eq 0 ]; then
182
+	VERSION=$(< ./VERSION)
183
+	cp bundles/$VERSION/binary/docker.exe $TEMP
184
+	ec=$?
185
+	if [ 0 -ne $ec ]; then
186
+		echo "ERROR: Failed to copy built binary to $TEMP"
187
+	fi
188
+	export PATH=$TEMP:$PATH
189
+fi
190
+
191
+# Run the integration tests
192
+if [ $ec -eq 0 ]; then
193
+	echo "INFO: Running Integration tests..."
194
+	set -x
195
+	hack/make.sh test-integration-cli
196
+	ec=$?
197
+	set +x
198
+	if [ 0 -ne $ec ]; then
199
+		echo "ERROR: CLI test failed."
200
+		# Next line is useful, but very long winded if included
201
+		# docker -H=$MAIN_DOCKER_HOST logs "docker-$COMMITHASH"
202
+	fi
203
+fi
204
+
205
+# Tidy up any temporary files from the CI run
206
+if [ ! -z $COMMITHASH ]; then
207
+	rm -rf $TEMP
208
+fi
209
+
210
+# CI Integrity check - ensure we are using the same version of go as present in the Dockerfile
211
+GOVER_DOCKERFILE=`grep 'ENV GO_VERSION' Dockerfile | awk '{print $3}'`
212
+GOVER_INSTALLED=`go version | awk '{print $3}'`
213
+if [ "${GOVER_INSTALLED:2}" != "$GOVER_DOCKERFILE" ]; then
214
+	ec=1  # Uncomment to make CI fail once all nodes are updated.
215
+	echo
216
+	echo "---------------------------------------------------------------------------"
217
+	echo "ERROR: CI should be using go version $GOVER_DOCKERFILE, but is using ${GOVER_INSTALLED:2}"
218
+	echo "      This is currently a warning, but should (will) become an error in the future."
219
+	echo "---------------------------------------------------------------------------"
220
+	echo
221
+fi
222
+
223
+# Check the Linux box is running a matching version of docker
224
+if [ "$uniques" -ne 1 ]; then
225
+    ec=1  # Uncomment to make CI fail once all nodes are updated.
226
+	echo
227
+	echo "---------------------------------------------------------------------------"
228
+	echo "ERROR: This CI node is not running the same version of docker as the daemon."
229
+	echo "       This is a CI configuration issue"
230
+	echo "---------------------------------------------------------------------------"
231
+	echo
232
+fi
233
+
234
+# Tell the user how we did.
235
+if [ $ec -eq 0 ]; then
236
+	echo INFO: Completed successfully at `date`. 
237
+else
238
+	echo ERROR: Failed with exitcode $ec at `date`.
239
+fi
240
+exit $ec
0 241
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+These files under this directory are for reference only. 
1
+
2
+They are used by Jenkins for CI runs.
0 3
\ No newline at end of file