-
Notifications
You must be signed in to change notification settings - Fork 4
/
.gitlab-ci.yml
286 lines (263 loc) · 8.51 KB
/
.gitlab-ci.yml
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
# SPDX-FileCopyrightText: 2021 The eminus developers
# SPDX-License-Identifier: Apache-2.0
default:
image: python:3.13-slim
stages:
- test
- fulltest
- deploy
- publish
.pytest:
stage: test
script:
# Use the python3 -m prefix to make the commands work under different OS
- python3 -m pip install .
- python3 -m pip install pytest
- python3 -m pytest tests/ -m "not slow"
rules:
- changes:
- eminus/*.py
- eminus/**/*.py
- tests/*.py
- tests/**/*.py
.pytest-full:
extends: .pytest
stage: fulltest
when: manual
# Allow failure in manual jobs, otherwise the pipeline status will be manual instead of passed
# This would, e.g., block the creation of coverage reports
allow_failure: true
############### test ###############
##### Create coverage reports #####
coverage:
stage: test
script:
- pip install .
- pip install coverage pyscf pytest
- coverage run -m pytest tests/ --ignore=tests/examples --ignore=tests/extras
- coverage report --precision=2
- coverage html --precision=2
- coverage xml
coverage: '/TOTAL.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
artifacts:
paths:
- htmlcov/
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == "main"
# Fix: Run coverage even if only the lint or pages job runs to prevent an unknown status badge
# Reference: https://gitlab.com/gitlab-org/gitlab/-/issues/346779
changes:
- "*.py"
- "**/*.py"
- docs/*
- docs/**/*
##### Lint Python files #####
lint:
image: ghcr.io/astral-sh/ruff:alpine
stage: test
script:
- ruff check
rules:
- changes:
- "*.py"
- "**/*.py"
##### Test the minimally supported versions #####
minimal:
extends: .pytest
image: python:3.7-slim
before_script:
- pip install numpy==1.17 scipy==1.6
##### Test using the newest dependency versions #####
newest:
extends: .pytest
rules:
# Only run in the dev branch since this is just a subset of the coverage test
- if: $CI_COMMIT_BRANCH == "dev"
changes:
- eminus/*.py
- eminus/**/*.py
- tests/*.py
- tests/**/*.py
##### Type check Python files #####
typecheck:
stage: test
script:
- pip install mypy[faster-cache] numpy
- mypy . --disable-error-code="import-not-found" --disable-error-code="unused-ignore"
rules:
- changes:
- "*.py"
- "**/*.py"
############### fulltest ###############
##### Test the docker build #####
docker:
extends: .pytest-full
image: docker:latest
services:
- docker:dind
script:
# Use sed to get the version since CI_COMMIT_TAG is only non-empty when triggered for tags
- VERSION=$(sed -n 's/^__version__ = "\(.*\)"/\1/p' eminus/version.py)
- docker buildx build -t wangenau/eminus:"${VERSION}" --build-arg BRANCH=${CI_COMMIT_BRANCH:-main} .
- docker run wangenau/eminus:"${VERSION}" bash -c "export OMP_NUM_THREADS=$(nproc);export MKL_NUM_THREADS=$(nproc);pytest"
##### Test the code installation after building #####
installation:
extends: .pytest-full
script:
- pip install --upgrade pip
- pip install build twine
- python -m build
# Do a check with twine
- twine check dist/*
# Copy the build directory to test the installation
- cp -r dist/ tmp/
- cd tmp/
# Test the source distribution
- tar -xf eminus-*.tar.gz
- pip install eminus-*/.
- python -c "import eminus; assert eminus.demo()"
# Test the wheel
- pip uninstall eminus -y
- pip install eminus-*.whl
- python -c "import eminus; assert eminus.demo()"
artifacts:
paths:
- dist/
##### Test code functionality under Linux, macOS, NixOS, and Windows #####
platform:linux:
extends: .pytest-full
image: ubuntu:latest
before_script:
- apt-get update -y
- apt-get install python3 python3-pip python3-venv -y --no-install-recommends
- python3 -m venv .venv
- source .venv/bin/activate
# Disabled due to removed image: https://github.com/sickcodes/Docker-OSX/issues/799
# platform:macos:
# extends: .pytest-full
# image: sickcodes/docker-osx:latest
# before_script:
# - python3 -m ensurepip
platform:nixos:
extends: .pytest-full
image: nixpkgs/nix:latest
script:
# In the CI nix develop will open a shell and close it immediately afterwards, use -c to execute commands
- nix --extra-experimental-features "nix-command flakes" develop -c pytest tests/ -m "not slow"
platform:windows:
extends: .pytest-full
tags:
- saas-windows-medium-amd64
before_script:
# Reference: https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/-/issues/13
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
- choco install python -y --no-progress
- refreshenv
- Set-Alias -Name python3 -Value python
##### Test code functionality for all supported Python versions #####
python:
extends: .pytest-full
image: python:$PYTHON_VERSIONS-slim
parallel:
matrix:
- PYTHON_VERSIONS: ['3.8', '3.9', '3.10', '3.11', '3.12']
############### deploy ###############
##### Build documentation #####
pages:
stage: deploy
needs: ["coverage"]
script:
- pip install .
- pip install furo notebook sphinx sphinx-design sphinxcontrib-bibtex
# Build Sphinx documentation
- sphinx-build -j "$(nproc)" -b html ./docs ./public
# Convert notebooks to HTML
- find examples -name '*.ipynb' -exec jupyter nbconvert --to html {} --template classic \;
- find examples -name '*.html' -exec mv {} public/_static \;
# Minify all text files
- apt-get update -y
- apt-get install minify -y --no-install-recommends
- find public \( -name '*.css' -o -name '*.js' -o -name '*.svg' \) -exec minify -vo {} {} \;
- find public -name '*.html' -exec minify -vo {} {} --html-keep-document-tags --html-keep-end-tags --html-keep-whitespace \;
# Compress all text files
- find public \( -name '*.css' -o -name '*.html' -o -name '*.js' -o -name '*.svg' \) -exec gzip -vrk9 {} \;
# Copy the coverage artifacts
# For the dev build we do not generate a coverage report, fail without an error in that case
- cp -r htmlcov/ public/ || true
artifacts:
paths:
- public/
rules:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == "main"
changes:
- docs/*
- docs/**/*
- examples/*
- examples/**/*
- eminus/version.py
##### Build the documentation for the dev branch under a different URL #####
pages:dev:
extends: pages
# Overwrite the pages needs
needs: []
after_script:
- echo "dev pages available at https://$CI_PROJECT_NAMESPACE.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html"
rules:
- if: $CI_COMMIT_BRANCH == "dev"
changes:
- docs/*
- docs/**/*
- examples/*
- examples/**/*
- eminus/version.py
variables:
PUBLIC_URL: "/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public"
############### publish ###############
##### Publish the package to Docker Hub #####
dockerhub:
image: docker:latest
stage: publish
services:
- docker:dind
needs:
- job: docker
optional: true
script:
- echo -n $DOCKER_ACCESS_TOKEN | docker login -u wangenau --password-stdin
# Use sed to get the version since CI_COMMIT_TAG is only non-empty when triggered for tags
- VERSION=$(sed -n 's/^__version__ = "\(.*\)"/\1/p' eminus/version.py)
# Build the image with full attestations and push it directly
- docker buildx create --driver=docker-container --name container default
- docker buildx build -t wangenau/eminus:"${VERSION}" --builder=container --sbom=true --provenance=true --push .
rules:
- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAG
when: manual
allow_failure: true
##### Publish the package to PyPI #####
pypi:
stage: publish
needs:
- job: installation
optional: true
id_tokens:
PYPI_ID_TOKEN:
aud: pypi
script:
- apt-get update -y
- apt-get install curl jq -y --no-install-recommends
- pip install id twine
# Reference: https://github.com/pypi/warehouse/issues/13575#issuecomment-1961187837
- OIDC_TOKEN=$(python -m id PYPI)
- RESP=$(curl -X POST https://pypi.org/_/oidc/mint-token -d "{\"token\":\"${OIDC_TOKEN}\"}")
- API_TOKEN=$(jq --raw-output '.token' <<< "${RESP}")
- twine upload -u __token__ -p "${API_TOKEN}" dist/*
rules:
- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAG
when: manual
allow_failure: true