diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f375b9028..aac2d51f9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,10 +3,10 @@ { "name": "Ubuntu", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - // "image": "mcr.microsoft.com/devcontainers/base:jammy" - "build": { - "dockerfile": "Dockerfile" - }, + "image": "ghcr.io/swyddfa/esbonio-devenv:latest", + // "build": { + // "dockerfile": "Dockerfile" + // }, // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, // Use 'forwardPorts' to make a list of ports inside the container available locally. diff --git a/.github/workflows/vscode-pr.yml b/.github/workflows/vscode-pr.yml index 1b3844683..bb51ddbb4 100644 --- a/.github/workflows/vscode-pr.yml +++ b/.github/workflows/vscode-pr.yml @@ -35,7 +35,7 @@ jobs: - run: | python --version python -m pip install --upgrade pip - python -m pip install --upgrade hatch tox towncrier 'importlib-resources<6' + python -m pip install --upgrade hatch towncrier name: Install Build Tools - run: | @@ -57,10 +57,7 @@ jobs: # Use in-repo version of esbonio for dev builds echo "whl=${ESBONIO_WHL}" - ESBONIO_WHL=${ESBONIO_WHL} tox run -e bundle-deps - - npm ci --prefer-offline - npm run package + ESBONIO=${ESBONIO_WHL} make dist id: assets name: Package Extension diff --git a/.vscode/launch.json b/.vscode/launch.json index 42e8d7c8f..3bd2b184d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -36,10 +36,7 @@ "outFiles": [ "${workspaceRoot}/code/dist/node/**/*.js" ], - // "preLaunchTask": "${defaultBuildTask}", - "env": { - // "VSCODE_LSP_DEBUG": "true" - } + "preLaunchTask": "${defaultBuildTask}", }, { "name": "VSCode Web Extension", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 25fc86497..d0181bd9d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,9 +2,13 @@ "version": "2.0.0", "tasks": [ { - "type": "npm", - "script": "watch", + "label": "npm: watch", + "type": "process", "isBackground": true, + "command": "make", + "args": [ + "watch" + ], "options": { "cwd": "${workspaceRoot}/code" }, @@ -14,17 +18,10 @@ }, "presentation": { "panel": "dedicated", - "reveal": "never" + "reveal": "always" }, "problemMatcher": [ - { - "base": "$tsc-watch", - "background": { - "activeOnStart": true, - "beginsPattern": "asset .*", - "endsPattern": "webpack .* compiled .*" - } - } + "$tsc-watch" ] }, { diff --git a/Makefile b/Makefile index 7f92c86eb..ae64af694 100644 --- a/Makefile +++ b/Makefile @@ -1,53 +1 @@ -.PHONY: preview-completion-docs completion-docs venv npm - -VENV := .env - -ifeq ($(CI),true) - PYTHON=python -endif - -# Default python env. -ifndef PYTHON - PYTHON=$(VENV)/bin/python -endif - -# ---------------------------------------- Development Environments ------------------------------------------- -$(VENV)/bin/python: - python3 -m venv $(VENV) - $@ -m pip install --upgrade pip - $@ -m pip install -r docs/requirements.txt - $@ -m pip install -e lib/esbonio[dev] - $@ -m pip install -e lib/esbonio-extensions[dev] - -venv: $(VENV)/bin/python - -code/node_modules: code/package.json code/package-lock.json - npm --prefix ./code/ install - -npm: code/node_modules - -# ---------------------------------------- Tests, Lints, Tools etc. ------------------------------------------- -mypy: $(PYTHON) - mypy --namespace-packages --explicit-package-bases -p esbonio - -# ---------------------------------------- CompletionItem Documentation --------------------------------------- -DOCUTILS_COMPLETION_DOCS=lib/esbonio/esbonio/lsp/rst/roles.json lib/esbonio/esbonio/lsp/rst/directives.json -SPHINX_COMPLETION_DOCS=lib/esbonio/esbonio/lsp/sphinx/roles.json lib/esbonio/esbonio/lsp/sphinx/directives.json -COMPLETION_DOCS=$(SPHINX_COMPLETION_DOCS) $(DOCUTILS_COMPLETION_DOCS) - -# '&:' Indicates that the multiple targets listed are 'grouped' and that they are produced together from running -# the command below once. This prevents the command being run once for each file produced. -# https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html -# -# '$^' Expands into the list of dependencies of the target (python .... in this case) -# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables -$(DOCUTILS_COMPLETION_DOCS) &: $(PYTHON) scripts/generate_docutils_documentation.py - $^ -o lib/esbonio/esbonio/lsp/rst/ - -$(SPHINX_COMPLETION_DOCS) &: $(PYTHON) scripts/generate_sphinx_documentation.py - $^ -o lib/esbonio/esbonio/lsp/sphinx/ - -completion-docs: $(COMPLETION_DOCS) - -preview-completion-docs: $(COMPLETION_DOCS) - $(PYTHON) scripts/preview_documentation.py $(COMPLETION_DOCS) +include .devcontainer/tools.mk diff --git a/code/Makefile b/code/Makefile new file mode 100644 index 000000000..227255abb --- /dev/null +++ b/code/Makefile @@ -0,0 +1,48 @@ +include ../.devcontainer/tools.mk + +ESBONIO ?= --pre esbonio + +.PHONY: dist dev-deps release-deps release + +watch: dev-deps $(NPM) + -test -d dist && rm -r dist + $(NPM) run watch + +compile: dev-deps $(NPM) + -test -d dist && rm -r dist + $(NPM) run compile + +dist: release-deps $(NPM) + -test -d dist && rm -r dist + $(NPM) run package + +release: $(TOWNCRIER) $(HATCH) $(PY) + $(PY) ../scripts/make_release.py lsp + $(PY) ../scripts/make_release.py vscode + +# Ensures the version of esbonio in ../lib/esbonio is used. +dev-deps: node_modules/.installed bundled/libs/.installed + -test -d bundled/libs/esbonio-*.dist-info && rm -r bundled/libs/esbonio-*.dist-info + -test -L bundled/libs/esbonio || rm -r bundled/libs/esbonio + if [ ! -f bundled/libs/esbonio/__main__.py ]; then \ + test -L bundled/libs/esbonio && rm bundled/libs/esbonio; \ + ln -s $(shell pwd)/../lib/esbonio/esbonio bundled/libs/esbonio; \ + fi + +# Ensures the latest version of esbonio from PyPi is used. +release-deps: node_modules/.installed bundled/libs/.installed + -test -L bundled/libs/esbonio && rm bundled/libs/esbonio + test -d bundled/libs/esbonio-*.dist-info || $(PY38) -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade $(ESBONIO) + +requirements.txt: $(HATCH) requirements.in + $(HATCH) run deps:update + +bundled/libs/.installed: $(PY38) requirements.txt + -test -d bundled/libs && rm -r bundled/libs + $(PY38) --version + $(PY38) -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade -r ./requirements.txt + touch $@ + +node_modules/.installed: package.json package-lock.json $(NPM) + $(NPM) ci + touch $@ diff --git a/code/hatch.toml b/code/hatch.toml new file mode 100644 index 000000000..df070ec3e --- /dev/null +++ b/code/hatch.toml @@ -0,0 +1,10 @@ +[envs.deps] +python = "3.8" +dependencies = ["pip-tools"] +skip-install = true + +[envs.deps.scripts] +update = [ + "python --version", + "pip-compile --resolver=backtracking --generate-hashes --upgrade requirements.in", +] diff --git a/code/requirements.txt b/code/requirements.txt index 58212da99..605a5505f 100644 --- a/code/requirements.txt +++ b/code/requirements.txt @@ -2,21 +2,21 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --generate-hashes ./requirements.in +# pip-compile --generate-hashes requirements.in # aiosqlite==0.20.0 \ --hash=sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6 \ --hash=sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7 # via -r requirements.in -attrs==23.1.0 \ - --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \ - --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015 +attrs==23.2.0 \ + --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ + --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 # via # cattrs # lsprotocol -cattrs==23.2.2 \ - --hash=sha256:66064e2060ea207c5a48d065ab1910c10bb8108c28f3df8d1a7b1aa6b19d191b \ - --hash=sha256:b790b1c2be1ce042611e33f740e343c2593918bbf3c1cc88cdddac4defc09655 +cattrs==23.2.3 \ + --hash=sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108 \ + --hash=sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f # via # lsprotocol # pygls @@ -24,9 +24,9 @@ docutils==0.20.1 \ --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b # via -r requirements.in -exceptiongroup==1.2.0 \ - --hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \ - --hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68 +exceptiongroup==1.2.1 \ + --hash=sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad \ + --hash=sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16 # via cattrs lsprotocol==2023.0.1 \ --hash=sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2 \ @@ -44,9 +44,9 @@ tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f # via -r requirements.in -typing-extensions==4.8.0 \ - --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \ - --hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef +typing-extensions==4.11.0 \ + --hash=sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0 \ + --hash=sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a # via # aiosqlite # cattrs diff --git a/code/tox.ini b/code/tox.ini deleted file mode 100644 index 0296ac9d1..000000000 --- a/code/tox.ini +++ /dev/null @@ -1,23 +0,0 @@ -[tox] -min_version = 4.0 - -[testenv:bundle-deps] -basepython = python3.8 -description = Install dependencies -skip_install = true -commands = - python --version - python -c "import sys; v = sys.version_info; sys.exit(v.major != 3 or v.minor != 8)" - python -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade -r ./requirements.txt - python -m pip install -t ./bundled/libs --no-cache-dir --implementation py --no-deps --upgrade {env:ESBONIO_WHL} - -[testenv:update-deps] -basepython = python3.8 -description = Update bundled dependency versions -skip_install = true -deps = - pip-tools -commands = - python --version - python -c "import sys; v = sys.version_info; sys.exit(v.major != 3 or v.minor != 8)" - pip-compile --resolver=backtracking --generate-hashes --upgrade ./requirements.in diff --git a/lib/esbonio/Makefile b/lib/esbonio/Makefile index 03bcea6f2..358390165 100644 --- a/lib/esbonio/Makefile +++ b/lib/esbonio/Makefile @@ -1,9 +1,9 @@ -PY ?= 310 +include ../../.devcontainer/tools.mk -.PHONY: develop test +.PHONY: dist -develop: - nix develop .#py$(PY) +dist: $(HATCH) + $(HATCH) build -test: - nix develop .#py$(PY) --command pytest +release: $(TOWNCRIER) $(HATCH) $(PY) + $(PY) ../scripts/make_release.py lsp diff --git a/lib/esbonio/hatch.toml b/lib/esbonio/hatch.toml index 079b35675..1b99f1bbf 100644 --- a/lib/esbonio/hatch.toml +++ b/lib/esbonio/hatch.toml @@ -7,3 +7,28 @@ include = ["esbonio", "tests", "CHANGES.rst"] [build.targets.wheel] packages = ["esbonio"] + +[envs.unit] +dependencies = ["pytest", "pytest-cov", "pytest-lsp>=0.3.1,<1"] + +[[envs.unit.matrix]] +python = ["3.8", "3.9", "3.10", "3.11", "3.12"] + +[envs.unit.scripts] +test = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=esbonio.server tests/server" + +[envs.e2e] +template = "unit" +extra-dependencies = [ + "furo", + "sphinx-design", + "myst-parser", + "sphinx~={matrix:sphinx}.0", +] + +[[envs.e2e.matrix]] +python = ["3.8", "3.9", "3.10", "3.11", "3.12"] +sphinx = ["5", "6", "7"] + +[envs.e2e.scripts] +test = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=esbonio tests/sphinx-agent tests/e2e" diff --git a/scripts/make_release.py b/scripts/make_release.py index ff7e201a8..c036b6813 100755 --- a/scripts/make_release.py +++ b/scripts/make_release.py @@ -6,6 +6,7 @@ - Commit, tag and push the new version (if it's a release) - Export the tag name and release date for use later on in the pipeline. """ + import argparse import io import json @@ -27,6 +28,8 @@ ENV = os.environ.get("GITHUB_ENV", "") STEP_SUMMARY = os.environ.get("GITHUB_STEP_SUMMARY", "") +REPO = pathlib.Path(__file__).parent.parent.resolve() + class Output: """An output destination that can be logged to. @@ -78,7 +81,7 @@ class Component(TypedDict): """The prefix to give to version bump commit messages for this component.""" src: str - """The directory containing the component, relative to repo root.""" + """The directory containing the component.""" tag_prefix: str """The prefix to give to tagged versions of this component.""" @@ -93,7 +96,7 @@ class Component(TypedDict): bump_minor="minor", bump_patch="patch", commit_prefix="Esbonio Extensions Release v", - src="lib/esbonio-extensions", + src=str(REPO / "lib/esbonio-extensions"), tag_prefix="esbonio-extensions-v", ), Component( @@ -103,7 +106,7 @@ class Component(TypedDict): bump_minor="b", bump_patch="b", commit_prefix="Esbonio Language Server Release v", - src="lib/esbonio", + src=str(REPO / "lib/esbonio"), tag_prefix="esbonio-language-server-v", ), Component( @@ -113,7 +116,7 @@ class Component(TypedDict): bump_minor="minor", bump_patch="patch", commit_prefix="Esbonio VSCode Extension Release v", - src="code", + src=str(REPO / "code"), tag_prefix="esbonio-vscode-extension-v", ), ]