Repository navigation
183 lines (164 loc) · 6.23 KB
/
Copy pathpython-ci.yml
File metadata and controls
183 lines (164 loc) · 6.23 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
name: Delphi Python Tests
concurrency:
group: python-ci-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [ edge, stable ]
paths: &paths
- 'delphi/**/*.py'
- 'delphi/requirements*.txt'
- 'delphi/Dockerfile'
- 'scripts/*install.sh'
- 'scripts/application_stop.sh'
- 'scripts/validate_service.sh'
- 'scripts/test-deploy-hooks.sh'
- 'scripts/run-import-dry-run.py'
- 'docker-compose*.yml'
- '.github/workflows/python-ci.yml'
- 'ci/test-migrations.sh'
- 'ci/local/delphi-python.sh'
- 'ci/local/delphi_python_results.py'
- 'ci/local/delphi-test-durations.json'
- 'ci/local/test-images.sh'
- '.github/workflows/test-images.yml'
- 'docker-compose.test.yml'
- 'server/Dockerfile-db'
- 'server/postgres/**'
- 'queue-rs/polis-migrate/**'
# server/src so a new server-side wildcard runs the projection-gate sweep
- 'server/src/**'
# Representative payload tests execute the probe planner and independent gate.
- 'ci/private_cert/**'
- 'ci/probe_box/**'
pull_request:
branches:
- edge
- stable
- 'jc/**'
paths: *paths
# Manual trigger: lets repo write-access users run CI on any branch
# (including spr/edge/* stack branches, which `pull_request` no longer
# auto-triggers for). UI: Actions → Delphi Python Tests → "Run workflow".
# CLI: `gh workflow run "Delphi Python Tests" --ref <branch>`.
workflow_dispatch:
jobs:
# Every step of the check lives in ci/local/delphi-python.sh, which runs the
# same way on any Docker host. Hosted CI builds the stack's images once
# (test-images.yml), splits the suite into shards (each also parallel inside
# its job) that run from those images, and the `test` job puts the shards
# back together: it proves every test ran in exactly one shard, adds up the
# counts and combines coverage.
images:
uses: ./.github/workflows/test-images.yml
with:
# The suite runs against Postgres and the delphi image (math-python runs it too).
images: postgres,delphi
shard:
name: test shard ${{ matrix.shard }}
needs: images
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4, 5, 6]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download the test images
uses: actions/download-artifact@v4
with:
name: test-images
path: ${{ runner.temp }}/test-images
- name: Load the test images
run: |
bash ci/local/test-images.sh load "$RUNNER_TEMP/test-images"
rm -rf "$RUNNER_TEMP/test-images"
df -h /
- name: Delphi pytest (shard ${{ matrix.shard }}/${{ strategy.job-total }})
env:
POLIS_TEST_IMAGES: ci
DELPHI_CHECK_OUT: ${{ github.workspace }}/delphi-results/shard-${{ matrix.shard }}
# The runner is discarded after the job; tearing the stack down only costs time.
DELPHI_CHECK_KEEP: '1'
run: bash ci/local/delphi-python.sh --shard ${{ matrix.shard }}/${{ strategy.job-total }}
- name: Upload shard results
if: always()
uses: actions/upload-artifact@v4
with:
name: delphi-shard-${{ matrix.shard }}
path: |
delphi-results/shard-${{ matrix.shard }}
!delphi-results/shard-${{ matrix.shard }}/stack
if-no-files-found: ignore
test:
needs: shard
if: always()
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Every shard passed
run: |
echo "shards: ${{ needs.shard.result }}"
test "${{ needs.shard.result }}" = success
- name: Download shard results
uses: actions/download-artifact@v4
with:
pattern: delphi-shard-*
path: delphi-results
- name: Combine shards (counts, coverage)
env:
DELPHI_CHECK_OUT: ${{ github.workspace }}/delphi-results/combined
run: |
bash ci/local/delphi-python.sh combine delphi-results/delphi-shard-*
cp delphi-results/combined/coverage-comment.md coverage-comment.md
- name: Upload Coverage Report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage-comment.md
- name: Post Coverage Comment
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const commentBody = fs.readFileSync('coverage-comment.md', 'utf8');
const marker = '<!-- delphi-coverage-report -->';
const body = `${marker}\n## Delphi Coverage Report\n\n${commentBody}`;
try {
// Find existing coverage comment
const { data: comments } = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const existingComment = comments.find(c => c.body.includes(marker));
if (existingComment) {
// Delete existing comment so new one appears after latest commit
await github.rest.issues.deleteComment({
comment_id: existingComment.id,
owner: context.repo.owner,
repo: context.repo.repo,
});
console.log('Existing coverage comment deleted.');
}
// Always create a new comment
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
console.log('Coverage comment posted successfully.');
} catch (error) {
if (error.status === 403) {
console.log('Note: Could not post coverage comment to PR.');
console.log('This is expected for PRs from forks due to GitHub token permissions.');
console.log('Coverage report is in the log of the test job and in the coverage-report artifact.');
} else {
console.log(`Unexpected error posting comment: ${error.message}`);
}
}