feat: add Python library API for programmatic use #107
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| # Skip CI for docs-only and metadata changes on push to main | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| - 'examples/**' | |
| - '.github/**' | |
| - '!.github/workflows/**' | |
| - '.gitignore' | |
| pull_request: | |
| branches: [main] | |
| # Always run on PRs (for review), but individual jobs can skip if needed | |
| # Cancel in-progress runs when a new workflow with the same group name starts | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| # Set read-only permissions by default | |
| permissions: | |
| contents: read | |
| jobs: | |
| # Separate lint job - runs once instead of on every matrix combination | |
| lint: | |
| name: Lint and format check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 | |
| with: | |
| python-version: "3.14" | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v7 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "pyproject.toml" | |
| - name: Install dependencies | |
| run: uv sync --extra dev | |
| - name: Run ruff check | |
| run: uv run ruff check peakbagger tests | |
| - name: Run ruff format check | |
| run: uv run ruff format --check peakbagger tests | |
| - name: Run ty | |
| run: uvx ty check peakbagger | |
| continue-on-error: true | |
| test: | |
| name: Test on ${{ matrix.os }} - Python ${{ matrix.python-version }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: ["3.12", "3.13", "3.14"] | |
| include: | |
| # Smoke tests on macOS and Windows with latest Python | |
| - os: macos-latest | |
| python-version: "3.14" | |
| - os: windows-latest | |
| python-version: "3.14" | |
| steps: | |
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: pip | |
| cache-dependency-path: pyproject.toml | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v7 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "pyproject.toml" | |
| - name: Install dependencies | |
| run: uv sync --extra dev | |
| - name: Run tests with coverage | |
| run: uv run pytest --cov=peakbagger --cov-report=xml --cov-report=term | |
| - name: Upload coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.14' | |
| uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| file: ./coverage.xml | |
| fail_ci_if_error: false | |
| validate-pr-title: | |
| name: Validate PR title | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Validate PR title follows conventional commit format | |
| uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| types: | | |
| feat | |
| fix | |
| docs | |
| style | |
| refactor | |
| perf | |
| test | |
| chore | |
| ci | |
| build | |
| requireScope: false | |
| subjectPattern: ^.+$ | |
| subjectPatternError: | | |
| The subject "{subject}" found in the PR title "{title}" | |
| must not be empty. | |
| validateSingleCommit: false | |
| ignoreLabels: | | |
| bot | |
| dependencies | |
| # Sentinel job that always runs - use this as the required status check | |
| required-checks: | |
| name: Required Checks | |
| runs-on: ubuntu-latest | |
| needs: [lint, test, validate-pr-title] | |
| if: always() | |
| steps: | |
| - name: Check results | |
| run: | | |
| lint_result="${{ needs.lint.result }}" | |
| test_result="${{ needs.test.result }}" | |
| pr_title_result="${{ needs.validate-pr-title.result }}" | |
| echo "Lint result: $lint_result" | |
| echo "Test result: $test_result" | |
| echo "PR title validation result: $pr_title_result" | |
| # Lint must always pass | |
| if [[ "$lint_result" == "failure" ]]; then | |
| echo "❌ Lint failed" | |
| exit 1 | |
| elif [[ "$lint_result" == "cancelled" ]]; then | |
| echo "❌ Lint was cancelled" | |
| exit 1 | |
| fi | |
| # Tests must always pass | |
| if [[ "$test_result" == "failure" ]]; then | |
| echo "❌ Tests failed" | |
| exit 1 | |
| elif [[ "$test_result" == "cancelled" ]]; then | |
| echo "❌ Tests were cancelled" | |
| exit 1 | |
| fi | |
| # PR title validation must pass (if it ran) | |
| if [[ "$pr_title_result" == "failure" ]]; then | |
| echo "❌ PR title validation failed" | |
| exit 1 | |
| elif [[ "$pr_title_result" == "cancelled" ]]; then | |
| echo "❌ PR title validation was cancelled" | |
| exit 1 | |
| fi | |
| echo "✅ All required checks passed" |