Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ci): add script and workflow for auto-updating schema #286

Merged
merged 6 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Update schema in Dependabot PR

on:
pull_request:
branches:
- master

permissions:
pull-requests: write
repository-projects: write

jobs:
update_schema:
name: Run schema update
runs-on: ubuntu-latest

if: github.actor == 'dependabot[bot]'
steps:
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use v5

with:
python-version: 3.11

- name: Update schema
id: update-schema
run: |
echo "::set-output name=UPDATE_OUTPUT::$(make update-schema)"

- name: Check for modified files
id: git-check
run: echo ::set-output name=modified::$(if [ -n "$(git status --porcelain)" ]; then echo "true"; else echo "false"; fi)

- name: Update changes in the PR
if: steps.git-check.outputs.modified == 'true'
run: |
git config --global user.name 'workflow'
git config --global user.email '[email protected]'
git add -A
git commit -m '[automated commit] update schema'
git push

- name: Find Comment
uses: peter-evans/find-comment@v2
id: find-comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: Build output

- name: Create or update comment
uses: peter-evans/create-or-update-comment@v3
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
schema-update output:
${{ steps.update-schema.outputs.UPDATE_OUTPUT }}
edit-mode: replace
11 changes: 1 addition & 10 deletions LSP-pyright.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@
// Specifies the level of logging for the Output panel
"python.analysis.logLevel": "Information",
// Defines the default rule set for type checking.
"python.analysis.typeCheckingMode": "basic",
"python.analysis.typeCheckingMode": "standard",
// Paths to look for typeshed modules.
// Hmm... doesn't seem to work on my side. May track https://github.com/microsoft/pylance-release/issues/29
"python.analysis.typeshedPaths": [],
// Use library implementations to extract type information when type stub is not present.
"python.analysis.useLibraryCodeForTypes": true,
Expand All @@ -58,13 +57,5 @@
// Path to folder with a list of Virtual Environments.
"python.venvPath": "",
},
// ST4
"selector": "source.python",
// ST3
"languages": [
{
"scopes": ["source.python - source.python.lsp"],
"syntaxes": ["Packages/Python/Python.sublime-syntax"],
},
],
}
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ fix:
autoflake --in-place .
black --preview .
isort .

