Skip to content

Commit ec3d3ca

Browse files
authored
Merge pull request #2874 from ytausch/parallel-tests
enable parallel tests with pytest-xdist and pytest-split
2 parents 7ecb031 + 18387e6 commit ec3d3ca

8 files changed

+208
-7
lines changed

.github/pull_request_template.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ conda_forge_tick/models appropriately and document any new fields or files. Tick
1010
Note that the model exists next to and independent of the actual production code.
1111
-->
1212

13-
Description:
13+
### Description
1414

1515
<!-- Please describe your PR here. -->
1616

17-
Checklist:
17+
### Checklist
1818

1919
- [ ] Pydantic model updated or no update needed
2020

21-
Cross-refs, links to issues, etc:
21+
### Cross-refs, links to issues, etc
2222

2323
<!-- Please cross-link your PR to any open issues, other PRs, etc. here. -->

.github/workflows/tests.yml

+83-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ jobs:
1919
tests:
2020
name: tests
2121
runs-on: "ubuntu-latest"
22+
permissions:
23+
actions: write # for deleting cache entries
24+
contents: read
25+
strategy:
26+
# continue running the tests even if one of the groups fails
27+
fail-fast: false
28+
matrix:
29+
# if change the number of groups here, also change it next to --splits below
30+
group: [1, 2]
2231
defaults:
2332
run:
2433
shell: bash -leo pipefail {0}
@@ -53,7 +62,7 @@ jobs:
5362
5463
python -m pip install -v --no-deps --no-build-isolation -e .
5564
56-
- name: Start MongoDB
65+
- name: start MongoDB
5766
uses: MongoCamp/mongodb-github-action@e76ad215d47c31a99b4b0b1fde05f6cd1185df1a # e76ad215d47c31a99b4b0b1fde05f6cd1185df1a
5867
with:
5968
mongodb-version: "latest"
@@ -68,12 +77,30 @@ jobs:
6877
run: |
6978
docker build -t ${{ env.IMAGE_NAME }}:test .
7079
80+
- name: restore test durations
81+
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
82+
with:
83+
path: .test_durations
84+
key: test-durations-${{ github.ref }}
85+
restore-keys: |
86+
test-durations-
87+
7188
- name: run pytest
7289
run: |
7390
export TEST_BOT_TOKEN_VAL=unpassword
7491
export BOT_TOKEN=${TEST_BOT_TOKEN_VAL}
92+
# note: we do not use pytest-xdist (-n auto) here for now because they interfere with hiding the
93+
# MONGODB_CONNECTION_STRING sensitive environment variable
94+
if [[ -f .test_durations ]]; then
95+
cp .test_durations .test_durations.${{ matrix.group }}
96+
fi
7597
pytest \
7698
-v \
99+
--splits 2 --group ${{ matrix.group }} \
100+
--store-durations \
101+
--durations-path=.test_durations.${{ matrix.group }} \
102+
--randomly-seed=${{ github.run_id }} \
103+
--splitting-algorithm least_duration \
77104
--cov=conda_forge_tick \
78105
--cov=tests \
79106
--cov-config=.coveragerc \
@@ -86,7 +113,62 @@ jobs:
86113
MONGODB_CONNECTION_STRING: "mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000"
87114
RUN_URL: ""
88115

