@@ -2,95 +2,175 @@ name: Test building package and publish
22
33on :
44 push :
5- branches :
6- - master
7- tags :
8- - " *"
5+ branches : [ master ] # add 'main' if you use it
6+ tags : [ "*" ]
97 pull_request :
10- branches :
11- - master
8+ branches : [ master ]
9+ workflow_dispatch :
10+
11+ # Auto-cancel in-progress runs for the same ref
12+ concurrency :
13+ group : ${{ github.workflow }}-${{ github.ref }}
14+ cancel-in-progress : true
15+
16+ # Principle of least privilege (override per-job if needed)
17+ permissions :
18+ contents : read
19+
1220defaults :
1321 run :
1422 shell : bash
23+
1524jobs :
1625 build :
26+ name : Build sdist/wheel + archive
1727 runs-on : ubuntu-latest
1828 steps :
19- - uses : actions/checkout@v4
29+ - name : Checkout
30+ uses : actions/checkout@v4
2031 with :
2132 fetch-depth : 0
22- - uses : actions/setup-python@v5
33+
34+ - name : Set up Python
35+ uses : actions/setup-python@v5
2336 with :
2437 python-version : " 3.10"
25- - run : pip install --upgrade build twine
38+ cache : " pip"
39+
40+ - name : Install build tooling
41+ run : |
42+ python -V
43+ pip install --upgrade pip
44+ pip install build twine
45+
2646 - name : Build sdist and wheel
2747 run : python -m build
28- - run : twine check dist/*
48+
49+ - name : Check artifacts with twine
50+ run : twine check dist/*
51+
2952 - name : Upload sdist and wheel artifacts
3053 uses : actions/upload-artifact@v4
3154 with :
3255 name : dist
3356 path : dist/
57+ if-no-files-found : error
58+
3459 - name : Build git archive
35- run : mkdir archive && git archive -v -o archive/archive.tgz HEAD
60+ run : |
61+ mkdir -p archive
62+ git archive -v -o archive/archive.tgz HEAD
63+
3664 - name : Upload git archive artifact
3765 uses : actions/upload-artifact@v4
3866 with :
3967 name : archive
4068 path : archive/
69+ if-no-files-found : error
70+
4171 test-package :
72+ name : Install & test from ${{ matrix.package }} on py${{ matrix.python }}
4273 runs-on : ubuntu-latest
43- needs : [build]
74+ needs : [ build ]
4475 strategy :
76+ fail-fast : false
4577 matrix :
46- package : ['wheel', 'sdist', 'archive']
78+ python : [ "3.10", "3.11" ]
79+ package : [ "wheel", "sdist", "archive" ]
80+
4781 steps :
48- - name : Download sdist and wheel artifacts
82+ - name : Checkout (for notebook test files)
83+ uses : actions/checkout@v4
84+ with :
85+ fetch-depth : 0
86+
87+ - name : Download sdist/wheel artifacts
4988 if : matrix.package != 'archive'
5089 uses : actions/download-artifact@v4
5190 with :
5291 name : dist
5392 path : dist/
93+
5494 - name : Download git archive artifact
5595 if : matrix.package == 'archive'
5696 uses : actions/download-artifact@v4
5797 with :
5898 name : archive
5999 path : archive/
60- - uses : actions/setup-python@v5
100+
101+ - name : Set up Python
102+ uses : actions/setup-python@v5
61103 with :
62- python-version : " 3.10"
104+ python-version : ${{ matrix.python }}
105+ cache : " pip"
106+
63107 - name : Display Python version
64108 run : python -c "import sys; print(sys.version)"
65- - name : Update pip
109+
110+ - name : Upgrade pip
66111 run : pip install --upgrade pip
67- - name : Install wheel
112+
113+ - name : Install from wheel
68114 if : matrix.package == 'wheel'
69115 run : pip install dist/*.whl
70- - name : Install sdist
116+
117+ - name : Install from sdist
71118 if : matrix.package == 'sdist'
72119 run : pip install dist/*.tar.gz
73- - name : Install archive
120+
121+ - name : Install from git archive (PEP 517 source tree)
74122 if : matrix.package == 'archive'
75123 run : pip install archive/archive.tgz
124+
76125 - name : Install test extras
77- run : pip install track_linearization[test]
126+ run : pip install "track_linearization[test]"
127+
78128 - name : Run tests
79129 run : pytest --doctest-modules -v --pyargs track_linearization
80- - name : Test notebook
81- shell : bash -l {0}
130+
131+ - name : Execute example notebook
82132 run : |
83- jupyter nbconvert --to notebook --ExecutePreprocessor.kernel_name=python3 --execute notebooks/test_linearization.ipynb
133+ jupyter nbconvert \
134+ --to notebook \
135+ --inplace \
136+ --ExecutePreprocessor.kernel_name=python3 \
137+ --ExecutePreprocessor.timeout=1800 \
138+ --execute notebooks/test_linearization.ipynb
139+
140+ - name : Upload executed notebook (always)
141+ if : always()
142+ uses : actions/upload-artifact@v4
143+ with :
144+ name : executed-notebook-${{ matrix.package }}-py${{ matrix.python }}
145+ path : notebooks/test_linearization.ipynb
146+ if-no-files-found : warn
147+
84148 publish :
149+ name : Publish to PyPI
85150 runs-on : ubuntu-latest
86- needs : [test-package]
151+ needs : [ test-package ]
87152 if : github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
153+ # If you use PyPI Trusted Publishing (OIDC), uncomment permissions below and
154+ # remove the 'user/password' inputs from the publish step.
155+ # permissions:
156+ # id-token: write
157+ # contents: read
88158 steps :
89- - uses : actions/download-artifact@v4
159+ - name : Download built artifacts
160+ uses : actions/download-artifact@v4
90161 with :
91162 name : dist
92163 path : dist/
93- - uses : pypa/gh-action-pypi-publish@release/v1
164+
165+ # Option A: API Token (what you have now)
166+ - name : Publish with API token
167+ uses : pypa/gh-action-pypi-publish@release/v1
94168 with :
95169 user : __token__
96- password : ${{ secrets.PYPI_API_TOKEN }}
170+ password : ${{ secrets.PYPI_API_TOKEN }}
171+
172+ # Option B (preferred): Trusted Publishing (OIDC)
173+ # 1) Enable Trusted Publishers on your PyPI project
174+ # 2) Remove the step above and uncomment the step below
175+ # - name: Publish via OIDC
176+ # uses: pypa/gh-action-pypi-publish@release/v1
0 commit comments