Skip to content

Commit 4125c2f

Browse files
authored
Merge pull request #80 from oesteban/ci/minimize-docker-image
MAINT: Skim Docker image, optimize CircleCI workflow, and reuse cached results
2 parents c781e6f + aa181a7 commit 4125c2f

File tree

3 files changed

+141
-163
lines changed

3 files changed

+141
-163
lines changed

.circleci/config.yml

Lines changed: 129 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,125 @@ docs_deploy: &docs
3434

3535
version: 2
3636
jobs:
37-
build:
37+
cache_test_data:
38+
docker:
39+
- image: python:3.7.4
40+
working_directory: /tmp/data
41+
environment:
42+
- TEMPLATEFLOW_HOME: /tmp/templateflow
43+
steps:
44+
- restore_cache:
45+
keys:
46+
- env-v2-{{ .Branch }}-
47+
- env-v2-master-
48+
- env-v2-
49+
- restore_cache:
50+
keys:
51+
- data-v2-{{ .Branch }}-
52+
- data-v2-master-
53+
- data-v2-
54+
55+
- run:
56+
name: Setup git-annex
57+
command: |
58+
if [[ ! -d /usr/lib/git-annex.linux ]]; then
59+
wget -O- http://neuro.debian.net/lists/trusty.us-ca.full | tee /etc/apt/sources.list.d/neurodebian.sources.list
60+
apt-key adv --recv-keys --keyserver hkp://pool.sks-keyservers.net:80 0xA5D32F012649A5A9
61+
apt update && apt-get install -y --no-install-recommends git-annex-standalone
62+
fi
63+
git config --global user.name 'CRN'
64+
git config --global user.email '[email protected]'
65+
66+
- run:
67+
name: Setup DataLad & TemplateFlow
68+
command: |
69+
python -m pip install --no-cache-dir -U pip
70+
python -m pip install --no-cache-dir -U datalad
71+
python -m pip install --no-cache-dir -U templateflow
72+
python -c "from templateflow import api as tfapi; \
73+
tfapi.get('MNI152NLin2009cAsym', resolution=2, desc='brain', suffix='mask'); \
74+
tfapi.get('MNI152NLin2009cAsym', resolution=2, desc='fMRIPrep', suffix='boldref');"
75+
76+
- save_cache:
77+
key: env-v2-{{ .Branch }}-{{ .BuildNum }}
78+
paths:
79+
- /tmp/cache/git-annex-standalone.tar.gz
80+
- /usr/local/bin
81+
- /usr/local/lib/python3.7/site-packages
82+
- /usr/bin/git-annex
83+
- /usr/bin/git-annex-shell
84+
- /usr/lib/git-annex.linux
85+
86+
- run:
87+
name: Install ds001600
88+
command: |
89+
datalad install https://github.com/OpenNeuroDatasets/ds001600.git
90+
datalad update --merge ds001600/
91+
datalad get -r ds001600/*
92+
- run:
93+
name: Get testdata
94+
command: |
95+
if [[ ! -d /tmp/data/testdata ]]; then
96+
wget --retry-connrefused --waitretry=5 --read-timeout=20 --timeout=15 -t 0 -q \
97+
-O testdata.zip "https://files.osf.io/v1/resources/9sy2a/providers/osfstorage/5d44b940bcd6d900198ed6be/?zip="
98+
unzip testdata.zip -d /tmp/data/testdata
99+
fi
100+
- save_cache:
101+
key: data-v2-{{ .Branch }}-{{ .BuildNum }}
102+
paths:
103+
- /tmp/data
104+
- /tmp/templateflow
105+
106+
- restore_cache:
107+
keys:
108+
- freesurfer-v1-{{ .BuildNum }}
109+
- freesurfer-v1-
110+
- run:
111+
name: Pull FreeSurfer down
112+
command: |
113+
if [[ ! -d /tmp/freesurfer ]]; then
114+
curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz | tar zxv --no-same-owner -C /tmp \
115+
--exclude='freesurfer/diffusion' \
116+
--exclude='freesurfer/docs' \
117+
--exclude='freesurfer/fsfast' \
118+
--exclude='freesurfer/lib/cuda' \
119+
--exclude='freesurfer/lib/qt' \
120+
--exclude='freesurfer/matlab' \
121+
--exclude='freesurfer/mni/share/man' \
122+
--exclude='freesurfer/subjects/fsaverage_sym' \
123+
--exclude='freesurfer/subjects/fsaverage3' \
124+
--exclude='freesurfer/subjects/fsaverage4' \
125+
--exclude='freesurfer/subjects/cvs_avg35' \
126+
--exclude='freesurfer/subjects/cvs_avg35_inMNI152' \
127+
--exclude='freesurfer/subjects/bert' \
128+
--exclude='freesurfer/subjects/lh.EC_average' \
129+
--exclude='freesurfer/subjects/rh.EC_average' \
130+
--exclude='freesurfer/subjects/sample-*.mgz' \
131+
--exclude='freesurfer/subjects/V1_average' \
132+
--exclude='freesurfer/trctrain'
133+
echo "b2VzdGViYW5Ac3RhbmZvcmQuZWR1CjMwNzU2CiAqQ1MzYkJ5VXMxdTVNCiBGU2kvUGJsejJxR1V3Cg==" | base64 -d > /tmp/freesurfer/license.txt
134+
else
135+
echo "FreeSurfer was cached."
136+
circleci step halt
137+
fi
138+
- save_cache:
139+
key: freesurfer-v1-{{ .BuildNum }}
140+
paths:
141+
- /tmp/freesurfer
142+
143+
build_n_pytest:
38144
machine:
39145
image: circleci/classic:201711-01
40-
working_directory: /tmp/src/sdcflows
146+
working_directory: /tmp/tests
41147
environment:
42148
TZ: "/usr/share/zoneinfo/America/Los_Angeles"
43-
SCRATCH: "/scratch"
44149
steps:
45150
- restore_cache:
46151
keys:
47-
- build-v1-{{ .Branch }}-{{ epoch }}
48-
- build-v1-{{ .Branch }}-
49-
- build-v1-master-
50-
- build-v1-
152+
- build-v2-{{ .Branch }}-{{ epoch }}
153+
- build-v2-{{ .Branch }}-
154+
- build-v2-master-
155+
- build-v2-
51156
paths:
52157
- /tmp/docker
53158
- run:
@@ -75,11 +180,13 @@ jobs:
75180
docker push localhost:5000/ubuntu
76181
docker pull poldracklab/sdcflows:latest
77182
fi
78-
- checkout
183+
- checkout:
184+
path: /tmp/src/sdcflows
79185
- run:
80186
name: Build Docker image
81187
no_output_timeout: 60m
82188
command: |
189+
cd /tmp/src/sdcflows
83190
export PY3=$(pyenv versions | grep '3\.' |
84191
sed -e 's/.* 3\./3./' -e 's/ .*//')
85192
pyenv local $PY3
@@ -113,87 +220,19 @@ jobs:
113220
docker exec -it registry /bin/registry garbage-collect --delete-untagged \
114221
/etc/docker/registry/config.yml
115222
- save_cache:
116-
key: build-v1-{{ .Branch }}-{{ epoch }}
223+
key: build-v2-{{ .Branch }}-{{ epoch }}
117224
paths:
118225
- /tmp/docker
119-
- persist_to_workspace:
120-
root: /tmp
121-
paths:
122-
- src/sdcflows
123226

