-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathcreate_docker_image.sh
executable file
·233 lines (193 loc) · 8.18 KB
/
create_docker_image.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
#!/bin/bash
# exit when any command fails
set -e
echo "::group::Validate Information"
if [ "$INPUT_APPENDIX_FILE" ]; then
APPENDIX=`cat $INPUT_APPENDIX_FILE`
echo "Appendix read from $INPUT_APPENDIX_FILE:\n$APPENDIX"
fi
# Set INPUT_NO_PUSH to false if it is not provided
if [ -z "$INPUT_NO_PUSH" ]; then
INPUT_NO_PUSH="false"
fi
# Login to Docker registry if about to push and credentials are passed
if [[ "$INPUT_NO_PUSH" = "false" && -n "$INPUT_DOCKER_PASSWORD" && -n "$INPUT_DOCKER_USERNAME" ]]; then
echo ${INPUT_DOCKER_PASSWORD} | docker login $INPUT_DOCKER_REGISTRY -u ${INPUT_DOCKER_USERNAME} --password-stdin
fi
REPO_NAME=`echo $GITHUB_REPOSITORY | cut -d "/" -f 2`
# Set image name to username/repo_name or github_actor/repo_name
if [ -z "$INPUT_IMAGE_NAME" ]; then
if [[ -z "$INPUT_DOCKER_USERNAME" ]]; then
INPUT_IMAGE_NAME="$GITHUB_ACTOR/$REPO_NAME"
else
INPUT_IMAGE_NAME="$INPUT_DOCKER_USERNAME/$REPO_NAME"
fi
# Lower-case
INPUT_IMAGE_NAME="${INPUT_IMAGE_NAME,,}"
fi
# Prepend image name with registry if it is supplied
if [ "$INPUT_DOCKER_REGISTRY" ]; then
INPUT_IMAGE_NAME="$INPUT_DOCKER_REGISTRY/$INPUT_IMAGE_NAME"
fi
# Set username
if [ -z "$INPUT_NOTEBOOK_USER" ] || [ "$INPUT_MYBINDERORG_TAG" ] || [ "$INPUT_BINDER_CACHE" ];
then
NB_USER="jovyan"
else
NB_USER="${INPUT_NOTEBOOK_USER}"
fi
# Set REPO_DIR
if [ -z "$INPUT_REPO_DIR" ];
then
REPO_DIR="/home/${NB_USER}"
else
REPO_DIR="${INPUT_REPO_DIR}"
fi
# Set Local Variables
shortSHA=$(echo "${GITHUB_SHA}" | cut -c1-12)
SHA_NAME="${INPUT_IMAGE_NAME}:${shortSHA}"
# Attempt to pull the image for a cached build
docker pull "${INPUT_IMAGE_NAME}" 2> /dev/null || true
echo "::endgroup::"
# Print variables for debugging
echo "::group::Show Variables"
echo "DOCKER_REGISTRY": ${INPUT_DOCKER_REGISTRY}
echo "INPUT_ADDITIONAL_TAG: ${INPUT_ADDITIONAL_TAG}"
echo "INPUT_APPENDIX_FILE: ${INPUT_APPENDIX_FILE}"
echo "INPUT_BINDER_CACHE: ${INPUT_BINDER_CACHE}"
echo "INPUT_IMAGE_NAME: ${INPUT_IMAGE_NAME}"
echo "INPUT_IMAGE_NAME: ${INPUT_IMAGE_NAME}"
echo "INPUT_MYBINDERORG_TAG: ${INPUT_MYBINDERORG_TAG}"
echo "INPUT_MYBINDERORG_TAG: ${INPUT_MYBINDERORG_TAG}"
echo "INPUT_NOTEBOOK_USER: ${INPUT_NOTEBOOK_USER}"
echo "INPUT_NO_PUSH: ${INPUT_NO_PUSH}"
echo "INPUT_PUBLIC_REGISTRY_CHECK: ${INPUT_PUBLIC_REGISTRY_CHECK}"
echo "INPUT_FORCE_REPO2DOCKER_VERSION: ${INPUT_FORCE_REPO2DOCKER_VERSION}"
echo "INPUT_REPO_DIR: ${INPUT_REPO_DIR}"
echo "NB_USER: ${NB_USER}"
echo "PWD: ${PWD}"
echo "SHA_NAME: ${SHA_NAME}"
echo "::endgroup::"
echo "IMAGE_SHA_NAME=${SHA_NAME}" >> $GITHUB_OUTPUT
echo "IMAGE_SHA_TAG=${shortSHA}" >> $GITHUB_OUTPUT
echo "::group::Build ${SHA_NAME}"
# Install specific version of repo2docker if required
if [ ! -z "${INPUT_FORCE_REPO2DOCKER_VERSION}" ]; then
python3 -m pip install --upgrade --force ${INPUT_FORCE_REPO2DOCKER_VERSION}
fi
# If BINDER_CACHE flag is specified, validate user intent by checking for the presence of .binder and binder directories.
if [ "$INPUT_BINDER_CACHE" ]; then
GENERIC_MSG="This Action assumes you are not explicitly using Binder to build your dependencies."
# Exit if .binder directory is present
if [ -d ".binder" ]; then
echo "Found directory .binder ${GENERIC_MSG} The presence of a directory named .binder indicates otherwise. Aborting this step.";
exit 1;
fi
# Delete binder directory if it exists and only contains Dockerfile, so repo2docker can do a fresh build.
if [ -d "binder" ]; then
# if /binder has files other than Dockerfile, exit with status code 1, else remove the binder folder.
num_files=`ls binder | grep -v 'Dockerfile' | wc -l`
if [[ "$num" -gt 0 ]];
then
echo "Files other than Dockerfile are present in your binder/ directory. ${GENERIC_MSG} This directory is used by this Action to point to an existing Docker image that Binder can pull.";
exit 1;
else
rm -rf binder
fi
fi
fi
# Just build the image, do not push it
# Don't quote ${INPUT_REPO2DOCKER_EXTRA_ARGS}, as it *should* be interpreted as arbitrary
# arguments to be passed to repo2docker.
# Explicitly specify repo and ref labels, as repo2docker only knows it is building something
# local.
jupyter-repo2docker --no-run --user-id 1000 --user-name ${NB_USER} \
--target-repo-dir ${REPO_DIR} --image-name ${SHA_NAME} --cache-from ${INPUT_IMAGE_NAME} \
--label "repo2docker.repo=https://github.com/${GITHUB_REPOSITORY}" \
--label "repo2docker.ref=${GITHUB_REF}" \
--appendix "$APPENDIX" ${INPUT_REPO2DOCKER_EXTRA_ARGS} ${PWD}
if [ -z "$INPUT_LATEST_TAG_OFF" ]; then
docker tag ${SHA_NAME} ${INPUT_IMAGE_NAME}:latest
fi
if [ "$INPUT_ADDITIONAL_TAG" ]; then
docker tag ${SHA_NAME} ${INPUT_IMAGE_NAME}:$INPUT_ADDITIONAL_TAG
fi
echo "::endgroup::"
# If a directory named image-tests exists, run tests on the built image
if [ -d "${PWD}/image-tests" ]; then
echo "::group::Run tests found in image-tests/"
# We pass in bash that is run inside the built container, so watch out for quoting.
docker run -u 1000 -w ${REPO_DIR} \
${SHA_NAME} /bin/bash -c '
export PYTEST_FLAGS="";
# If there is a requirements.txt file inside image-tests, install it.
# Useful if you want to install a bunch of pytest packages.
[ -f image-tests/requirements.txt ] && \
echo "Installing from image-tests/requirements.txt..." && \
python3 -m pip install --no-cache -r image-tests/requirements.txt;
# If pytest is not already installed in the image, install it.
which py.test > /dev/null || \
echo "Installing pytest inside the image..." && \
python3 -m pip install --no-cache pytest > /dev/null;
# If there are any .ipynb files in image-tests, install pytest-notebook
# if necessary, and set PYTEST_FLAGS so notebook tests are run.
ls image-tests/*.ipynb > /dev/null && \
echo "Found notebooks, using pytest-notebook to run them..." && \
export PYTEST_FLAGS="--nb-test-files ${PYTEST_FLAGS}" && \
python3 -c "import pytest_notebook" 2> /dev/null || \
python3 -m pip install --no-cache pytest-notebook > /dev/null;
py.test ${PYTEST_FLAGS} image-tests/
'
echo "::endgroup::"
fi
if [ "$INPUT_NO_PUSH" = "false" ]; then
echo "::group::Pushing ${SHA_NAME}"
docker push ${SHA_NAME}
if [ -z "$INPUT_LATEST_TAG_OFF" ]; then
docker push ${INPUT_IMAGE_NAME}:latest
fi
if [ "$INPUT_ADDITIONAL_TAG" ]; then
docker push ${INPUT_IMAGE_NAME}:$INPUT_ADDITIONAL_TAG
fi
echo "::endgroup::"
echo "PUSH_STATUS=true" >> $GITHUB_OUTPUT
if [ "$INPUT_PUBLIC_REGISTRY_CHECK" ]; then
echo "::group::Verify That Image Is Public"
docker logout
if docker pull $SHA_NAME; then
echo "Verified that $SHA_NAME is publicly visible."
else
echo "Could not pull docker image: $SHA_NAME. Make sure this image is public before proceeding."
exit 1
fi
echo "::endgroup::"
fi
else
if [ "$INPUT_NO_PUSH" != "true" ]; then
echo "Error: invalid value for NO_PUSH: $INPUT_NO_PUSH. Valid values are true or false."
exit 1
fi
echo "PUSH_STATUS=false" >> $GITHUB_OUTPUT
fi
if [ "$INPUT_BINDER_CACHE" ]; then
echo "::group::Commit Local Dockerfile For Binder Cache"
python /binder_cache.py "$SHA_NAME"
git config --global --add safe.directory /github/workspace
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git add binder/Dockerfile
if [ "$INPUT_COMMIT_MSG" ]; then
git commit -m"${INPUT_COMMIT_MSG}"
else
git commit -m'Update image tag'
fi
if [ ! "$INPUT_NO_GIT_PUSH" ]; then
git push -f
fi
echo "::endgroup::"
fi
if [ "$INPUT_MYBINDERORG_TAG" ]; then
echo "::group::Triggering Image Build on mybinder.org"
/trigger_binder.sh "https://gke.mybinder.org/build/gh/$GITHUB_REPOSITORY/$INPUT_MYBINDERORG_TAG"
echo "::endgroup::"
fi