diff --git a/.githooks/README.md b/.githooks/README.md new file mode 100644 index 00000000000..cf79397337c --- /dev/null +++ b/.githooks/README.md @@ -0,0 +1,57 @@ +# Git Hooks + +This directory contains Git hooks for the ExecuTorch repository. + +## Pre-commit Hook + +The pre-commit hook automatically updates the PyTorch commit pin in `.ci/docker/ci_commit_pins/pytorch.txt` whenever `torch_pin.py` is modified. + +### How It Works + +1. When you commit changes to `torch_pin.py`, the hook detects the change +2. It parses the `NIGHTLY_VERSION` field (e.g., `dev20251004`) +3. Converts it to a date string (e.g., `2025-10-04`) +4. Fetches the corresponding commit hash from the PyTorch nightly branch at https://github.com/pytorch/pytorch/tree/nightly +5. Updates `.ci/docker/ci_commit_pins/pytorch.txt` with the new commit hash +6. Automatically stages the updated file for commit + +### Installation + +To install the Git hooks, run: + +```bash +.githooks/install.sh +``` + +This will copy the pre-commit hook to `.git/hooks/` and make it executable. + +### Manual Usage + +You can also run the update script manually at any time: + +```bash +python .github/scripts/update_pytorch_pin.py +``` + +### Uninstalling + +To remove the pre-commit hook: + +```bash +rm .git/hooks/pre-commit +``` + +## Troubleshooting + +If the hook fails during a commit: + +1. Check that Python 3 is available in your PATH +2. Ensure you have internet connectivity to fetch commits from GitHub +3. Verify that the `NIGHTLY_VERSION` in `torch_pin.py` is in the correct format (`devYYYYMMDD`) +4. Make sure the corresponding nightly release exists in the PyTorch nightly branch + +You can run the script manually to see detailed error messages: + +```bash +python .github/scripts/update_pytorch_pin.py +``` diff --git a/.githooks/install.sh b/.githooks/install.sh new file mode 100755 index 00000000000..b79f750177b --- /dev/null +++ b/.githooks/install.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Script to install Git hooks from .githooks directory + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +GIT_DIR="$(git rev-parse --git-dir)" +HOOKS_DIR="${GIT_DIR}/hooks" + +echo "Installing Git hooks..." + +# Install pre-commit hook +echo "đŸ“Ļ Installing pre-commit hook..." +cp "${SCRIPT_DIR}/pre-commit" "${HOOKS_DIR}/pre-commit" +chmod +x "${HOOKS_DIR}/pre-commit" +echo "✅ pre-commit hook installed" + +echo "" +echo "🎉 Git hooks installed successfully!" +echo "" +echo "The pre-commit hook will automatically update .ci/docker/ci_commit_pins/pytorch.txt" +echo "whenever you commit changes to torch_pin.py" diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000000..5de24d0da1c --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Pre-commit hook to automatically update PyTorch commit pin when torch_pin.py changes + +# Check if torch_pin.py is being committed +if git diff --cached --name-only | grep -q "^torch_pin.py$"; then + echo "🔍 Detected changes to torch_pin.py" + echo "📝 Updating PyTorch commit pin..." + + # Run the update script + if python .github/scripts/update_pytorch_pin.py; then + # Check if pytorch.txt was modified + if ! git diff --quiet .ci/docker/ci_commit_pins/pytorch.txt; then + echo "✅ PyTorch commit pin updated successfully" + # Stage the updated file + git add .ci/docker/ci_commit_pins/pytorch.txt + echo "📌 Staged .ci/docker/ci_commit_pins/pytorch.txt" + else + echo "â„šī¸ PyTorch commit pin unchanged" + fi + else + echo "❌ Failed to update PyTorch commit pin" + echo "Please run: python .github/scripts/update_pytorch_pin.py" + exit 1 + fi +fi + +exit 0 diff --git a/.github/scripts/update_pytorch_pin.py b/.github/scripts/update_pytorch_pin.py new file mode 100644 index 00000000000..85ffd680019 --- /dev/null +++ b/.github/scripts/update_pytorch_pin.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +import json +import re +import sys +import urllib.request +from datetime import datetime + + +def parse_nightly_version(nightly_version): + """ + Parse NIGHTLY_VERSION (e.g., 'dev20251004') to date string (e.g., '2025-10-04'). + + Args: + nightly_version: String in format 'devYYYYMMDD' + + Returns: + Date string in format 'YYYY-MM-DD' + """ + match = re.match(r"dev(\d{4})(\d{2})(\d{2})", nightly_version) + if not match: + raise ValueError(f"Invalid NIGHTLY_VERSION format: {nightly_version}") + + year, month, day = match.groups() + return f"{year}-{month}-{day}" + + +def get_torch_nightly_version(): + """ + Read NIGHTLY_VERSION from torch_pin.py. + + Returns: + NIGHTLY_VERSION string + """ + with open("torch_pin.py", "r") as f: + content = f.read() + + match = re.search(r'NIGHTLY_VERSION\s*=\s*["\']([^"\']+)["\']', content) + if not match: + raise ValueError("Could not find NIGHTLY_VERSION in torch_pin.py") + + return match.group(1) + + +def get_commit_hash_for_nightly(date_str): + """ + Fetch commit hash from PyTorch nightly branch for a given date. + + Args: + date_str: Date string in format 'YYYY-MM-DD' + + Returns: + Commit hash string + """ + api_url = "https://api.github.com/repos/pytorch/pytorch/commits" + params = f"?sha=nightly&per_page=100" + url = api_url + params + + req = urllib.request.Request(url) + req.add_header("Accept", "application/vnd.github.v3+json") + req.add_header("User-Agent", "ExecuTorch-Bot") + + try: + with urllib.request.urlopen(req) as response: + commits = json.loads(response.read().decode()) + except Exception as e: + print(f"Error fetching commits: {e}", file=sys.stderr) + sys.exit(1) + + # Look for commit with title matching "{date_str} nightly release" + target_title = f"{date_str} nightly release" + + for commit in commits: + commit_msg = commit.get("commit", {}).get("message", "") + # Check if the first line of commit message matches + first_line = commit_msg.split("\n")[0].strip() + if first_line == target_title or first_line.startswith(f"{date_str} nightly"): + return commit["sha"] + + raise ValueError( + f"Could not find commit with title matching '{target_title}' in nightly branch" + ) + + +def update_pytorch_pin(commit_hash): + """ + Update .ci/docker/ci_commit_pins/pytorch.txt with the new commit hash. + + Args: + commit_hash: Commit hash to write + """ + pin_file = ".ci/docker/ci_commit_pins/pytorch.txt" + with open(pin_file, "w") as f: + f.write(f"{commit_hash}\n") + print(f"Updated {pin_file} with commit hash: {commit_hash}") + + +def main(): + try: + # Read NIGHTLY_VERSION from torch_pin.py + nightly_version = get_torch_nightly_version() + print(f"Found NIGHTLY_VERSION: {nightly_version}") + + # Parse to date string + date_str = parse_nightly_version(nightly_version) + print(f"Parsed date: {date_str}") + + # Fetch commit hash from PyTorch nightly branch + commit_hash = get_commit_hash_for_nightly(date_str) + print(f"Found commit hash: {commit_hash}") + + # Update the pin file + update_pytorch_pin(commit_hash) + + print("Successfully updated PyTorch commit pin!") + + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main()