diff --git a/poetry.lock b/poetry.lock index b4eaa0ae..285e3f12 100644 --- a/poetry.lock +++ b/poetry.lock @@ -236,6 +236,17 @@ humanfriendly = ">=9.1" [package.extras] cron = ["capturer (>=2.4)"] +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + [[package]] name = "coverage" version = "5.5" @@ -250,6 +261,25 @@ toml = {version = "*", optional = true, markers = "extra == \"toml\""} [package.extras] toml = ["toml"] +[[package]] +name = "cryptography" +version = "35.0.0" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cffi = ">=1.12" + +[package.extras] +docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] +docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] +sdist = ["setuptools_rust (>=0.11.4)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] + [[package]] name = "discord.py" version = "2.0.0a0" @@ -436,6 +466,26 @@ python-dateutil = ">=2.8.1" [package.extras] dev = ["twine", "markdown", "flake8", "wheel"] +[[package]] +name = "gidgethub" +version = "5.0.1" +description = "An async GitHub API library" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +PyJWT = {version = ">=2.0.0", extras = ["crypto"]} +uritemplate = ">=3.0.1" + +[package.extras] +aiohttp = ["aiohttp"] +dev = ["aiohttp", "black", "coverage[toml] (>=5.0.3)", "httpx", "mypy", "pytest-cov", "pytest-xdist", "tornado"] +doc = ["sphinx"] +httpx = ["httpx (>=0.16.1)"] +test = ["importlib-resources", "pytest (>=5.4.1)", "pytest-asyncio", "pytest-tornasync"] +tornado = ["tornado"] + [[package]] name = "gitdb" version = "4.0.7" @@ -839,10 +889,27 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" name = "pygments" version = "2.10.0" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" +category = "main" optional = false python-versions = ">=3.5" +[[package]] +name = "pyjwt" +version = "2.3.0" +description = "JSON Web Token implementation in Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cryptography = {version = ">=3.3.1", optional = true, markers = "extra == \"crypto\""} + +[package.extras] +crypto = ["cryptography (>=3.3.1)"] +dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"] + [[package]] name = "pymdown-extensions" version = "8.2" @@ -1043,6 +1110,22 @@ urllib3 = ">=1.21.1,<1.27" socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] +[[package]] +name = "rich" +version = "10.12.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" +optional = false +python-versions = ">=3.6.2,<4.0.0" + +[package.dependencies] +colorama = ">=0.4.0,<0.5.0" +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] + [[package]] name = "six" version = "1.16.0" @@ -1137,6 +1220,14 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "uritemplate" +version = "4.1.1" +description = "Implementation of RFC 6570 URI Templates" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "urllib3" version = "1.26.6" @@ -1207,7 +1298,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "e99a8dc25d0c2d30dd939af8e60aa92c8e4851614508fb46387d0663a0a8c261" +content-hash = "45e2d2658fd40f79150eb9bff33090f0dabda45b07905b513856dd7ca0656c32" [metadata.files] aiodns = [ @@ -1440,6 +1531,10 @@ coloredlogs = [ {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, ] +commonmark = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] coverage = [ {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"}, @@ -1494,6 +1589,28 @@ coverage = [ {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"}, {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, ] +cryptography = [ + {file = "cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9"}, + {file = "cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6"}, + {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d"}, + {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa"}, + {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e"}, + {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992"}, + {file = "cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6"}, + {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d"}, + {file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6"}, + {file = "cryptography-35.0.0-cp36-abi3-win32.whl", hash = "sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8"}, + {file = "cryptography-35.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588"}, + {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953"}, + {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6"}, + {file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd"}, + {file = "cryptography-35.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"}, + {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999"}, + {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad"}, + {file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2"}, + {file = "cryptography-35.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c"}, + {file = "cryptography-35.0.0.tar.gz", hash = "sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d"}, +] "discord.py" = [] distlib = [ {file = "distlib-0.3.2-py2.py3-none-any.whl", hash = "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"}, @@ -1549,6 +1666,10 @@ ghp-import = [ {file = "ghp-import-2.0.1.tar.gz", hash = "sha256:753de2eace6e0f7d4edfb3cce5e3c3b98cd52aadb80163303d1d036bda7b4483"}, {file = "ghp_import-2.0.1-py3-none-any.whl", hash = "sha256:8241a8e9f8dd3c1fafe9696e6e081b57a208ef907e9939c44e7415e407ab40ea"}, ] +gidgethub = [ + {file = "gidgethub-5.0.1-py3-none-any.whl", hash = "sha256:67245e93eb0918b37df038148af675df43b62e832c529d7f859f6b90d9f3e70d"}, + {file = "gidgethub-5.0.1.tar.gz", hash = "sha256:3efbd6998600254ec7a2869318bd3ffde38edc3a0d37be0c14bc46b45947b682"}, +] gitdb = [ {file = "gitdb-4.0.7-py3-none-any.whl", hash = "sha256:6c4cc71933456991da20917998acbe6cf4fb41eeaab7d6d67fbc05ecd4c865b0"}, {file = "gitdb-4.0.7.tar.gz", hash = "sha256:96bf5c08b157a666fec41129e6d327235284cca4c81e92109260f353ba138005"}, @@ -1861,6 +1982,10 @@ pygments = [ {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, ] +pyjwt = [ + {file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"}, + {file = "PyJWT-2.3.0.tar.gz", hash = "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41"}, +] pymdown-extensions = [ {file = "pymdown-extensions-8.2.tar.gz", hash = "sha256:b6daa94aad9e1310f9c64c8b1f01e4ce82937ab7eb53bfc92876a97aca02a6f4"}, {file = "pymdown_extensions-8.2-py3-none-any.whl", hash = "sha256:141452d8ed61165518f2c923454bf054866b85cf466feedb0eb68f04acdc2560"}, @@ -1990,6 +2115,10 @@ requests = [ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, ] +rich = [ + {file = "rich-10.12.0-py3-none-any.whl", hash = "sha256:c30d6808d1cd3defd56a7bd2d587d13e53b5f55de6cf587f035bcbb56bc3f37b"}, + {file = "rich-10.12.0.tar.gz", hash = "sha256:83fb3eff778beec3c55201455c17cccde1ccdf66d5b4dade8ef28f56b50c4bd4"}, +] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -2030,6 +2159,10 @@ typing-extensions = [ {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, ] +uritemplate = [ + {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, + {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, +] urllib3 = [ {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, diff --git a/pyproject.toml b/pyproject.toml index aa3423f0..575f2254 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ coloredlogs = "^15.0" "discord.py" = { url = "https://github.com/Rapptz/discord.py/archive/master.zip" } pydantic = { version = "^1.8.2", extras = ["dotenv"] } toml = "^0.10.2" +rich = "^10.12.0" [tool.poetry.extras] @@ -58,6 +59,7 @@ mkdocs-material = ">=7.1.9,<8.0.0" mkdocs-markdownextradata-plugin = ">=0.1.7,<0.2.0" click = "^8.0.3" Jinja2 = "^3.0.2" +gidgethub = "^5.0.1" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/requirements.txt b/requirements.txt index 701d5a63..dfe57f98 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ cffi==1.14.6 chardet==4.0.0 ; python_version >= "2.7" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" and python_version != "3.3" and python_version != "3.4" colorama==0.4.4 ; python_version >= "2.7" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" and python_version != "3.3" and python_version != "3.4" coloredlogs==15.0.1 ; python_version >= "2.7" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" and python_version != "3.3" and python_version != "3.4" +commonmark==0.9.1 discord.py @ https://github.com/Rapptz/discord.py/archive/master.zip ; python_full_version >= "3.8.0" humanfriendly==9.2 ; python_version >= "2.7" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" and python_version != "3.3" and python_version != "3.4" idna==3.2 ; python_version >= "3.5" @@ -19,9 +20,11 @@ multidict==5.1.0 ; python_version >= "3.6" pycares==4.0.0 pycparser==2.20 ; python_version >= "2.7" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" and python_version != "3.3" pydantic==1.8.2 ; python_full_version >= "3.6.1" +pygments==2.10.0 ; python_version >= "3.5" pyreadline==2.1 ; sys_platform == "win32" python-dateutil==2.8.2 ; python_version != "3.0" python-dotenv==0.19.0 ; python_version >= "3.5" +rich==10.12.0 ; python_full_version >= "3.6.2" six==1.16.0 ; python_version >= "2.7" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" toml==0.10.2 ; python_version >= "2.6" and python_version != "3.0" and python_version != "3.1" and python_version != "3.2" typing-extensions==3.10.0.2 diff --git a/scripts/news/__pycache__/__init__.cpython-39.pyc b/scripts/news/__pycache__/__init__.cpython-39.pyc index 7a931482..c5348475 100644 Binary files a/scripts/news/__pycache__/__init__.cpython-39.pyc and b/scripts/news/__pycache__/__init__.cpython-39.pyc differ diff --git a/scripts/news/__pycache__/__main__.cpython-39.pyc b/scripts/news/__pycache__/__main__.cpython-39.pyc index 101eb7ae..301a9536 100644 Binary files a/scripts/news/__pycache__/__main__.cpython-39.pyc and b/scripts/news/__pycache__/__main__.cpython-39.pyc differ diff --git a/scripts/news/__pycache__/utils.cpython-39.pyc b/scripts/news/__pycache__/utils.cpython-39.pyc index 1246dd94..af48b881 100644 Binary files a/scripts/news/__pycache__/utils.cpython-39.pyc and b/scripts/news/__pycache__/utils.cpython-39.pyc differ diff --git a/scripts/news/check_news_workflow/__init__.py b/scripts/news/check_news_workflow/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/scripts/news/check_news_workflow/__main__.py b/scripts/news/check_news_workflow/__main__.py new file mode 100644 index 00000000..efaf96e0 --- /dev/null +++ b/scripts/news/check_news_workflow/__main__.py @@ -0,0 +1,83 @@ +import enum +import pathlib +import re + +import click +import requests +from rich import print + +from ..utils import load_toml_config + + +NEWS_NEXT_DIR = "news/next/" +SKIP_NEWS_LABEL = "skip changelog" +GH_API_URL = "https://api.github.com/" +HEADERS = {"accept": "application/vnd.github.v3+json"} + +CONFIG = load_toml_config() +SECTIONS = [_type for _type, _ in CONFIG.get("types").items()] + +FILENAME_RE = re.compile( + r"\d{4}-\d{2}-\d{2}(?:-\d{2}-\d{2}-\d{2})?\." # match `yyyy-mm-dd` or `yyyy-m-d` + r"pr-\d+(?:,\d+)*\." # Issue number(s) + fr"({'|'.join(SECTIONS)})\." # Section type + r"[A-Za-z0-9_=-]+\." # Nonce (URL-safe base64) + r"md", # File extension""" + re.VERBOSE, +) + + +class StatusState(enum.Enum): + """Status state for the changelog checking.""" + + SUCCESS = "success" + ERROR = "error" + FAILURE = "failure" + + +def is_news_dir(filename: str) -> bool: + """Return True if file is in the News directory.""" + return filename.startswith(NEWS_NEXT_DIR) + + +@click.command() +@click.argument("pr", nargs=1, type=int) +def main(pr: int) -> None: + """Main function to check for a changelog entry.""" + r = requests.get(f"{GH_API_URL}repos/discord-modmail/modmail/pulls/{pr}/files", headers=HEADERS) + files_changed = r.json() + in_next_dir = file_found = False + status = None + + for file in files_changed: + if not is_news_dir(file["filename"]): + continue + in_next_dir = True + file_path = pathlib.PurePath(file["filename"]) + if len(file_path.parts) != 4: # news, next, , + continue + file_found = True + if FILENAME_RE.match(file_path.name) and len(file["patch"]) >= 1: + status = (f"News entry found in {NEWS_NEXT_DIR}", StatusState.SUCCESS) + break + else: + _r = requests.get(f"{GH_API_URL}repos/discord-modmail/modmail/pulls/{pr}", headers=HEADERS) + pr_data = _r.json() + labels = [label["name"] for label in pr_data["labels"]] + if SKIP_NEWS_LABEL in labels: + description = f"'{SKIP_NEWS_LABEL}' label found" + else: + if not in_next_dir: + description = f'No news entry in {NEWS_NEXT_DIR} or "{SKIP_NEWS_LABEL}" label found' + elif not file_found: + description = "News entry not in an appropriate directory" + else: + description = "News entry file name incorrectly formatted" + + status = (description, StatusState.ERROR) + + print(status) + + +if __name__ == "__main__": + main() diff --git a/scripts/news/config.toml b/scripts/news/config.toml index c300c997..a77b70de 100644 --- a/scripts/news/config.toml +++ b/scripts/news/config.toml @@ -9,3 +9,4 @@ bugfix = { name = "Bug Fixes" } doc = { name = "Improved Documentation" } deprecation = { name = "Deprecations" } breaking = { name = "Breaking Changes" } +internal = { name = "Internal" }