diff --git a/.github/workflows/update_mypy_pyright.yml b/.github/workflows/update_mypy_pyright.yml new file mode 100644 index 000000000000..e5c2c561ee0e --- /dev/null +++ b/.github/workflows/update_mypy_pyright.yml @@ -0,0 +1,50 @@ +name: Update mypy, pytype and pyright + +on: + schedule: + # Runs every day at 00:00 UTC + - cron: '0 0 * * *' + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + - name: Install dependencies + run: | + pip install requests + - name: Run script + run: python scripts/check_for_update_dependency.py + - uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + title: "Daily dependencies update" + commit-message: "Updated dependencies after the daily check" + body: | + There appear to be some dependency updates in ${{ github.sha }}. This pull request + uses the script to find and update these dependencies. + base: ${{ github.head_ref }} + # https://github.community/t/run-github-actions-job-only-if-previous-job-has-failed/174786/2 + create-issue-on-failure: + name: Create an issue if Update mypy, pytype and pyright failed + runs-on: ubuntu-latest + needs: [build] + if: ${{ github.repository == 'python/typeshed' && always() && (needs.build.result == 'failure') }} + steps: + - uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + await github.rest.issues.create({ + owner: "python", + repo: "typeshed", + title: `Update mypy, pytype and pyright failed on ${new Date().toDateString()}`, + body: "Update mypy, pytype and pyright runs are listed here: https://github.com/python/typeshed/actions/workflows/update_mypy_pyright.yml", + }) \ No newline at end of file diff --git a/scripts/check_for_update_dependency.py b/scripts/check_for_update_dependency.py new file mode 100644 index 000000000000..75d90aeb2428 --- /dev/null +++ b/scripts/check_for_update_dependency.py @@ -0,0 +1,65 @@ +import re +import requests +from typing import List + +from typing import Optional + + +def get_latest_version(package_name: str) -> Optional[str]: + """Fetch the latest version of a package from PyPI.""" + response = requests.get(f"https://pypi.org/pypi/{package_name}/json") + response.raise_for_status() + data = response.json() + return str(data["info"]["version"]) + + +def update_versions(file_path: str) -> None: + with open(file_path, "r") as file: + content = file.readlines() + + pattern = re.compile(r"^(pytype|mypy)==([\d.]+)") + + updated_content: List[str] = [] + + for line in content: + match = pattern.match(line) + if match: + package_name = match.group(1) + current_version = match.group(2) + latest_version = get_latest_version(package_name) + if latest_version and current_version != latest_version: + print(f"Updating {package_name} from {current_version} to {latest_version}") + line = line.replace(current_version, latest_version) + updated_content.append(line) + + with open(file_path, "w") as file: + file.writelines(updated_content) + + +def update_pyright_version(file_path: str) -> None: + """Update pyright version in a TOML configuration file.""" + with open(file_path, "r", encoding="utf-8") as file: + lines = file.readlines() + + latest_version = get_latest_version("pyright") + if latest_version: + updated_lines = [] + for line in lines: + if line.startswith("pyright_version = "): + updated_lines.append(f'pyright_version = "{latest_version}"\n') + print(f"Updated pyright to version {latest_version} in {file_path}") + else: + updated_lines.append(line) + + with open(file_path, "w", encoding="utf-8") as file: + file.writelines(updated_lines) + + +file_paths: List[str] = ["requirements-tests.txt", "pyproject.toml"] + +if __name__ == "__main__": + for file_path in file_paths: + if file_path.endswith(".txt"): + update_versions(file_path) + elif file_path.endswith(".toml"): + update_pyright_version(file_path)