Skip to content

Commit ae711c5

Browse files
committed
Support date-based PyPI versioning and dev packages
1 parent a6e793a commit ae711c5

6 files changed

Lines changed: 146 additions & 19 deletions

File tree

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ jobs:
8787
run: cp CNAME public/CNAME
8888

8989
- name: Deploy
90-
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
90+
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
9191
if: github.ref == 'refs/heads/main'
9292
with:
9393
github_token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/nightly.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
gh release view "nightly" && gh release delete "nightly" -y --cleanup-tag
4444
4545
- name: GH Release
46-
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
46+
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
4747
with:
4848
prerelease: true
4949
tag_name: nightly
@@ -64,7 +64,7 @@ jobs:
6464
issues: write
6565
steps:
6666
- name: Create issue on failure
67-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
67+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
6868
with:
6969
script: |
7070
github.rest.issues.create({

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
4141
- name: Create Release
4242
id: release
43-
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
43+
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
4444
with:
4545
tag_name: v${{ steps.date.outputs.date }}
4646
generate_release_notes: true
@@ -71,7 +71,7 @@ jobs:
7171

7272
- name: Create issue on failure
7373
if: steps.wait_for_wheels.outcome == 'failure'
74-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
74+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
7575
with:
7676
script: |
7777
github.rest.issues.create({

.github/workflows/wheels.yml

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,57 @@ on:
99
types: [labeled]
1010

1111
jobs:
12+
setup-version:
13+
name: Setup version and publication status
14+
runs-on: ubuntu-latest
15+
outputs:
16+
version: ${{ steps.get-version.outputs.version }}
17+
should_publish: ${{ steps.get-version.outputs.should_publish }}
18+
steps:
19+
- name: Check out repo
20+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
21+
- name: Install dependencies
22+
run: pip install requests
23+
- name: Get version
24+
id: get-version
25+
shell: bash
26+
run: |
27+
python scripts/get_version.py \
28+
--event "${{ github.event_name }}" \
29+
--ref "${{ github.ref }}" \
30+
--tag "${{ github.event.release.tag_name }}" \
31+
--package "heir_py" \
32+
--gha
33+
1234
build_sdist:
1335
name: Build source distribution
36+
needs: [setup-version]
1437
if: github.ref == 'refs/heads/main' || github.event.label.name == 'ci:wheels'
1538
runs-on: ubuntu-latest
1639
steps:
1740
- name: Check out repo
18-
uses: actions/checkout@v6
41+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1942
with:
2043
fetch-depth: 0
2144
- name: Install Python 3.12
22-
uses: actions/setup-python@v6
45+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
2346
with:
2447
python-version: "3.12"
2548
- run: python -m pip install build
2649
- name: Build sdist
27-
run: python -m build --sdist
28-
- uses: actions/upload-artifact@v6
50+
run: |
51+
if [[ -n "${{ needs.setup-version.outputs.version }}" ]]; then
52+
export SETUPTOOLS_SCM_PRETEND_VERSION="${{ needs.setup-version.outputs.version }}"
53+
fi
54+
python -m build --sdist
55+
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
2956
with:
3057
name: dist-sdist
3158
path: dist/*.tar.gz
3259

3360
build_wheels:
3461
name: Build HEIR wheels on ${{ matrix.name }}
62+
needs: [setup-version]
3563
# On PRs, only run when the ci:wheels label is added.
3664
if: github.ref == 'refs/heads/main' || github.event.label.name == 'ci:wheels'
3765
runs-on: ${{ matrix.runner }}
@@ -50,36 +78,40 @@ jobs:
5078

5179
steps:
5280
- name: Check out HEIR
53-
uses: actions/checkout@v6
81+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
82+
with:
83+
fetch-depth: 0
5484

55-
- uses: actions/setup-python@v6
85+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
5686
name: Install Python 3.12
5787
with:
5888
python-version: "3.12"
5989
- run: pip install --upgrade pip uv
6090

6191
- name: Build wheels on ${{ matrix.name }} using cibuildwheel
62-
uses: pypa/cibuildwheel@v3.0.0
92+
uses: pypa/cibuildwheel@5f22145df44122af0f5a201f93cf0207171beca7 # v3.0.0
93+
env:
94+
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.setup-version.outputs.version }}
6395

6496
- name: Upload HEIR ${{ matrix.name }} wheels
6597
if: always()
66-
uses: actions/upload-artifact@v6
98+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
6799
with:
68100
name: dist-${{ matrix.name }}
69101
path: wheelhouse/*.whl
70102

71103
pypi_upload:
72104
name: Publish heir wheels to PyPI
73-
needs: [build_sdist, build_wheels]
74-
# Only publish from main, not PRs
75-
if: github.ref == 'refs/heads/main'
105+
needs: [setup-version, build_sdist, build_wheels]
106+
# Only publish from main or releases based on setup-version logic
107+
if: needs.setup-version.outputs.should_publish == 'true'
76108
runs-on: ubuntu-latest
77109
# Cf. trusted publishers on PyPI
78110
environment: pypi
79111
permissions:
80112
id-token: write
81113
steps:
82-
- uses: actions/download-artifact@v7
114+
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
83115
with:
84116
path: dist
85117
pattern: dist-*

pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[build-system]
2-
requires = ["setuptools"]
2+
requires = ["setuptools", "setuptools-scm"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "heir_py"
7-
version = "0.0.3"
7+
dynamic = ["version"]
88
authors = [
99
{ name = "Jeremy Kun", email = "jkun@google.com" },
1010
{ name = "Asra Ali", email = "asraa@google.com" },
@@ -126,3 +126,6 @@ ignore-words-list = "crate,fpt,LogArithmetic,olt,allOne"
126126
write-changes = false
127127
# files to exclude
128128
skip = "*.lock"
129+
130+
[tool.setuptools_scm]
131+
# Can be empty, setuptools-scm handles the rest by default.

scripts/get_version.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""Script to calculate the version for the HEIR Python package."""
2+
3+
import argparse
4+
import datetime
5+
import os
6+
import re
7+
import sys
8+
import requests
9+
10+
11+
def get_pypi_versions(package_name):
12+
"""Fetch all published versions for a package from PyPI."""
13+
url = f"https://pypi.org/pypi/{package_name}/json"
14+
try:
15+
response = requests.get(url, timeout=10)
16+
if response.status_code == 200:
17+
data = response.json()
18+
return list(data.get("releases", {}).keys())
19+
except Exception as e:
20+
print(f"Error fetching from PyPI: {e}", file=sys.stderr)
21+
return []
22+
23+
24+
def get_next_dev_version(package_name):
25+
"""Calculate the next .devN version for today's date."""
26+
today = datetime.datetime.now(datetime.timezone.utc).strftime("%Y.%m.%d")
27+
versions = get_pypi_versions(package_name)
28+
29+
# Find versions matching today's date and the .dev suffix
30+
pattern = re.compile(rf"^{re.escape(today)}\.dev(\d+)$")
31+
max_dev = -1
32+
33+
for v in versions:
34+
match = pattern.match(v)
35+
if match:
36+
max_dev = max(max_dev, int(match.group(1)))
37+
38+
next_dev = max_dev + 1
39+
return f"{today}.dev{next_dev}"
40+
41+
42+
def main():
43+
parser = argparse.ArgumentParser(
44+
description="Calculate HEIR package version."
45+
)
46+
parser.add_argument(
47+
"--event",
48+
default="workflow_dispatch",
49+
help="GitHub event name (e.g., release, workflow_dispatch)",
50+
)
51+
parser.add_argument(
52+
"--ref",
53+
default="refs/heads/main",
54+
help="GitHub ref (e.g., refs/heads/main)",
55+
)
56+
parser.add_argument("--tag", help="Release tag name")
57+
parser.add_argument("--package", default="heir_py", help="PyPI package name")
58+
parser.add_argument(
59+
"--gha", action="store_true", help="Output for GitHub Actions"
60+
)
61+
62+
args = parser.parse_args()
63+
64+
version = ""
65+
should_publish = "false"
66+
67+
if args.event == "release":
68+
if args.tag:
69+
version = args.tag.lstrip("v")
70+
should_publish = "true"
71+
elif args.event == "workflow_dispatch" and args.ref == "refs/heads/main":
72+
version = get_next_dev_version(args.package)
73+
should_publish = "true"
74+
else:
75+
# For PRs or other events, we let setuptools-scm handle it automatically
76+
# or we don't publish.
77+
should_publish = "false"
78+
79+
if args.gha:
80+
# Writing to GITHUB_OUTPUT if available
81+
output_file = os.environ.get("GITHUB_OUTPUT")
82+
if output_file:
83+
with open(output_file, "a") as f:
84+
f.write(f"version={version}\n")
85+
f.write(f"should_publish={should_publish}\n")
86+
87+
print(f"version={version}")
88+
print(f"should_publish={should_publish}")
89+
90+
91+
if __name__ == "__main__":
92+
main()

0 commit comments

Comments
 (0)