Skip to content

Commit 762ba27

Browse files
authored
Make GHA tests parallel by using xdist (spack#32361)
* Add two no-op jobs named "all-prechecks" and "all" These are a suggestion from @tgamblin, they are stable named markers we can use from gitlab and possibly for required checks to make CI more resilient to refactors changing the names of specific checks. * Enable parallel testing using xdist for unit testing in CI * Normalize tmp paths to deal with macos * add -u flag compatibility to spack python As of now, it is accepted and ignored. The usage with xdist, where it is invoked specifically by `python -u spack python` which is then passed `-u` by xdist is the entire reason for doing this. It should never be used without explicitly passing -u to the executing python interpreter. * use spack python in xdist to support python 2 When running on python2, spack has many import cycles unless started through main. To allow that, this uses `spack python` as the interpreter, leveraging the `-u` support so xdist doesn't error out when it unconditionally requests unbuffered binary IO. * Use shutil.move to account for tmpdir being in a separate filesystem sometimes
1 parent 8e5ccdd commit 762ba27

25 files changed

+221
-123
lines changed

.flake8

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ max-line-length = 99
2929
#
3030
per-file-ignores =
3131
var/spack/repos/*/package.py:F403,F405,F821
32+
*-ci-package.py:F403,F405,F821
3233

3334
# exclude things we usually do not want linting for.
3435
# These still get linted when passed explicitly, as when spack flake8 passes

.github/workflows/audit.yaml

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: audit
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
with_coverage:
7+
required: true
8+
type: string
9+
python_version:
10+
required: true
11+
type: string
12+
13+
concurrency:
14+
group: audit-${{inputs.python_version}}-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
# Run audits on all the packages in the built-in repository
19+
package-audits:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
23+
- uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # @v2
24+
with:
25+
python-version: ${{inputs.python_version}}
26+
- name: Install Python packages
27+
run: |
28+
pip install --upgrade pip six setuptools pytest codecov 'coverage[toml]<=6.2'
29+
- name: Package audits (with coverage)
30+
if: ${{ inputs.with_coverage == 'true' }}
31+
run: |
32+
. share/spack/setup-env.sh
33+
coverage run $(which spack) audit packages
34+
coverage combine
35+
coverage xml
36+
- name: Package audits (without coverage)
37+
if: ${{ inputs.with_coverage == 'false' }}
38+
run: |
39+
. share/spack/setup-env.sh
40+
$(which spack) audit packages
41+
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
42+
if: ${{ inputs.with_coverage == 'true' }}
43+
with:
44+
flags: unittests,linux,audits

.github/workflows/bootstrap.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ on:
99
- cron: '16 2 * * *'
1010

1111
concurrency:
12-
group: bootstrap-${{ github.workflow }}-${{ github.event.pull_request.number || github.run_number }}
12+
group: bootstrap-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
1313
cancel-in-progress: true
1414

1515
jobs:

.github/workflows/build-containers.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ on:
2020
types: [published]
2121

2222
concurrency:
23-
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_number }}
23+
group: build_containers-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
2424
cancel-in-progress: true
2525

2626
jobs:

.github/workflows/ci.yaml

+22-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ on:
1111
- releases/**
1212

1313
concurrency:
14-
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_number }}
14+
group: ci-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
1515
cancel-in-progress: true
1616

1717
jobs:
@@ -20,6 +20,18 @@ jobs:
2020
uses: ./.github/workflows/valid-style.yml
2121
with:
2222
with_coverage: ${{ needs.changes.outputs.with_coverage }}
23+
audit-ancient-python:
24+
uses: ./.github/workflows/audit.yaml
25+
needs: [ changes ]
26+
with:
27+
with_coverage: ${{ needs.changes.outputs.with_coverage }}
28+
python_version: 2.7
29+
all-prechecks:
30+
needs: [ prechecks ]
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Success
34+
run: "true"
2335
# Check which files have been updated by the PR
2436
changes:
2537
runs-on: ubuntu-latest
@@ -53,6 +65,7 @@ jobs:
5365
- 'share/spack/**'
5466
- '.github/workflows/bootstrap.yml'
5567
core:
68+
- '!lib/spack/docs/**'
5669
- './!(var/**)/**'
5770
packages:
5871
- 'var/**'
@@ -79,15 +92,21 @@ jobs:
7992
needs: [ prechecks, changes ]
8093
uses: ./.github/workflows/bootstrap.yml
8194
unit-tests:
82-
if: ${{ github.repository == 'spack/spack' }}
95+
if: ${{ github.repository == 'spack/spack' && needs.changes.outputs.core == 'true' }}
8396
needs: [ prechecks, changes ]
8497
uses: ./.github/workflows/unit_tests.yaml
8598
with:
8699
core: ${{ needs.changes.outputs.core }}
87100
packages: ${{ needs.changes.outputs.packages }}
88101
with_coverage: ${{ needs.changes.outputs.with_coverage }}
89102
windows:
90-
if: ${{ github.repository == 'spack/spack' }}
103+
if: ${{ github.repository == 'spack/spack' && needs.changes.outputs.core == 'true' }}
91104
needs: [ prechecks ]
92105
uses: ./.github/workflows/windows_python.yml
106+
all:
107+
needs: [ windows, unit-tests, bootstrap, audit-ancient-python ]
108+
runs-on: ubuntu-latest
109+
steps:
110+
- name: Success
111+
run: "true"
93112

.github/workflows/unit_tests.yaml

+25-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: unit tests
22

33
on:
4+
workflow_dispatch:
45
workflow_call:
56
inputs:
67
core:
@@ -14,7 +15,7 @@ on:
1415
type: string
1516

1617
concurrency:
17-
group: unit_tests-${{ github.workflow }}-${{ github.event.pull_request.number || github.run_number }}
18+
group: unit_tests-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
1819
cancel-in-progress: true
1920

2021
jobs:
@@ -25,11 +26,26 @@ jobs:
2526
matrix:
2627
python-version: ['2.7', '3.6', '3.7', '3.8', '3.9', '3.10']
2728
concretizer: ['clingo']
29+
on_develop:
30+
- ${{ github.ref == 'refs/heads/develop' }}
2831
include:
2932
- python-version: 2.7
3033
concretizer: original
31-
- python-version: 3.9
34+
on_develop: false
35+
- python-version: '3.10'
3236
concretizer: original
37+
on_develop: false
38+
exclude:
39+
- python-version: '3.7'
40+
concretizer: 'clingo'
41+
on_develop: false
42+
- python-version: '3.8'
43+
concretizer: 'clingo'
44+
on_develop: false
45+
- python-version: '3.9'
46+
concretizer: 'clingo'
47+
on_develop: false
48+
3349
steps:
3450
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
3551
with:
@@ -46,7 +62,7 @@ jobs:
4662
patchelf cmake bison libbison-dev kcov
4763
- name: Install Python packages
4864
run: |
49-
pip install --upgrade pip six setuptools pytest codecov "coverage[toml]<=6.2"
65+
pip install --upgrade pip six setuptools pytest codecov "coverage[toml]<=6.2" pytest-xdist
5066
# ensure style checks are not skipped in unit tests for python >= 3.6
5167
# note that true/false (i.e., 1/0) are opposite in conditions in python and bash
5268
if python -c 'import sys; sys.exit(not sys.version_info >= (3, 6))'; then
@@ -108,7 +124,7 @@ jobs:
108124
sudo apt-get install -y coreutils kcov csh zsh tcsh fish dash bash
109125
- name: Install Python packages
110126
run: |
111-
pip install --upgrade pip six setuptools pytest codecov coverage[toml]==6.2
127+
pip install --upgrade pip six setuptools pytest codecov coverage[toml]==6.2 pytest-xdist
112128
- name: Setup git configuration
113129
run: |
114130
# Need this for the git tests to succeed.
@@ -174,7 +190,7 @@ jobs:
174190
patchelf kcov
175191
- name: Install Python packages
176192
run: |
177-
pip install --upgrade pip six setuptools pytest codecov coverage[toml]==6.2 clingo
193+
pip install --upgrade pip six setuptools pytest codecov coverage[toml]==6.2 clingo pytest-xdist
178194
- name: Setup git configuration
179195
run: |
180196
# Need this for the git tests to succeed.
@@ -216,7 +232,7 @@ jobs:
216232
- name: Install Python packages
217233
run: |
218234
pip install --upgrade pip six setuptools
219-
pip install --upgrade pytest codecov coverage[toml]==6.2
235+
pip install --upgrade pytest codecov coverage[toml]==6.2 pytest-xdist
220236
- name: Setup Homebrew packages
221237
run: |
222238
brew install dash fish gcc gnupg2 kcov
@@ -229,17 +245,18 @@ jobs:
229245
. share/spack/setup-env.sh
230246
$(which spack) bootstrap untrust spack-install
231247
$(which spack) solve zlib
248+
common_args=(--dist loadfile --tx '4*popen//python=./bin/spack-tmpconfig python -u ./bin/spack python' -x)
232249
if [ "${{ inputs.with_coverage }}" == "true" ]
233250
then
234-
coverage run $(which spack) unit-test -x
251+
coverage run $(which spack) unit-test "${common_args[@]}"
235252
coverage combine
236253
coverage xml
237254
# Delete the symlink going from ./lib/spack/docs/_spack_root back to
238255
# the initial directory, since it causes ELOOP errors with codecov/actions@2
239256
rm lib/spack/docs/_spack_root
240257
else
241258
echo "ONLY PACKAGE RECIPES CHANGED [skipping coverage]"
242-
$(which spack) unit-test -x -m "not maybeslow" -k "test_all_virtual_packages_have_default_providers"
259+
$(which spack) unit-test "${common_args[@]}" -m "not maybeslow" -k "test_all_virtual_packages_have_default_providers"
243260
fi
244261
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
245262
if: ${{ inputs.with_coverage == 'true' }}

.github/workflows/valid-style.yml

+6-28
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
type: string
99

1010
concurrency:
11-
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_number }}
11+
group: style-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
1212
cancel-in-progress: true
1313

1414

@@ -53,30 +53,8 @@ jobs:
5353
- name: Run style tests
5454
run: |
5555
share/spack/qa/run-style-tests
56-
# Run audits on all the packages in the built-in repository
57-
package-audits:
58-
runs-on: ubuntu-latest
59-
steps:
60-
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # @v2
61-
- uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # @v2
62-
with:
63-
python-version: '3.10'
64-
- name: Install Python packages
65-
run: |
66-
pip install --upgrade pip six setuptools pytest codecov coverage[toml]==6.2
67-
- name: Package audits (with coverage)
68-
if: ${{ inputs.with_coverage == 'true' }}
69-
run: |
70-
. share/spack/setup-env.sh
71-
coverage run $(which spack) audit packages
72-
coverage combine
73-
coverage xml
74-
- name: Package audits (without coverage)
75-
if: ${{ inputs.with_coverage == 'false' }}
76-
run: |
77-
. share/spack/setup-env.sh
78-
$(which spack) audit packages
79-
- uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # @v2.1.0
80-
if: ${{ inputs.with_coverage == 'true' }}
81-
with:
82-
flags: unittests,linux,audits
56+
audit:
57+
uses: ./.github/workflows/audit.yaml
58+
with:
59+
with_coverage: ${{ inputs.with_coverage }}
60+
python_version: '3.10'

.github/workflows/windows_python.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
workflow_call:
55

66
concurrency:
7-
group: windows-${{ github.workflow }}-${{ github.event.pull_request.number || github.run_number }}
7+
group: windows-${{github.ref}}-${{github.event.pull_request.number || github.run_number}}
88
cancel-in-progress: true
99

1010
defaults:

bin/spack-tmpconfig

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export TMPDIR="${XDG_RUNTIME_DIR}"
77
export TMP_DIR="$(mktemp -d -t spack-test-XXXXX)"
88
clean_up() {
99
[[ -n "$TMPCONFIG_DEBUG" ]] && printf "cleaning up: $TMP_DIR\n"
10-
[[ -n "$TMPCONFIG_DEBUG" ]] && tree "$TMP_DIR"
1110
rm -rf "$TMP_DIR"
1211
}
1312
trap clean_up EXIT

lib/spack/llnl/util/tty/pty.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ def __init__(self, controller_function, minion_function):
228228
self.minion_function = minion_function
229229

230230
# these can be optionally set to change defaults
231-
self.controller_timeout = 1
232-
self.sleep_time = 0
231+
self.controller_timeout = 3
232+
self.sleep_time = 0.1
233233

234234
def start(self, **kwargs):
235235
"""Start the controller and minion processes.

lib/spack/spack/cmd/python.py

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ def setup_parser(subparser):
3030
help="print the Python version number and exit",
3131
)
3232
subparser.add_argument("-c", dest="python_command", help="command to execute")
33+
subparser.add_argument(
34+
"-u",
35+
dest="unbuffered",
36+
action="store_true",
37+
help="for compatibility with xdist, do not use without adding -u to the interpreter",
38+
)
3339
subparser.add_argument(
3440
"-i",
3541
dest="python_interpreter",

0 commit comments

Comments
 (0)