diff --git a/.cspell.json b/.cspell.json index d1f4ffc..9234f7d 100644 --- a/.cspell.json +++ b/.cspell.json @@ -49,6 +49,7 @@ "noreply", "numprocesses", "pyright", + "rtoml", "taplo", "tomllib" ], diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 3bff1e1..ef498be 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -19,6 +19,7 @@ on: env: DISABLE_PRE_COMMIT_UV_PATCH: True + FORCE_COLOR: true jobs: determine-hooks: @@ -51,10 +52,6 @@ jobs: **/pyproject.toml **/uv.lock enable-cache: true - - name: Determine if repository is Python package - run: | - uv_command=$(uv pip install -e '.[sty]' > /dev/null && uv sync --group style --no-dev && echo "uv run --group style --no-dev" || echo uvx) - echo "UV_COMMAND=$uv_command" | tee -a "$GITHUB_ENV" - name: Fetch pre-commit cache uses: actions/cache@v4 with: @@ -63,8 +60,10 @@ jobs: restore-keys: | pre-commit-${{ runner.os }}-py${{ inputs.python-version }} path: ~/.cache/pre-commit/ + - id: uv-run + uses: ComPWA/actions/run-pre-commit@v2 - if: needs.determine-hooks.outputs.skipped-hooks == 'ALL' - run: ${{ env.UV_COMMAND }} --with pre-commit-uv pre-commit run --all-files --color always + run: ${{ steps.uv-run.outputs.cmd }} --with pre-commit-uv pre-commit run --all-files - if: needs.determine-hooks.outputs.skipped-hooks != 'ALL' name: Run pre-commit hooks that don't work on pre-commit.ci run: |- @@ -73,7 +72,7 @@ jobs: export PRETTIER_LEGACY_CLI=1 fi for hook in $skipped_hooks; do - ${{ env.UV_COMMAND }} --with pre-commit-uv pre-commit run $hook --all-files --color always + ${{ steps.uv-run.outputs.cmd }} --with pre-commit-uv pre-commit run $hook --all-files done - id: diff if: always() diff --git a/get-skipped-pre-commit-hooks/action.yml b/get-skipped-pre-commit-hooks/action.yml index 12c78fd..a9c7121 100644 --- a/get-skipped-pre-commit-hooks/action.yml +++ b/get-skipped-pre-commit-hooks/action.yml @@ -15,6 +15,8 @@ runs: using: composite steps: - uses: actions/checkout@v4 + with: + sparse-checkout: .pre-commit-config.yaml - uses: actions/setup-python@v5 with: python-version: "3.12" diff --git a/pyproject.toml b/pyproject.toml index b2f46cb..d607522 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,8 +15,15 @@ content-type = "text/markdown" file = "README.md" [dependency-groups] -dev = ["ruff"] -style = ["packaging"] +dev = [ + "ruff", + {include-group = "style"}, +] +style = [ + "PyYAML", + "packaging", + "rtoml", +] [tool.setuptools] include-package-data = false @@ -32,6 +39,8 @@ reportUnknownMemberType = false reportUnknownParameterType = false reportUnknownVariableType = false typeCheckingMode = "strict" +venv = ".venv" +venvPath = "." [tool.ruff] preview = true diff --git a/run-pre-commit/action.yml b/run-pre-commit/action.yml new file mode 100644 index 0000000..657ae22 --- /dev/null +++ b/run-pre-commit/action.yml @@ -0,0 +1,19 @@ +name: Run pre-commit hooks with style environment +description: >- + Run local pre-commit hooks that may require the installation of a virtual environment. + +outputs: + cmd: + description: >- + The uv run command to use for `pre-commit` + value: ${{ steps.uv-run.outputs.cmd }} + +runs: + using: composite + steps: + - env: + UV_SYSTEM_PYTHON: 1 + id: uv-run + name: Determine skipped hooks + run: echo "cmd=$(uv run -p3.12 $GITHUB_ACTION_PATH/main.py)" | tee -a $GITHUB_OUTPUT + shell: bash diff --git a/run-pre-commit/main.py b/run-pre-commit/main.py new file mode 100644 index 0000000..e76918e --- /dev/null +++ b/run-pre-commit/main.py @@ -0,0 +1,42 @@ +"""Determine which pre-commit hooks should be skipped.""" + +# /// script +# dependencies = ["rtoml"] +# /// +from pathlib import Path + +import rtoml + + +def main() -> None: + cmd = _get_uv_run_command() + print(cmd) + + +def _get_uv_run_command() -> str: + pyproject_path = Path("pyproject.toml") + if pyproject_path.is_file(): + pyproject = rtoml.load(pyproject_path) + dependency_groups = pyproject.get("dependency-groups") + candidate_groups = [ + "style", + "sty", + "lint", + ] + if dependency_groups is not None: + for group in candidate_groups: + if group in dependency_groups: + return f"uv run --group {group} --no-dev" + project_table = pyproject.get("project", {}) + extras = project_table.get("optional-dependencies") + if extras is not None: + for extra in candidate_groups: + if extra in extras: + return f"uv run --extra {extra} --no-dev" + if "dependencies" in project_table: + return "uv run --no-dev" + return "uvx" + + +if __name__ == "__main__": + raise SystemExit(main())