Skip to content

Commit 7efe09c

Browse files
authored
Add a precommit hook to automatically update .ci/docker/ci_commit_pins/pytorch.txt when torch_pin.py is changed. (#15072)
This pull request introduces a new script, `.github/scripts/update_pytorch_pin.py`, which automates the process of updating the PyTorch commit pin based on the nightly version specified in `torch_pin.py`. The script parses the nightly version, fetches the corresponding commit hash from the PyTorch nightly branch using the GitHub API, and updates the pin file accordingly. This automation helps ensure that the CI environment uses the correct nightly commit for PyTorch. Automation of PyTorch nightly pin updating: * Added `.github/scripts/update_pytorch_pin.py`, a script that reads the nightly version from `torch_pin.py`, parses the date, fetches the corresponding commit hash from the PyTorch nightly branch via the GitHub API, and updates `.ci/docker/ci_commit_pins/pytorch.txt` with the new hash. Test plan: Run `.githooks/install.sh` Tested manually by changing `NIGHTLY_VERSION` and try to commit locally. Was able to see `.ci/docker/ci_commit_pins/pytorch.txt` being updated.
1 parent a7d4c5b commit 7efe09c

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

.githooks/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Git Hooks
2+
3+
This directory contains Git hooks for the ExecuTorch repository.
4+
5+
## Pre-commit Hook
6+
7+
The pre-commit hook automatically updates the PyTorch commit pin in `.ci/docker/ci_commit_pins/pytorch.txt` whenever `torch_pin.py` is modified.
8+
9+
### How It Works
10+
11+
1. When you commit changes to `torch_pin.py`, the hook detects the change
12+
2. It parses the `NIGHTLY_VERSION` field (e.g., `dev20251004`)
13+
3. Converts it to a date string (e.g., `2025-10-04`)
14+
4. Fetches the corresponding commit hash from the PyTorch nightly branch at https://github.com/pytorch/pytorch/tree/nightly
15+
5. Updates `.ci/docker/ci_commit_pins/pytorch.txt` with the new commit hash
16+
6. Automatically stages the updated file for commit
17+
18+
### Installation
19+
20+
To install the Git hooks, run:
21+
22+
```bash
23+
.githooks/install.sh
24+
```
25+
26+
This will copy the pre-commit hook to `.git/hooks/` and make it executable.
27+
28+
### Manual Usage
29+
30+
You can also run the update script manually at any time:
31+
32+
```bash
33+
python .github/scripts/update_pytorch_pin.py
34+
```
35+
36+
### Uninstalling
37+
38+
To remove the pre-commit hook:
39+
40+
```bash
41+
rm .git/hooks/pre-commit
42+
```
43+
44+
## Troubleshooting
45+
46+
If the hook fails during a commit:
47+
48+
1. Check that Python 3 is available in your PATH
49+
2. Ensure you have internet connectivity to fetch commits from GitHub
50+
3. Verify that the `NIGHTLY_VERSION` in `torch_pin.py` is in the correct format (`devYYYYMMDD`)
51+
4. Make sure the corresponding nightly release exists in the PyTorch nightly branch
52+
53+
You can run the script manually to see detailed error messages:
54+
55+
```bash
56+
python .github/scripts/update_pytorch_pin.py
57+
```

.githooks/install.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env bash
2+
3+
# Script to install Git hooks from .githooks directory
4+
5+
set -e
6+
7+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
GIT_DIR="$(git rev-parse --git-dir)"
9+
HOOKS_DIR="${GIT_DIR}/hooks"
10+
11+
echo "Installing Git hooks..."
12+
13+
# Install pre-commit hook
14+
echo "📦 Installing pre-commit hook..."
15+
cp "${SCRIPT_DIR}/pre-commit" "${HOOKS_DIR}/pre-commit"
16+
chmod +x "${HOOKS_DIR}/pre-commit"
17+
echo "✅ pre-commit hook installed"
18+
19+
echo ""
20+
echo "🎉 Git hooks installed successfully!"
21+
echo ""
22+
echo "The pre-commit hook will automatically update .ci/docker/ci_commit_pins/pytorch.txt"
23+
echo "whenever you commit changes to torch_pin.py"

.githooks/pre-commit

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env bash
2+
3+
# Pre-commit hook to automatically update PyTorch commit pin when torch_pin.py changes
4+
5+
# Check if torch_pin.py is being committed
6+
if git diff --cached --name-only | grep -q "^torch_pin.py$"; then
7+
echo "🔍 Detected changes to torch_pin.py"
8+
echo "📝 Updating PyTorch commit pin..."
9+
10+
# Run the update script
11+
if python .github/scripts/update_pytorch_pin.py; then
12+
# Check if pytorch.txt was modified
13+
if ! git diff --quiet .ci/docker/ci_commit_pins/pytorch.txt; then
14+
echo "✅ PyTorch commit pin updated successfully"
15+
# Stage the updated file
16+
git add .ci/docker/ci_commit_pins/pytorch.txt
17+
echo "📌 Staged .ci/docker/ci_commit_pins/pytorch.txt"
18+
else
19+
echo "ℹ️ PyTorch commit pin unchanged"
20+
fi
21+
else
22+
echo "❌ Failed to update PyTorch commit pin"
23+
echo "Please run: python .github/scripts/update_pytorch_pin.py"
24+
exit 1
25+
fi
26+
fi
27+
28+
exit 0
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/env python3
2+
3+
import json
4+
import re
5+
import sys
6+
import urllib.request
7+
from datetime import datetime
8+
9+
10+
def parse_nightly_version(nightly_version):
11+
"""
12+
Parse NIGHTLY_VERSION (e.g., 'dev20251004') to date string (e.g., '2025-10-04').
13+
14+
Args:
15+
nightly_version: String in format 'devYYYYMMDD'
16+
17+
Returns:
18+
Date string in format 'YYYY-MM-DD'
19+
"""
20+
match = re.match(r"dev(\d{4})(\d{2})(\d{2})", nightly_version)
21+
if not match:
22+
raise ValueError(f"Invalid NIGHTLY_VERSION format: {nightly_version}")
23+
24+
year, month, day = match.groups()
25+
return f"{year}-{month}-{day}"
26+
27+
28+
def get_torch_nightly_version():
29+
"""
30+
Read NIGHTLY_VERSION from torch_pin.py.
31+
32+
Returns:
33+
NIGHTLY_VERSION string
34+
"""
35+
with open("torch_pin.py", "r") as f:
36+
content = f.read()
37+
38+
match = re.search(r'NIGHTLY_VERSION\s*=\s*["\']([^"\']+)["\']', content)
39+
if not match:
40+
raise ValueError("Could not find NIGHTLY_VERSION in torch_pin.py")
41+
42+
return match.group(1)
43+
44+
45+
def get_commit_hash_for_nightly(date_str):
46+
"""
47+
Fetch commit hash from PyTorch nightly branch for a given date.
48+
49+
Args:
50+
date_str: Date string in format 'YYYY-MM-DD'
51+
52+
Returns:
53+
Commit hash string
54+
"""
55+
api_url = "https://api.github.com/repos/pytorch/pytorch/commits"
56+
params = f"?sha=nightly&per_page=100"
57+
url = api_url + params
58+
59+
req = urllib.request.Request(url)
60+
req.add_header("Accept", "application/vnd.github.v3+json")
61+
req.add_header("User-Agent", "ExecuTorch-Bot")
62+
63+
try:
64+
with urllib.request.urlopen(req) as response:
65+
commits = json.loads(response.read().decode())
66+
except Exception as e:
67+
print(f"Error fetching commits: {e}", file=sys.stderr)
68+
sys.exit(1)
69+
70+
# Look for commit with title matching "{date_str} nightly release"
71+
target_title = f"{date_str} nightly release"
72+
73+
for commit in commits:
74+
commit_msg = commit.get("commit", {}).get("message", "")
75+
# Check if the first line of commit message matches
76+
first_line = commit_msg.split("\n")[0].strip()
77+
if first_line == target_title or first_line.startswith(f"{date_str} nightly"):
78+
return commit["sha"]
79+
80+
raise ValueError(
81+
f"Could not find commit with title matching '{target_title}' in nightly branch"
82+
)
83+
84+
85+
def update_pytorch_pin(commit_hash):
86+
"""
87+
Update .ci/docker/ci_commit_pins/pytorch.txt with the new commit hash.
88+
89+
Args:
90+
commit_hash: Commit hash to write
91+
"""
92+
pin_file = ".ci/docker/ci_commit_pins/pytorch.txt"
93+
with open(pin_file, "w") as f:
94+
f.write(f"{commit_hash}\n")
95+
print(f"Updated {pin_file} with commit hash: {commit_hash}")
96+
97+
98+
def main():
99+
try:
100+
# Read NIGHTLY_VERSION from torch_pin.py
101+
nightly_version = get_torch_nightly_version()
102+
print(f"Found NIGHTLY_VERSION: {nightly_version}")
103+
104+
# Parse to date string
105+
date_str = parse_nightly_version(nightly_version)
106+
print(f"Parsed date: {date_str}")
107+
108+
# Fetch commit hash from PyTorch nightly branch
109+
commit_hash = get_commit_hash_for_nightly(date_str)
110+
print(f"Found commit hash: {commit_hash}")
111+
112+
# Update the pin file
113+
update_pytorch_pin(commit_hash)
114+
115+
print("Successfully updated PyTorch commit pin!")
116+
117+
except Exception as e:
118+
print(f"Error: {e}", file=sys.stderr)
119+
sys.exit(1)
120+
121+
122+
if __name__ == "__main__":
123+
main()

0 commit comments

Comments
 (0)