Skip to content

Commit

Permalink
vnext issue creator script (Azure#31474)
Browse files Browse the repository at this point in the history
* try getting build id

* try more env vars in ci

* try print env var

* try print env var

* wip

* add vnext script

* update label for creating issue

* move dep

* add envar to vnext steps

* add gh token to pipeline

* fix package name and lines too long

* move vnext script to azure-sdk-tools/gh_tools per feedback

* cspell

* fix more cspell
  • Loading branch information
kristapratico authored Aug 11, 2023
1 parent 4cc7c58 commit 33f3fe6
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,13 @@
"thead"
]
},
{
"filename": "tools/azure-sdk-tools/gh_tools/**",
"words": [
"JOBID",
"vnext"
]
},
{
"filename": "doc/esrp_release.md",
"words": [
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/prepare-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ extends:
Prefix: python
CIConventionOptions: ''
UPConventionOptions: '--variablegroups 58 76 56 93'
TestsConventionOptions: '--variablegroups 64'
TestsConventionOptions: '--variablegroups 58 64'
8 changes: 6 additions & 2 deletions eng/pipelines/templates/stages/archetype-sdk-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ stages:
--toxenv="next-pylint"
--disablecov
--filter-type="Omit_management"
env: ${{ parameters.EnvVars }}
env:
GH_TOKEN: $(azuresdk-github-pat)

- task: PythonScript@0
displayName: 'Run MyPy Next'
Expand All @@ -195,7 +196,8 @@ stages:
--service="${{ parameters.ServiceDirectory }}"
--toxenv="next-mypy"
--disablecov
env: ${{ parameters.EnvVars }}
env:
GH_TOKEN: $(azuresdk-github-pat)

- task: PythonScript@0
displayName: 'Run Pyright Next'
Expand All @@ -208,6 +210,8 @@ stages:
--service="${{ parameters.ServiceDirectory }}"
--toxenv="next-pyright"
--disablecov
env:
GH_TOKEN: $(azuresdk-github-pat)

- task: PythonScript@0
displayName: 'Run Ruff'
Expand Down
7 changes: 6 additions & 1 deletion eng/tox/run_mypy.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
is_check_enabled, is_typing_ignored
)
from ci_tools.variables import in_ci
from gh_tools.vnext_issue_creator import create_vnext_issue


logging.getLogger().setLevel(logging.INFO)

Expand Down Expand Up @@ -88,7 +90,10 @@
except CalledProcessError as sample_err:
sample_code_error = sample_err

print("See https://aka.ms/python/typing-guide for information.\n\n")
if args.next and in_ci() and is_check_enabled(args.target_package, "mypy") and not is_typing_ignored(package_name):
if src_code_error or sample_code_error:
create_vnext_issue(package_name, "mypy")

if src_code_error and sample_code_error:
raise Exception(
[
Expand Down
4 changes: 4 additions & 0 deletions eng/tox/run_pylint.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from ci_tools.environment_exclusions import is_check_enabled
from ci_tools.parsing import ParsedSetup
from ci_tools.variables import in_ci
from gh_tools.vnext_issue_creator import create_vnext_issue

logging.getLogger().setLevel(logging.INFO)

Expand Down Expand Up @@ -72,4 +73,7 @@
logging.error(
"{} exited with linting error {}. Please see this link for more information https://aka.ms/azsdk/python/pylint-guide".format(pkg_details.name, e.returncode)
)
if args.next and in_ci() and is_check_enabled(args.target_package, "pylint"):
create_vnext_issue(pkg_details.name, "pylint")

exit(1)
4 changes: 4 additions & 0 deletions eng/tox/run_pyright.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
is_check_enabled, is_typing_ignored
)
from ci_tools.variables import in_ci
from gh_tools.vnext_issue_creator import create_vnext_issue

logging.getLogger().setLevel(logging.INFO)

Expand Down Expand Up @@ -71,5 +72,8 @@
try:
check_call(commands)
except CalledProcessError as error:
if args.next and in_ci() and is_check_enabled(args.target_package, "pyright") and not is_typing_ignored(package_name):
create_vnext_issue(package_name, "pyright")

print("See https://aka.ms/python/typing-guide for information.\n\n")
raise error
Empty file.
137 changes: 137 additions & 0 deletions tools/azure-sdk-tools/gh_tools/vnext_issue_creator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# This script is used to create issues for client libraries failing the vnext of mypy, pyright, and pylint.

import sys
import os
import subprocess
import logging
import datetime
import re
import calendar
import typing
from typing_extensions import Literal
from github import Github, Auth

logging.getLogger().setLevel(logging.INFO)


def get_version_running(check_type: Literal["mypy", "pylint", "pyright"]) -> str:
commands = [
sys.executable,
"-m",
check_type,
"--version"
]
version = subprocess.run(
commands,
check=True,
capture_output=True,
)
version = version.stdout.rstrip().decode("utf-8")
version_running = re.findall(r'(\d+.\d+.\d+)', version)[0]
logging.info(f"Running {check_type} version {version_running}")
return version_running


def get_build_link(check_type: Literal["mypy", "pylint", "pyright"]) -> str:
build_id = os.getenv('BUILD_BUILDID')
job_id = os.getenv('SYSTEM_JOBID')

next_id: str
if check_type == "mypy":
next_id = "59f5c573-b3ce-57f7-6a79-55fe2db3a175"
if check_type == "pyright":
next_id = "c0edaab3-85d6-5e4b-81a8-d1190a6ee92b"
if check_type == "pylint":
next_id = "e1fa7d9e-8471-5a74-cd7d-e1c9a992e07e"

return f"https://dev.azure.com/azure-sdk/internal/_build/results?buildId={build_id}&view=logs&j={job_id}&t={next_id}"


def get_merge_dates(year: str) -> typing.List[datetime.datetime]:
"""We'll merge the latest version of the type checker/linter quarterly
on the Monday after release week. This function returns those 4 Mondays
for the given year.
"""
c = calendar.Calendar(firstweekday=calendar.FRIDAY)
first = c.monthdatescalendar(year, 1)
second = c.monthdatescalendar(year, 4)
third = c.monthdatescalendar(year, 7)
fourth = c.monthdatescalendar(year, 10)

merge_months = [first, second, third, fourth]

merge_dates = []
for month in merge_months:
code_complete = [day for week in month for day in week if \
day.weekday() == calendar.FRIDAY and day.month in [1, 4, 7, 10]][0]
monday_after_release_week = code_complete + datetime.timedelta(days=10)
merge_dates.append(monday_after_release_week)
return merge_dates


def get_date_for_version_bump(today: datetime.datetime) -> str:
merge_dates = get_merge_dates(today.year)
try:
merge_date = min(date for date in merge_dates if date >= today)
except ValueError:
# today's date is after October merge date, so rollover to next year
merge_dates = get_merge_dates(today.year+1)
merge_date = min(date for date in merge_dates if date >= today)
return merge_date.strftime('%Y-%m-%d')


def create_vnext_issue(package_name: str, check_type: Literal["mypy", "pylint", "pyright"]) -> None:
"""This is called when a client library fails a vnext check.
An issue is created with the details or an existing issue is updated with the latest information."""

auth = Auth.Token(os.environ["GH_TOKEN"])
g = Github(auth=auth)

today = datetime.date.today()
repo = g.get_repo("Azure/azure-sdk-for-python")

issues = repo.get_issues(state="open", labels=[check_type], creator="azure-sdk")
vnext_issue = [issue for issue in issues if issue.body.find(package_name) != -1]

version = get_version_running(check_type)
build_link = get_build_link(check_type)
merge_date = get_date_for_version_bump(today)
error_type = "linting" if check_type == "pylint" else "typing"
guide_link = "[Pylint Guide](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/pylint_checking.md)" \
if check_type == "pylint" else "[Typing Guide](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/static_type_checking.md#run-mypy)"

title = f"{package_name} needs {error_type} updates for {check_type} version {version}"
template = (
f"**ACTION NEEDED:** This version of {check_type} will be merged on **{merge_date}**. "
f"The build will begin to fail for this library if errors are not fixed."
f"\n\n**Library name:** {package_name}"
f"\n**{check_type.capitalize()} version:** {version}"
f"\n**{check_type.capitalize()} errors:** [Link to build ({today.strftime('%Y-%m-%d')})]({build_link})"
f"\n**How to fix:** Run the `next-{check_type}` tox command at the library package-level and resolve "
f"the {error_type} errors.\n"
f"1) `../{package_name}>pip install tox<5`\n"
f"2) `../{package_name}>tox run -e next-{check_type} -c ../../../eng/tox/tox.ini --root .`\n\n"
f"See the {guide_link} for more information."
)

# create an issue for the library failing the vnext check
if not vnext_issue:
logging.info(f"Issue does not exist for {package_name} with {check_type} version {version}. Creating...")
repo.create_issue(
title=title,
body=template,
labels=[check_type]
)
return

# an issue exists, let's update it so it reflects the latest typing/linting errors
logging.info(f"Issue exists for {package_name} with {check_type} version {version}. Updating...")
vnext_issue[0].edit(
title=title,
body=template,
)
4 changes: 3 additions & 1 deletion tools/azure-sdk-tools/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"python-dotenv",
"PyYAML",
"urllib3<2",
"tomli"
"tomli",
# gh tools
"PyGithub>=1.59.0"
]

setup(
Expand Down

0 comments on commit 33f3fe6

Please sign in to comment.