116+
- name: upload test durations
117+
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
118+
with:
119+
name: test-durations-${{ matrix.group }}
120+
path: .test_durations.${{ matrix.group }}
121+
122+
- name: upload coverage
123+
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
124+
with:
125+
name: coverage-${{ matrix.group }}
126+
path: .coverage
127+
128+
test-coverage-and-durations:
129+
name: test-coverage-and-durations
130+
needs: tests
131+
runs-on: "ubuntu-latest"
132+
defaults:
133+
run:
134+
shell: bash -leo pipefail {0}
135+
steps:
136+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
137+
138+
- uses: mamba-org/setup-micromamba@f8b8a1e23a26f60a44c853292711bacfd3eac822 # v1
139+
with:
140+
environment-file: conda-lock.yml
141+
environment-name: cf-scripts
142+
condarc-file: autotick-bot/condarc
143+
144+
- name: download coverage artifacts
145+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
146+
with:
147+
pattern: coverage-*
148+
149+
- name: combine coverage
150+
run: |
151+
coverage combine coverage-*/.coverage*
152+
coverage xml
153+
89154
- name: upload codecov
90155
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4
91156
with:
92157
token: ${{ secrets.CODECOV_TOKEN }}
158+
159+
- name: cache test durations
160+
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
161+
with:
162+
path: .test_durations
163+
key: test-durations-${{ github.ref }}
164+
restore-keys: |
165+
test-durations-
166+
167+
- name: download test duration artifacts
168+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
169+
with:
170+
pattern: test-durations-*
171+
172+
- name: combine test durations
173+
run: |
174+
jq '. + input' test-durations-*/.test_durations.* > .test_durations

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ versions/*
5757
.pixi
5858
pixi.lock
5959
pixi.toml
60+
.ruff_cache/

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ As `conda-forge` grew, the "single job + global data access" model became increa
285285

286286
#### Current Bot Jobs and Structure
287287

288+
[**Current GitHub Runner Allocation**](docs/runner_allocation.md)
289+
288290
In this section, we list the collection of jobs that comprise the bot. Each job touches a distinct part of the bot's data structure and is run in parallel with the other jobs. We have also specified the GitHub Actions workflow that runs each job. See those files for further details on which commands are run.
289291

290292
**bot** / `bot-bot.yml`: The main job that runs the bot, making PRs to feedstocks, etc. This job writes data on the PRs it makes to `cf-graph-countyfair/pr_info` and `cf-graph-countyfair/version_pr_info`. It also writes new PR JSON blobs to `cf-graph-countyfair/pr_json` for each PR to track their statuses on GitHub.

conda-lock.yml

+90-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ metadata:
33
- url: conda-forge
44
used_env_vars: []
55
content_hash:
6-
linux-64: 2b3c0976e57cb73f4954a13b0019b2082ff53a96d28c7dc99af6330878412da3
7-
osx-64: a823286e2d460d09bcee256454c86ab7a53966fa2b7539cf573af939e8711fff
8-
osx-arm64: c3255180ca12c8077951328d65d1f846ebe057235066735d459a689c605ae02d
6+
linux-64: 74b8ba2455a1c26564be8d99f414d006c68b4448b50a09a2682b6cd487deb834
7+
osx-64: d4f9ea8b9b5e8c6656029f5f2c36281636e03170c29250e41541975a8d5c78b6
8+
osx-arm64: 0df568ade8cdfaea2654d2331a61e925288d6d56e0072d96c53941b5e8221271
99
platforms:
1010
- osx-arm64
1111
- linux-64
@@ -10447,6 +10447,93 @@ package:
1044710447
url:
1044810448
https://conda.anaconda.org/conda-forge/noarch/pytest-env-1.1.3-pyhd8ed1ab_0.conda
1044910449
version: 1.1.3
10450+
- category: main
10451+
dependencies:
10452+
importlib-metadata: '>=3.6.0'
10453+
pytest: ''
10454+
python: '>=3.6'
10455+
hash:
10456+
md5: 203b5d3f85a47940f7ec6b6e1747786e
10457+
sha256: bd1953e4bc20ffd52cfee41b27b3a781ca6e281004d0dd59e2dd60b0192c7a86
10458+
manager: conda
10459+
name: pytest-randomly
10460+
optional: false
10461+
platform: linux-64
10462+
url:
10463+
https://conda.anaconda.org/conda-forge/noarch/pytest-randomly-3.15.0-pyhd8ed1ab_0.conda
10464+
version: 3.15.0
10465+
- category: main
10466+
dependencies:
10467+
importlib-metadata: '>=3.6.0'
10468+
pytest: ''
10469+
python: '>=3.6'
10470+
hash:
10471+
md5: 203b5d3f85a47940f7ec6b6e1747786e
10472+
sha256: bd1953e4bc20ffd52cfee41b27b3a781ca6e281004d0dd59e2dd60b0192c7a86
10473+
manager: conda
10474+
name: pytest-randomly
10475+
optional: false
10476+
platform: osx-64
10477+
url:
10478+
https://conda.anaconda.org/conda-forge/noarch/pytest-randomly-3.15.0-pyhd8ed1ab_0.conda
10479+
version: 3.15.0
10480+
- category: main
10481+
dependencies:
10482+
importlib-metadata: '>=3.6.0'
10483+
pytest: ''
10484+
python: '>=3.6'
10485+
hash:
10486+
md5: 203b5d3f85a47940f7ec6b6e1747786e
10487+
sha256: bd1953e4bc20ffd52cfee41b27b3a781ca6e281004d0dd59e2dd60b0192c7a86
10488+
manager: conda
10489+
name: pytest-randomly
10490+
optional: false
10491+
platform: osx-arm64
10492+
url:
10493+
https://conda.anaconda.org/conda-forge/noarch/pytest-randomly-3.15.0-pyhd8ed1ab_0.conda
10494+
version: 3.15.0
10495+
- category: main
10496+
dependencies:
10497+
pytest: '>=5.4'
10498+
python: '>=3.6,<4'
10499+
hash:
10500+
md5: d15a8b5c3a050fc3cf7d4509c70441f4
10501+
sha256: 34b2849d08d1cd7672b873c72df37d071d10402df89c6f8ac82d43cbeaa33442
10502+
manager: conda
10503+
name: pytest-split
10504+
optional: false
10505+
platform: linux-64
10506+
url:
10507+
https://conda.anaconda.org/conda-forge/noarch/pytest-split-0.8.2-pyhd8ed1ab_0.conda
10508+
version: 0.8.2
10509+
- category: main
10510+
dependencies:
10511+
pytest: '>=5.4'
10512+
python: '>=3.6,<4'
10513+
hash:
10514+
md5: d15a8b5c3a050fc3cf7d4509c70441f4
10515+
sha256: 34b2849d08d1cd7672b873c72df37d071d10402df89c6f8ac82d43cbeaa33442
10516+
manager: conda
10517+
name: pytest-split
10518+
optional: false
10519+
platform: osx-64
10520+
url:
10521+
https://conda.anaconda.org/conda-forge/noarch/pytest-split-0.8.2-pyhd8ed1ab_0.conda
10522+
version: 0.8.2
10523+
- category: main
10524+
dependencies:
10525+
pytest: '>=5.4'
10526+
python: '>=3.6,<4'
10527+
hash:
10528+
md5: d15a8b5c3a050fc3cf7d4509c70441f4
10529+
sha256: 34b2849d08d1cd7672b873c72df37d071d10402df89c6f8ac82d43cbeaa33442
10530+
manager: conda
10531+
name: pytest-split
10532+
optional: false
10533+
platform: osx-arm64
10534+
url:
10535+
https://conda.anaconda.org/conda-forge/noarch/pytest-split-0.8.2-pyhd8ed1ab_0.conda
10536+
version: 0.8.2
1045010537
- category: main
1045110538
dependencies:
1045210539
execnet: '>=2.1'

docs/runner_allocation.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# GitHub Runner Allocation
2+
3+
Last Updated: 2024-07-29
4+
5+
We have a
6+
[concurrency of 20 runners available](https://docs.github.com/en/actions/administering-github-actions/usage-limits-billing-and-administration#usage-limits) in the entire `regro` account.
7+
8+
These are split across our workflows as follows:
9+
- `bot-bot` - 1 runner
10+
- `bot-cache` - currently disabled
11+
- `bot-feedstocks` (daily for ~30 minutes) - 1 runner
12+
- `bot-make-graph` - 3 runners
13+
- `bot-make-migrators` - 1 runner
14+
- `bot-prs` - 4 runners
15+
- `bot-pypi-mapping` (hourly for ~5 minutes) - 1 runner
16+
- `bot-update-status-page` - 1 runner
17+
- `bot-versions` - 6 runners
18+
- `docker` (on demand) - 1 runner
19+
- `keepalive` (hourly for ~5 minutes) - 1 runner
20+
- `relock` (every 3 hours for ~1 minute) - 1 runner
21+
- `test-model` (daily for ~4 minutes, on demand) - 1 runner
22+
- `tests` (on demand) - 1 runner
23+
24+
Total: 16 runners used permanently, 4 runners can be used on demand.

environment.yml

+2
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,7 @@ dependencies:
6868
- pytest-xdist
6969
- pytest-cov
7070
- pytest-env
71+
- pytest-randomly
72+
- pytest-split
7173
- setuptools_scm>=7
7274
- python-build

tests/test_lazy_json_backends.py

+3
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ def test_lazy_json(tmpdir, backend):
502502
assert len(lj) == 0
503503
assert not lj
504504
finally:
505+
be = LAZY_JSON_BACKENDS[backend]()
506+
be.hdel("lazy_json", ["hi"])
507+
505508
conda_forge_tick.lazy_json_backends.CF_TICK_GRAPH_DATA_BACKENDS = (
506509
old_backend
507510
)

0 commit comments

Comments
 (0)