From 05a9fa8e592d8d7615c96c56f7458a316a1111f2 Mon Sep 17 00:00:00 2001 From: Richard Abrich Date: Mon, 2 Mar 2026 01:47:03 -0500 Subject: [PATCH] ci: add release automation and CI workflows - Add test.yml workflow (lint + pytest on Python 3.10-3.12) - Add release.yml workflow (python-semantic-release + PyPI publish via OIDC) - Add semantic_release config to pyproject.toml - Add project.urls metadata - Bump version to 0.3.0 to match latest PyPI release Co-Authored-By: Claude Opus 4.6 --- .github/workflows/release.yml | 63 +++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 32 ++++++++++++++++++ pyproject.toml | 21 +++++++++++- src/consilium/__init__.py | 2 +- 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..72dadbb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,63 @@ +name: Release and PyPI Publish + +# Requires ADMIN_TOKEN secret (GitHub PAT with repo scope) to push release +# commits to protected branches. Without it, the tag gets created but the +# version bump commit is rejected by branch protection, orphaning the tag. + +on: + push: + branches: + - main + +jobs: + release: + runs-on: ubuntu-latest + concurrency: release + permissions: + id-token: write + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.ADMIN_TOKEN }} + + - name: Check if should skip + id: check_skip + run: | + if [ "$(git log -1 --pretty=format:'%an')" = "semantic-release" ]; then + echo "skip=true" >> $GITHUB_OUTPUT + fi + + - name: Set up Python + if: steps.check_skip.outputs.skip != 'true' + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install uv + if: steps.check_skip.outputs.skip != 'true' + uses: astral-sh/setup-uv@v4 + + - name: Python Semantic Release + if: steps.check_skip.outputs.skip != 'true' + id: release + uses: python-semantic-release/python-semantic-release@v9.15.2 + with: + github_token: ${{ secrets.ADMIN_TOKEN }} + + - name: Build package + if: steps.check_skip.outputs.skip != 'true' && steps.release.outputs.released == 'true' + run: uv build + + - name: Publish to PyPI + if: steps.check_skip.outputs.skip != 'true' && steps.release.outputs.released == 'true' + uses: pypa/gh-action-pypi-publish@release/v1 + + - name: Publish to GitHub Releases + if: steps.check_skip.outputs.skip != 'true' && steps.release.outputs.released == 'true' + uses: python-semantic-release/publish-action@v9.15.2 + with: + github_token: ${{ secrets.ADMIN_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..d7cc1ca --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,32 @@ +name: test + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - uses: astral-sh/setup-uv@v4 + + - name: Install dependencies + run: uv sync --extra dev + + - name: Lint + run: uv run ruff check src/ tests/ + + - name: Test + run: uv run pytest tests/ -m "not live" -v --timeout=60 diff --git a/pyproject.toml b/pyproject.toml index 86d7f79..9fb76d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "consilium" -version = "0.1.0" +version = "0.3.0" description = "Multi-LLM council for consensus-driven AI responses" readme = "README.md" requires-python = ">=3.10" @@ -46,6 +46,25 @@ markers = [ "live: integration tests that require real API keys (deselect with '-m \"not live\"')", ] +[project.urls] +Homepage = "https://github.com/OpenAdaptAI/openadapt-consilium" +Repository = "https://github.com/OpenAdaptAI/openadapt-consilium" +"Bug Tracker" = "https://github.com/OpenAdaptAI/openadapt-consilium/issues" + [tool.ruff] target-version = "py310" line-length = 88 + +[tool.semantic_release] +version_toml = ["pyproject.toml:project.version"] +version_variables = ["src/consilium/__init__.py:__version__"] +commit_message = "chore: release {version}" +major_on_zero = false + +[tool.semantic_release.branches.main] +match = "main" + +[tool.semantic_release.commit_parser_options] +allowed_tags = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test"] +minor_tags = ["feat"] +patch_tags = ["fix", "perf"] diff --git a/src/consilium/__init__.py b/src/consilium/__init__.py index 5f1128d..d5ed4df 100644 --- a/src/consilium/__init__.py +++ b/src/consilium/__init__.py @@ -21,7 +21,7 @@ from consilium.model_registry import get_latest, list_models from consilium.sdk import council_query -__version__ = "0.1.0" +__version__ = "0.3.0" __all__ = [ "Council", "CouncilResult",