@@ -2,125 +2,99 @@ name: Release
22
33on :
44 push :
5- tags : ["v*"]
6- workflow_dispatch :
7- inputs :
8- package :
9- description : " Which package to publish (bootstrap helper). Use 'all' for normal releases."
10- required : true
11- default : " all"
12- type : choice
13- options :
14- - devqubit-engine
15- - devqubit
16- - devqubit-ui
17- - devqubit-qiskit
18- - devqubit-qiskit-runtime
19- - devqubit-pennylane
20- - devqubit-cirq
21- - devqubit-braket
22- - all
5+ tags :
6+ - " v*"
237
248jobs :
259 build :
10+ name : Build + test + package (all)
2611 runs-on : ubuntu-latest
12+
2713 steps :
28- - uses : actions/checkout@v4
14+ - uses : actions/checkout@v6
2915 with :
3016 fetch-depth : 0
3117 persist-credentials : false
3218
33- - uses : astral-sh/setup-uv@v7
19+ - name : Install uv (Python 3.12)
20+ uses : astral-sh/setup-uv@v7
3421 with :
3522 python-version : " 3.12"
3623 enable-cache : true
3724
38- - run : uv sync --all-packages --all-extras --dev --locked
39- - run : uv run pytest
40- - run : uv run python -m pip install --upgrade build
25+ - name : Sync (workspace + dev + all extras)
26+ run : uv sync --all-packages --all-extras --dev --locked
27+
28+ - name : Run tests
29+ run : uv run pytest
4130
42- - name : Verify tag matches all package versions (tag runs only)
43- if : ${{ startsWith(github.ref, 'refs/tags/v') }}
31+ - name : Install build backend
32+ run : uv run python -m pip install --upgrade build
33+
34+ - name : Verify tag matches all package versions
4435 run : |
4536 uv run python - << 'PY'
4637 import os, sys, pathlib, tomllib
47- tag = os.environ["GITHUB_REF_NAME"]
38+
39+ tag = os.environ["GITHUB_REF_NAME"] # v0.1.0
4840 ver = tag[1:] if tag.startswith("v") else tag
49- pyprojects = [pathlib.Path("pyproject.toml")] + sorted(pathlib.Path("packages").glob("*/pyproject.toml"))
50- bad = []
41+
42+ pyprojects = [pathlib.Path("pyproject.toml")]
43+ pyprojects += sorted(pathlib.Path("packages").glob("*/pyproject.toml"))
44+
45+ mismatches = []
5146 for p in pyprojects:
52- v = tomllib.loads(p.read_text(encoding="utf-8")).get("project", {}).get("version")
47+ data = tomllib.loads(p.read_text(encoding="utf-8"))
48+ v = data.get("project", {}).get("version")
5349 if v != ver:
54- bad.append((str(p), v))
55- if bad:
56- for p, v in bad:
50+ mismatches.append((str(p), v))
51+
52+ if mismatches:
53+ for p, v in mismatches:
5754 print(f"Version mismatch: {p}: {v!r} != {ver!r}")
5855 sys.exit(1)
59- print("OK:", ver)
60- PY
6156
62- - name : Build all distributions into per-package dirs
63- run : |
64- uv run python - << 'PY'
65- import pathlib, tomllib, subprocess, sys
66- root = pathlib.Path(".").resolve()
67- dist = root / "dist"
68- dist.mkdir(exist_ok=True)
69-
70- def name(pp):
71- return tomllib.loads(pp.read_text(encoding="utf-8"))["project"]["name"]
72-
73- # root
74- root_name = name(root / "pyproject.toml")
75- (dist / root_name).mkdir(parents=True, exist_ok=True)
76- subprocess.check_call([sys.executable, "-m", "build", "--outdir", str(dist / root_name), str(root)])
77-
78- # members
79- for pp in sorted((root / "packages").glob("*/pyproject.toml")):
80- pkg = pp.parent
81- n = name(pp)
82- (dist / n).mkdir(parents=True, exist_ok=True)
83- subprocess.check_call([sys.executable, "-m", "build", "--outdir", str(dist / n), str(pkg)])
57+ print("OK: all versions match", ver)
8458 PY
8559
86- - uses : actions/upload-artifact@v4
60+ - name : Build root dist (devqubit)
61+ run : uv run python -m build --outdir dist .
62+
63+ - name : Build workspace member dists
64+ run : |
65+ set -euo pipefail
66+ for pkg in packages/*; do
67+ if [ -f "$pkg/pyproject.toml" ]; then
68+ echo "Building $pkg"
69+ uv run python -m build --outdir dist "$pkg"
70+ fi
71+ done
72+
73+ - name : Upload dists artifact
74+ uses : actions/upload-artifact@v6
8775 with :
8876 name : python-package-distributions
8977 path : dist/
9078
9179 publish :
80+ name : Publish to PyPI (Trusted Publishing)
9281 needs : [build]
9382 runs-on : ubuntu-latest
83+
9484 permissions :
9585 id-token : write
9686 contents : read
9787
98- strategy :
99- fail-fast : false
100- matrix :
101- package :
102- - devqubit-engine
103- - devqubit
104- - devqubit-ui
105- - devqubit-qiskit
106- - devqubit-qiskit-runtime
107- - devqubit-pennylane
108- - devqubit-cirq
109- - devqubit-braket
110-
111- if : ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && (inputs.package == 'all' || inputs.package == matrix.package)) }}
112-
11388 environment :
11489 name : pypi
115- url : https://pypi.org/project/${{ matrix.package }}/
90+ url : https://pypi.org/
11691
11792 steps :
118- - uses : actions/download-artifact@v4
93+ - name : Download dists
94+ uses : actions/download-artifact@v4
11995 with :
12096 name : python-package-distributions
12197 path : dist/
12298
123- - uses : pypa/gh-action-pypi-publish@release/v1
124- with :
125- packages-dir : dist/${{ matrix.package }}
126- skip-existing : true
99+ - name : Publish
100+ uses : pypa/gh-action-pypi-publish@release/v1
0 commit comments