Skip to content
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
142 changes: 86 additions & 56 deletions .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
@@ -1,103 +1,133 @@
name: Release & Publish 🚀
name: CI & Release

on:
push:
branches:
- main
branches: [main]
pull_request:
branches: [main]

permissions:
contents: write
id-token: write

jobs:
# ── Run tests and linters on every push / PR ─────────────────────────────
ci:
name: Tests & Lint
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Install dependencies
run: uv sync

- name: Lint
run: uv run ruff check .

- name: Type-check
run: uv run mypy

- name: Tests
run: uv run pytest --cov --cov-report=term-missing

# ── Semantic release (main branch only, after CI passes) ─────────────────
release:
name: Semantic Release 📦
name: Semantic Release
needs: ci
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
concurrency: release
concurrency:
group: release
cancel-in-progress: false

outputs:
released: ${{ steps.release.outputs.released }}
version: ${{ steps.release.outputs.version }}
tag: ${{ steps.release.outputs.tag }}

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Python Semantic Release
id: release
uses: python-semantic-release/python-semantic-release@v9.21.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Python Semantic Release
id: release
uses: python-semantic-release/python-semantic-release@v9.21.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

# ── Build the distribution from the released tag ─────────────────────────
build:
name: Build distribution 📦
name: Build distribution
needs: release
if: needs.release.outputs.released == 'true'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.tag }}
fetch-depth: 0

- uses: actions/setup-python@v5
with:
python-version: "3.12"
- uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.tag }}
fetch-depth: 0

- name: Install build dependencies
run: pip install build setuptools-scm
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Build a binary wheel and a source tarball
run: python -m build
- name: Build wheel and sdist
run: uv build

- uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
- uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

# ── Publish to PyPI via trusted publishing ────────────────────────────────
publish-to-pypi:
name: Publish to PyPI 🐍
name: Publish to PyPI
needs: [release, build]
if: needs.release.outputs.released == 'true'
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/cssinj
url: https://pypi.org/p/cssinj/
permissions:
id-token: write

steps:
- uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- uses: pypa/gh-action-pypi-publish@release/v1
- uses: pypa/gh-action-pypi-publish@release/v1

# ── Attach dist files to the GitHub release ──────────────────────────────
github-release:
name: GitHub Release 🏷️
name: GitHub Release
needs: [release, build]
if: needs.release.outputs.released == 'true'
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release.outputs.tag }}
files: dist/*
generate_release_notes: true
- uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release.outputs.tag }}
files: dist/*
generate_release_notes: true
33 changes: 33 additions & 0 deletions .gitlint
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[general]
contrib=contrib-title-conventional-commits,contrib-disallow-cleanup-commits
ignore=body-is-missing,body-min-length
ignore-merge-commits=true
ignore-revert-commits=true
ignore-fixup-commits=true
ignore-squash-commits=true
regex-style-search=true
verbosity=2

[title-max-length]
line-length=72

[title-min-length]
min-length=10

[title-must-not-contain-word]
words=wip,fixme,xxx,todo

[title-match-regex]
regex=^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([\w\-\.\/]+\))?!?: .+$

[body-max-line-length]
line-length=100

[body-min-length]
min-length=0

[body-is-missing]
ignore-merge-commits=true

[contrib-title-conventional-commits]
types=feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert
79 changes: 55 additions & 24 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,41 +1,72 @@
default_language_version:
python: python3.13
default_stages: [pre-commit]

default_install_hook_types: [pre-commit, commit-msg]

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
rev: v5.0.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: ["--maxkb=1000"]
- id: check-json
- id: check-toml
- id: check-added-large-files
- id: check-merge-conflict
- id: check-case-conflict
- id: debug-statements
- id: detect-private-key
- id: mixed-line-ending
args: ["--fix=lf"]
args: [--fix=lf]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
hooks:
- id: mypy
files: ^(cssinj|tests)/
additional_dependencies:
- pydantic
- pydantic-settings
- httpx
- pytest
- types-requests
- types-toml
- types-jsonschema

- repo: https://github.com/adrienverge/yamllint
rev: v1.35.1
hooks:
- id: yamllint
args: [-c=.yamllint.yaml]

- repo: https://github.com/executablebooks/mdformat
rev: 0.7.21
hooks:
- id: mdformat
additional_dependencies:
- mdformat-gfm
- mdformat-frontmatter

- repo: https://github.com/psf/black
rev: 25.9.0
- repo: https://github.com/jorisroovers/gitlint
rev: v0.19.1
hooks:
- id: black
language_version: python3.13
args: ["--line-length=148"]
- id: gitlint
stages: [commit-msg]

- repo: https://github.com/pycqa/isort
rev: 7.0.0
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.5.11
hooks:
- id: isort
args: ["--profile", "black", "--line-length", "148"]
- id: uv-lock

- repo: https://github.com/pycqa/flake8
rev: 7.3.0
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: flake8
args:
[
"--max-line-length=148",
"--extend-ignore=E203,W503,E701",
"--exclude=*/migrations/*,*/settings/*,venv,env",
]
- id: gitleaks
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
22 changes: 22 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"recommendations": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.debugpy",
"ms-python.mypy-type-checker",
"charliermarsh.ruff",
"tamasfe.even-better-toml",
"redhat.vscode-yaml",
"DavidAnson.vscode-markdownlint",
"njpwerner.autodocstring",
"eamodio.gitlens",
"streetsidesoftware.code-spell-checker"
],
"unwantedRecommendations": [
"ms-python.black-formatter",
"ms-python.isort",
"ms-python.flake8",
"ms-python.pylint",
"ms-python.mypy"
]
}
Loading
Loading