From e51e171bf1b4f0eb5b98bf2ba799e02234e20308 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:47:01 +0200 Subject: [PATCH 01/11] pelican: install lint deps from pyproject.toml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lint job tried `pip install -r requirements.txt --no-deps` but pelican no longer has a requirements.txt — it ships a PEP 621 pyproject.toml. Replace the missing-file install with `pip install ./pelican`, which picks up the runtime dependencies declared in pelican/pyproject.toml. The mypy / pylint type-stub install line is unchanged; those tools are still needed on top of the runtime deps for the type-checking and pylint steps. --- .github/workflows/linting.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 84be4718..2bae6b12 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -45,8 +45,9 @@ jobs: - name: Install dependencies run: | pip list - cd pelican - pip install -r requirements.txt --no-deps # Explicit dependency-only installation + # Install pelican action runtime deps declared in pelican/pyproject.toml + # (replaces the old `pip install -r requirements.txt --no-deps` flow). + pip install ./pelican pip install mypy types-PyYAML types-requests types-beautifulsoup4 types-markdown pylint pip list From 7998f826c65e042071aa416156143523028e199a Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:50:58 +0200 Subject: [PATCH 02/11] pelican: drive lint workflow via `uv sync` and dev group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move mypy, pylint and the types-* stubs into `pelican/pyproject.toml`'s PEP 735 `dev` dependency group so they are declared alongside ruff / pytest rather than hard-coded in the workflow. In `.github/workflows/linting.yml`, set up uv via `astral-sh/setup-uv` (pinned to the same SHA used elsewhere in the repo) and replace the `pip install ./pelican` flow with: cd pelican uv sync --no-install-project --group dev `--no-install-project` drops installing `apache-pelican-action` itself — we only need the runtime deps plus the dev group. mypy and pylint then run via `uv run --no-sync` so `uv run` does not implicitly rebuild and install the project before the check. Locally verified with `uv sync --no-install-project --group dev` followed by `uv run --no-sync mypy` and `uv run --no-sync pylint` against a clean copy of pelican/ — both pass and `apache-pelican-action` is absent from the resulting venv. --- .github/workflows/linting.yml | 25 +++++++++++++++---------- pelican/pyproject.toml | 10 +++++++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 2bae6b12..ecf263e7 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -42,22 +42,27 @@ jobs: with: python-version: '3.11' - - name: Install dependencies + - name: Set up uv + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 + + - name: Install lint / mypy dependencies run: | - pip list - # Install pelican action runtime deps declared in pelican/pyproject.toml - # (replaces the old `pip install -r requirements.txt --no-deps` flow). - pip install ./pelican - pip install mypy types-PyYAML types-requests types-beautifulsoup4 types-markdown pylint - pip list + # `--no-install-project` skips building `apache-pelican-action` + # itself; we only need the runtime dependencies plus the `dev` + # group (mypy, pylint and type stubs) to run the checks below. + cd pelican + uv sync --no-install-project --group dev + uv pip list - name: Type testing with mypy run: | cd pelican - mypy --cache-dir /tmp/ --install-types --non-interactive - mypy --cache-dir /tmp/ --ignore-missing-imports . + # `--no-sync` stops `uv run` from implicitly building and + # installing `apache-pelican-action` into the venv before it + # runs mypy — we only want the deps from the previous step. + uv run --no-sync mypy --cache-dir /tmp/ --ignore-missing-imports . - name: Code linting with pylint run: | cd pelican - pylint **/*.py + uv run --no-sync pylint **/*.py diff --git a/pelican/pyproject.toml b/pelican/pyproject.toml index 2b5e6002..9b34404d 100644 --- a/pelican/pyproject.toml +++ b/pelican/pyproject.toml @@ -62,12 +62,20 @@ dependencies = [ # but the runtime install does not: Pelican itself (installed by the action # at runtime via `uv tool install 'pelican[markdown]=='`, with the # version controlled by the action's `version` input rather than this file), -# plus linting and test tooling. +# plus linting, type-checking and test tooling. The `Linting and MyPy +# (Pelican)` workflow syncs this group via `uv sync --no-install-project` +# and runs mypy / pylint out of the resulting venv. [dependency-groups] dev = [ "pelican[markdown]>=4.11,<4.12", "ruff>=0.6", "pytest>=8", + "mypy>=1.10", + "pylint>=3", + "types-PyYAML", + "types-requests", + "types-beautifulsoup4", + "types-markdown", ] [project.urls] From 16f5ca09818ae0233c74c2d9921d90a276c9ef2b Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:52:44 +0200 Subject: [PATCH 03/11] pelican: collapse lint install step into `uv run` `uv run` implicitly creates the venv, installs the project's runtime dependencies and the default `dev` group on its first invocation, so the separate `uv sync --no-install-project --group dev` step is redundant. Drop that step and call `uv run mypy` / `uv run pylint` directly. Subsequent `uv run` calls reuse the same venv. --- .github/workflows/linting.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index ecf263e7..71c67ade 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -45,24 +45,12 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 - - name: Install lint / mypy dependencies - run: | - # `--no-install-project` skips building `apache-pelican-action` - # itself; we only need the runtime dependencies plus the `dev` - # group (mypy, pylint and type stubs) to run the checks below. - cd pelican - uv sync --no-install-project --group dev - uv pip list - - name: Type testing with mypy run: | cd pelican - # `--no-sync` stops `uv run` from implicitly building and - # installing `apache-pelican-action` into the venv before it - # runs mypy — we only want the deps from the previous step. - uv run --no-sync mypy --cache-dir /tmp/ --ignore-missing-imports . + uv run mypy --cache-dir /tmp/ --ignore-missing-imports . - name: Code linting with pylint run: | cd pelican - uv run --no-sync pylint **/*.py + uv run pylint **/*.py From 8bda72dfe74ff8d65a0d355ab8f25d98652c03d2 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:53:38 +0200 Subject: [PATCH 04/11] pelican: enable uv cache in lint workflow Turn on `astral-sh/setup-uv`'s built-in CI cache and key it on `pelican/uv.lock`. With the cache enabled, the implicit sync that `uv run` performs on first invocation restores from cache instead of redownloading the runtime deps and the `dev` group on every run. --- .github/workflows/linting.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 71c67ade..11279cb3 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -44,6 +44,9 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 + with: + enable-cache: true + cache-dependency-glob: "pelican/uv.lock" - name: Type testing with mypy run: | From b14f98bfe178a333ddecedcf97ace48ab8a9c9bb Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:54:24 +0200 Subject: [PATCH 05/11] pelican: drop mypy --cache-dir override in lint workflow --- .github/workflows/linting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 11279cb3..66ec1c38 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -51,7 +51,7 @@ jobs: - name: Type testing with mypy run: | cd pelican - uv run mypy --cache-dir /tmp/ --ignore-missing-imports . + uv run mypy --ignore-missing-imports . - name: Code linting with pylint run: | From 085fd6393858be18dd22372c7fce8587565957a4 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:55:17 +0200 Subject: [PATCH 06/11] pelican: set pelican/ as default working-directory for lint job Hoist the `cd pelican` from each run step into a job-level `defaults.run.working-directory: pelican`. Every `run:` step now executes from pelican/; `uses:` steps are unaffected, so setup-uv's `cache-dependency-glob` still resolves `pelican/uv.lock` from the repository root. --- .github/workflows/linting.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 66ec1c38..7e3db84a 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -32,6 +32,12 @@ permissions: jobs: lint: runs-on: ubuntu-latest + defaults: + run: + # Applies to every `run:` step in this job; `uses:` steps are + # unaffected, so setup-uv's `cache-dependency-glob` below still + # resolves from the repository root. + working-directory: pelican steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -49,11 +55,7 @@ jobs: cache-dependency-glob: "pelican/uv.lock" - name: Type testing with mypy - run: | - cd pelican - uv run mypy --ignore-missing-imports . + run: uv run mypy --ignore-missing-imports . - name: Code linting with pylint - run: | - cd pelican - uv run pylint **/*.py + run: uv run pylint **/*.py From b86a85b4fc20ff37ba28684065871e09508fb46f Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:55:40 +0200 Subject: [PATCH 07/11] pelican: rename lint job to lint-pelican --- .github/workflows/linting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 7e3db84a..f96dcd2a 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -30,7 +30,7 @@ permissions: contents: read jobs: - lint: + lint-pelican: runs-on: ubuntu-latest defaults: run: From e0ad0069fd3d0e9546092762613e444c8ade8de4 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:57:12 +0200 Subject: [PATCH 08/11] pelican: pin minimum versions on types-* dev dependencies Add `>=` floors to the four `types-*` stub packages in the `dev` dependency group so every entry in pelican/pyproject.toml has an explicit minimum version (matching the style of the rest of the project and dev dependencies): types-PyYAML>=6.0 types-requests>=2.33 types-beautifulsoup4>=4.12 types-markdown>=3.10 Floors track the runtime deps the stubs cover. `uv lock` still resolves to the same concrete versions. --- pelican/pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pelican/pyproject.toml b/pelican/pyproject.toml index 9b34404d..12c34fa6 100644 --- a/pelican/pyproject.toml +++ b/pelican/pyproject.toml @@ -72,10 +72,10 @@ dev = [ "pytest>=8", "mypy>=1.10", "pylint>=3", - "types-PyYAML", - "types-requests", - "types-beautifulsoup4", - "types-markdown", + "types-PyYAML>=6.0", + "types-requests>=2.33", + "types-beautifulsoup4>=4.12", + "types-markdown>=3.10", ] [project.urls] From 4a254f4d8d68bd549f88394043c479e64c3cf8aa Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 00:58:49 +0200 Subject: [PATCH 09/11] pelican: alphabetize imports in plugin_paths.py to retrigger lint --- pelican/plugin_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/plugin_paths.py b/pelican/plugin_paths.py index a9dd830f..b5b9b958 100755 --- a/pelican/plugin_paths.py +++ b/pelican/plugin_paths.py @@ -32,8 +32,8 @@ """ -import sys import json +import sys DEFAULT_PELCONF = 'pelicanconf.py' # in current dir From 7c1762f0baa83d3290b3cc19e268c5502c5fd97e Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 01:00:16 +0200 Subject: [PATCH 10/11] pelican: drop unrecognized suggestion-mode from pylintrc Recent pylint versions no longer recognize `suggestion-mode=yes` and emit `E0015: Unrecognized option found: suggestion-mode` at the top of every run. Remove the option (and its now-orphaned comment) so pylint output is clean. --- pelican/pylintrc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pelican/pylintrc b/pelican/pylintrc index fb17ac18..d1bfb293 100644 --- a/pelican/pylintrc +++ b/pelican/pylintrc @@ -72,10 +72,6 @@ persistent=yes # the version used to run pylint. py-version=3.10 -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages. -suggestion-mode=yes - # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no From 0be6156f5b337b518380dbef4814c2520e55d4fd Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Wed, 15 Apr 2026 01:01:39 +0200 Subject: [PATCH 11/11] pelican: force colorized mypy / pylint output in lint job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub Actions log output is not a TTY, so mypy and pylint autodetect that and emit plain text. Force colors on via both env vars (`FORCE_COLOR=1`, `PY_COLORS=1` — the common conventions honored by pylint, rich, uv etc.) and the explicit per-tool flags: mypy gets `--color-output --pretty`, pylint gets `--output-format=colorized`. GitHub's log viewer renders ANSI color escapes, so the output is readable and much easier to scan. --- .github/workflows/linting.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index f96dcd2a..8a87408d 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -32,6 +32,16 @@ permissions: jobs: lint-pelican: runs-on: ubuntu-latest + # GitHub Actions log output is not a TTY, so tools that autodetect + # colors turn them off in CI. Force colorized output via the common + # `FORCE_COLOR` convention (honored by pylint, rich, uv, etc.) plus + # `PY_COLORS=1` which mypy's `rich`-based pretty printer picks up. + # The per-tool flags below (`--output-format=colorized`, + # `--color-output`) make the intent explicit and work even for + # tools that don't read the env vars. + env: + FORCE_COLOR: "1" + PY_COLORS: "1" defaults: run: # Applies to every `run:` step in this job; `uses:` steps are @@ -55,7 +65,7 @@ jobs: cache-dependency-glob: "pelican/uv.lock" - name: Type testing with mypy - run: uv run mypy --ignore-missing-imports . + run: uv run mypy --color-output --pretty --ignore-missing-imports . - name: Code linting with pylint - run: uv run pylint **/*.py + run: uv run pylint --output-format=colorized **/*.py