name: CI
on:
pull_request:
types: [opened, synchronize, reopened, edited]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
permissions:
contents: write
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install uv and tools
uses: astral-sh/setup-uv@v3
- name: Sync dependencies (dev + extras)
run: uv sync --all-extras --dev
# --- LINT STEP ---
- name: Lint
id: lint_step
continue-on-error: false
run: |
uv run ruff format stac_mcp/ tests/
uv run ruff check stac_mcp/ tests/ --fix --no-cache
# --- BUILD STEP ---
- name: Build (hatchling via uv) to validate packaging
id: build_step
continue-on-error: false
run: uv build
# --- TESTS + COVERAGE STEPS ---
- name: Tests + coverage
id: tests_step
continue-on-error: false
run: |
uv run coverage run -m pytest -v
uv run coverage xml
uv run python scripts/generate_coverage_badge.py coverage.xml coverage-badge.svg
uv run coverage report
- name: Check coverage threshold
id: coverage_threshold_step
continue-on-error: false
run: uv run coverage report --fail-under=85
# --- JULES FIX TRIGGER (Error Reporting) ---
- name: π Export Failure Context
if: failure()
run: |
mkdir -p failure-context
ERROR_MESSAGE=""
if [ "${{ steps.lint_step.outcome }}" = "failure" ]; then
ERROR_MESSAGE="${ERROR_MESSAGE}π¨ The Lint step failed. Please run 'uv run ruff check --fix' to resolve formatting and style issues.\n"
fi
if [ "${{ steps.build_step.outcome }}" = "failure" ]; then
ERROR_MESSAGE="${ERROR_MESSAGE}ποΈ The Build step failed. This often indicates a packaging or dependency issue.\n"
fi
if [ "${{ steps.tests_step.outcome }}" = "failure" ]; then
ERROR_MESSAGE="${ERROR_MESSAGE}π The Tests step failed. There are broken tests that need fixing. Run 'uv run pytest'.\n"
fi
if [ "${{ steps.coverage_threshold_step.outcome }}" = "failure" ]; then
ERROR_MESSAGE="${ERROR_MESSAGE}π The Coverage check failed. The current coverage is below the required 85% threshold. Please add more tests.\n"
fi
printf "%s" "$ERROR_MESSAGE" > failure-context/error_message.txt
# - name: Upload artifacts
# uses: actions/upload-artifact@v4
# with:
# name: coverage-artifacts-${{ matrix.python-version }}
# path: |
# coverage.xml
# coverage-badge.svg
- name: π€ Upload Failure Context
if: failure()
uses: actions/upload-artifact@v4
with:
name: failure-context-${{ matrix.python-version }}
path: failure-context/
# - name: Commit badge (main only)
# if: github.ref == 'refs/heads/main' && matrix.python-version == '3.12'
# run: |
# if git diff --quiet coverage-badge.svg 2>/dev/null; then
# echo 'No badge changes'
# else
# git config user.name 'github-actions'
# git config user.email 'actions@github.com'
# git add coverage-badge.svg
# git commit -m 'chore(ci): update coverage badge'
# git pull --rebase origin main
# git push
# fi
get_commit_author:
name: Get Commit Author
runs-on: ubuntu-latest
outputs:
author: ${{ steps.get_author.outputs.commit_author }}
steps:
- uses: actions/checkout@v4
- name: Get latest commit author
id: get_author
run: echo "commit_author=$(git log -1 --pretty=format:'%an' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
jules_autofix:
name: π€ Jules Fix Session
runs-on: ubuntu-latest
needs: [test, get_commit_author]
permissions:
pull-requests: write # Needed to comment on the PR if necessary
if: |
github.event_name == 'pull_request' &&
always() &&
needs.test.result == 'failure' &&
(github.event.pull_request.user.login == 'bnjam' || github.event.pull_request.user.login == 'BnJam') &&
(needs.get_commit_author.outputs.author == 'google-labs-jules[bot]' || (needs.get_commit_author.outputs.author == 'bnjam' || needs.get_commit_author.outputs.author == 'BnJam'))
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: π₯ Download Failure Context
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: failure-context-3.12
path: failure-context
- name: Install dependencies for API interaction
run: pip install requests # Need 'requests' to talk to the Jules API
- name: π¬ Check/Message Existing Jules Session
env:
JULES_API_KEY: ${{ secrets.JULES_API_KEY }}
REPO_NAME: ${{ github.repository }}
BRANCH_NAME: ${{ github.head_ref }}
run: |
if [ -f failure-context/error_message.txt ]; then
export ERROR_MESSAGE=$(cat failure-context/error_message.txt)
else
export ERROR_MESSAGE="CI failed, but could not retrieve specific error message from artifacts."
fi
python ./scripts/jules_session_manager.py
codeql:
name: CodeQL Analysis
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["python"]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Install dependencies (runtime only)
run: |
uv sync
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3