diff options
Diffstat (limited to '.github')
-rw-r--r-- | .github/dependabot.yml | 46 | ||||
-rw-r--r-- | .github/release.yml | 17 | ||||
-rw-r--r-- | .github/workflows/codeql-analysis.yml | 70 | ||||
-rw-r--r-- | .github/workflows/issue-labels.yml | 39 | ||||
-rw-r--r-- | .github/workflows/lsp_updater.py | 132 | ||||
-rw-r--r-- | .github/workflows/pr-check.yml | 238 | ||||
-rw-r--r-- | .github/workflows/pr-labels.yml | 21 | ||||
-rw-r--r-- | .github/workflows/push-check.yml | 189 | ||||
-rw-r--r-- | .github/workflows/updater.yml | 30 | ||||
-rw-r--r-- | .github/workflows/version-check.yml | 21 | ||||
-rw-r--r-- | .github/workflows/version_check.py | 27 |
11 files changed, 830 insertions, 0 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..051cace --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,46 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: / + schedule: + interval: monthly + labels: + - 'no-changelog' + + - package-ecosystem: 'github-actions' + directory: .github/actions/lint + schedule: + interval: monthly + labels: + - 'no-changelog' + + - package-ecosystem: 'github-actions' + directory: .github/actions/build-package + schedule: + interval: monthly + labels: + - 'no-changelog' + + - package-ecosystem: 'pip' + directory: /generator + schedule: + interval: daily + labels: + - 'no-changelog' + + - package-ecosystem: 'pip' + directory: /tests + schedule: + interval: daily + labels: + - 'no-changelog' + + - package-ecosystem: 'pip' + directory: / + schedule: + interval: daily + labels: + - 'debt' + commit-message: + include: 'scope' + prefix: 'pip' diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..6dedc3e --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,17 @@ +changelog: + exclude: + labels: + - "no-changelog" + + categories: + - title: Enhancements + labels: + - "feature-request" + + - title: Bug Fixes + labels: + - "bug" + + - title: Code Health + labels: + - "debt" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..054549e --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,70 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [main] + pull_request: + # The branches below must be a subset of the branches above + branches: [main] + schedule: + - cron: "15 16 * * 2" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["python"] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # âšī¸ Command-line programs to run using the OS shell. + # đ https://git.io/JvXDl + + # âī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/issue-labels.yml b/.github/workflows/issue-labels.yml new file mode 100644 index 0000000..c8198c5 --- /dev/null +++ b/.github/workflows/issue-labels.yml @@ -0,0 +1,39 @@ +name: Issue labels + +on: + issues: + types: [opened, reopened] + +permissions: + issues: write + +jobs: + # From https://github.com/marketplace/actions/github-script#apply-a-label-to-an-issue. + add-triage-label: + name: "Add 'triage-needed'" + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const result = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }) + const labels = result.data.map((label) => label.name) + const hasNeeds = labels.some((label) => label.startsWith('needs')) + + if (!hasNeeds) { + console.log('This issue is not labeled with a "needs __" label, add the "triage-needed" label.') + + github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: ['triage-needed'] + }) + } else { + console.log('This issue already has a "needs __" label, do not add the "triage-needed" label.') + } diff --git a/.github/workflows/lsp_updater.py b/.github/workflows/lsp_updater.py new file mode 100644 index 0000000..01f1c91 --- /dev/null +++ b/.github/workflows/lsp_updater.py @@ -0,0 +1,132 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + + +import hashlib +import json +import os +import pathlib +import urllib.request as url_lib +from typing import Optional, Union + +import github +import github.Issue +import github.PullRequest + +MODEL_SCHEMA = "https://raw.githubusercontent.com/microsoft/vscode-languageserver-node/main/protocol/metaModel.schema.json" +MODEL = "https://raw.githubusercontent.com/microsoft/vscode-languageserver-node/main/protocol/metaModel.json" + +LABEL_DEBT = "debt" +LABEL_UPDATE = "lsp-update" + +GH = github.Github(os.getenv("GITHUB_ACCESS_TOKEN")) +GH_REPO = GH.get_repo(os.getenv("GITHUB_REPOSITORY")) + + +def _get_content(uri) -> str: + with url_lib.urlopen(uri) as response: + content = response.read() + if isinstance(content, str): + return content + else: + return content.decode("utf-8") + + +def _get_update_issue_body(schema_hash: str, model_hash: str) -> str: + return "\n".join( + [ + "LSP Schema has changed. Please update the generator.", + f"Schema: [source]({MODEL_SCHEMA})", + f"Model: [source]({MODEL})", + "", + "Instructions:", + "1. Setup a virtual environment and install nox.", + "2. Install all requirements for generator.", + "3. Run `nox --session update_lsp`.", + "", + "Hashes:", + f"* schema: `{schema_hash}`", + f"* model: `{model_hash}`", + ] + ) + + +def is_schema_changed(old_schema: str, new_schema: str) -> bool: + old_schema = json.loads(old_schema) + new_schema = json.loads(new_schema) + return old_schema != new_schema + + +def is_model_changed(old_model: str, new_model: str) -> bool: + old_model = json.loads(old_model) + new_model = json.loads(new_model) + return old_model != new_model + + +def get_hash(text: str) -> str: + hash_object = hashlib.sha256() + hash_object.update(json.dumps(json.loads(text)).encode()) + return hash_object.hexdigest() + + +def get_existing_issue( + schema_hash: str, model_hash: str +) -> Union[github.PullRequest.PullRequest, None]: + issues = GH_REPO.get_issues(state="open", labels=[LABEL_UPDATE, LABEL_DEBT]) + for issue in issues: + if schema_hash in issue.body and model_hash in issue.body: + return issue + + return None + + +def cleanup_stale_issues( + schema_hash: str, model_hash: str, new_issue: Optional[github.Issue.Issue] = None +): + issues = GH_REPO.get_issues(state="open", labels=[LABEL_UPDATE, LABEL_DEBT]) + for issue in issues: + if schema_hash not in issue.body or model_hash not in issue.body: + if new_issue: + issue.create_comment( + "\n".join( + [ + "This issue is stale as the schema has changed.", + f"Closing in favor of {new_issue.url} .", + ] + ) + ) + issue.edit(state="closed") + + +def main(): + lsp_root = pathlib.Path(__file__).parent.parent.parent / "generator" + + old_schema = pathlib.Path(lsp_root / "lsp.schema.json").read_text(encoding="utf-8") + old_model = pathlib.Path(lsp_root / "lsp.json").read_text(encoding="utf-8") + + new_schema = _get_content(MODEL_SCHEMA) + new_model = _get_content(MODEL) + + schema_changed = is_schema_changed(old_schema, new_schema) + model_changed = is_model_changed(old_model, new_model) + + if schema_changed or model_changed: + schema_hash = get_hash(new_schema) + model_hash = get_hash(new_model) + + issue = get_existing_issue(schema_hash, model_hash) + + if not issue: + issue = GH_REPO.create_issue( + title="Update LSP schema and model", + body=_get_update_issue_body(schema_hash, model_hash), + labels=[LABEL_UPDATE, LABEL_DEBT], + ) + cleanup_stale_issues(schema_hash, model_hash, issue) + print(f"Created issue {issue.url}") + else: + print("No changes detected.") + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..7fdb047 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,238 @@ +name: PR Validation + +on: + pull_request: + +jobs: + build-package: + name: Create PyPI Packages + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python 3.7 + uses: actions/setup-python@v4 + with: + python-version: 3.7 + + - name: Pip cache + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-build-vsix-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip-build-vsix- + + - name: Install nox + run: python -m pip install nox + shell: bash + + - name: Build sdist and wheels + run: python -m nox --session build + shell: bash + + - name: Upload Python Packages to Artifacts + uses: actions/upload-artifact@v3 + with: + name: pypi-packages + path: | + packages/python/dist/*.gz + packages/python/dist/*.whl + if-no-files-found: error + retention-days: 7 + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Pip cache + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-lint-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip-lint- + + - name: Install nox + run: python -m pip install nox + shell: bash + + - name: Check linting and formatting + run: python -m nox --session lint + shell: bash + + - name: Rust Tool Chain setup + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rustfmt + + - name: Rustfmt Check + uses: actions-rust-lang/rustfmt@v1 + with: + manifest-path: packages/rust/lsprotocol/Cargo.toml + + - name: Dotnet Tool Chain setup + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '6.0.x' + + - name: Dotnet Format Check + run: dotnet format packages/dotnet/lsprotocol/lsprotocol.csproj --verify-no-changes + shell: bash + + python-tests: + name: Python Tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + python: ['3.7', '3.8', '3.9', '3.10', '3.11'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python ${{ matrix.python }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + - name: Update pip, install wheel and nox + run: python -m pip install -U pip wheel nox + shell: bash + + - name: Run tests + run: python -m nox --session tests + shell: bash + + dotnet-tests: + name: Dotnet Tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Dotnet Tool Chain setup + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '6.0.x' + + - name: Install Generator + run: python -m pip install -r ./requirements.txt + + - name: Generate Test Data + run: python -m generator --plugin testdata + + - name: Generate C# Code + run: python -m generator --plugin dotnet + + - name: Dotnet Build Tests + run: dotnet build tests/dotnet/lsprotocol_tests/lsprotocol_tests.csproj + shell: bash + + - name: Dotnet Run Tests + run: dotnet test tests/dotnet/lsprotocol_tests/lsprotocol_tests.csproj + shell: bash + env: + LSP_TEST_DATA_PATH: ${{ github.workspace }}/packages/testdata + + dotnet-project: + name: Dotnet Project + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Generator + run: python -m pip install -r ./requirements.txt + + - name: Generate C# Code + run: python -m generator --plugin dotnet + + - name: Format generated code + run: dotnet format packages/dotnet/lsprotocol/lsprotocol.csproj + shell: bash + + - name: Upload Dotnet Project to Artifacts + uses: actions/upload-artifact@v3 + with: + name: dotnet-project + path: | + packages/dotnet/lsprotocol/*.csproj + packages/dotnet/lsprotocol/*.cs + if-no-files-found: error + retention-days: 7 + + smoke-tests: + name: Smoke Tests (pygls) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + python: ['3.7', '3.8', '3.9', '3.10', '3.11'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Checkout Pygls + uses: actions/checkout@v4 + with: + repository: openlawlibrary/pygls + path: smoke_tests + + - name: Use Python ${{ matrix.python }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + - name: Update pip, install wheel + run: python -m pip install -U pip wheel + shell: bash + + - name: Install pip pygls dependencies + run: python -m pip install typeguard mock pytest pytest-asyncio + shell: bash + + - name: Install pip lsprotocol dependencies + run: python -m pip install -r ./packages/python/requirements.txt + shell: bash + + - name: Install pygls + run: python -m pip install --no-deps ./smoke_tests + shell: bash + + - name: Pip List + run: python -m pip list + shell: bash + + - name: Run Tests + run: python -m pytest smoke_tests/tests + env: + PYTHONPATH: ./packages/python + shell: bash diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml new file mode 100644 index 0000000..0bc6130 --- /dev/null +++ b/.github/workflows/pr-labels.yml @@ -0,0 +1,21 @@ +name: "PR labels" +on: + pull_request: + types: + - "opened" + - "reopened" + - "labeled" + - "unlabeled" + - "synchronize" + +jobs: + add-pr-label: + name: "Ensure Required Labels" + runs-on: ubuntu-latest + steps: + - name: "PR impact specified" + uses: mheap/github-action-required-labels@v5 + with: + mode: exactly + count: 1 + labels: "bug, debt, feature-request, no-changelog" diff --git a/.github/workflows/push-check.yml b/.github/workflows/push-check.yml new file mode 100644 index 0000000..091402e --- /dev/null +++ b/.github/workflows/push-check.yml @@ -0,0 +1,189 @@ +name: Push Validation + +on: + push: + branches: + - 'main' + - 'release' + - 'release/*' + - 'release-*' + +jobs: + build-package: + name: Create PyPI Packages + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python 3.7 + uses: actions/setup-python@v4 + with: + python-version: 3.7 + + - name: Pip cache + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-build-vsix-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip-build-vsix- + + - name: Install nox + run: python -m pip install nox + shell: bash + + - name: Build sdist and wheels + run: python -m nox --session build + shell: bash + + - name: Upload Python Packages to Artifacts + uses: actions/upload-artifact@v3 + with: + name: pypi-packages + path: | + packages/python/dist/*.gz + packages/python/dist/*.whl + if-no-files-found: error + retention-days: 7 + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Pip cache + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-lint-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip-lint- + + - name: Install nox + run: python -m pip install nox + shell: bash + + - name: Check linting and formatting + run: python -m nox --session lint + shell: bash + + - name: Rust Tool Chain setup + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + components: rustfmt + + - name: Rustfmt Check + uses: actions-rust-lang/rustfmt@v1 + with: + manifest-path: packages/rust/lsprotocol/Cargo.toml + + - name: Dotnet Tool Chain setup + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '6.0.x' + + - name: Dotnet Format Check + run: dotnet format packages/dotnet/lsprotocol/lsprotocol.csproj --verify-no-changes + shell: bash + + python-tests: + name: Python Tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + python: ['3.7', '3.8', '3.9', '3.10', '3.11'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python ${{ matrix.python }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + - name: Update pip, install wheel and nox + run: python -m pip install -U pip wheel nox + shell: bash + + - name: Run tests + run: python -m nox --session tests + shell: bash + + dotnet-tests: + name: Dotnet Tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Dotnet Tool Chain setup + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '6.0.x' + + - name: Install Generator + run: python -m pip install -r ./requirements.txt + + - name: Generate Test Data + run: python -m generator --plugin testdata + + - name: Generate C# Code + run: python -m generator --plugin dotnet + + - name: Dotnet Run Tests + run: dotnet test tests/dotnet/lsprotocol_tests/lsprotocol_tests.csproj + shell: bash + env: + LSP_TEST_DATA_PATH: ${{ github.workspace }}/packages/testdata + + dotnet-project: + name: Dotnet Project + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Generator + run: python -m pip install -r ./requirements.txt + + - name: Generate C# Code + run: python -m generator --plugin dotnet + + - name: Format generated code + run: dotnet format packages/dotnet/lsprotocol/lsprotocol.csproj + shell: bash + + - name: Upload Dotnet Project to Artifacts + uses: actions/upload-artifact@v3 + with: + name: dotnet-project + path: | + packages/dotnet/lsprotocol/*.csproj + packages/dotnet/lsprotocol/*.cs + if-no-files-found: error + retention-days: 7 diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml new file mode 100644 index 0000000..f43b22a --- /dev/null +++ b/.github/workflows/updater.yml @@ -0,0 +1,30 @@ +name: LSP Update check + +on: + schedule: + - cron: '0 10 * * 1-5' # 10AM UTC (2AM PDT) MON-FRI + +jobs: + update-lsp: + name: Check for LSP update and create issue + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Update pip, install wheel and nox + run: python -m pip install -U pip wheel nox PyGithub + shell: bash + + - name: Run Checker + run: python ./.github/workflows/lsp_updater.py + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml new file mode 100644 index 0000000..628ac66 --- /dev/null +++ b/.github/workflows/version-check.yml @@ -0,0 +1,21 @@ +name: Version Check + +on: + pull_request: + +jobs: + version-check: + name: Ensure Version is as expected + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python 3.x + uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: Version Check + run: python ./.github/workflows/version_check.py + shell: bash diff --git a/.github/workflows/version_check.py b/.github/workflows/version_check.py new file mode 100644 index 0000000..c9b3e54 --- /dev/null +++ b/.github/workflows/version_check.py @@ -0,0 +1,27 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + + +import datetime +import pathlib +import sys + +pyproject = ( + pathlib.Path(__file__).parent.parent.parent + / "packages" + / "python" + / "pyproject.toml" +) + +content = pyproject.read_text(encoding="utf-8") + +for line in content.splitlines(): + if line.startswith("version"): + version = line.split("=")[1].strip().strip('"') + year, minor, micro = version.split(".") + today = datetime.date.today() + if int(year) != today.year: + print(f"Version {version} year should be {today.year}") + sys.exit(1) + +print("Version check passed") |