-
Notifications
You must be signed in to change notification settings - Fork 0
422 lines (370 loc) · 18.6 KB
/
python-package.yml
File metadata and controls
422 lines (370 loc) · 18.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
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/action-semantic-pull-request@v5.5.3
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"
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 3
matrix:
python-version: ["3.10", "3.11", "3.12"]
package-name:
- geos-ats
- geos-geomechanics
- geos-mesh
- geos-posp
- geos-timehistory
- geos-trame
- geos-utils
- geos-xml-tools
- 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'
# Step 1: Validate that all standard CI tests pass BEFORE checking GEOS integration
validate_standard_ci:
runs-on: ubuntu-latest
needs: [semantic_pull_request, build]
steps:
- name: Check standard CI results
run: |
echo "Checking standard CI results..."
echo "Semantic PR check: ${{ needs.semantic_pull_request.result }}"
echo "Build and test: ${{ needs.build.result }}"
# All standard tests must pass before proceeding
if [[ "${{ needs.semantic_pull_request.result }}" != "success" ]]; then
echo "❌ Semantic PR check failed - fix PR title before proceeding"
exit 1
fi
if [[ "${{ needs.build.result }}" != "success" ]]; then
echo "❌ Build and test failed - fix code issues before proceeding"
exit 1
fi
echo "✅ All standard CI tests passed! Ready for GEOS integration testing."
# Step 2: Only after standard tests pass, check for GEOS integration label
check_geos_integration_label:
runs-on: ubuntu-latest
needs: [validate_standard_ci]
permissions:
pull-requests: read
outputs:
should_test_geos: ${{ steps.check_label.outputs.should_test_geos }}
has_label: ${{ steps.check_label.outputs.has_label }}
steps:
- name: Check for GEOS integration test label
id: check_label
run: |
set -e # Exit immediately if a command exits with a non-zero status.
echo "Standard CI tests have passed. Now checking for GEOS integration requirements..."
# Check if the PR has the 'test-geos-integration' label
# -fsS gives Fails on Error (f), Silent on Success (s), Shows Error Message (S)
pr_json=$(curl -fsS -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.number }})
LABELS=$(echo ${pr_json} | jq -r '[.labels[].name] | join(",")')
echo "PR labels: ${LABELS}"
if [[ "${LABELS}" == *"test-geos-integration"* ]]; then
echo "has_label=true" >> $GITHUB_OUTPUT
echo "should_test_geos=true" >> $GITHUB_OUTPUT
echo "✅ Found 'test-geos-integration' label - will proceed with GEOS integration testing"
else
echo "has_label=false" >> $GITHUB_OUTPUT
echo "should_test_geos=false" >> $GITHUB_OUTPUT
echo "❌ Missing 'test-geos-integration' label"
echo ""
echo "REQUIRED: This PR must have the 'test-geos-integration' label to be merged"
echo "This ensures that changes are tested against GEOS before merging"
echo ""
echo "To add the label:"
echo "1. Go to your PR page"
echo "2. Click on 'Labels' in the right sidebar"
echo "3. Add the 'test-geos-integration' label"
exit 1
fi
# Step 3: Only trigger GEOS integration if label exists AND standard tests passed
trigger_geos_integration_test:
runs-on: ubuntu-latest
needs: [check_geos_integration_label]
if: needs.check_geos_integration_label.outputs.should_test_geos == 'true'
permissions:
pull-requests: read
outputs:
workflow_run_id: ${{ steps.trigger_workflow.outputs.workflow_run_id }}
steps:
- name: Get PR information
id: pr_info
run: |
echo "Triggering GEOS integration test..."
pr_json=$(curl -fsSL -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.number }}")
LABELS=$(echo "${pr_json}" | jq -r '[.labels[].name] | join(",")')
PR_HEAD_REPO=$(echo ${pr_json} | jq -r '.head.repo.clone_url')
PR_HEAD_BRANCH=$(echo ${pr_json} | jq -r '.head.ref')
PR_HEAD_SHA=$(echo ${pr_json} | jq -r '.head.sha')
echo "pr_repo=${PR_HEAD_REPO}" >> $GITHUB_OUTPUT
echo "pr_branch=${PR_HEAD_BRANCH}" >> $GITHUB_OUTPUT
echo "pr_sha=${PR_HEAD_SHA}" >> $GITHUB_OUTPUT
echo "PR Repository: ${PR_HEAD_REPO}"
echo "PR Branch: ${PR_HEAD_BRANCH}"
echo "PR SHA: ${PR_HEAD_SHA}"
- name: Trigger GEOS integration test workflow
id: trigger_workflow
run: |
set -e
echo "All standard tests passed ✅"
echo "GEOS integration label found ✅"
echo "Now triggering GEOS integration test workflow..."
# Determine which GEOS branch contains the workflow file
# Priority: 1) ci/benedicto/testGeosPythonPackagesIntegration (current dev branch)
# 2) develop (main branch)
# 3) main (fallback)
GEOS_BRANCH="ci/benedicto/testGeosPythonPackagesIntegration"
# Check if workflow exists on the target branch
echo "Checking if workflow exists on branch: ${GEOS_BRANCH}"
workflow_check=$(curl -fsSL \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
https://api.github.com/repos/GEOS-DEV/GEOS/contents/.github/workflows/test_geospythonpackages_integration.yml?ref=${GEOS_BRANCH} 2>/dev/null || echo "not_found")
if [[ "$workflow_check" == "not_found" ]]; then
echo "Workflow not found on ${GEOS_BRANCH}, trying develop branch..."
GEOS_BRANCH="develop"
workflow_check=$(curl -fsSL \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
https://api.github.com/repos/GEOS-DEV/GEOS/contents/.github/workflows/test_geospythonpackages_integration.yml?ref=${GEOS_BRANCH} 2>/dev/null || echo "not_found")
if [[ "$workflow_check" == "not_found" ]]; then
echo "❌ ERROR: Workflow file not found on develop branch either!"
echo "This could indicate a permissions issue with GEOS_INTEGRATION_TOKEN"
echo "Please verify the token has proper repository access"
exit 1
fi
fi
echo "✅ Found workflow on branch: ${GEOS_BRANCH}"
# Test the dispatch endpoint first
echo "Testing workflow dispatch endpoint access..."
dispatch_test=$(curl -fsSL \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
"https://api.github.com/repos/GEOS-DEV/GEOS/actions/workflows/test_geospythonpackages_integration.yml" 2>&1 || echo "endpoint_error")
if [[ "$dispatch_test" == "endpoint_error" ]]; then
echo "❌ ERROR: Cannot access workflow dispatch endpoint"
echo "This suggests the GEOS_INTEGRATION_TOKEN lacks 'actions:write' permission"
exit 1
fi
echo "✅ Workflow dispatch endpoint accessible"
# Trigger the workflow_dispatch event in the GEOS repository
# Note: ref should point to a branch that contains the workflow file
# The python package branch info is passed as inputs
echo "Triggering workflow dispatch on GEOS repository..."
echo "Target branch: ${GEOS_BRANCH}"
echo "Python package repo: ${{ steps.pr_info.outputs.pr_repo }}"
echo "Python package branch: ${{ steps.pr_info.outputs.pr_branch }}"
# Make the request with detailed error reporting
echo "Making workflow dispatch request..."
http_code=$(curl -w "%{http_code}" -o /tmp/dispatch_response.txt \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/GEOS-DEV/GEOS/actions/workflows/test_geospythonpackages_integration.yml/dispatches \
-d "{\"ref\": \"${GEOS_BRANCH}\", \"inputs\": {\"python_package_repo\": \"${{ steps.pr_info.outputs.pr_repo }}\", \"python_package_branch\": \"${{ steps.pr_info.outputs.pr_branch }}\", \"python_package_pr\": \"${{ github.event.number }}\", \"requested_by\": \"${{ github.actor }}\"}}")
echo "HTTP response code: $http_code"
echo "Response body:"
cat /tmp/dispatch_response.txt
# Check the HTTP response code
if [[ "$http_code" -eq 204 ]]; then
echo "✅ GEOS integration test workflow triggered successfully on branch: ${GEOS_BRANCH}"
elif [[ "$http_code" -eq 404 ]]; then
echo "❌ ERROR: 404 Not Found"
echo "Possible causes:"
echo "1. Workflow file does not exist on branch ${GEOS_BRANCH}"
echo "2. GEOS_INTEGRATION_TOKEN lacks access to GEOS-DEV/GEOS repository"
echo "3. Token is invalid or expired"
exit 1
elif [[ "$http_code" -eq 403 ]]; then
echo "❌ ERROR: 403 Forbidden"
echo "GEOS_INTEGRATION_TOKEN lacks 'actions:write' permission"
echo "The token needs both 'repo' and 'actions:write' scopes"
exit 1
elif [[ "$http_code" -eq 422 ]]; then
echo "❌ ERROR: 422 Unprocessable Entity"
echo "Invalid input data or workflow configuration issue"
echo "Check that all required inputs are provided correctly"
exit 1
else
echo "❌ ERROR: Unexpected HTTP response code: $http_code"
echo "Response body:"
cat /tmp/dispatch_response.txt
exit 1
fi
# Wait a moment for the workflow to start, then find the run ID
sleep 10
# Get the latest workflow runs to find our triggered run
runs_response=$(curl -fsS -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
https://api.github.com/repos/GEOS-DEV/GEOS/actions/workflows/test_geospythonpackages_integration.yml/runs?per_page=5)
# Find the most recent run (this assumes it's our triggered run)
workflow_run_id=$(echo "$runs_response" | jq -r '.workflow_runs[0].id')
echo "workflow_run_id=${workflow_run_id}" >> $GITHUB_OUTPUT
echo "Triggered workflow run ID: ${workflow_run_id}"
# Step 4: Wait for GEOS integration results (only if triggered)
wait_for_geos_integration_result:
runs-on: ubuntu-latest
needs: [trigger_geos_integration_test]
if: needs.trigger_geos_integration_test.outputs.workflow_run_id != ''
outputs:
geos_test_result: ${{ steps.wait_for_result.outputs.geos_test_result }}
steps:
- name: Wait for GEOS integration test to complete
id: wait_for_result
run: |
WORKFLOW_RUN_ID="${{ needs.trigger_geos_integration_test.outputs.workflow_run_id }}"
echo "Waiting for GEOS integration test to complete (Run ID: ${WORKFLOW_RUN_ID})..."
echo "This may take 15-30 minutes..."
# Wait for the workflow to complete (with timeout)
timeout=1800 # 30 minutes
elapsed=0
interval=60
while [ $elapsed -lt $timeout ]; do
run_status=$(curl -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
https://api.github.com/repos/GEOS-DEV/GEOS/actions/runs/${WORKFLOW_RUN_ID} \
| jq -r '.status')
conclusion=$(curl -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GEOS_INTEGRATION_TOKEN }}" \
https://api.github.com/repos/GEOS-DEV/GEOS/actions/runs/${WORKFLOW_RUN_ID} \
| jq -r '.conclusion')
echo "Workflow status: ${run_status}, conclusion: ${conclusion} (${elapsed}s elapsed)"
if [[ "${run_status}" == "completed" ]]; then
echo "Workflow completed with conclusion: ${conclusion}"
if [[ "${conclusion}" == "success" ]]; then
echo "✅ GEOS integration test PASSED"
echo "geos_test_result=success" >> $GITHUB_OUTPUT
exit 0
else
echo "❌ GEOS integration test FAILED"
echo "geos_test_result=failure" >> $GITHUB_OUTPUT
exit 1
fi
fi
sleep $interval
elapsed=$((elapsed + interval))
done
echo "❌ TIMEOUT: GEOS integration test did not complete within ${timeout} seconds"
echo "geos_test_result=timeout" >> $GITHUB_OUTPUT
exit 1
# Step 5: Final validation - requires ALL tests to pass
final_validation:
runs-on: ubuntu-latest
needs: [check_geos_integration_label, wait_for_geos_integration_result]
if: always()
steps:
- name: Final merge validation
run: |
echo "=== FINAL MERGE VALIDATION ==="
echo ""
echo "Standard CI Tests: ✅ PASSED (already validated)"
echo "GEOS Integration Label: ${{ needs.check_geos_integration_label.outputs.has_label == 'true' && '✅ PRESENT' || '❌ MISSING' }}"
echo "GEOS Integration Tests: ${{ needs.wait_for_geos_integration_result.outputs.geos_test_result == 'success' && '✅ PASSED' || needs.wait_for_geos_integration_result.result == 'skipped' && '⏭️ SKIPPED (no label)' || '❌ FAILED' }}"
echo ""
# Check label requirement
if [[ "${{ needs.check_geos_integration_label.outputs.has_label }}" != "true" ]]; then
echo "❌ INVALID: Missing 'test-geos-integration' label"
echo ""
echo "This PR cannot be merged without the 'test-geos-integration' label"
echo "Please add the label and wait for GEOS integration tests to pass"
exit 1
fi
# Check GEOS test results (only if they were supposed to run)
if [[ "${{ needs.wait_for_geos_integration_result.result }}" == "failure" || "${{ needs.wait_for_geos_integration_result.outputs.geos_test_result }}" == "failure" ]]; then
echo "❌ INVALID: GEOS integration tests failed"
echo ""
echo "The changes in this PR break GEOS functionality"
echo "Please check the GEOS workflow logs and fix the issues"
echo "GEOS workflow: https://github.com/GEOS-DEV/GEOS/actions/runs/${{ needs.trigger_geos_integration_test.outputs.workflow_run_id }}"
exit 1
fi
if [[ "${{ needs.wait_for_geos_integration_result.outputs.geos_test_result }}" == "timeout" ]]; then
echo "❌ INVALID: GEOS integration tests timed out"
echo ""
echo "Please check the GEOS workflow manually and re-run if needed"
echo "GEOS workflow: https://github.com/GEOS-DEV/GEOS/actions/runs/${{ needs.trigger_geos_integration_test.outputs.workflow_run_id }}"
exit 1
fi
# All validations passed
echo "✅ VALID: All requirements met"
echo ""
echo "This PR is ready for review and merge:"
echo " ✅ Standard CI tests passed"
echo " ✅ 'test-geos-integration' label present"
echo " ✅ GEOS integration tests passed"
echo ""
echo "🎉 Ready for merge!"