forked from streamlit/streamlit
-
Notifications
You must be signed in to change notification settings - Fork 0
254 lines (225 loc) · 9.39 KB
/
Copy pathplaywright.yml
File metadata and controls
254 lines (225 loc) · 9.39 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
name: Playwright E2E Tests
on:
push:
branches:
- "develop"
pull_request:
types: [opened, synchronize, reopened]
# Allows workflow to be called from other workflows
workflow_call:
inputs:
ref:
required: true
type: string
# Avoid duplicate workflows on same branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-playwright
cancel-in-progress: true
jobs:
playwright-e2e-tests:
runs-on: ubuntu-latest-64-cores
timeout-minutes: 30
defaults:
run:
shell: bash
steps:
- name: Checkout Streamlit code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs.ref }}
persist-credentials: false
submodules: "recursive"
fetch-depth: 2
- name: Set Python version vars
uses: ./.github/actions/build_info
- name: Setup virtual env
uses: ./.github/actions/make_init
with:
python_version: ${{ env.PYTHON_MAX_VERSION }}
- name: Install playwright
uses: ./.github/actions/playwright_install
- name: Build frontend
run: make frontend-with-profiler
- name: Get short SHA
id: short_sha
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "sha_short=$(echo ${{ github.event.pull_request.head.sha }} | cut -c1-6)" >> $GITHUB_OUTPUT
else
echo "sha_short=$(echo ${{ github.sha }} | cut -c1-6)" >> $GITHUB_OUTPUT
fi
- name: Run playwright tests
# With psutil installed, pytest-xdist's `-n auto` uses physical cores (32 on 64-core runner)
run: |
cd e2e_playwright && rm -rf ./test-results
uv run pytest --ignore ./custom_components --ignore ./load_testing --browser webkit --browser chromium --browser firefox -n auto --reruns 1 -m "not performance"
- name: Upload test statistics
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: playwright_test_stats
path: e2e_playwright/test-results/test-stats.json
if-no-files-found: ignore
- name: Upload failed test results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: playwright_test_results_${{ steps.short_sha.outputs.sha_short }}
path: e2e_playwright/test-results
check-e2e-test-count:
runs-on: ubuntu-latest
needs: playwright-e2e-tests
if: github.event_name == 'pull_request' && github.repository == 'streamlit/streamlit'
continue-on-error: true
permissions:
contents: read
pull-requests: write
actions: read
env:
NEW_TEST_THRESHOLD: 30
steps:
- name: Download current test stats
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
continue-on-error: true
with:
name: playwright_test_stats
path: current_stats
- name: Get latest develop run ID
id: get-latest-run
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { data: runs } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'playwright.yml',
branch: 'develop',
status: 'success',
per_page: 1
});
if (runs.workflow_runs.length === 0) {
core.warning('No successful workflow runs found on develop branch');
return;
}
core.setOutput('run_id', runs.workflow_runs[0].id);
- name: Download develop test stats
if: steps.get-latest-run.outputs.run_id
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
continue-on-error: true
with:
repository: streamlit/streamlit
run-id: ${{ steps.get-latest-run.outputs.run_id }}
name: playwright_test_stats
path: develop_stats
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Compare test counts and comment
if: steps.get-latest-run.outputs.run_id
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const fs = require('fs');
const path = require('path');
const threshold = +process.env.NEW_TEST_THRESHOLD;
const loadStats = (dir) => {
try {
const jsonPath = path.join(process.cwd(), dir, 'test-stats.json');
if (fs.existsSync(jsonPath)) {
return JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
}
console.log(`File not found: ${jsonPath}`);
return null;
} catch (e) {
console.log(`Error loading stats from ${dir}:`, e.message);
return null;
}
};
const currentStats = loadStats('current_stats');
const developStats = loadStats('develop_stats');
if (!currentStats) {
console.log('Missing current test stats, skipping comparison.');
return;
}
if (!developStats) {
console.log('Missing develop test stats, skipping comparison.');
return;
}
const currentTotal = currentStats.summary?.total_tests || 0;
const developTotal = developStats.summary?.total_tests || 0;
const newTests = currentTotal - developTotal;
console.log(`Current PR test count: ${currentTotal}`);
console.log(`Develop test count: ${developTotal}`);
console.log(`New tests: ${newTests}`);
console.log(`Threshold: ${threshold}`);
// Check if this PR is from a fork
const isForkPR = context.payload.pull_request?.head?.repo?.fork === true;
if (isForkPR) {
console.log('PR is from a fork - skipping comment (insufficient permissions)');
console.log('Test count information is available in the job logs above.');
return;
}
const isSignificant = newTests > threshold;
const commentIdentifier = '<!-- STREAMLIT-E2E-TEST-COUNT-CHECK -->';
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existingComment = comments.find(comment => comment.body.includes(commentIdentifier));
// Only comment if tests increased significantly (> threshold)
if (isSignificant || existingComment) {
let header;
let message;
if (isSignificant) {
header = `### 🧪 Significant E2E test count increase detected`;
message = `This PR has **added ${newTests} E2E test cases** (threshold: ${threshold})`;
} else {
// Previous comment exists but change is now within range
header = `### ✅ E2E test count change is within normal range`;
if (newTests === 0) {
message = `This PR has **no change** in E2E test count`;
} else if (newTests > 0) {
message = `This PR has **added ${newTests} E2E test cases**`;
} else {
message = `This PR has **removed ${Math.abs(newTests)} E2E test cases**`;
}
}
const lines = [
header,
'',
message,
'',
`- Current PR: ${currentTotal} tests`,
`- Latest develop: ${developTotal} tests`,
];
if (isSignificant) {
lines.push(
'',
'> ⚠️ **Note:** E2E tests are expensive to run. Please ensure you\'re following best practices:',
'> - Prefer aggregated scenario tests over many micro-tests',
'> - Add tests to existing files when they fit the scope',
'> - Test each aspect only once per browser run'
);
}
const commentBody = lines.join('\n');
const fullCommentBody = `${commentIdentifier}\n${commentBody}`;
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: fullCommentBody
});
console.log('Updated existing E2E test count comment');
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: fullCommentBody
});
console.log('Created new E2E test count comment');
}
} else {
console.log('Test count change is not significant (added <= threshold), skipping comment');
}