Skip to content

refactor: Move and refactor Surface Geomechanics vtk filter and plugin #658

refactor: Move and refactor Surface Geomechanics vtk filter and plugin

refactor: Move and refactor Surface Geomechanics vtk filter and plugin #658

name: geosPythonPackages CI
on: pull_request
# Cancels in-progress workflows for a PR when updated
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Checks if PR title follows conventional semantics
semantic_pull_request:
permissions:
pull-requests: write # for amannn/action-semantic-pull-request to analyze PRs and
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
contents: read
runs-on: ubuntu-latest
steps:
- name: Check if the PR name has conventional semantics
if: github.event_name == 'pull_request'
uses: amannn/[email protected]
id: lint_pr_title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
wip: true
# Configure that a scope doesn't need to be provided.
requireScope: false
- name: Skip the check on main branch
if: github.ref_name == 'main'
run: |
echo "This is not a Pull-Request, skipping"
check_draft:
runs-on: ubuntu-latest
needs: [semantic_pull_request]
steps:
- name: Fail if PR is a draft
run: |
if [ "${{ github.event.pull_request.draft }}" = "true" ]; then
echo "✗ This PR is a draft. CI will not proceed."
exit 1
else
echo "✓ This PR is ready for review."
fi
# build and test the standalone CI
build:
runs-on: ubuntu-latest
needs: [check_draft]
strategy:
fail-fast: false
max-parallel: 3
matrix:
python-version: ["3.10","3.11","3.12"]
package-name:
- geos-ats
- geos-utils
- geos-geomechanics
- geos-mesh
- geos-posp
- geos-timehistory
- geos-trame
- geos-xml-tools
- geos-xml-viewer
- hdf5-wrapper
- pygeos-tools
include:
- package-name: geos-geomechanics
dependencies: "geos-utils"
- package-name: geos-mesh
dependencies: "geos-utils geos-geomechanics"
- package-name: geos-posp
dependencies: "geos-utils geos-mesh geos-geomechanics"
- package-name: pygeos-tools
dependencies: "geos-utils geos-mesh"
- package-name: geos-timehistory
dependencies: "hdf5-wrapper"
steps:
- uses: actions/checkout@v4
- uses: mpi4py/setup-mpi@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install package
# working-directory: ./${{ matrix.package-name }}
run: |
python -m pip install --upgrade pip
python -m pip install pytest yapf toml
DEPS="${{ matrix.dependencies || '' }}"
if [ -n "$DEPS" ]; then
echo "Installing additional dependencies: $DEPS"
for dep in $DEPS; do
python -m pip install ./$dep
done
fi
echo "Installing main package..."
python -m pip install ./${{ matrix.package-name }}/[test]
- name: Lint with yapf
# working-directory: ./${{ matrix.package-name }}
run: |
yapf -r --diff ./${{ matrix.package-name }} --style .style.yapf
- name: Test with pytest
#working-directory: ./${{ matrix.package-name }}
run:
# python -m pytest ./${{ matrix.package-name }} --doctest-modules --junitxml=junit/test-results.xml --cov-report=xml --cov-report=html |
# wrap pytest to avoid error when no tests in the package
sh -c 'python -m pytest ./${{ matrix.package-name }}; ret=$?; [ $ret = 5 ] && exit 0 || exit $ret'
# check if GEOS has label for testing GEOS integration
check_integration_label:
runs-on: ubuntu-latest
needs: [build]
outputs:
has_geos_integration_label: ${{ steps.set-label.outputs.has_label }}
steps:
- name: Check if PR has 'test-geos-integration' label
id: set-label
run: |
echo "Checking for label..."
LABEL_FOUND=false
for label in "${{ toJson(github.event.pull_request.labels) }}"; do
if [[ "$label" == *"test-geos-integration"* ]]; then
LABEL_FOUND=true
echo "Label ${label} found"
break
fi
done
echo "has_label=$LABEL_FOUND" >> $GITHUB_OUTPUT
check_force_integration_label:
runs-on: ubuntu-latest
needs: [build]
outputs:
has_geos_integration_force_label: ${{ steps.set-label.outputs.has_label }}
steps:
- name: Check if PR has 'force-geos-integration' label
id: set-label
run: |
echo "Checking for label..."
LABEL_FOUND=false
for label in "${{ toJson(github.event.pull_request.labels) }}"; do
if [[ "$label" == *"force-geos-integration"* ]]; then
LABEL_FOUND=true
echo "Label ${label} found"
break
fi
done
echo "has_label=$LABEL_FOUND" >> $GITHUB_OUTPUT
# Step 3: Check if GEOS integration is required based on changed files
check_geos_integration_required:
name: Check GEOS Integration Required
runs-on: ubuntu-latest
needs: [build]
if: github.event_name == 'pull_request'
outputs:
geos_integration_required: ${{ steps.check_changes.outputs.required }}
skip_reason: ${{ steps.check_changes.outputs.skip_reason }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history to compare with base branch
- name: Check if GEOS integration is required
id: check_changes
run: |
echo "Analyzing changed files to determine if GEOS integration test is required..."
# Get list of changed files
git fetch origin ${{ github.base_ref }}
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
echo "Changed files:"
echo "$CHANGED_FILES"
echo ""
# Define packages that are integrated into GEOS (from GEOS/scripts/setupPythonEnvironment.bash)
GEOS_INTEGRATED_PACKAGES=(
"geos-utils"
"geos-mesh"
"geos-xml-tools"
"hdf5-wrapper"
"pygeos-tools"
"geos-ats"
)
# Define patterns that DON'T require GEOS integration testing
SKIP_PATTERNS=(
"^docs/"
"^\.github/workflows/doc-test\.yml$"
"^\.github/workflows/typing-check\.yml$"
"^README\.md$"
"^\.readthedocs\.yml$"
"^\.gitignore$"
"^\.gitattributes$"
"^\.style\.yapf$"
"^\.ruff\.toml$"
"^\.mypy\.ini$"
# Packages not used in GEOS
"^geos-geomechanics/"
"^geos-posp/"
"^geos-pv/"
"^geos-timehistory/"
"^geos-trame/"
"^geos-xml-viewer/"
)
# Check if any changed file affects GEOS-integrated packages
REQUIRES_GEOS_TEST=false
AFFECTED_PACKAGES=""
for file in $CHANGED_FILES; do
# Check if file matches any skip pattern
SHOULD_SKIP=false
for pattern in "${SKIP_PATTERNS[@]}"; do
if echo "$file" | grep -qE "$pattern"; then
SHOULD_SKIP=true
break
fi
done
if [[ "$SHOULD_SKIP" == "false" ]]; then
# Check if file is in a GEOS-integrated package
for package in "${GEOS_INTEGRATED_PACKAGES[@]}"; do
if echo "$file" | grep -qE "^${package}/"; then
REQUIRES_GEOS_TEST=true
if [[ ! "$AFFECTED_PACKAGES" =~ "$package" ]]; then
AFFECTED_PACKAGES="$AFFECTED_PACKAGES $package"
fi
fi
done
# Check for CI workflow changes that affect GEOS integration
if echo "$file" | grep -qE "^\.github/workflows/(python-package\.yml|test_geos_integration\.yml)$"; then
REQUIRES_GEOS_TEST=true
AFFECTED_PACKAGES="$AFFECTED_PACKAGES [CI-workflows]"
fi
# Check for root-level scripts that might affect integration
if echo "$file" | grep -qE "^install_packages\.sh$"; then
REQUIRES_GEOS_TEST=true
AFFECTED_PACKAGES="$AFFECTED_PACKAGES [install-scripts]"
fi
fi
done
if [[ "$REQUIRES_GEOS_TEST" == "true" ]]; then
echo "✓ GEOS integration test REQUIRED"
echo " Affected packages/components:$AFFECTED_PACKAGES"
echo " These packages are integrated into GEOS and require testing"
echo "required=true" >> "$GITHUB_OUTPUT"
echo "skip_reason=none" >> "$GITHUB_OUTPUT"
else
echo "⊘ GEOS integration test NOT required"
echo " All changes are in documentation, non-integrated packages, or config files"
echo " To force GEOS integration testing, add the 'test-geos-integration' label"
echo "required=false" >> "$GITHUB_OUTPUT"
echo "skip_reason=no-geos-integrated-changes" >> "$GITHUB_OUTPUT"
fi
geos_ci_dispatch:
name: Dispatch cases of GEOS CI
runs-on: ubuntu-latest
outputs:
is_GEOS_CI_skipped: ${{ steps.dispatch.outputs.skipped }}
fwd_geos_integration_required: ${{ steps.dispatch.outputs.fwd_geos_integration_required }}
fwd_skip_reason: ${{ steps.dispatch.outputs.skip_reason }}
needs: [check_geos_integration_required, check_integration_label, check_force_integration_label]
steps:
- name: Dispatch flag and req cases
id: dispatch
run: |
GEOS_REQUIRED="${{ needs.check_geos_integration_required.outputs.geos_integration_required }}"
HAS_TEST_LABEL="${{ needs.check_integration_label.outputs.has_geos_integration_label }}"
HAS_FORCE_LABEL="${{ needs.check_force_integration_label.outputs.has_geos_integration_force_label }}"
SKIP_REASON="${{ needs.check_geos_integration_required.outputs.skip_reason }}"
echo "fwd_geos_integration_required=${GEOS_REQUIRED}" >> "$GITHUB_OUTPUT"
echo "fwd_skip_reason=${SKIP_REASON}" >> "$GITHUB_OUTPUT"
echo "=== GEOS Integration Dispatch ==="
echo "GEOS Required (by file changes): ${GEOS_REQUIRED}"
echo "Has 'test-geos-integration' label: ${HAS_TEST_LABEL}"
echo "Has 'force-geos-integration' label: ${HAS_FORCE_LABEL}"
echo ""
# Case 1: Force label - always run tests
if [[ "$HAS_FORCE_LABEL" == "true" ]]; then
echo "✓ 'force-geos-integration' label present - forcing GEOS integration tests"
echo "skipped=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Case 2: GEOS required AND test label present - run tests
if [[ "$GEOS_REQUIRED" == "true" && "$HAS_TEST_LABEL" == "true" ]]; then
echo "✓ GEOS integration required and 'test-geos-integration' label present"
echo " Will proceed with GEOS integration tests"
echo "skipped=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Case 3: GEOS required BUT test label missing - ERROR
if [[ "$GEOS_REQUIRED" == "true" && "$HAS_TEST_LABEL" == "false" ]]; then
echo "✗ ERROR: GEOS integration is required but 'test-geos-integration' label is missing"
echo ""
echo "Your PR modifies GEOS-integrated packages:"
echo " - geos-utils, geos-mesh, geos-xml-tools"
echo " - hdf5-wrapper, pygeos-tools, geos-ats"
echo ""
echo "Action required: Add the 'test-geos-integration' label to this PR"
exit 1
fi
# Case 4: GEOS NOT required BUT test label present - SKIP TESTS
if [[ "$GEOS_REQUIRED" == "false" && "$HAS_TEST_LABEL" == "true" ]]; then
echo "⊘ SKIPPED: 'test-geos-integration' label present but GEOS integration is not required"
echo ""
echo "Your changes only affect:"
echo " - Documentation"
echo " - Non-integrated packages"
echo " - Configuration files"
echo ""
echo "If you want to run GEOS integration tests anyway, use 'force-geos-integration' label to explicitly force testing"
echo "skipped=true" >> "$GITHUB_OUTPUT"
exit 0
fi
# Case 5: GEOS NOT required AND no labels - SKIP TESTS
if [[ "$GEOS_REQUIRED" == "false" && "$HAS_TEST_LABEL" == "false" ]]; then
echo "⊘ GEOS integration not required and no labels present"
echo " Skipping GEOS integration tests"
echo " Reason: ${SKIP_REASON}"
echo "skipped=true" >> "$GITHUB_OUTPUT"
exit 0
fi
# Should never reach here
echo "✗ ERROR: Unexpected state in dispatch logic"
exit 1
# Step 4: Run GEOS integration tests (only if required or label present)
geos_integration_test:
name: GEOS Integration Test
needs: [geos_ci_dispatch]
if: ${{ needs.geos_ci_dispatch.outputs.is_GEOS_CI_skipped.skipped != 'true' }}
uses: ./.github/workflows/test_geos_integration.yml
# Final validation - Summarize CI results
final_validation:
name: Final CI Validation
runs-on: ubuntu-latest
needs: [geos_ci_dispatch, geos_integration_test]
if: always() && github.event_name == 'pull_request'
steps:
- name: Validate CI completion
run: |
echo "Final CI Validation"
echo "==================="
GEOS_REQUIRED="${{ needs.geos_ci_dispatch.outputs.fwd_geos_integration_required }}"
SKIP_REASON="${{ needs.geos_ci_dispatch.outputs.fwd_skip_reason }}"
GEOS_RESULT="${{ needs.geos_integration_test.result }}"
if [[ "$GEOS_REQUIRED" == "true" ]]; then
echo "GEOS integration test was required and triggered"
if [[ "$GEOS_RESULT" == "success" ]]; then
echo "✓ GEOS integration test PASSED"
echo "✓ All CI requirements satisfied - PR can be merged"
else
echo "✗ GEOS integration test FAILED or was skipped"
echo "✗ CI FAILED - PR cannot be merged until GEOS integration passes"
exit 1
fi
else
echo "GEOS integration test was NOT required"
echo "Reason: $SKIP_REASON"
echo ""
echo "Changed files do not affect GEOS-integrated packages:"
echo " - geos-utils, geos-mesh, geos-xml-tools"
echo " - hdf5-wrapper, pygeos-tools, geos-ats"
echo ""
echo "If you want to run GEOS integration tests anyway,"
echo "add the 'test-geos-integration' label to this PR"
echo ""
echo "✓ CI requirements satisfied - PR can be merged"
fi