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
4 changes: 3 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.git
.github
.venv
*.coverage
*.egg-info
.eggs
*.eggs
*.pyc
__pycache__
.pytest_cache
Expand Down
199 changes: 133 additions & 66 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ jobs:
name: "📝 Pre-commit / Code Quality"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: ⚡ Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- uses: actions/checkout@v6
- name: ⚡ Setup uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}
cache-suffix: ${{ github.job }}
- name: 🏃 Run Pre-commit
run: |
uv tool install pre-commit
uv tool run pre-commit run --show-diff-on-failure --all-files
- name: 🧹 Cache Prune
run: uv cache prune --ci

setup:
name: "🏗️ Build Py${{ matrix.python-version }}"
Expand All @@ -40,25 +46,27 @@ jobs:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: 📥 Apply Dependency Overrides
if: "${{ inputs.override-deps-artifact != '' && inputs.override-deps-artifact != 'null' }}"
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: ${{ inputs.override-deps-artifact }}

- name: ⚡ Install uv
run: |
apt-get update && apt-get install -y curl
curl -LsSf https://astral.sh/uv/install.sh | BINDIR=/usr/local/bin sh
- name: ⚡ Setup uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}
cache-suffix: setup-${{ matrix.python-version }}

- name: 📝 Export Locked Requirements
run: |
uv export --frozen --all-extras --format requirements-txt > requirements.txt

- name: 📤 Upload Requirements
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: frozen-reqs-${{ matrix.python-version }}
path: requirements.txt
Expand All @@ -73,21 +81,24 @@ jobs:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: 📥 Download Requirements
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: frozen-reqs-${{ matrix.python-version }}

- name: ⚡ Install uv, git & GIS Dependencies
- name: ⚡ Install git & GIS Dependencies
run: |
sudo apt-add-repository -y ppa:ubuntugis/ubuntugis-unstable
sudo apt-get update
sudo apt-get install -y curl git gpg gdal-bin libgdal-dev libproj-dev libgeos-dev g++

curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="/usr/local/bin" sh

uv --version

- name: ⚡ Setup uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}
cache-suffix: test-${{ matrix.python-version }}

- name: 🏗️ Restore Native Env
run: |
Expand All @@ -104,7 +115,7 @@ jobs:
CURL_CA_BUNDLE: /etc/ssl/certs/ca-certificates.crt
COVERAGE_FILE: .coverage.python.${{ matrix.python-version }}
run: |
uv run pytest -v \
uv run pytest -v --log-cli-level=DEBUG \
--cov=mapchete_hub \
--cov-report=xml:coverage.xml \
--junitxml="pytest-${{ matrix.python-version }}.xml"
Expand All @@ -119,43 +130,56 @@ jobs:

- name: 📤 Upload Coverage Chunk (Latest Only)
if: matrix.python-version == '3.13'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: coverage-all
name: coverage-python-${{ matrix.python-version }}
path: .coverage.python.${{ matrix.python-version }}
include-hidden-files: true
retention-days: 1

- name: 📤 Archive JUnit Results
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: results-${{ matrix.python-version }}
path: pytest-${{ matrix.python-version }}.xml
retention-days: 1

- name: 🧹 Cache Prune
run: uv cache prune --ci

integration-tests:
name: "🚀 Integration Tests"
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: ⚡ Setup uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}
cache-suffix: ${{ github.job }}
- name: 🏗️ Sync Environment
run: uv sync --all-extras
- name: 🏃 Run Integration Tests
run: |
chmod +x ./run_integration_tests.sh
./run_integration_tests.sh
- name: 🧹 Cache Prune
run: uv cache prune --ci

build-docker-image:
name: "🐳 Docker Build & CLI Check"
if: github.event_name == 'pull_request'
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: ⚡ Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 🏗️ Build image for validation
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
push: false
Expand All @@ -173,66 +197,109 @@ jobs:
if: always()
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # Needed for coverage to see source files
- uses: actions/checkout@v6 # Needed for coverage to see source files

- name: ⚡ Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: ⚡ Setup uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}
cache-suffix: ${{ github.job }}

- name: 📥 Download Artifacts
uses: actions/download-artifact@v4
- name: 📥 Download Results
uses: actions/download-artifact@v8
with:
path: all-results
pattern: "*-*"
pattern: results-*
merge-multiple: true

- name: 📥 Download Coverage
uses: actions/download-artifact@v8
with:
path: all-results
pattern: coverage-*
merge-multiple: true

- name: 📊 Check Tests & Coverage
run: |
echo "### 🧪 Test & Coverage Summary" >> $GITHUB_STEP_SUMMARY

# 1. CHECK OVERALL TEST STATUS
if [[ "${{ needs.test.result }}" != "success" || "${{ needs.integration-tests.result }}" != "success" || ( "${{ github.event_name }}" == "pull_request" && "${{ needs.build-docker-image.result }}" != "success" ) ]]; then
echo "❌ **Test Suite Failed**" >> $GITHUB_STEP_SUMMARY
echo "- Unit/Doc Tests: ${{ needs.test.result }}" >> $GITHUB_STEP_SUMMARY
echo "- Integration Tests: ${{ needs.integration-tests.result }}" >> $GITHUB_STEP_SUMMARY
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "- Docker Build: ${{ needs.build-docker-image.result }}" >> $GITHUB_STEP_SUMMARY
fi
echo "Coverage check skipped because tests failed." >> $GITHUB_STEP_SUMMARY
exit 1
# 1. STATUS REPORT
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY

