Skip to content

Commit d5f4daa

Browse files
Merge branch 'main' into u/elizabethdavis/sphinx-sidebar-fix
2 parents 5e314d1 + af262ba commit d5f4daa

78 files changed

Lines changed: 4811 additions & 908 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yaml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,23 @@ jobs:
3838
run: make check
3939

4040
test-smoke:
41-
name: Linux / make test-smoke
41+
name: Linux / make test-smoke / torch=${{ matrix.torch_version }}
4242
runs-on: ubuntu-latest
4343
timeout-minutes: 60
4444
env:
4545
INSTALL_PRECOMMIT: "false"
46+
strategy:
47+
fail-fast: false
48+
matrix:
49+
include:
50+
- torch_group: torch_2_8
51+
torch_version: "2.8"
52+
- torch_group: torch_2_9
53+
torch_version: "2.9"
54+
- torch_group: torch_2_10
55+
torch_version: "2.10"
56+
- torch_group: torch_2_11
57+
torch_version: "2.11"
4658
steps:
4759
- name: Check out repository
4860
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
@@ -51,7 +63,7 @@ jobs:
5163
with:
5264
enable-cache: false
5365
- name: Run `make test-smoke`
54-
run: make test-smoke
66+
run: make test-smoke TORCH_GROUP=${{ matrix.torch_group }}
5567

5668
test-tutorials:
5769
name: Linux / make test-tutorials

.github/workflows/release.yml

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
name: Release
2+
3+
run-name: 'Release ${{ github.ref_name }} · @${{ github.actor }}'
4+
5+
# Publishing to PyPI uses Trusted Publishing (OIDC) — no API token is stored.
6+
# A release manager pushes a `vMAJOR.MINOR.PATCH` tag; the `build` and
7+
# `smoke-test` jobs run automatically, then the `publish` job pauses on the
8+
# `pypi` GitHub environment until a reviewer approves it. That environment's
9+
# protection rules (required reviewers, prevent-self-review so the tag pusher
10+
# can't approve their own release, and a wait timer) live in the repo's
11+
# Environment settings, not in this file.
12+
on:
13+
push:
14+
tags:
15+
# Strictly vMAJOR.MINOR.PATCH with numeric parts (e.g. v0.2.2). This is a
16+
# glob, not a regex: `.` is a literal dot and `[0-9]` a digit range. The
17+
# filter must match the entire tag, so pre-releases (v1.2.3rc1 — the
18+
# trailing `rc1` is left unmatched) and other non-release tags never start
19+
# the release run. The `pypi` environment tag rule and approval gate are
20+
# secondary controls; the version guard below is the final backstop.
21+
- 'v[0-9]+.[0-9]+.[0-9]+'
22+
# Manual dry run: builds and smoke-tests the current ref but never publishes
23+
# (the publish job is gated to tag pushes). Trigger from the Actions tab
24+
# ("Release" -> "Run workflow") or `gh workflow run release.yml --ref <branch>`.
25+
workflow_dispatch:
26+
27+
# Least privilege by default; the publish job opts into `id-token: write`.
28+
permissions:
29+
contents: read
30+
31+
concurrency:
32+
# Serialize releases per tag and never cancel an in-flight publish.
33+
group: release-${{ github.ref }}
34+
cancel-in-progress: false
35+
36+
jobs:
37+
# ── Build the exact wheel + sdist that will be smoke-tested and published. ──
38+
build:
39+
name: Build distributions
40+
runs-on: ubuntu-latest
41+
timeout-minutes: 15
42+
steps:
43+
- name: Check out repository
44+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
45+
with:
46+
persist-credentials: false
47+
- name: Install uv
48+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
49+
with:
50+
enable-cache: false
51+
- name: Verify the tag matches the package version
52+
# The published version comes from src/coreai_opt/_about.py, not the tag.
53+
# Fail early if they disagree so we never publish a mismatched/duplicate
54+
# version (PyPI uploads are immutable and cannot be overwritten).
55+
# `print_version.py --release` computes the version exactly as the
56+
# `make build` step below does, so this guard can't drift from what
57+
# actually gets published.
58+
# Skipped on manual dry runs, where the ref is a branch, not a vX.Y.Z tag.
59+
# Run via uv (installed above) so the interpreter satisfies
60+
# requires-python whatever the runner image ships; see the Makefile's
61+
# `version` target.
62+
if: github.event_name == 'push'
63+
run: |
64+
tag="${GITHUB_REF_NAME}"
65+
version="$(uv run --no-config --no-project --python '>=3.11' scripts/make/print_version.py --release)"
66+
echo "tag=${tag} package version=${version}"
67+
if [ "${tag}" != "v${version}" ]; then
68+
echo "::error::Tag ${tag} does not match package version v${version} (src/coreai_opt/_about.py). Update latest_released_version so the release it implies matches the tag."
69+
exit 1
70+
fi
71+
- name: Build wheel and sdist
72+
run: make build
73+
- name: Upload distributions
74+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
75+
with:
76+
name: dist
77+
path: dist/
78+
if-no-files-found: error
79+
80+
# ── Smoke test the exact built wheel and sdist via `make test-smoke`. ──
81+
# Reuses the repo's smoke suite (ci/nox/noxfile.py → tests/test_smoke.py) but
82+
# points it at the pre-built artifact instead of rebuilding, so we test the
83+
# bytes we are about to publish. `make test-smoke` runs across every supported
84+
# Python version internally.
85+
smoke-test:
86+
name: Smoke test (${{ matrix.format }}, ${{ matrix.torch_group }})
87+
needs: build
88+
runs-on: ubuntu-latest
89+
timeout-minutes: 60
90+
env:
91+
INSTALL_PRECOMMIT: 'false'
92+
strategy:
93+
fail-fast: false
94+
matrix:
95+
# Test both distribution formats against every supported torch version,
96+
# mirroring the PR CI smoke matrix (ci.yaml).
97+
format: [wheel, sdist]
98+
torch_group: [torch_2_8, torch_2_9, torch_2_10, torch_2_11]
99+
steps:
100+
- name: Check out repository
101+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
102+
with:
103+
persist-credentials: false
104+
- name: Install uv
105+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
106+
with:
107+
enable-cache: false
108+
- name: Download distributions
109+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
110+
with:
111+
name: dist
112+
path: dist/
113+
- name: Smoke test the built ${{ matrix.format }} against ${{ matrix.torch_group }}
114+
run: |
115+
# Expand the glob to the single built artifact; the `test -f` below
116+
# fails the job if it's missing or if more than one matched.
117+
case "${{ matrix.format }}" in
118+
wheel) dist="$(echo dist/*.whl)" ;;
119+
sdist) dist="$(echo dist/*.tar.gz)" ;;
120+
esac
121+
test -f "${dist}" || { echo "::error::Expected exactly one ${{ matrix.format }} in dist/"; exit 1; }
122+
echo "Smoke testing ${dist} against ${{ matrix.torch_group }}"
123+
make test-smoke SMOKE_TEST_DIST="${dist}" TORCH_GROUP="${{ matrix.torch_group }}"
124+
125+
# ── Publish to PyPI via Trusted Publishing. Only this job holds `id-token`. ──
126+
# It builds nothing and runs no project code: it just downloads the vetted
127+
# artifact and uploads it, keeping build/test dependencies out of the
128+
# OIDC-privileged job.
129+
publish:
130+
name: Publish to PyPI
131+
needs: [build, smoke-test]
132+
# Publish only on a tag push (never on a manual dry run) and never from forks.
133+
if: github.event_name == 'push' && github.repository == 'apple/coreai-optimization'
134+
runs-on: ubuntu-latest
135+
timeout-minutes: 15
136+
environment:
137+
name: pypi
138+
url: https://pypi.org/p/coreai-opt
139+
permissions:
140+
id-token: write # mint the OIDC token PyPI validates for Trusted Publishing
141+
contents: read
142+
steps:
143+
- name: Install uv
144+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
145+
with:
146+
enable-cache: false
147+
- name: Download distributions
148+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
149+
with:
150+
name: dist
151+
path: dist/
152+
- name: Publish to PyPI
153+
# `always` requires Trusted Publishing (OIDC) — no fallback to tokens.
154+
run: uv publish --trusted-publishing always

