-
Notifications
You must be signed in to change notification settings - Fork 349
263 lines (232 loc) · 11.5 KB
/
python_metapackages.yml
File metadata and controls
263 lines (232 loc) · 11.5 KB
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
on:
workflow_call:
inputs:
cudaq_version:
required: true
type: string
description: The version of the built CUDA-Q packages.
python_versions:
required: true
type: string
description: Json array of the Python versions to test the packages with (e.g. ['3.10', '3.12']).
cuda_versions:
required: true
type: string
description: Json array of the CUDA versions to test the packages with (e.g. ['11.8', '12.0']).
wheel_artifacts:
required: true
type: string
description: A pattern that matches all artifacts that contain wheels that the metapackages depend on.
github_commit:
required: false
type: string
description: Optional argument to set the GitHub commit to use for the build.
outputs:
artifact_name:
description: "The name of the artifact that contains the built metapackages."
value: ${{ jobs.build_metapackages.outputs.artifact_name }}
name: Python metapackages
jobs:
build_metapackages:
name: Build Python metapackages
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
artifact_name: ${{ steps.metapackage_build.outputs.artifact_name }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: "${{ inputs.github_commit || '' }}"
- name: Build metapackages
id: metapackage_build
run: |
sed -i "s/README.md.in/README.md/g" python/metapackages/pyproject.toml
for file in LICENSE NOTICE CITATION.cff; do
cp $file python/metapackages/$file
done
apt-get update && apt-get install -y --no-install-recommends \
python3 python3-pip python3-venv
python3 -m pip install build
echo "Creating README.md for cudaq package"
package_name=cudaq
cuda_version_requirement="11.x (where x \>= 8) or 12.x"
cuda_version_conda=12.4.0 # only used as example in the install script
deprecation_notice="**Note**: Support for CUDA 11 will be removed in future releases. Please update to CUDA 12."
cat python/README.md.in > python/metapackages/README.md
for variable in package_name cuda_version_requirement cuda_version_conda deprecation_notice; do
sed -i "s/.{{[ ]*$variable[ ]*}}/${!variable}/g" python/metapackages/README.md
done
if [ -n "$(cat python/metapackages/README.md | grep -e '.{{.*}}')" ]; then
echo "::error file=python_metapackages.yml::Incomplete template substitutions in README."
exit 1
fi
echo "Building cudaq metapackage ..."
cd python/metapackages && echo ${{ inputs.cudaq_version }} > _version.txt
CUDAQ_META_WHEEL_BUILD=1 python3 -m build . --sdist
mkdir /tmp/packages && mv dist/cudaq-* /tmp/packages/
rm -rf cudaq.egg-info dist
echo "Creating README.md for cuda-quantum package"
echo "# Welcome to the CUDA-Q Python API" > README.md
echo "This package is deprecated and new versions are published under the name \`cudaq\` instead." >> README.md
echo "For more information, please see [CUDA-Q on PyPI](https://pypi.org/project/cudaq)." >> README.md
echo "Building cuda-quantum metapackage ..."
sed -i 's/name = "cudaq"/name = "cuda-quantum"/' pyproject.toml
echo 'Please remove the cuda-quantum package and `pip install cudaq` instead.' > _deprecated.txt
CUDAQ_META_WHEEL_BUILD=1 python3 -m build . --sdist
mv dist/cuda_quantum-* /tmp/packages/
echo "artifact_name=cudaq-metapackage-${{ inputs.cudaq_version }}" >> $GITHUB_OUTPUT
- name: Upload metapackages
uses: actions/upload-artifact@v4
with:
name: ${{ steps.metapackage_build.outputs.artifact_name }}
path: /tmp/packages/
retention-days: 1
if-no-files-found: error
test_metapackages:
name: Test Python metapackages
needs: build_metapackages
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
container:
image: ghcr.io/nvidia/pypa/manylinux_2_28_x86_64:latest
credentials:
username: ${{ github.actor }}
password: ${{ github.token }}
strategy:
matrix:
cuda_version: ${{ fromJSON(inputs.cuda_versions) }}
python_version: ${{ fromJSON(inputs.python_versions) }}
fail-fast: false
steps:
- name: Load metapackages
uses: actions/download-artifact@v4
with:
pattern: ${{ needs.build_metapackages.outputs.artifact_name }}
path: /tmp/metapackages/
merge-multiple: true
- name: Load wheels
uses: actions/download-artifact@v4
with:
pattern: ${{ inputs.wheel_artifacts }}
path: /tmp/wheels/
merge-multiple: true
- name: Test installation
run: |
mkdir -p /tmp/packages
mv /tmp/wheels/* /tmp/packages && mv /tmp/metapackages/* /tmp/packages
rmdir /tmp/wheels /tmp/metapackages
if [ -n "${{ matrix.cuda_version }}" ]; then
CUDA_DOWNLOAD_URL=https://developer.download.nvidia.com/compute/cuda/repos
CUDA_ARCH_FOLDER=$([ "$(uname -m)" == "aarch64" ] && echo sbsa || echo x86_64)
CUDA_DISTRIBUTION=rhel8
dnf config-manager --add-repo \
"${CUDA_DOWNLOAD_URL}/${CUDA_DISTRIBUTION}/${CUDA_ARCH_FOLDER}/cuda-${CUDA_DISTRIBUTION}.repo"
cuda_version_suffix=`echo ${{ matrix.cuda_version }} | tr . -`
dnf install -y --nobest --setopt=install_weak_deps=False \
cuda-cudart-${cuda_version_suffix}
fi
python=python${{ matrix.python_version }}
$python -m pip install pip3-autoremove
# autoremove is in an odd location that isn't found unless we search for it...
autoremove="$python $($python -m pip show pip3-autoremove | grep -e 'Location: .*$' | cut -d ' ' -f2)/pip_autoremove.py"
$python -m pip install pypiserver
server="$python $($python -m pip show pypiserver | grep -e 'Location: .*$' | cut -d ' ' -f2)/pypiserver/__main__.py"
$server run -p 8080 /tmp/packages &
package_dep=`echo cuda-quantum${cuda_version_suffix:+-cu$cuda_version_suffix} | cut -d '-' -f1-2`
if [ -n "$($python -m pip list | grep $package_dep)" ]; then
echo "::error file=python_metapackages.yml::Unexpected installation of $package_dep package."
exit 1
fi
$python -m pip install cudaq==${{ inputs.cudaq_version }} \
--extra-index-url http://localhost:8080
if [ -z "$($python -m pip list | grep $package_dep)" ]; then
echo "::error file=python_metapackages.yml::Missing installation of $package_dep package."
exit 1
elif [ "$($python -c 'import cudaq; print(cudaq.get_target().name)')" != "qpp-cpu" ]; then
echo "::error file=python_metapackages.yml::Unexpected output for cudaq.get_target()."
exit 1
fi
$autoremove -y cudaq
if [ -n "$($python -m pip list | grep $package_dep)" ]; then
echo "::error file=python_metapackages.yml::Unexpected installation of $package_dep package."
exit 1
fi
if [ "$package_dep" != "cuda-quantum" ]; then
$python -m pip install ${package_dep}==${{ inputs.cudaq_version }} \
--extra-index-url http://localhost:8080
$python -m pip install cudaq==${{ inputs.cudaq_version }} \
--extra-index-url http://localhost:8080
$python -c 'import cudaq; print(cudaq.get_target().name)'
$autoremove -y cudaq
if [ -z "$($python -m pip list | grep $package_dep)" ]; then
echo "::error file=python_metapackages.yml::Missing installation of $package_dep package."
exit 1
fi
$autoremove -y $package_dep
fi
- name: Test installation error
run: |
python=python${{ matrix.python_version }}
$python -m pip install pypiserver
server="$python $($python -m pip show pypiserver | grep -e 'Location: .*$' | cut -d ' ' -f2)/pypiserver/__main__.py"
$server run -p 8080 /tmp/packages &
case "${{ matrix.cuda_version }}" in
"")
set +e # continue on error
$python -m pip install cuda-quantum==${{ inputs.cudaq_version }} \
--extra-index-url http://localhost:8080
set -e && check_package=cuda-quantum
;;
12.*)
test_conflicting=cuda-quantum-cu11
$python -m pip install cuda-quantum-cu11==${{ inputs.cudaq_version }} \
--extra-index-url http://localhost:8080
set +e # continue on error
$python -m pip install cudaq==${{ inputs.cudaq_version }} -v \
--extra-index-url http://localhost:8080 \
2>&1 | tee /tmp/install.out
set -e && check_package=cudaq
;;
*)
set +e # continue on error
# test that we get an error for an existing cuda-quantum installation
$python -m pip install cuda-quantum==0.8.0
set -e
if [ -z "$($python -m pip list | grep cuda-quantum)" ]; then
# if we don't have a 0.8.0 version for this python version, test other conflict
test_conflicting=cuda-quantum-cu12
$python -m pip install cuda-quantum-cu12==${{ inputs.cudaq_version }} \
--extra-index-url http://localhost:8080
else
test_conflicting=cuda-quantum
fi
set +e # continue on error
$python -m pip install cudaq==${{ inputs.cudaq_version }} -v \
--extra-index-url http://localhost:8080 \
2>&1 | tee /tmp/install.out
set -e && check_package=cudaq
;;
esac
# The autodetection will fail if the runner does not have a GPU.
# In that case, we will only check if the install failed, if the
# package we want to test the conflict detection for is not the
# default package that is installed when there is no GPU.
if [ -f /tmp/install.out ] && [ -z "$(cat /tmp/install.out | grep -o 'Autodetection succeeded')" ]; then
# Autodetection failed - a default choice of the binary distribution will be installed.
echo "::warning::Autodetection to determine cudaq binary distribution failed."
# Take the first Identified best package because the logs print multiple lines.
# They should all be the same, if they differ in the build environment then there is probably issues.
installed_default=$(cat /tmp/install.out | sed -nE 's/.*Identified (\S*) as the best package.*/\1/p' | head -n 1)
echo "::warning::The installed default is ${installed_default}, the potential conflicting package is ${test_conflicting}"
if [ "$installed_default" == "$test_conflicting" ]; then
check_package=none
fi
fi
if [ "$check_package" != "none" ] && [ -n "$($python -m pip list | grep ${check_package})" ]; then
echo "::error file=python_metapackages.yml::Unexpected installation of ${check_package} package."
exit 1
fi