124-
cache_test_data:
125-
machine:
126-
image: circleci/classic:201711-01
127-
working_directory: /tmp/data
128-
steps:
227+
- restore_cache:
228+
keys:
229+
- freesurfer-v1-{{ .BuildNum }}
230+
- freesurfer-v1-
129231
- restore_cache:
130232
keys:
131233
- data-v2-{{ .Branch }}-
132234
- data-v2-master-
133235
- data-v2-
134-
- run:
135-
name: Setup git-annex
136-
command: |
137-
mkdir -p /tmp/cache
138-
if [[ ! -e "/tmp/cache/git-annex-standalone.tar.gz" ]]; then
139-
wget -O- http://neuro.debian.net/lists/trusty.us-ca.full | sudo tee /etc/apt/sources.list.d/neurodebian.sources.list
140-
sudo apt-key adv --recv-keys --keyserver hkp://pool.sks-keyservers.net:80 0xA5D32F012649A5A9
141-
sudo apt update && sudo apt-get install -y --no-install-recommends git-annex-standalone
142-
mkdir -p /tmp/cache
143-
tar czvf /tmp/cache/git-annex-standalone.tar.gz /usr/bin/git-annex /usr/bin/git-annex-shell /usr/lib/git-annex.linux
144-
else
145-
sudo tar xzfv /tmp/cache/git-annex-standalone.tar.gz -C /
146-
fi
147-
git config --global user.name 'CRN'
148-
git config --global user.email '[email protected]'
149-
150-
- run:
151-
name: Setup DataLad
152-
command: |
153-
pyenv global 3.5.2
154-
virtualenv venv
155-
pip install --no-cache-dir -U pip
156-
pip install --no-cache-dir -U datalad
157-
- run:
158-
name: Install ds001600
159-
command: |
160-
datalad install https://github.com/OpenNeuroDatasets/ds001600.git
161-
datalad update --merge ds001600/
162-
datalad get -r ds001600/*
163-
- run:
164-
name: Get testdata
165-
command: |
166-
if [[ ! -d /tmp/data/testdata ]]; then
167-
wget --retry-connrefused --waitretry=5 --read-timeout=20 --timeout=15 -t 0 -q \
168-
-O testdata.zip "https://files.osf.io/v1/resources/9sy2a/providers/osfstorage/5d44b940bcd6d900198ed6be/?zip="
169-
unzip testdata.zip -d /tmp/data/testdata
170-
fi
171-
172-
- run:
173-
name: Store FreeSurfer license file
174-
command: |
175-
mkdir -p /tmp/data/
176-
echo "b2VzdGViYW5Ac3RhbmZvcmQuZWR1CjMwNzU2CiAqQ1MzYkJ5VXMxdTVNCiBGU2kvUGJsejJxR1V3Cg==" | base64 -d > /tmp/data/fslicense.txt
177-
178-
- save_cache:
179-
key: data-v2-{{ .Branch }}-{{ .BuildNum }}
180-
paths:
181-
- "/opt/circleci/.pyenv/versions/3.5.2"
182-
- /tmp/data
183-
- /tmp/cache/git-annex-standalone.tar.gz
184-
185-
- persist_to_workspace:
186-
root: /tmp
187-
paths:
188-
- data
189-
190-
test_sdcflows:
191-
machine:
192-
image: circleci/classic:201711-01
193-
working_directory: /tmp/tests
194-
steps:
195-
- attach_workspace:
196-
at: /tmp
197236
- restore_cache:
198237
keys:
199238
- workdir-v2-{{ .Branch }}-
@@ -225,32 +264,15 @@ jobs:
225264
echo "Found tag [wipe ${wipe_dir}] - clearing up $path ..."
226265
rm -rf ${path}
227266
fi
228-
- restore_cache:
229-
keys:
230-
- build-v1-{{ .Branch }}-{{ epoch }}
231-
- build-v1-{{ .Branch }}-
232-
- build-v1-master-
233-
- build-v1-
234-
paths:
235-
- /tmp/docker
236-
- run:
237-
name: Set-up a Docker registry
238-
command: |
239-
docker run -d -p 5000:5000 --restart=always --name=registry \
240-
-v /tmp/docker:/var/lib/registry registry:2
241-
- run:
242-
name: Pull images from local registry
243-
command: |
244-
docker pull localhost:5000/sdcflows
245-
docker tag localhost:5000/sdcflows poldracklab/sdcflows:latest
246267
- run:
247268
name: Run tests
248269
no_output_timeout: 2h
249270
command: |
250271
mkdir -p /tmp/work
251272
docker run -it --rm -e TEST_DATA_HOME=/data/ -e TEST_OUTPUT_DIR=/out \
252-
-v /tmp/data/fslicense.txt:/opt/freesurfer/license.txt:ro -e FS_LICENSE=/opt/freesurfer/license.txt \
273+
-v /tmp/freesurfer:/opt/freesurfer:ro -e FS_LICENSE=/opt/freesurfer/license.txt \
253274
-v /tmp/work:/work -e TEST_WORK_DIR=/work \
275+
-v /tmp/templateflow:/home/sdcflows/.cache/templateflow \
254276
-v /tmp/data:/data:ro -v /tmp/src:/src -v /tmp/tests:/out \
255277
-w /work poldracklab/sdcflows:latest \
256278
pytest -v --junit-xml=/out/pytest.xml /src/sdcflows/sdcflows
@@ -324,10 +346,10 @@ jobs:
324346
steps:
325347
- restore_cache:
326348
keys:
327-
- build-v1-{{ .Branch }}-{{ epoch }}
328-
- build-v1-{{ .Branch }}-
329-
- build-v1-master-
330-
- build-v1-
349+
- build-v2-{{ .Branch }}-{{ epoch }}
350+
- build-v2-{{ .Branch }}-
351+
- build-v2-master-
352+
- build-v2-
331353
paths:
332354
- /tmp/docker
333355
- run:
@@ -466,13 +488,6 @@ workflows:
466488
version: 2
467489
build_deploy:
468490
jobs:
469-
- build:
470-
filters:
471-
branches:
472-
ignore:
473-
- /docs?\/.*/
474-
tags:
475-
only: /.*/
476491
- cache_test_data:
477492
filters:
478493
branches:
@@ -481,9 +496,8 @@ workflows:
481496
tags:
482497
only: /.*/
483498

484-
- test_sdcflows:
499+
- build_n_pytest:
485500
requires:
486-
- build
487501
- cache_test_data
488502
filters:
489503
branches:
@@ -503,10 +517,9 @@ workflows:
503517

504518
- deploy_pypi:
505519
requires:
506-
- build
507520
- build_docs
508521
- test_package
509-
- test_sdcflows
522+
- build_n_pytest
510523
filters:
511524
branches:
512525
ignore: /.*/
@@ -527,14 +540,12 @@ workflows:
527540
branches:
528541
ignore:
529542
- /tests?\/.*/
530-
- /ds005\/.*/
531-
- /ds054\/.*/
532543
tags:
533544
only: /.*/
534545

535546
- deploy_docs_master:
536547
requires:
537-
- test_sdcflows
548+
- build_n_pytest
538549
- test_package
539550
- build_docs
540551
filters:

.docker/files/nipype.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[execution]
2+
hash_method = content
23
poll_sleep_duration = 0.01
34
remove_unnecessary_outputs = true
45
crashfile_format = txt

0 commit comments

Comments
 (0)