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
|
# https://aka.ms/yaml
jobs:
- job: test
displayName: 'Lint & Test'
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: ShellScript@2
displayName: 'Check If Images Need to Be Built'
name: check
inputs:
scriptPath: scripts/check_dockerfiles.sh
disableAutoCwd: true
# Without a login the following Docker build tasks won't add image tags.
- task: Docker@1
displayName: 'Log into Docker Hub'
inputs:
command: login
containerregistrytype: 'Container Registry'
dockerRegistryEndpoint: 'DockerHub'
# The venv image depends on this image. Build it if it can't be pulled
# from Docker Hub, which will be the case if the base Dockerfile has had
# changes.
- script: |
docker build \
-f docker/base.Dockerfile \
-t pythondiscord/snekbox-base:latest \
.
displayName: 'Build Base Image'
condition: and(succeeded(), ne(variables['check.BASE_PULL'], True))
# The dev image is never pushed and therefore is always built.
- script: |
docker build \
-f docker/venv.Dockerfile \
-t pythondiscord/snekbox-venv:dev \
--build-arg DEV=1 \
.
displayName: 'Build Development Image'
# The linter and all tests run inside this container.
- script: |
docker run \
--tty \
--detach \
--name snekbox_test \
--privileged \
--network host \
--hostname pdsnk-dev \
-e PYTHONDONTWRITEBYTECODE=1 \
-e PIPENV_PIPFILE="/snekbox/Pipfile" \
-e ENV="${PWD}/scripts/.profile" \
--volume "${PWD}":"${PWD}" \
--workdir "${PWD}"\
--entrypoint /bin/bash \
pythondiscord/snekbox-venv:dev
displayName: 'Start Container'
- script: |
docker exec snekbox_test /bin/bash -c \
'pipenv run lint --format junit-xml --output-file test-lint.xml'
displayName: 'Run Linter'
- task: PublishTestResults@2
displayName: 'Publish Lint Results'
condition: succeededOrFailed()
inputs:
testResultsFiles: '**/test-lint.xml'
testRunTitle: 'Lint Results'
# Memory limit tests would fail if this isn't disabled.
- script: sudo swapoff -a
displayName: 'Disable Swap Memory'
- script: |
docker exec snekbox_test /bin/bash -c \
'pipenv run coverage run -m xmlrunner'
displayName: 'Run Unit Tests'
- task: PublishTestResults@2
displayName: 'Publish Test Results'
condition: succeededOrFailed()
inputs:
testResultsFiles: '**/TEST-*.xml'
testRunTitle: 'Test Results'
# Run report too because the XML report doesn't output to stdout.
- script: |
docker exec snekbox_test /bin/bash -c \
'pipenv run /bin/bash -c "coverage report && coverage xml"'
displayName: 'Generate Coverage Report'
- task: PublishCodeCoverageResults@1
displayName: 'Publish Coverage Results'
condition: succeededOrFailed()
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '**/coverage.xml'
# When a pull request, only perform this job if images need to be built.
# It's always performed for non-PRs because the final image will always need
# to be built.
- job: build
displayName: 'Build'
condition: >
and(
succeeded(),
or(
ne(variables['Build.Reason'], 'PullRequest'),
eq(coalesce(dependencies.test.outputs['check.BASE_CHANGED'], True), True),
eq(coalesce(dependencies.test.outputs['check.VENV_CHANGED'], True), True)
)
)
dependsOn: test
# coalesce() gives variables default values if they are null (i.e. unset).
variables:
BASE_CHANGED: $[ coalesce(dependencies.test.outputs['check.BASE_CHANGED'], True) ]
VENV_CHANGED: $[ coalesce(dependencies.test.outputs['check.VENV_CHANGED'], True) ]
BASE_PULL: $[ coalesce(dependencies.test.outputs['check.BASE_PULL'], False) ]
steps:
- task: Docker@1
displayName: 'Log into Docker Hub'
inputs:
command: login
containerregistrytype: 'Container Registry'
dockerRegistryEndpoint: 'DockerHub'
# Because this is the base image for the venv image, if the venv needs to
# be built, this base image must also be present. Build it if it has
# changed or can't be pulled from Docker Hub.
- script: |
docker build \
-f docker/base.Dockerfile \
-t pythondiscord/snekbox-base:latest \
.
displayName: 'Build Base Image'
condition: >
and(
succeeded(),
ne(variables.BASE_PULL, True),
or(
eq(variables.BASE_CHANGED, True),
eq(variables.VENV_CHANGED, True)
)
)
# Also build this image if base has changed - even if this image hasn't.
- script: |
docker build \
-f docker/venv.Dockerfile \
-t pythondiscord/snekbox-venv:latest \
.
displayName: 'Build Virtual Environment Image'
condition: >
and(
succeeded(),
or(
eq(variables.BASE_CHANGED, True),
eq(variables.VENV_CHANGED, True)
)
)
# Always build this image unless it's for a pull request.
- script: |
docker build \
-f docker/Dockerfile \
-t pythondiscord/snekbox:latest \
.
displayName: 'Build Final Image'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
# Push images only after they've all successfully been built.
# These have the same conditions as the build tasks. However, for safety,
# a condition for not being a pull request is added.
- script: docker push pythondiscord/snekbox-base:latest
displayName: 'Push Base Image'
condition: >
and(
succeeded(),
ne(variables['Build.Reason'], 'PullRequest'),
ne(variables.BASE_PULL, True),
or(
eq(variables.BASE_CHANGED, True),
eq(variables.VENV_CHANGED, True)
)
)
- script: docker push pythondiscord/snekbox-venv:latest
displayName: 'Push Virtual Environment Image'
condition: >
and(
succeeded(),
ne(variables['Build.Reason'], 'PullRequest'),
or(
eq(variables.BASE_CHANGED, True),
eq(variables.VENV_CHANGED, True)
)
)
- script: docker push pythondiscord/snekbox:latest
displayName: 'Push Final Image'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
|