Skip to content

Commit 645f2ea

Browse files
authored
Merge branch 'main' into hash-based-parameter-names
2 parents f9c8e0d + 8a75faa commit 645f2ea

File tree

4 files changed

+446
-0
lines changed

4 files changed

+446
-0
lines changed

.github/workflows/nightly.yml

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
---
2+
name: Nightly Build and Publish
3+
'on':
4+
schedule:
5+
- cron: '0 3 * * 1,3,5'
6+
workflow_dispatch: null
7+
env:
8+
UV_SYSTEM_PYTHON: 1
9+
jobs:
10+
check-changes:
11+
runs-on: ubuntu-latest
12+
outputs:
13+
has-changes: '${{ steps.check.outputs.has-changes }}'
14+
last-nightly-commit: '${{ steps.check.outputs.last-nightly-commit }}'
15+
current-commit: '${{ steps.check.outputs.current-commit }}'
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
- name: Check for changes since last nightly
21+
id: check
22+
run: >
23+
# Get the latest nightly release tag
24+
25+
LATEST_NIGHTLY_TAG=$(git tag --list "nightly-*"
26+
--sort=-version:refname | head -n 1)
27+
28+
29+
if [ -z "$LATEST_NIGHTLY_TAG" ]; then
30+
echo "No nightly tags found, will build (first time)"
31+
echo "has-changes=true" >> $GITHUB_OUTPUT
32+
echo "last-nightly-commit=" >> $GITHUB_OUTPUT
33+
echo "current-commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
34+
exit 0
35+
fi
36+
37+
38+
# Get the commit hash from the latest nightly tag
39+
40+
LATEST_NIGHTLY_COMMIT=$(git rev-list -n 1 "$LATEST_NIGHTLY_TAG")
41+
42+
CURRENT_COMMIT=$(git rev-parse HEAD)
43+
44+
45+
echo "last-nightly-commit=${LATEST_NIGHTLY_COMMIT}" >> $GITHUB_OUTPUT
46+
47+
echo "current-commit=${CURRENT_COMMIT}" >> $GITHUB_OUTPUT
48+
49+
50+
# Check if there are any commits since the last nightly
51+
52+
if [ "$LATEST_NIGHTLY_COMMIT" = "$CURRENT_COMMIT" ]; then
53+
echo "No changes since last nightly build"
54+
echo "has-changes=false" >> $GITHUB_OUTPUT
55+
else
56+
echo "Changes detected since last nightly build"
57+
echo "has-changes=true" >> $GITHUB_OUTPUT
58+
fi
59+
nightly-build:
60+
needs: check-changes
61+
if: needs.check-changes.outputs.has-changes == 'true'
62+
runs-on: ubuntu-latest
63+
strategy:
64+
matrix:
65+
python-version:
66+
- '3.9'
67+
- '3.10'
68+
- '3.11'
69+
- '3.12'
70+
- '3.13'
71+
name: 'Test py ${{ matrix.python-version }}'
72+
steps:
73+
- uses: actions/checkout@v4
74+
- name: 'Set up Python ${{ matrix.python-version }}'
75+
uses: actions/setup-python@v5
76+
with:
77+
python-version: '${{ matrix.python-version }}'
78+
- name: Install uv
79+
uses: astral-sh/setup-uv@v6
80+
- name: Install dependencies
81+
run: |
82+
uv sync --all-extras
83+
- name: Test with pytest
84+
run: |
85+
uv run task test
86+
- name: Run linting checks
87+
run: |
88+
uv run task ruff-check
89+
uv run task type-check
90+
- name: Build documentation
91+
run: |
92+
uv run task doc-clean-build
93+
nightly-publish:
94+
needs:
95+
- check-changes
96+
- nightly-build
97+
if: needs.check-changes.outputs.has-changes == 'true'
98+
runs-on: ubuntu-latest
99+
steps:
100+
- uses: actions/checkout@v4
101+
with:
102+
fetch-depth: 0
103+
- name: Set up Python
104+
uses: actions/setup-python@v5
105+
with:
106+
python-version: '3.12'
107+
- name: Install uv
108+
uses: astral-sh/setup-uv@v6
109+
- name: Install dependencies
110+
run: |
111+
uv sync --all-extras
112+
- name: Generate nightly version
113+
id: version
114+
run: |
115+
# Generate nightly version based on current date and commit
116+
DATE=$(date +%Y%m%d)
117+
COMMIT=$(git rev-parse --short HEAD)
118+
NIGHTLY_VERSION="${DATE}.dev0+${COMMIT}"
119+
echo "nightly_version=${NIGHTLY_VERSION}" >> $GITHUB_OUTPUT
120+
echo "Generated nightly version: ${NIGHTLY_VERSION}"
121+
- name: Update version files
122+
run: >
123+
# Update version in __init__.py
124+
125+
sed -i "s/__version__ = .*/__version__ = \"${{
126+
steps.version.outputs.nightly_version }}\"/" altair/__init__.py
127+
128+
# Update version in conf.py
129+
130+
sed -i "s/release = .*/release = \"${{
131+
steps.version.outputs.nightly_version }}\"/" doc/conf.py
132+
- name: Build package
133+
run: |
134+
uv run task build
135+
- name: Sign wheel with Sigstore
136+
uses: sigstore/[email protected]
137+
with:
138+
cosign-release: v2.2.0
139+
- name: Sign wheel
140+
run: >
141+
cosign sign-blob dist/altair-${{ steps.version.outputs.nightly_version
142+
}}-py3-none-any.whl \
143+
--output-signature dist/altair-${{ steps.version.outputs.nightly_version }}-py3-none-any.whl.sig \
144+
--output-certificate dist/altair-${{ steps.version.outputs.nightly_version }}-py3-none-any.whl.cert
145+
- name: Generate dependency diff
146+
id: deps
147+
run: |
148+
# Get current dependencies
149+
uv pip freeze > current_deps.txt
150+
151+
# Get previous nightly dependencies if available
152+
if [ -f "previous_deps.txt" ]; then
153+
diff -u previous_deps.txt current_deps.txt > dependency_diff.txt || true
154+
echo "dependency_changes=true" >> $GITHUB_OUTPUT
155+
else
156+
echo "No previous dependencies found (first nightly build)" > dependency_diff.txt
157+
echo "dependency_changes=false" >> $GITHUB_OUTPUT
158+
fi
159+
160+
# Save current deps for next run
161+
cp current_deps.txt previous_deps.txt
162+
- name: Generate binary file checksums
163+
id: checksums
164+
run: >
165+
# Find all binary files in the project
166+
167+
find . -name "*.csv.gz" -o -name "*.parquet" -o -name "*.json.gz" |
168+
while read file; do
169+
if [ -f "$file" ]; then
170+
# Generate SHA256 checksum
171+
sha256sum "$file" >> binary_checksums.txt
172+
echo "Processed: $file"
173+
fi
174+
done
175+
176+
177+
# Compare with previous checksums if available
178+
179+
if [ -f "previous_checksums.txt" ]; then
180+
echo "=== Binary File Changes ===" > binary_changes.txt
181+
diff -u previous_checksums.txt binary_checksums.txt >> binary_changes.txt || true
182+
echo "binary_changes=true" >> $GITHUB_OUTPUT
183+
else
184+
echo "No previous binary checksums found (first nightly build)" > binary_changes.txt
185+
echo "binary_changes=false" >> $GITHUB_OUTPUT
186+
fi
187+
188+
189+
# Save current checksums for next run
190+
191+
cp binary_checksums.txt previous_checksums.txt
192+
- name: Create GitHub release with assets
193+
id: create_release
194+
uses: actions/create-release@v1
195+
env:
196+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
197+
with:
198+
tag_name: 'nightly-${{ steps.version.outputs.nightly_version }}'
199+
release_name: 'Nightly Build ${{ steps.version.outputs.nightly_version }}'
200+
body: >
201+
Nightly build of Altair
202+
203+
204+
**Version:** ${{ steps.version.outputs.nightly_version }}
205+
206+
**Commit:** ${{ github.sha }}
207+
208+
**Date:** ${{ github.event.schedule }}
209+
210+
**Changes since last nightly:** ${{
211+
needs.check-changes.outputs.last-nightly-commit }}
212+
213+
214+
This is a pre-release version for testing purposes.
215+
216+
217+
## Installation
218+
219+
220+
### From GitHub Release
221+
222+
Download the wheel file from the assets below and install:
223+
224+
```bash
225+
226+
pip install altair-${{ steps.version.outputs.nightly_version
227+
}}-py3-none-any.whl
228+
229+
```
230+
231+
232+
### From GitHub Repository
233+
234+
```bash
235+
236+
pip install git+https://github.com/vega/altair.git@${{ github.sha }}
237+
238+
```
239+
draft: false
240+
prerelease: true
241+
- name: Upload wheel to release
242+
uses: actions/upload-release-asset@v1
243+
env:
244+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
245+
with:
246+
upload_url: '${{ steps.create_release.outputs.upload_url }}'
247+
asset_path: >-
248+
./dist/altair-${{ steps.version.outputs.nightly_version
249+
}}-py3-none-any.whl
250+
asset_name: 'altair-${{ steps.version.outputs.nightly_version }}-py3-none-any.whl'
251+
asset_content_type: application/octet-stream
252+
- name: Upload signatures to release
253+
uses: actions/upload-release-asset@v1
254+
env:
255+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
256+
with:
257+
upload_url: '${{ steps.create_release.outputs.upload_url }}'
258+
asset_path: >-
259+
./dist/altair-${{ steps.version.outputs.nightly_version
260+
}}-py3-none-any.whl.sig
261+
asset_name: >-
262+
altair-${{ steps.version.outputs.nightly_version
263+
}}-py3-none-any.whl.sig
264+
asset_content_type: application/octet-stream
265+
- name: Upload certificates to release
266+
uses: actions/upload-release-asset@v1
267+
env:
268+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
269+
with:
270+
upload_url: '${{ steps.create_release.outputs.upload_url }}'
271+
asset_path: >-
272+
./dist/altair-${{ steps.version.outputs.nightly_version
273+
}}-py3-none-any.whl.cert
274+
asset_name: >-
275+
altair-${{ steps.version.outputs.nightly_version
276+
}}-py3-none-any.whl.cert
277+
asset_content_type: application/octet-stream
278+
- name: Upload dependency diff to release
279+
if: steps.deps.outputs.dependency_changes == 'true'
280+
uses: actions/upload-release-asset@v1
281+
env:
282+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
283+
with:
284+
upload_url: '${{ steps.create_release.outputs.upload_url }}'
285+
asset_path: ./dependency_diff.txt
286+
asset_name: dependency_diff.txt
287+
asset_content_type: text/plain
288+
- name: Upload binary changes to release
289+
if: steps.checksums.outputs.binary_changes == 'true'
290+
uses: actions/upload-release-asset@v1
291+
env:
292+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
293+
with:
294+
upload_url: '${{ steps.create_release.outputs.upload_url }}'
295+
asset_path: ./binary_changes.txt
296+
asset_name: binary_changes.txt
297+
asset_content_type: text/plain
298+
- name: Upload full checksums to release
299+
uses: actions/upload-release-asset@v1
300+
env:
301+
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
302+
with:
303+
upload_url: '${{ steps.create_release.outputs.upload_url }}'
304+
asset_path: ./binary_checksums.txt
305+
asset_name: binary_checksums.txt
306+
asset_content_type: text/plain

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ clean = "python -c \"import tools;tools.fs.rm('dist')\""
301301
build = "task clean && uv build"
302302
publish = "task build && uv publish"
303303

304+
nightly-build = "python tools/generate_nightly_version.py --update && task build"
305+
nightly-release = "task nightly-build && echo 'Package built, ready for GitHub release'"
306+
304307
[tool.pytest.ini_options]
305308
# Pytest does not need to search these folders for test functions.
306309
# They contain examples which are being executed by the

tools/cleanup_nightlies.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Simple script to clean up old nightly releases.
4+
5+
Keeps only the last 10 nightly releases to avoid clutter.
6+
"""
7+
8+
9+
def cleanup_old_nightlies():
10+
"""Remove nightly releases older than 30 days."""
11+
# This would need GitHub API token and implementation
12+
# For now, just a placeholder
13+
print(
14+
"Cleanup script placeholder - would remove nightly releases older than 30 days"
15+
)
16+
print("Implementation would use GitHub API to list and delete old releases")
17+
18+
19+
if __name__ == "__main__":
20+
cleanup_old_nightlies()

0 commit comments

Comments
 (0)