if [[ "${{ needs.test.result }}" == "success" ]]; then
echo "| Unit Tests | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
else
echo "| Unit Tests | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
fi
echo "✅ **Test Suite Passed**" >> $GITHUB_STEP_SUMMARY
echo "- Unit/Doc Tests: Passed" >> $GITHUB_STEP_SUMMARY
echo "- Integration Tests: Passed" >> $GITHUB_STEP_SUMMARY
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "- Docker Build: Passed" >> $GITHUB_STEP_SUMMARY

if [[ "${{ needs.integration-tests.result }}" == "success" ]]; then
echo "| Integration Tests | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
else
echo "- Docker Build: Skipped (Not a PR)" >> $GITHUB_STEP_SUMMARY
echo "| Integration Tests | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
fi

if [[ "${{ github.event_name }}" == "pull_request" ]]; then
if [[ "${{ needs.build-docker-image.result }}" == "success" ]]; then
echo "| Docker Build | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
else
echo "| Docker Build | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
fi
fi

# 2. PREPARE COVERAGE DATA
# 2. PREPARE COVERAGE DATA (Fetch from Python 3.13 tests only)
uv tool install coverage

if ls all-results/.coverage* 1> /dev/null 2>&1; then
mv all-results/.coverage* .
if [ -d all-results ]; then
echo "DEBUG: Content of all-results (including hidden):"
ls -Ra all-results
find all-results -name ".coverage*" -exec mv {} . \;
else
echo "⚠️ **Warning:** all-results directory not found. Artifacts might have failed to download." >> $GITHUB_STEP_SUMMARY
fi

echo "Merging/Preparing coverage data..."
# combine will merge .coverage.* into .coverage
uv tool run coverage combine --append || echo "No extra coverage files to combine."
# Rename the specific 3.13 file to .coverage if it exists
if [ -f .coverage.python.3.13 ]; then
echo "Found Python 3.13 coverage data, renaming to .coverage"
mv .coverage.python.3.13 .coverage
else
# Fallback: if there's only one coverage file, rename it
FILES=$(ls -a .coverage.* 2>/dev/null | grep -v '^\.$' | grep -v '^\.\.$' | wc -l)
if [ "$FILES" -eq 1 ]; then
mv .coverage.* .coverage
elif [ "$FILES" -gt 1 ]; then
uv tool run coverage combine --append
fi
fi

# 3. ENFORCE 70%
REPORT_OUTPUT=$(uv tool run coverage report --show-missing --fail-under=70 2>&1)
EXIT_CODE=$?

echo "$REPORT_OUTPUT"

echo '```' >> $GITHUB_STEP_SUMMARY
echo "$REPORT_OUTPUT" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

if [ $EXIT_CODE -ne 0 ]; then
echo "❌ **Coverage Failed:** Python 3.13 coverage is below 70%." >> $GITHUB_STEP_SUMMARY
exit $EXIT_CODE
if [ -f .coverage ]; then
echo "Generating coverage report..."
REPORT_OUTPUT=$(uv tool run coverage report --show-missing --fail-under=70 2>&1)
EXIT_CODE=$?

echo "$REPORT_OUTPUT"

echo '```' >> $GITHUB_STEP_SUMMARY
echo "$REPORT_OUTPUT" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

# 🔗 GENERATE DYNAMIC CODECOV LINK
CODECOV_URL="https://app.codecov.io/github/${{ github.repository }}/commit/${{ github.sha }}"
echo "🔗 **[View full line-by-line report on Codecov]($CODECOV_URL)**" >> $GITHUB_STEP_SUMMARY

if [ $EXIT_CODE -ne 0 ]; then
echo "❌ **Coverage Failed:** Python 3.13 coverage is below 70%." >> $GITHUB_STEP_SUMMARY
exit $EXIT_CODE
else
echo "✅ **Coverage Passed:** 70% coverage achieved (Py3.13)." >> $GITHUB_STEP_SUMMARY
fi
else
echo "✅ **Coverage Passed:** 70% coverage achieved (Py3.13)." >> $GITHUB_STEP_SUMMARY
fi
echo "⚠️ **Warning:** No coverage data found for Python 3.13." >> $GITHUB_STEP_SUMMARY
fi

# Fail overall if unit tests failed
if [[ "${{ needs.test.result }}" != "success" ]]; then
exit 1
fi
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
Expand Down
19 changes: 12 additions & 7 deletions .github/workflows/sync-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,27 @@ jobs:
outputs:
sync_needed: ${{ steps.check.outputs.changed }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref || github.ref }}

- name: ⚡ Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: 🛠️ Upgrade & Sync
run: |
# Robust repair: if the lockfile is out of sync/corrupted, fix it, then upgrade everything
uv lock || (rm uv.lock && uv lock)
# Upgrade lockfile
uv lock --upgrade

# Sync the conda recipe
uvx pyproject2conda yaml -f pyproject.toml --output conda/meta.yaml --python-include infer
uvx pyproject2conda yaml --pyproject pyproject.toml --output conda/meta.yaml --python-include infer

- name: 🧹 Cache Prune
run: uv cache prune --ci

- name: 📋 Check for Changes
id: check
Expand Down Expand Up @@ -111,14 +116,14 @@ jobs:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref || github.ref }}
token: ${{ secrets.MAPCHETE_PAT_CONTAINER_IMAGES_TOKEN }}

- name: 📥 Download Verified Artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: updated-deps

Expand Down
Loading
Loading