diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..abd2e58 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + - package-ecosystem: pip + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index c0eb8e2..4b2fa22 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -1,18 +1,28 @@ name: Python application -on: [push] +on: + push: + branches: [master] + pull_request: + +permissions: + contents: read jobs: build: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - - uses: actions/checkout@v1 - - name: Set up Python 3.7 - uses: actions/setup-python@v1 + - uses: actions/checkout@v5 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 with: - python-version: 3.7 + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip @@ -28,3 +38,11 @@ jobs: run: | pip install pytest pytest -v test.py + + # Single stable check name for the branch ruleset, independent of the matrix + ci-ok: + if: always() + needs: build + runs-on: ubuntu-latest + steps: + - run: test "${{ needs.build.result }}" = success diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 21f2f01..c693117 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -4,23 +4,24 @@ on: release: types: [created] +permissions: + contents: read + jobs: deploy: runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write # PyPI Trusted Publishing steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v6 with: python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + - name: Build run: | - python setup.py sdist bdist_wheel - twine upload dist/* + python -m pip install --upgrade pip build + python -m build + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/CLAUDE.md b/CLAUDE.md index 11e66c0..238ce04 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,15 +13,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Code -- Target modern Python 3. Py2-isms (`from __future__`, `super(Cls, self)`) may be modernized; CI's pinned Python 3.7 is outdated. +- Target modern Python 3 (CI matrix: 3.10–3.14). Py2-isms (`from __future__`, `super(Cls, self)`) may be modernized. +- master is protected by a ruleset: changes go through PRs, and the `ci-ok` check (aggregates the matrix) must pass. - The whole extension is a single `Preprocessor` in `md_condition/preprocessor.py`, registered at priority 50. `makeExtension` in `__init__.py` is what lets `md_condition` work as a string name in MkDocs `markdown_extensions`. - Known behaviors to keep in mind (don't change them silently, since they're user-visible): - The symbol is interpolated into a regex unescaped and matched as a substring (`.*DEBUG.*`), so `DEBUG` also matches `#if DEBUG_X`. - Nested `#if` blocks are not supported. `validate` only checks that the counts of `#if` and `#endif` are equal. - Unbalanced blocks raise `AssertionError` from an `assert` statement (stripped under `python -O`). The tests rely on `AssertionError`. -- `test.py`'s `assertExpectedMarkdown` uses `e.message` (Python 2 only), so a failing comparison raises `AttributeError` and hides the diff. Read the raw assertion if a test fails that way. ## Release 1. Bump `version` in `setup.py` and commit. -2. Create a GitHub release with tag `v`. `.github/workflows/pythonpublish.yml` builds and uploads to PyPI (secrets `PYPI_USERNAME`/`PYPI_PASSWORD`). +2. Create a GitHub release with tag `v`. `.github/workflows/pythonpublish.yml` builds and uploads to PyPI via Trusted Publishing (OIDC, GitHub environment `pypi`; no API token secrets). diff --git a/test.py b/test.py index ada611f..5279189 100644 --- a/test.py +++ b/test.py @@ -18,7 +18,7 @@ def assertExpectedMarkdown(self, md_input, expected_output): try: self.assertEqual(output, expected) except AssertionError as e: - raise AssertionError('\n' + re.sub("' != '", '\n!=\n', e.message)) + raise AssertionError('\n' + re.sub("' != '", '\n!=\n', str(e))) def test_single(self): md_input = """\