.pre-commit-config.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,34 @@ repos:
305305
types: [python]
306306
exclude: ^tests/
307307

308+
- repo: local
309+
hooks:
310+
- id: check-internal-import-aliases
311+
name: Check `_`-prefix aliasing of internal imports
312+
description: |
313+
Enforce code_style_guide.md §3.3: public modules must alias symbols
314+
imported from private modules with a `_` prefix; private modules must
315+
not. Fails the commit and reports each violation with a suggested fix;
316+
it does not edit files — run the script with `--fix` to apply fixes.
317+
entry: python scripts/pre_commit/check_internal_import_aliases.py
318+
language: system
319+
types: [python]
320+
exclude: ^tests/
321+
322+
- repo: local
323+
hooks:
324+
- id: check-about-version
325+
name: Check _about.py version fields
326+
description: |
327+
Check that _about.py's latest_released_version matches the repo's
328+
latest release tag, and that __version__ is its last number plus
329+
one, plus .dev0. Catches a release candidate that looks like a
330+
release has already shipped when it hasn't.
331+
entry: python scripts/pre_commit/check_about_version.py
332+
language: system
333+
files: (^|/)_about\.py$
334+
pass_filenames: false
335+
308336
- repo: local
309337
hooks:
310338
- id: towncrier-check

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ The API surface is intentionally limited. This keeps the library reliable, well-
2222
Set up the environment as described in [README.md](README.md#getting-started). Then, from the activated venv:
2323

2424
```shell
25-
# Build the package.
26-
make build
25+
# Build the package (development build).
26+
make build-dev
2727

2828
# Build the documentation.
2929
make docs

0 commit comments

Comments
 (0)