-
Notifications
You must be signed in to change notification settings - Fork 0
184 lines (169 loc) · 7.14 KB
/
Copy pathpython-packages.yml
File metadata and controls
184 lines (169 loc) · 7.14 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
name: Python packages
# Builds and publishes the Python distributions in packages/.
#
# The C/CUDA core is built by build.yml and is unrelated to this workflow.
#
# Publishing is driven by an annotated tag of the form <pypi-name>-v<version>,
# which packages/<pkg>/release.sh creates. The tag -> package map below is a
# hand-maintained chain: a tag that matches NO branch builds nothing and
# publishes nothing, silently. release.sh greps this file before pushing for
# exactly that reason.
on:
push:
# main as well as tags: the suites ran on pull requests and releases only,
# so a push straight to main tested nothing -- including the seven test
# files that moved in from scripts/tests/, which had never run in CI at all.
# The build/publish jobs stay tag-gated below.
branches: [ "main" ]
tags:
- 'laue-torch-v*'
- 'laue-jax-v*'
- 'laue-index-v*'
pull_request:
paths:
- 'packages/**'
- '.github/workflows/python-packages.yml'
workflow_dispatch:
jobs:
# Which packages does this event test? On a TAG, only the one being released:
# gating laue-torch's upload on laue_index's suite couples unrelated releases,
# and did -- laue-torch 0.1.1 was blocked with its own tests fully green. On a
# PR or manual run, everything.
select:
name: select packages
runs-on: ubuntu-latest
outputs:
packages: ${{ steps.pick.outputs.packages }}
package: ${{ steps.pick.outputs.package }}
pypi_name: ${{ steps.pick.outputs.pypi_name }}
steps:
- id: pick
run: |
TAG="${GITHUB_REF#refs/tags/}"
case "$GITHUB_REF" in
refs/tags/laue-torch-v*)
echo 'packages=["laue_torch"]' >> "$GITHUB_OUTPUT"
echo "package=laue_torch" >> "$GITHUB_OUTPUT"
echo "pypi_name=laue-torch" >> "$GITHUB_OUTPUT" ;;
refs/tags/laue-jax-v*)
echo 'packages=["laue_jax"]' >> "$GITHUB_OUTPUT"
echo "package=laue_jax" >> "$GITHUB_OUTPUT"
echo "pypi_name=laue-jax" >> "$GITHUB_OUTPUT" ;;
refs/tags/laue-index-v*)
echo 'packages=["laue_index"]' >> "$GITHUB_OUTPUT"
echo "package=laue_index" >> "$GITHUB_OUTPUT"
echo "pypi_name=laue-index" >> "$GITHUB_OUTPUT" ;;
refs/tags/*)
echo "::error::Tag '$TAG' matches no package. Nothing would be published."
exit 1 ;;
*)
echo 'packages=["laue_torch","laue_jax","laue_index"]' >> "$GITHUB_OUTPUT" ;;
esac
test:
name: test ${{ matrix.package }} (py${{ matrix.python-version }})
needs: select
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package: ${{ fromJSON(needs.select.outputs.packages) }}
python-version: ['3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install package + dev extras
working-directory: packages/${{ matrix.package }}
run: |
python -m pip install --upgrade pip
# Sibling packages must come from THIS TREE, not from PyPI. laue_jax's
# dev extra names laue-torch, and resolving that from the index either
# fails before the first release or -- worse, afterwards -- silently
# tests the last published version instead of the code being changed.
if [ "${{ matrix.package }}" = "laue_jax" ]; then
pip install --extra-index-url https://download.pytorch.org/whl/cpu \
-e ../laue_torch
fi
# CPU-only torch: the GPU wheels are multi-GB and nothing here needs them.
pip install --extra-index-url https://download.pytorch.org/whl/cpu -e ".[dev]"
- name: Run tests
working-directory: packages/${{ matrix.package }}
env:
KMP_DUPLICATE_LIB_OK: 'TRUE'
run: pytest -q --tb=short
build:
name: build sdist + wheel
# `needs: [select, test]` gates the upload on the tests -- without it,
# build and publish run in parallel with the matrix and a red suite does not
# stop the release. laue-torch 0.1.0 published with two of its own tests
# failing. The matrix `test` gates on is now scoped to this package (see
# `select`), so a sibling's failure no longer blocks an unrelated release.
needs: [select, test]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Build
working-directory: packages/${{ needs.select.outputs.package }}
run: |
python -m pip install --upgrade pip build
# laue_index compiles C via scikit-build-core, so a wheel here would be
# tagged linux_x86_64 -- which PyPI refuses. Publish the sdist and let
# pip compile on the user's machine. laue_torch and laue_jax are pure
# Python, so their py3-none-any wheels are fine and worth shipping.
if [ "${{ needs.select.outputs.package }}" = "laue_index" ]; then
python -m build --sdist
else
python -m build
fi
- name: Verify the sdist carries no unpublished research
working-directory: packages/${{ needs.select.outputs.package }}
run: |
SDIST=$(ls dist/*.tar.gz | head -1)
echo "Inspecting $SDIST"
if tar -tzf "$SDIST" | grep -iE '(^|/)(report|experiments|research)/'; then
echo "::error::sdist contains unpublished research paths. Refusing to publish."
exit 1
fi
SIZE_MB=$(( $(wc -c < "$SDIST") / 1048576 ))
echo "sdist size: ${SIZE_MB} MB"
if [ "$SIZE_MB" -gt 10 ]; then
echo "::error::sdist is ${SIZE_MB} MB; expected ~1 MB. Something bulky got swept in."
exit 1
fi
- uses: actions/upload-artifact@v4
with:
name: dist
path: packages/${{ needs.select.outputs.package }}/dist/
publish:
name: publish to PyPI
needs: build
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
environment: pypi
permissions:
# Required for PyPI trusted publishing (OIDC). No API token is stored.
id-token: write
# Required to attach the same artifact to the GitHub release.
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Publish
uses: pypa/gh-action-pypi-publish@release/v1
- name: Attach the SAME artifact to the GitHub release
# release.sh used to upload its own locally-built sdist here while this
# job published a separately-built one to PyPI. The two then differed:
# laue-index 0.2.0's GitHub asset carried a stray 32 MB median.bin that
# happened to be sitting in the working tree, and PyPI's did not. One
# build, from a clean checkout, reaches both.
uses: softprops/action-gh-release@v2
with:
files: dist/*
generate_release_notes: true