Skip to content

Commit f32dae6

Browse files
Merge branch 'main' into benedicto/feature/mesh_doctor_to_camel_case
2 parents b840333 + ffc89dc commit f32dae6

File tree

32 files changed

+2353
-228
lines changed

32 files changed

+2353
-228
lines changed

.github/workflows/README.md

Lines changed: 485 additions & 0 deletions
Large diffs are not rendered by default.

.github/workflows/python-package.yml

Lines changed: 306 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: geosPythonPackages CI
1+
name: geosPythonPackages CI
22
on: pull_request
33

44
# Cancels in-progress workflows for a PR when updated
@@ -9,13 +9,13 @@ concurrency:
99

1010
jobs:
1111
# Checks if PR title follows conventional semantics
12-
semantic_pull_request:
12+
semantic_pull_request:
1313
permissions:
14-
pull-requests: write # for amannn/action-semantic-pull-request to analyze PRs and
14+
pull-requests: write # for amannn/action-semantic-pull-request to analyze PRs and
1515
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
16-
contents: read
16+
contents: read
1717
runs-on: ubuntu-latest
18-
18+
1919
steps:
2020
- name: Check if the PR name has conventional semantics
2121
if: github.event_name == 'pull_request'
@@ -27,27 +27,42 @@ jobs:
2727
wip: true
2828
# Configure that a scope doesn't need to be provided.
2929
requireScope: false
30-
30+
3131
- name: Skip the check on main branch
3232
if: github.ref_name == 'main'
3333
run: |
3434
echo "This is not a Pull-Request, skipping"
3535
36+
check_draft:
37+
runs-on: ubuntu-latest
38+
needs: [semantic_pull_request]
39+
steps:
40+
- name: Fail if PR is a draft
41+
run: |
42+
if [ "${{ github.event.pull_request.draft }}" = "true" ]; then
43+
echo "✗ This PR is a draft. CI will not proceed."
44+
exit 1
45+
else
46+
echo "✓ This PR is ready for review."
47+
fi
48+
49+
# build and test the standalone CI
3650
build:
3751
runs-on: ubuntu-latest
52+
needs: [check_draft]
3853
strategy:
3954
fail-fast: false
4055
max-parallel: 3
4156
matrix:
42-
python-version: ["3.10", "3.11", "3.12"]
57+
python-version: ["3.10","3.11","3.12"]
4358
package-name:
4459
- geos-ats
60+
- geos-utils
4561
- geos-geomechanics
4662
- geos-mesh
4763
- geos-posp
4864
- geos-timehistory
4965
- geos-trame
50-
- geos-utils
5166
- geos-xml-tools
5267
- geos-xml-viewer
5368
- hdf5-wrapper
@@ -77,7 +92,7 @@ jobs:
7792
python -m pip install --upgrade pip
7893
python -m pip install pytest yapf toml
7994
80-
DEPS="${{ matrix.dependencies || '' }}"
95+
DEPS="${{ matrix.dependencies || '' }}"
8196
8297
if [ -n "$DEPS" ]; then
8398
echo "Installing additional dependencies: $DEPS"
@@ -88,7 +103,6 @@ jobs:
88103
89104
echo "Installing main package..."
90105
python -m pip install ./${{ matrix.package-name }}/[test]
91-
92106
- name: Lint with yapf
93107
# working-directory: ./${{ matrix.package-name }}
94108
run: |
@@ -98,4 +112,285 @@ jobs:
98112
run:
99113
# python -m pytest ./${{ matrix.package-name }} --doctest-modules --junitxml=junit/test-results.xml --cov-report=xml --cov-report=html |
100114
# wrap pytest to avoid error when no tests in the package
101-
sh -c 'python -m pytest ./${{ matrix.package-name }}; ret=$?; [ $ret = 5 ] && exit 0 || exit $ret'
115+
sh -c 'python -m pytest ./${{ matrix.package-name }}; ret=$?; [ $ret = 5 ] && exit 0 || exit $ret'
116+
117+
# check if GEOS has label for testing GEOS integration
118+
check_integration_label:
119+
runs-on: ubuntu-latest
120+
needs: [build]
121+
outputs:
122+
has_geos_integration_label: ${{ steps.set-label.outputs.has_label }}
123+
steps:
124+
- name: Check if PR has 'test-geos-integration' label
125+
id: set-label
126+
run: |
127+
echo "Checking for label..."
128+
LABEL_FOUND=false
129+
for label in "${{ toJson(github.event.pull_request.labels) }}"; do
130+
if [[ "$label" == *"test-geos-integration"* ]]; then
131+
LABEL_FOUND=true
132+
echo "Label ${label} found"
133+
break
134+
fi
135+
done
136+
echo "has_label=$LABEL_FOUND" >> $GITHUB_OUTPUT
137+
138+
check_force_integration_label:
139+
runs-on: ubuntu-latest
140+
needs: [build]
141+
outputs:
142+
has_geos_integration_force_label: ${{ steps.set-label.outputs.has_label }}
143+
steps:
144+
- name: Check if PR has 'force-geos-integration' label
145+
id: set-label
146+
run: |
147+
echo "Checking for label..."
148+
LABEL_FOUND=false
149+
for label in "${{ toJson(github.event.pull_request.labels) }}"; do
150+
if [[ "$label" == *"force-geos-integration"* ]]; then
151+
LABEL_FOUND=true
152+
echo "Label ${label} found"
153+
break
154+
fi
155+
done
156+
echo "has_label=$LABEL_FOUND" >> $GITHUB_OUTPUT
157+
158+
# Step 3: Check if GEOS integration is required based on changed files
159+
check_geos_integration_required:
160+
name: Check GEOS Integration Required
161+
runs-on: ubuntu-latest
162+
needs: [build]
163+
if: github.event_name == 'pull_request'
164+
outputs:
165+
geos_integration_required: ${{ steps.check_changes.outputs.required }}
166+
skip_reason: ${{ steps.check_changes.outputs.skip_reason }}
167+
steps:
168+
- name: Checkout code
169+
uses: actions/checkout@v4
170+
with:
171+
fetch-depth: 0 # Fetch all history to compare with base branch
172+
- name: Check if GEOS integration is required
173+
id: check_changes
174+
run: |
175+
echo "Analyzing changed files to determine if GEOS integration test is required..."
176+
177+
# Get list of changed files
178+
git fetch origin ${{ github.base_ref }}
179+
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
180+
181+
echo "Changed files:"
182+
echo "$CHANGED_FILES"
183+
echo ""
184+
185+
# Define packages that are integrated into GEOS (from GEOS/scripts/setupPythonEnvironment.bash)
186+
GEOS_INTEGRATED_PACKAGES=(
187+
"geos-utils"
188+
"geos-mesh"
189+
"geos-xml-tools"
190+
"hdf5-wrapper"
191+
"pygeos-tools"
192+
"geos-ats"
193+
)
194+
195+
# Define patterns that DON'T require GEOS integration testing
196+
SKIP_PATTERNS=(
197+
"^docs/"
198+
"^\.github/workflows/doc-test\.yml$"
199+
"^\.github/workflows/typing-check\.yml$"
200+
"^README\.md$"
201+
"^\.readthedocs\.yml$"
202+
"^\.gitignore$"
203+
"^\.gitattributes$"
204+
"^\.style\.yapf$"
205+
"^\.ruff\.toml$"
206+
"^\.mypy\.ini$"
207+
# Packages not used in GEOS
208+
"^geos-geomechanics/"
209+
"^geos-posp/"
210+
"^geos-pv/"
211+
"^geos-timehistory/"
212+
"^geos-trame/"
213+
"^geos-xml-viewer/"
214+
)
215+
216+
# Check if any changed file affects GEOS-integrated packages
217+
REQUIRES_GEOS_TEST=false
218+
AFFECTED_PACKAGES=""
219+
220+
for file in $CHANGED_FILES; do
221+
# Check if file matches any skip pattern
222+
SHOULD_SKIP=false
223+
for pattern in "${SKIP_PATTERNS[@]}"; do
224+
if echo "$file" | grep -qE "$pattern"; then
225+
SHOULD_SKIP=true
226+
break
227+
fi
228+
done
229+
230+
if [[ "$SHOULD_SKIP" == "false" ]]; then
231+
# Check if file is in a GEOS-integrated package
232+
for package in "${GEOS_INTEGRATED_PACKAGES[@]}"; do
233+
if echo "$file" | grep -qE "^${package}/"; then
234+
REQUIRES_GEOS_TEST=true
235+
if [[ ! "$AFFECTED_PACKAGES" =~ "$package" ]]; then
236+
AFFECTED_PACKAGES="$AFFECTED_PACKAGES $package"
237+
fi
238+
fi
239+
done
240+
241+
# Check for CI workflow changes that affect GEOS integration
242+
if echo "$file" | grep -qE "^\.github/workflows/(python-package\.yml|test_geos_integration\.yml)$"; then
243+
REQUIRES_GEOS_TEST=true
244+
AFFECTED_PACKAGES="$AFFECTED_PACKAGES [CI-workflows]"
245+
fi
246+
247+
# Check for root-level scripts that might affect integration
248+
if echo "$file" | grep -qE "^install_packages\.sh$"; then
249+
REQUIRES_GEOS_TEST=true
250+
AFFECTED_PACKAGES="$AFFECTED_PACKAGES [install-scripts]"
251+
fi
252+
fi
253+
done
254+
255+
if [[ "$REQUIRES_GEOS_TEST" == "true" ]]; then
256+
echo "✓ GEOS integration test REQUIRED"
257+
echo " Affected packages/components:$AFFECTED_PACKAGES"
258+
echo " These packages are integrated into GEOS and require testing"
259+
echo "required=true" >> "$GITHUB_OUTPUT"
260+
echo "skip_reason=none" >> "$GITHUB_OUTPUT"
261+
else
262+
echo "⊘ GEOS integration test NOT required"
263+
echo " All changes are in documentation, non-integrated packages, or config files"
264+
echo " To force GEOS integration testing, add the 'test-geos-integration' label"
265+
echo "required=false" >> "$GITHUB_OUTPUT"
266+
echo "skip_reason=no-geos-integrated-changes" >> "$GITHUB_OUTPUT"
267+
fi
268+
269+
geos_ci_dispatch:
270+
name: Dispatch cases of GEOS CI
271+
runs-on: ubuntu-latest
272+
outputs:
273+
is_GEOS_CI_skipped: ${{ steps.dispatch.outputs.skipped }}
274+
fwd_geos_integration_required: ${{ steps.dispatch.outputs.fwd_geos_integration_required }}
275+
fwd_skip_reason: ${{ steps.dispatch.outputs.skip_reason }}
276+
needs: [check_geos_integration_required, check_integration_label, check_force_integration_label]
277+
steps:
278+
- name: Dispatch flag and req cases
279+
id: dispatch
280+
run: |
281+
GEOS_REQUIRED="${{ needs.check_geos_integration_required.outputs.geos_integration_required }}"
282+
HAS_TEST_LABEL="${{ needs.check_integration_label.outputs.has_geos_integration_label }}"
283+
HAS_FORCE_LABEL="${{ needs.check_force_integration_label.outputs.has_geos_integration_force_label }}"
284+
SKIP_REASON="${{ needs.check_geos_integration_required.outputs.skip_reason }}"
285+
286+
echo "fwd_geos_integration_required=${GEOS_REQUIRED}" >> "$GITHUB_OUTPUT"
287+
echo "fwd_skip_reason=${SKIP_REASON}" >> "$GITHUB_OUTPUT"
288+
289+
echo "=== GEOS Integration Dispatch ==="
290+
echo "GEOS Required (by file changes): ${GEOS_REQUIRED}"
291+
echo "Has 'test-geos-integration' label: ${HAS_TEST_LABEL}"
292+
echo "Has 'force-geos-integration' label: ${HAS_FORCE_LABEL}"
293+
echo ""
294+
295+
# Case 1: Force label - always run tests
296+
if [[ "$HAS_FORCE_LABEL" == "true" ]]; then
297+
echo "✓ 'force-geos-integration' label present - forcing GEOS integration tests"
298+
echo "skipped=false" >> "$GITHUB_OUTPUT"
299+
exit 0
300+
fi
301+
302+
# Case 2: GEOS required AND test label present - run tests
303+
if [[ "$GEOS_REQUIRED" == "true" && "$HAS_TEST_LABEL" == "true" ]]; then
304+
echo "✓ GEOS integration required and 'test-geos-integration' label present"
305+
echo " Will proceed with GEOS integration tests"
306+
echo "skipped=false" >> "$GITHUB_OUTPUT"
307+
exit 0
308+
fi
309+
310+
# Case 3: GEOS required BUT test label missing - ERROR
311+
if [[ "$GEOS_REQUIRED" == "true" && "$HAS_TEST_LABEL" == "false" ]]; then
312+
echo "✗ ERROR: GEOS integration is required but 'test-geos-integration' label is missing"
313+
echo ""
314+
echo "Your PR modifies GEOS-integrated packages:"
315+
echo " - geos-utils, geos-mesh, geos-xml-tools"
316+
echo " - hdf5-wrapper, pygeos-tools, geos-ats"
317+
echo ""
318+
echo "Action required: Add the 'test-geos-integration' label to this PR"
319+
exit 1
320+
fi
321+
322+
# Case 4: GEOS NOT required BUT test label present - SKIP TESTS
323+
if [[ "$GEOS_REQUIRED" == "false" && "$HAS_TEST_LABEL" == "true" ]]; then
324+
echo "⊘ SKIPPED: 'test-geos-integration' label present but GEOS integration is not required"
325+
echo ""
326+
echo "Your changes only affect:"
327+
echo " - Documentation"
328+
echo " - Non-integrated packages"
329+
echo " - Configuration files"
330+
echo ""
331+
echo "If you want to run GEOS integration tests anyway, use 'force-geos-integration' label to explicitly force testing"
332+
echo "skipped=true" >> "$GITHUB_OUTPUT"
333+
exit 0
334+
fi
335+
336+
# Case 5: GEOS NOT required AND no labels - SKIP TESTS
337+
if [[ "$GEOS_REQUIRED" == "false" && "$HAS_TEST_LABEL" == "false" ]]; then
338+
echo "⊘ GEOS integration not required and no labels present"
339+
echo " Skipping GEOS integration tests"
340+
echo " Reason: ${SKIP_REASON}"
341+
echo "skipped=true" >> "$GITHUB_OUTPUT"
342+
exit 0
343+
fi
344+
345+
# Should never reach here
346+
echo "✗ ERROR: Unexpected state in dispatch logic"
347+
exit 1
348+
349+
# Step 4: Run GEOS integration tests (only if required or label present)
350+
geos_integration_test:
351+
name: GEOS Integration Test
352+
needs: [geos_ci_dispatch]
353+
if: ${{ needs.geos_ci_dispatch.outputs.is_GEOS_CI_skipped.skipped != 'true' }}
354+
uses: ./.github/workflows/test_geos_integration.yml
355+
356+
# Final validation - Summarize CI results
357+
final_validation:
358+
name: Final CI Validation
359+
runs-on: ubuntu-latest
360+
needs: [geos_ci_dispatch, geos_integration_test]
361+
if: always() && github.event_name == 'pull_request'
362+
steps:
363+
- name: Validate CI completion
364+
run: |
365+
echo "Final CI Validation"
366+
echo "==================="
367+
368+
GEOS_REQUIRED="${{ needs.geos_ci_dispatch.outputs.fwd_geos_integration_required }}"
369+
SKIP_REASON="${{ needs.geos_ci_dispatch.outputs.fwd_skip_reason }}"
370+
371+
GEOS_RESULT="${{ needs.geos_integration_test.result }}"
372+
373+
if [[ "$GEOS_REQUIRED" == "true" ]]; then
374+
echo "GEOS integration test was required and triggered"
375+
if [[ "$GEOS_RESULT" == "success" ]]; then
376+
echo "✓ GEOS integration test PASSED"
377+
echo "✓ All CI requirements satisfied - PR can be merged"
378+
else
379+
echo "✗ GEOS integration test FAILED or was skipped"
380+
echo "✗ CI FAILED - PR cannot be merged until GEOS integration passes"
381+
exit 1
382+
fi
383+
else
384+
echo "GEOS integration test was NOT required"
385+
echo "Reason: $SKIP_REASON"
386+
echo ""
387+
echo "Changed files do not affect GEOS-integrated packages:"
388+
echo " - geos-utils, geos-mesh, geos-xml-tools"
389+
echo " - hdf5-wrapper, pygeos-tools, geos-ats"
390+
echo ""
391+
echo "If you want to run GEOS integration tests anyway,"
392+
echo "add the 'test-geos-integration' label to this PR"
393+
echo ""
394+
echo "✓ CI requirements satisfied - PR can be merged"
395+
fi
396+

0 commit comments

Comments
 (0)