Skip to content

Commit 08a3417

Browse files
feat: Add complete CI/CD infrastructure and enhancements (#1)
* v0.1.0a2 * 0.1.0a3 * fix: rm type hint * 0.10.0a14 * 0.1.0a16. 'injected_kwargs' to 'vars' * 0.1.0a18 * 0.1.0a18 * fix docs * fix strict * fix uv cache * fix * add: image details and file and video support in signature * 0.1.0a19 * add: cache response, mcp * 0.1.0a19 * 0.1.0a20 * refactor: create MCPTool class and enable parallel execution for MCP tools Major improvements to tool architecture: 1. Created MCPTool class that wraps MCP tools as Tool objects - Enables polymorphism: Local and MCP tools treated uniformly - Automatic telemetry with MCP-specific attributes - Consistent error handling 2. Refactored ToolLibrary.forward() and aforward() - Reduced from ~200 lines to ~90 lines (55% reduction) - Removed ~110 lines of duplicated MCP inline code - Unified logic for Local and MCP tools 3. MAJOR: Added parallelism for MCP tools - Before: MCP tools executed serially (one at a time) - After: MCP tools execute in parallel via scatter_gather - Performance gain: up to 3x speedup for multiple MCP tool calls 4. Enhanced Tool base class - Added tool-specific telemetry in _call() method - Both Local and MCP tools now properly traced - Automatic mcp.tool.type attribute ("local" vs "remote") Benefits: - Cleaner, more maintainable code - Better performance for MCP tools - Unified telemetry approach - Backward compatible 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * add: batch support jinaai * refactor: telemetry * fix: handle MCP connection failures gracefully Fixes two critical bugs when MCP server connection fails: 1. filter_tools() crash on None - Added None/empty check before iterating tools - Returns empty list instead of crashing 2. ToolLibrary stops initialization on MCP failure - Wrapped MCP connection in try/except - Logs error and continues instead of failing - Local tools remain functional even if MCP fails 3. Missing tool_config attribute - Added getattr() with default {} in add() method - Handles tools without tool_config attribute Result: Agent creation succeeds even when MCP servers are unavailable, allowing local tools to work normally. MCP failures are logged but don't break the entire agent. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: remove duplicated _call_impl and _acall_impl from Tool Tool class was unnecessarily overriding _call_impl and _acall_impl with identical implementations to Module. These methods only handle forward hooks, which don't need customization for tools. Changes: - Removed _call_impl override (25 lines) - Removed _acall_impl override (25 lines) - Tool now inherits these from Module - Kept _call and _acall overrides (have tool-specific telemetry) Result: -50 lines of duplicated code, cleaner inheritance hierarchy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: introduce LM (Language Model) wrapper module Adds LM module as a Module wrapper around language models, enabling: - Forward hooks for intercepting/modifying LM calls - Composition patterns (fallback, retry, caching) - Symmetry with other Agent components like ToolLibrary Architecture: - Agent now uses self.lm internally (wraps model automatically) - Agent accepts both Model and LM as 'model' parameter - Auto-detection: if model is LM, uses directly; otherwise wraps it - Backward compatible: agent.model property still works Benefits: - Enables powerful hooks on LM calls (pre/post-processing) - Facilitates composition (FallbackLM, CachedLM, RetryLM) - Consistent architecture (agent.lm + agent.tools) - 100% backward compatible Usage: # Standard usage (auto-wraps) agent = nn.Agent(model=mf.Model.chat_completion("openai/gpt-4o")) # Advanced usage with hooks lm = nn.LM(model=model) lm.register_forward_pre_hook(adjust_temperature) agent = nn.Agent(model=lm) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: cleanup LM and move _set_config to Agent LM improvements: - Added model_type validation in LM.__init__ (moved from Agent) - Removed auto name-setting (was problematic with model_name) - Removed __repr__ override (use Module's default) - Removed model_name and model_type properties (unnecessary) - Removed _set_model method (simplified) - Cleaner, minimal LM implementation Module/Agent separation: - Moved _set_config from Module to Agent where it belongs - _set_config has Agent-specific keys (verbose, tool_choice, etc.) - Other modules (Embedder, Retriever, etc.) define their own _set_config - Cleaner separation of concerns Result: -88 lines total, better architecture 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * clean lm * add: image e video kwargs * refactor: apply auto-wrapping pattern to Retriever/Embedder Applied the same pattern used for Agent/LM to Retriever/Embedder: - Changed `embedder` parameter to `model` with auto-wrapping - Auto-wraps EmbedderModel in Embedder if not already an Embedder - Added model property for convenient access to underlying model - Changed `response_template` parameter to `templates` dict - Uses Module's _set_templates for template handling This enables users to: 1. Pass Embedder directly for advanced usage with hooks 2. Pass EmbedderModel which gets auto-wrapped in Embedder 3. Use standardized templates API consistent with Agent 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: remove backward compatibility comments Removed backward compatibility comments from codebase as we are in alpha phase without released users. Kept the actual compatibility code in place, only removed explanatory comments. Changes: - Removed comments from __init__.py (ToolBase alias) - Removed comments from module.py (call_super_init, aforward fallback) - Removed comments from tool.py (mcp_clients storage) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * lint * telemetry * refactor tool * fix: tool md * chore: improve .gitignore organization and coverage - Organize into clear sections with comments - Add coverage for test artifacts (.coverage, htmlcov/) - Add more cache types (.mypy_cache, .pytype, etc) - Add IDE support (.idea/, swap files) - Keep uv.lock for reproducibility (removed *.lock wildcard) - Keep .python-version for project consistency - Add .claude/ for Claude Code local config - Temporarily ignore: - /docs/, /examples/, /next_version/ - CI/CD workflows (only gh-pages needed for now) - /tests/ (work in progress) - MCP docs (to be moved to /docs later) - New providers (anthropic, google, mistral - dedicated branches) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: add project configuration files - Add .python-version (3.12) for consistent Python version - Add .pre-commit-config.yaml with gitleaks, uv-lock, and ruff hooks - Add uv.lock for dependency reproducibility These files ensure consistent development environment across all contributors and CI/CD pipelines. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: add project context documentation (CLAUDE.md) Add comprehensive context documentation for AI assistants and developers working on the project. This document includes: - Project overview and current status - Architecture evolution and separated components - Dependency information and integration notes - Development workflow and tooling - Migration roadmap and key decisions - Notes for AI assistants about the codebase This helps maintain context across development sessions and provides clear guidance on project structure and future plans. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: add msgtrace dependency group Add msgtrace development dependency group with: - FastAPI and uvicorn for backend server - Pydantic for data validation - WebSockets for real-time communication - aiohttp and httpx for async HTTP clients - python-multipart for form data handling This group supports local development and testing of the msgtrace observability service integration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: remove unused import in telemetry Remove unused NoOpTracerProvider import from tracer.py. This import was not being used in the module. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: improve mkdocs configuration Enhance MkDocs setup with: - Better theme configuration (logo, favicon, colors) - More navigation features (tabs, instant loading, tracking) - Enhanced search capabilities - Better code highlighting and annotations - Improved content features (tabs, tooltips) - Repository links and metadata - Extended markdown extensions support Documentation structure and content remain work in progress. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate to msgtrace-sdk for telemetry Migrate from built-in OpenTelemetry implementation to msgtrace-sdk, creating a cleaner separation of concerns and leveraging a dedicated AI tracing SDK. ## Changes ### Dependencies - Add msgtrace-sdk>=1.0.0 as core dependency - Remove direct OpenTelemetry dependencies (now via msgtrace-sdk) - Keep OpenTelemetry instrumenters for providers (openai, google) ### Environment Configuration (envs.py) - Add telemetry_enabled (maps to MSGTRACE_TELEMETRY_ENABLED) - Add telemetry_exporter (otlp/console, maps to MSGTRACE_EXPORTER) - Add telemetry_service_name (maps to MSGTRACE_SERVICE_NAME) - Add configure_msgtrace_env() to sync MSGFLUX_* → MSGTRACE_* vars - Keep telemetry_requires_trace as property for backward compat ### Telemetry Module - **tracer.py**: Re-export msgtrace-sdk tracer - **attributes.py**: Re-export MsgTraceAttributes from msgtrace-sdk - **span.py**: - Inherit Spans from msgtrace-sdk (gets all context managers & decorators) - Keep msgflux-specific tool decorators (set_tool_attributes, aset_tool_attributes) - Keep msgflux-specific agent decorators (set_agent_attributes, aset_agent_attributes) - Detailed capture: tool_call_id, execution_type, protocol, arguments, responses ### Features Preserved - ✅ Tool execution tracking (local/remote, MCP/A2A protocols) - ✅ Agent telemetry (name, ID hash, responses) - ✅ Detailed argument/response capture with msgspec encoding - ✅ Conditional capture based on envs (telemetry_capture_tool_call_responses) - ✅ Stream response detection (avoid capturing ModelStreamResponse) ### Features from msgtrace-sdk - ✅ Spans API (span_context, init_flow, init_module) - ✅ Async support (aspan_context, ainit_flow, ainit_module) - ✅ Decorators (instrument, ainstrument) - ✅ 60+ GenAI attributes following OpenTelemetry spec - ✅ Zero-overhead when disabled - ✅ Thread-safe singleton pattern ### Documentation - Update CLAUDE.md with msgtrace-sdk integration status - Add test_msgtrace_migration.py for validating integration ## Dependencies This migration requires msgtrace-sdk PR#13 to be merged and released: - Module attributes (set_module_name, set_module_type) - Extended tool attributes (set_tool_execution_type, set_tool_protocol) - Extended agent attributes (set_agent_response) ## Testing Testing awaits msgtrace-sdk v1.0.1 release with new attributes. Use test_msgtrace_migration.py to validate after release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: update all imports to use Spans.instrument from msgtrace-sdk Replace deprecated 'instrument' function imports with Spans class: - Updated src/msgflux/__init__.py to export Spans instead of instrument - Updated src/msgflux/nn/functional.py to use @Spans.instrument decorator - Updated src/msgflux/protocols/mcp/client.py to use @Spans.instrument decorator - Updated pyproject.toml to require msgtrace-sdk>=1.1.0 and Python>=3.10 All migration tests passing successfully. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: use Spans class methods and MsgTraceAttributes in Module Replace instance-based telemetry with static class methods: - Use Spans.init_module/ainit_module instead of self._spans.init_module - Use Spans.init_flow/ainit_flow instead of self._spans.init_flow - Add MsgTraceAttributes.set_module_name and set_module_type calls - Remove _spans instance variable from Module.__init__ Benefits: - Cleaner API with direct class method calls - Explicit attribute setting with MsgTraceAttributes - Consistent with msgtrace-sdk patterns - Reduces instance state overhead All tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: clean up telemetry integration with msgtrace-sdk Major simplifications and improvements: 1. Remove unnecessary files: - Delete tracer.py (use msgtrace.sdk.tracer directly) - Delete attributes.py (use msgtrace.sdk.MsgTraceAttributes directly) - Remove spans singleton instance (use Spans class methods) 2. Simplify envs.py: - Remove msgtrace-specific envs (telemetry_enabled, otlp_endpoint, etc) - Keep only msgflux-specific settings (capture_tool_call_responses, etc) - Make configure_msgtrace_env() user-callable with parameters - Don't call configure automatically on import 3. Fix decorator usage: - Use @Spans.ainstrument() for async functions - Use @Spans.instrument() for sync functions - Remove redundant function names from decorators - Applied in: functional.py (13 functions), mcp/client.py (5 methods) 4. Import directly from msgtrace-sdk: - Import Spans and MsgTraceAttributes from msgtrace.sdk - Export only msgflux-specific decorators in telemetry module Benefits: - Cleaner, more maintainable code - Less abstraction overhead - User controls msgtrace configuration - Proper async instrumentation - DRY principle (no redundant names) All tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: bump msgspec-ext to >=0.5.0 Update msgspec-ext dependency to use the latest version (>=0.5.0). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add Optional types to configure_msgtrace_env parameters Mark all parameters in configure_msgtrace_env as Optional since they all have default values. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add model profiles system with models.dev integration Implements comprehensive model profile system that provides metadata, capabilities, pricing, and limits for models from models.dev API. Features: - Lazy loading with background fetch from models.dev - HuggingFace-style disk cache (~/.cache/msgflux/) - 24h TTL with automatic background refresh - vLLM/Ollama fallback to OpenRouter data (open-source models) - Cost calculation per token and per 1M tokens - Thread-safe singleton registry Components: - profiles/base.py: Dataclasses (ModelProfile, ProviderProfile, etc) - profiles/loader.py: Fetch & cache with timestamp validation - profiles/registry.py: Singleton registry with lazy loading - profiles/__init__.py: Public API Integration: - HTTPXModelClient._initialize(): Triggers profile loading - .profile property on OpenAI, vLLM, Ollama providers - Uses self.provider and self.model_id for lookups Example usage: model = OpenAIChatCompletion("gpt-4o") profile = model.profile # Check capabilities if profile.capabilities.tool_call: print("Supports tool calling") # Calculate cost cost = profile.cost.calculate( input_tokens=1000, output_tokens=500 ) Environment variables: - MSGFLUX_CACHE_HOME: Override cache location - MSGFLUX_PROFILE_CACHE_TTL: Cache TTL in seconds (default: 86400) All tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: move imports to top and use envs for cache TTL - Move ensure_profiles_loaded import to top of httpx.py - Add profile_cache_ttl to envs.py with type validation - Use envs.profile_cache_ttl instead of os.environ.get() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: remove test_msgtrace_migration.py and move test_profiles.py to tests/ * refactor: simplify test_profiles.py and move to tests/models/ * feat: add complete CI/CD infrastructure - Add GitHub Actions workflows for CI, publishing, and automation - Add pre-commit hooks for code quality (gitleaks, ruff, uv-lock) - Add automated release script with security validation - Add branch protection and label management scripts - Add CONTRIBUTING.md with detailed development workflows - Add CHANGELOG.md for tracking changes - Add pull request and issue templates - Add automated merge bot and release drafter - Add security scanning with CodeQL - Add twine and packaging to dev dependencies for release validation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add CI and publish workflows - Add GitHub Actions CI workflow for lint, test, and build - Add publish workflow for automated PyPI releases - Force add workflows despite gitignore 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * style: format code with ruff - Auto-format 79 files with ruff format - Auto-fix 67 lint errors with ruff check --fix - Improve code consistency and readability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: prepare repo for upstream merge - Update .github/labeler.yml to use msgflux structure instead of msgtrace - Remove init branch from docs.yml workflow (merging to main) - Update CONTRIBUTING.md examples to use msgflux classes Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4cceeca commit 08a3417

File tree

217 files changed

+33449
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

217 files changed

+33449
-0
lines changed

.github/CODEOWNERS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# See https://help.github.com/articles/about-codeowners/
2+
# for more info about CODEOWNERS file
3+
4+
# CODEOWNERS
5+
* @vilsonrodrigues

.github/labeler.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Configuration for labeler action
2+
# https://github.com/actions/labeler
3+
4+
# Models
5+
models:
6+
- changed-files:
7+
- any-glob-to-any-file: 'src/msgflux/models/**'
8+
9+
# Core
10+
core:
11+
- changed-files:
12+
- any-glob-to-any-file:
13+
- 'src/msgflux/generation/**'
14+
- 'src/msgflux/dsl/**'
15+
- 'src/msgflux/nn/**'
16+
17+
# Tests
18+
tests:
19+
- changed-files:
20+
- any-glob-to-any-file: 'tests/**'
21+
22+
# Documentation
23+
documentation:
24+
- changed-files:
25+
- any-glob-to-any-file:
26+
- '**/*.md'
27+
- 'docs/**'
28+
29+
# CI/CD
30+
ci:
31+
- changed-files:
32+
- any-glob-to-any-file:
33+
- '.github/workflows/**'
34+
- '.github/dependabot.yml'
35+
- '.github/labeler.yml'
36+
37+
# Dependencies
38+
dependencies:
39+
- changed-files:
40+
- any-glob-to-any-file:
41+
- 'pyproject.toml'
42+
- 'uv.lock'
43+
- '.pre-commit-config.yaml'
44+
45+
# Examples
46+
examples:
47+
- changed-files:
48+
- any-glob-to-any-file: 'examples/**'

.github/pull_request_template.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
## Summary
2+
3+
<!-- Brief description of what this PR does -->
4+
5+
## Changes
6+
7+
<!-- List the main changes in this PR -->
8+
-
9+
-
10+
-
11+
12+
## Type of Change
13+
14+
<!-- Mark the relevant option with an "x" -->
15+
- [ ] Bug fix (non-breaking change which fixes an issue)
16+
- [ ] New feature (non-breaking change which adds functionality)
17+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
18+
- [ ] Documentation update
19+
- [ ] Code refactoring
20+
- [ ] Performance improvement
21+
- [ ] Test improvement
22+
- [ ] CI/CD improvement
23+
- [ ] Chore/maintenance
24+
25+
## Testing
26+
27+
<!-- Describe how you tested these changes -->
28+
- [ ] Tests pass locally (`uv run pytest -v`)
29+
- [ ] Added new tests for this change
30+
- [ ] Updated existing tests
31+
32+
## Documentation
33+
34+
<!-- Check if documentation needs updating -->
35+
- [ ] Updated README.md (if API changed)
36+
- [ ] Updated CHANGELOG.md (if notable change)
37+
- [ ] Added/updated code comments
38+
- [ ] Added/updated docstrings
39+
40+
## Checklist
41+
42+
<!-- Mark completed items with an "x" -->
43+
- [ ] Code formatted (`uv run ruff format`)
44+
- [ ] Lint checks pass (`uv run ruff check`)
45+
- [ ] Tests pass (`uv run pytest -v`)
46+
- [ ] **Version NOT changed** (maintainers bump version after merge)
47+
- [ ] Commit messages follow [conventional commits](https://www.conventionalcommits.org/)
48+
- [ ] No breaking changes (or documented above)
49+
- [ ] Added tests for new features
50+
- [ ] Documentation is up to date
51+
52+
## Additional Notes
53+
54+
<!-- Any additional information reviewers should know -->

.github/release-drafter.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name-template: 'v$RESOLVED_VERSION'
2+
tag-template: 'v$RESOLVED_VERSION'
3+
4+
categories:
5+
- title: '🚨 Breaking Changes'
6+
labels:
7+
- 'breaking-change'
8+
- 'breaking'
9+
- title: '🚀 Features'
10+
labels:
11+
- 'enhancement'
12+
- 'feat'
13+
- 'feature'
14+
- title: '🐛 Bug Fixes'
15+
labels:
16+
- 'bug'
17+
- 'fix'
18+
- title: '⚡ Performance'
19+
labels:
20+
- 'performance'
21+
- 'perf'
22+
- title: '🔐 Security'
23+
labels:
24+
- 'security'
25+
- title: '📚 Documentation'
26+
labels:
27+
- 'documentation'
28+
- 'docs'
29+
- title: '🔄 Refactoring'
30+
labels:
31+
- 'refactor'
32+
- 'refactoring'
33+
- title: '🧪 Tests'
34+
labels:
35+
- 'tests'
36+
- 'test'
37+
- title: '🤖 CI/CD'
38+
labels:
39+
- 'ci'
40+
- 'ci-cd'
41+
- title: '📦 Dependencies'
42+
labels:
43+
- 'dependencies'
44+
- title: '🔧 Maintenance'
45+
labels:
46+
- 'maintenance'
47+
- 'chore'
48+
49+
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
50+
change-title-escapes: '\<*_&'
51+
52+
version-resolver:
53+
major:
54+
labels:
55+
- 'breaking-change'
56+
- 'major'
57+
minor:
58+
labels:
59+
- 'enhancement'
60+
- 'feat'
61+
- 'feature'
62+
patch:
63+
labels:
64+
- 'bug'
65+
- 'fix'
66+
- 'patch'
67+
- 'documentation'
68+
- 'dependencies'
69+
default: patch
70+
71+
template: |
72+
## Changes
73+
74+
$CHANGES
75+
76+
## Contributors
77+
78+
Thank you to all contributors! 🙏
79+
80+
$CONTRIBUTORS

.github/workflows/ci.yml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
lint-format:
13+
name: Ruff Lint & Format
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Install uv
20+
uses: astral-sh/setup-uv@v7.1.4
21+
with:
22+
version: "latest"
23+
24+
- name: Set up Python
25+
run: uv python install 3.12
26+
27+
- name: Install dependencies
28+
run: uv sync --group dev
29+
30+
- name: Run ruff format check
31+
run: uv run ruff format --check
32+
33+
- name: Run ruff lint
34+
run: uv run ruff check --output-format=github
35+
36+
test:
37+
name: Test Python ${{ matrix.python-version }}
38+
runs-on: ubuntu-latest
39+
strategy:
40+
fail-fast: false
41+
matrix:
42+
python-version: ['3.10', '3.11', '3.12', '3.13']
43+
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- name: Install uv
48+
uses: astral-sh/setup-uv@v7.1.4
49+
with:
50+
version: "latest"
51+
52+
- name: Set up Python ${{ matrix.python-version }}
53+
run: uv python install ${{ matrix.python-version }}
54+
55+
- name: Install dependencies
56+
run: uv sync --group dev
57+
58+
- name: Run tests
59+
run: uv run pytest -v --cov=src/msgflux --cov-report=xml --cov-report=term
60+
61+
- name: Upload coverage
62+
uses: codecov/codecov-action@v5
63+
if: matrix.python-version == '3.12'
64+
with:
65+
file: ./coverage.xml
66+
fail_ci_if_error: false
67+
68+
build:
69+
name: Build distribution
70+
runs-on: ubuntu-latest
71+
needs: [lint-format, test]
72+
73+
steps:
74+
- uses: actions/checkout@v4
75+
76+
- name: Install uv
77+
uses: astral-sh/setup-uv@v7.1.4
78+
79+
- name: Set up Python
80+
run: uv python install 3.12
81+
82+
- name: Install dependencies
83+
run: uv sync --group dev
84+
85+
- name: Build package
86+
run: uv build
87+
88+
- name: Check package
89+
run: |
90+
ls -lh dist/
91+
uv run twine check dist/*
92+
93+
- name: Store distribution
94+
uses: actions/upload-artifact@v5
95+
with:
96+
name: python-package-distributions
97+
path: dist/

.github/workflows/docs.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Deploy Documentation
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
deploy:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: '3.11'
22+
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v5
25+
with:
26+
version: "latest"
27+
enable-cache: true
28+
cache-dependency-glob: "pyproject.toml"
29+
30+
- name: Install dependencies
31+
run: |
32+
uv sync --group doc
33+
34+
- name: Build documentation
35+
run: uv run --group doc mkdocs build --clean
36+
37+
- name: Deploy to GitHub Pages
38+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
39+
uses: peaceiris/actions-gh-pages@v4
40+
with:
41+
github_token: ${{ secrets.GITHUB_TOKEN }}
42+
publish_dir: ./site
43+
publish_branch: gh-pages

0 commit comments

Comments
 (0)