.PHONY: update-schema
update-schema:
python3 ./scripts/update_schema.py
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ skip_glob = [
"branch-*/**",
"libs/**",
"resources/**",
"scripts/**",
"stubs/**",
"typings/**",
"vendor/**",
Expand All @@ -20,7 +21,7 @@ skip_glob = [
quiet = true
recursive = true
remove-all-unused-imports = true
exclude = '\.git,\.?venv(-.*)?,\.mypy_cache,br-.*,branch-.*,libs,stubs,tests/files,typings'
exclude = '\.git,\.?venv(-.*)?,\.mypy_cache,br-.*,branch-.*,libs,scripts,stubs,tests/files,typings'

[tool.black]
preview = true # use latest feature
Expand All @@ -33,6 +34,7 @@ exclude = '''
language-server |
plugin/libs |
resources |
scripts |
stubs |
typings |
_resources
Expand Down
103 changes: 103 additions & 0 deletions scripts/update_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from json import dump, dumps, load
from typing import Any, Dict, List, Optional, Tuple
from urllib.request import urlopen
import os

DIRNAME = os.path.dirname(os.path.abspath(__file__))
PYRIGHTCONFIG_SCHEMA_ID = 'sublime://pyrightconfig'
PYRIGHT_CONFIGURATION_SCHEMA_URL = 'https://raw.githubusercontent.com/microsoft/pyright/main/packages/vscode-pyright/schemas/pyrightconfig.schema.json' # noqa: E501
SUBLIME_PACKAGE_JSON_PATH = os.path.join(DIRNAME, '..', 'sublime-package.json')
# Keys that are in the pyrightconfig.json schema but should not raise a comment when not present in the LSP schema.
IGNORED_PYRIGHTCONFIG_KEYS = [
'defineConstant',
'exclude',
'executionEnvironments',
'ignore',
'include',
'pythonPlatform',
'pythonVersion',
'strict',
'typeshedPath',
'venv',
'verboseOutput',
]

JSON = Dict[str, Any]


def main() -> None:
pyrightconfig_schema_json, sublime_package_schema_json = read_sublime_package_json()
before = dumps(sublime_package_schema_json)
new_schema_keys = update_schema(sublime_package_schema_json, pyrightconfig_schema_json)
after = dumps(sublime_package_schema_json)
if before != after:
with open(SUBLIME_PACKAGE_JSON_PATH, 'w', encoding='utf-8') as f:
dump(sublime_package_schema_json, f, indent=2)
print('sublime-package.json schema updated.')
else:
print('No updates done to sublime-package.json.')
if new_schema_keys:
print('\nThe following new keys were found in the latest pyrightconfig.json schema: {}\n\n'.format(
'\n - '.join(new_schema_keys)))
print('Ensure that those are added to the sublime-package.json manually, if relevant.')


def read_sublime_package_json() -> Tuple[JSON, JSON]:
with urlopen(PYRIGHT_CONFIGURATION_SCHEMA_URL) as response:
pyrightconfig_schema_json = load(response)
with open(SUBLIME_PACKAGE_JSON_PATH, 'r', encoding='utf-8') as f:
sublime_package_schema_json = load(f)
return (pyrightconfig_schema_json, sublime_package_schema_json)


def update_schema(sublime_package_json: JSON, pyrightconfig_schema_json: JSON) -> List[str]:
pyrightconfig_contribution: Optional[JSON] = None
lsp_pyright_contribution: Optional[JSON] = None
for contribution in sublime_package_json['contributions']['settings']:
if '/pyrightconfig.json' in contribution['file_patterns']:
pyrightconfig_contribution = contribution
elif '/LSP-pyright.sublime-settings' in contribution['file_patterns']:
lsp_pyright_contribution = contribution
if not pyrightconfig_contribution or not lsp_pyright_contribution:
raise Exception('Expected contributions not found in sublime-package.json!')
# Update to latest pyrightconfig schema.
pyrightconfig_contribution['schema'] = pyrightconfig_schema_json
# Add ID.
pyrightconfig_contribution['schema']['$id'] = PYRIGHTCONFIG_SCHEMA_ID
# Update LSP settings to reference options from the pyrightconfig schema.
settings_properties: JSON = lsp_pyright_contribution['schema']['definitions']['PluginConfig']['properties']['settings']['properties'] # noqa: E501
pyrightconfig_properties: JSON = pyrightconfig_contribution['schema']['properties']
for setting_key, setting_value in settings_properties.items():
# get last dotted component.
last_component_key = setting_key.split('.').pop()
if last_component_key in pyrightconfig_properties:
update_property_ref(last_component_key, setting_value, pyrightconfig_properties)
if setting_key == 'python.analysis.diagnosticSeverityOverrides':
overrides_properties: JSON = setting_value['properties']
for override_key, override_value in overrides_properties.items():
if override_key in pyrightconfig_properties:
update_property_ref(override_key, override_value, pyrightconfig_properties)
else:
del overrides_properties[override_key]
# Check if there are any properties that might need to be added to the LSP properties.
# If the property is neither in `diagnosticSeverityOverrides`, the root LSP settings nor in ignored keys
# then it might have to be added manually.
all_settings_keys = list(map(lambda k: k.split('.').pop(), settings_properties.keys()))
all_overrides_keys = settings_properties['python.analysis.diagnosticSeverityOverrides']['properties'].keys()
new_schema_keys = []
for pyrightconfig_key in pyrightconfig_properties.keys():
if pyrightconfig_key not in all_settings_keys \
and pyrightconfig_key not in all_overrides_keys \
and pyrightconfig_key not in IGNORED_PYRIGHTCONFIG_KEYS:
new_schema_keys.append(pyrightconfig_key)
return new_schema_keys


def update_property_ref(property_key: str, property_schema: JSON, pyrightconfig_properties: JSON) -> None:
property_schema.clear()
pyrightconfig_property_id: str = pyrightconfig_properties[property_key]['$id']
property_schema['$ref'] = PYRIGHTCONFIG_SCHEMA_ID + pyrightconfig_property_id


if __name__ == '__main__':
main()
Loading