-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.gitlab-ci.yml
More file actions
319 lines (272 loc) · 11 KB
/
.gitlab-ci.yml
File metadata and controls
319 lines (272 loc) · 11 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
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#
# three jobs are structured as a DAG
#
# A) update halligan server
# updates files on the halligan server in /g/COURSENUM/TERM and resets file permissions
#
# B) deploy autograding container
# builds and uploads the docker container with relevant autograding files
#
# C) build reference output
# uses the autograding container to run reference as a submission; pushes the results back to the repo
#
# If B and C are both to be run, B runs first.
# A can run concurrently with either.
#
# Note! toml-cli is required to be installed on the runner host's python acct
# python3 -m pip install toml-cli
#
#
# This job updates halligan server files and file-permissions.
#
update halligan server:
#
# only run this script when server-facing files are updated
#
rules:
- when: always
changes:
paths:
- assignments/**/*
- bin/**/*
- files/**/*
- public_html/**/*
- staff-bin/**/*
- staff-docs/**/*
- .gitlab-ci.yml
#
# extract relevant variables from `config.toml`
#
before_script:
- /bin/bash
#
# load the halligan info from config.toml
#
- export HALLIGAN_COURSE_NUM=$(toml get halligan.COURSE_NUM)
- export HALLIGAN_COURSE_SEM=$(toml get halligan.TERM)
- export HALLIGAN_COURSE_GRP=$(toml get halligan.FILE_GROUP)
- export HALLIGAN_COURSE_PTH="/g/${HALLIGAN_COURSE_NUM}/${HALLIGAN_COURSE_SEM}"
script:
#
# log the most recent commit
#
- git log -1 --stat | tee server_log
#
# sync the repo with halligan
#
- rsync -a --force --exclude='.git/' ./ ${HALLIGAN_COURSE_PTH}
#
# set course files to the right group
#
- chgrp -R ${HALLIGAN_COURSE_GRP} ${HALLIGAN_COURSE_PTH}
#
# restore course file permission
#
- chmod +x ${HALLIGAN_COURSE_PTH}/staff-bin/*
- cd ${HALLIGAN_COURSE_PTH}/staff-bin
- sg ${HALLIGAN_COURSE_GRP} -c "./restore-permissions | tee -a ../server_log"
#
# This job builds and deploys the autograding container for gradescope.
#
deploy autograding container:
#
# only update docker container when necessary
#
rules:
- when: always
changes:
paths:
- ${AUTOGRADING_ROOT}/bin/run_autograder
- ${AUTOGRADING_ROOT}/bin/container_prep.py
- ${AUTOGRADING_ROOT}/bin/login.sh
- ${AUTOGRADING_ROOT}/etc/*
- .gitlab-ci.yml
- config.toml
variables:
#
# automatically determine path for docker container
# NOTE: uses group level variables to do this; pushes to a private dockerhub acct visible only to gradescope.
# CAUTION: !!! IF YOU CHANGE THESE VARIABLES ENSURE THAT THE RESULTING REMOTE IS PRIVATE !!!
#
REMOTE_TAG: ${CONTAINER_REGISTRY}/${CONTAINER_REGISTRY_USER}/${CONTAINER_NAME}:${CI_PROJECT_NAME}
#
# automatically determine path of git repo
# NOTE: uses ${REPO_PAT} - by default, a read-only [w/ developer permissions] group-level token for course-repos.
#
REPO_REMOTE_PATH: https://${CI_PROJECT_NAME}:${REPO_PAT}@gitlab.cs.tufts.edu/${CI_PROJECT_PATH}.git
before_script:
#
# login to the container registry
#
- echo ${CONTAINER_REGISTRY_PASS} | docker login ${CONTAINER_REGISTRY} --username ${CONTAINER_REGISTRY_USER} --password-stdin
script:
#
# create a .secrets file for token management
# NOTE: this file is deleted by a PAM module when anyone ssh-s into the container
# NOTE: if anyone accesses the container directly, then they can access the info; see !!!CAUTION!!! above.
#
- echo "TOKENS_PKEY=\"\"\"${TOKENS_PKEY}\"\"\"" > .secrets
- echo "TOKENS_UTLN=\"${TOKENS_UTLN}\"" >> .secrets
- echo "TOKENS_HOST=\"${TOKENS_HOST}\"" >> .secrets
- echo "COURSE_SLUG=\"${CI_PROJECT_NAME}\"" >> .secrets
- echo "MYSQL_USER=\"${MYSQL_USER}\"" >> .secrets
- echo "MYSQL_PASS=\"${MYSQL_PASS}\"" >> .secrets
- echo "MYSQL_DBNAME=\"${MYSQL_DBNAME}\"" >> .secrets
- echo "MYSQL_LOC=\"${MYSQL_LOC}\"" >> .secrets
#
# build and push the container
#
- podman build --pull --tag ${REMOTE_TAG} --build-arg AUTOGRADING_ROOT=${AUTOGRADING_ROOT} --build-arg REPO_REMOTE=${REPO_REMOTE_PATH} --build-arg REPO_BRANCH=${CI_COMMIT_BRANCH} -f ${AUTOGRADING_ROOT}/etc/Dockerfile .
- podman push ${REMOTE_TAG}
#
# cleanup secrets file just because
#
- rm .secrets
#
# cleanup podman images so we don't have things lingering, and show current podman disk usage
#
- podman rmi --all --force
- podman system prune --all --force
- podman system df
#
# This job builds reference output for the autograder.
#
build reference output:
#
# If we have to update the container for some reason, only build ref output after the fact.
#
needs:
- job: deploy autograding container
optional: true
#
# Only build reference output when changes are made inside of an autograding or solution folder.
#
rules:
- when: always
changes:
paths:
- "**/autograder/**/*"
- "**/solution/**/*"
variables:
#
# automatically determine repo remote path and remote tag as above
# NOTE: Uses a repo-level environment variable REPO_WRITE_DEPLOY_TOKEN
# NOTE: REPO_WRITE_DEPLOY_TOKEN must have 'read' and 'write' permission and 'maintainer' access to your repo.
#
REPO_REMOTE_PATH: https://${CI_PROJECT_NAME}:${REPO_WRITE_DEPLOY_TOKEN}@gitlab.cs.tufts.edu/${CI_PROJECT_PATH}.git
REMOTE_TAG: ${CONTAINER_REGISTRY}/${CONTAINER_REGISTRY_USER}/${CONTAINER_NAME}:${CI_PROJECT_NAME}
GRADER_DEV_FOLDER: "grading"
before_script:
- /bin/bash
- export REPO_ASSIGN_RDIR=$(toml get repo.ASSIGN_ROOT)
- export REPO_ASSIGN_AUGD=$(toml get repo.ASSIGN_AG_DIR)
- export REPO_ASSIGN_SOLD=$(toml get repo.ASSIGN_SOL_DIR)
- export HALLIGAN_COURSE_NUM=$(toml get halligan.COURSE_NUM)
- export HALLIGAN_COURSE_SEM=$(toml get halligan.TERM)
- export HALLIGAN_COURSE_GRP=$(toml get halligan.FILE_GROUP)
- export HALLIGAN_COURSE_PTH="/g/${HALLIGAN_COURSE_NUM}/${HALLIGAN_COURSE_SEM}"
script:
- /bin/bash
#
# Update the default repo's remote to include the deploy token. Checkout branch and pull.
#
- git remote set-url origin ${REPO_REMOTE_PATH}
- git fetch origin ${CI_COMMIT_BRANCH}
- git checkout -B ${CI_COMMIT_BRANCH} origin/${CI_COMMIT_BRANCH}
- git pull origin ${CI_COMMIT_BRANCH}
#
# Determine which assignments' autograder/ or solution/ directories have changed.
#
- changed_assignments=$(git diff-tree --no-commit-id --name-only -r $CI_COMMIT_SHA | grep -o -E "${REPO_ASSIGN_RDIR}/[^/]*/(${REPO_ASSIGN_AUGD}|${REPO_ASSIGN_SOLD})" | awk -F'/' '{print $2}' | sort | uniq)
#
# Build the reference output for each changed assignment
# To do this, copy the reference into the autograding container as the submission, run the autograder, and push the results
# back to the repo [make sure not to run the pipelines on the push]
# NOTE: !!! Can't work with podman in the nfs mount, so do the work in /var/tmp/utln !!!
#
- >
for ASSIGN_NAME in $changed_assignments; do
#
# determine path to files within the repo for the assignment
#
REPO_ASSGN_DIR=${CI_PROJECT_DIR}/${REPO_ASSIGN_RDIR}/${ASSIGN_NAME}
REPO_SOLTN_DIR=${REPO_ASSGN_DIR}/${REPO_ASSIGN_SOLD}
REPO_AUTOG_DIR=${REPO_ASSGN_DIR}/${REPO_ASSIGN_AUGD}
#
# sometimes the assignment name is empty; skip it if so
#
if [ ! -d ${REPO_SOLTN_DIR} ]; then
echo "solution dir doesn't exit for assignment: ${ASSIGN_NAME}; skipping"
continue
fi
if [ ! -d ${REPO_AUTOG_DIR} ]; then
echo "autograder dir doesn't exit for assignment: ${ASSIGN_NAME}; skipping"
continue
fi
#
# determine directories to run the autograder and to copy the results to
#
RUN_DIR=/var/tmp/${USER}/${CI_PROJECT_NAME}-${ASSIGN_NAME}-build
GRD_DIR=${HALLIGAN_COURSE_PTH}/${GRADER_DEV_FOLDER}/${ASSIGN_NAME}
#
# create results directories; wipe first if they exist
#
rm -rf ${RUN_DIR} ${GRD_DIR}
mkdir -p ${RUN_DIR}/results ${GRD_DIR}/results
#
# Grab solution code.
#
cp -r ${REPO_SOLTN_DIR} ${RUN_DIR}/solution
#
# Run the autograder!
# NOTE: The -v X:Y indicates to mount local:container.
# NOTE: This works bi-directionally, so output will be available
# NOTE: at ${RUN_DIR}/results when the container finishes.
#
podman run \
--rm \
--env ASSIGNMENT_TITLE=${ASSIGN_NAME} \
-v ${RUN_DIR}/solution:/autograder/submission \
-v ${RUN_DIR}/results:/autograder/results/ \
${REMOTE_TAG} \
/autograder/run_autograder 2>&1 | tee ${RUN_DIR}/autograder_results.txt
#
# .diff files are irrelevant [reference diffing against what?]
#
rm -f ${RUN_DIR}/results/output/*.diff*
#
# copy the results to grader-visible spot; don't follow symlinks! [gerp!]
#
cp -r --no-dereference ${RUN_DIR}/results ${RUN_DIR}/autograder_results.txt ${GRD_DIR}
#
# chgrp and chmod so graders can rwx everything.
# note: chmod parent dir to be safe.
#
chgrp -R ${HALLIGAN_COURSE_GRP} ${HALLIGAN_COURSE_PTH}/${GRADER_DEV_FOLDER}
chmod -R 770 ${HALLIGAN_COURSE_PTH}/${GRADER_DEV_FOLDER}
#
# copy the new reference output to the repo
# note: nuke old output if it exists first
#
rm -rf ${REPO_AUTOG_DIR}/testset/ref_output
mkdir -p ${REPO_AUTOG_DIR}/testset/ref_output
cp -r ${RUN_DIR}/results/output/* ${REPO_AUTOG_DIR}/testset/ref_output/
#
# commit and push the new reference output back to the repo.
# NOTE: push with -o ci.skip to avoid an infinite loop of rebuilds :)
#
cd ${REPO_AUTOG_DIR}
git config pull.rebase true
git add testset/ref_output
git commit -m "build ref output for ${ASSIGN_NAME}" || \
echo "No changes to repo or commit failed"
git pull
git push origin ${CI_COMMIT_BRANCH} -o ci.skip
done
#
# cleanup podman images so we don't have things lingering, and show current podman disk usage
#
- podman rmi --all --force
- podman system prune --all --force
- podman system df
### TODO: add no-pull job that does hard podman cleanup on disk space failure.