Skip to content

Commit e7c128f

Browse files
Merge branch 'main' into fix/centralized-timeseries-cleanup-on-entity-delete
2 parents edc3901 + 219490a commit e7c128f

252 files changed

Lines changed: 12259 additions & 1532 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-openmetadata-test-environment/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ runs:
5353

5454
- name: Install yarn
5555
if: ${{ inputs.install-server == 'true' }}
56-
run: npm install -g yarn
56+
run: corepack enable
5757
shell: bash
5858
# ------------------------------------------------------------------------------
5959

.github/workflows/openmetadata-service-unit-tests.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ jobs:
6565
timeout-minutes: 90
6666
needs: changes
6767
if: ${{ needs.changes.outputs.java == 'true' }}
68+
strategy:
69+
fail-fast: false
70+
matrix:
71+
database: [mysql, postgresql]
6872
steps:
6973
- name: Checkout
7074
uses: actions/checkout@v4
@@ -97,20 +101,20 @@ jobs:
97101
librdkafka-dev unixodbc-dev libevent-dev jq
98102
sudo make install_antlr_cli
99103
100-
- name: Run openmetadata-service unit tests
104+
- name: Run openmetadata-service unit tests (${{ matrix.database }})
101105
env:
102106
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
103107
run: |
104108
mvn -B clean package -pl openmetadata-service -am \
105-
-Pstatic-code-analysis \
109+
-Pstatic-code-analysis,${{ matrix.database }} \
106110
-DfailIfNoTests=false \
107111
-Dsonar.skip=true
108112
109113
- name: Upload surefire reports
110114
if: ${{ failure() && hashFiles('openmetadata-service/target/surefire-reports/TEST-*.xml') != '' }}
111115
uses: actions/upload-artifact@v4
112116
with:
113-
name: openmetadata-service-surefire-reports
117+
name: openmetadata-service-surefire-reports-${{ matrix.database }}
114118
path: openmetadata-service/target/surefire-reports/
115119

116120
- name: Publish Test Report
@@ -120,6 +124,7 @@ jobs:
120124
github_token: ${{ secrets.GITHUB_TOKEN }}
121125
fail_on_test_failures: true
122126
report_paths: "openmetadata-service/target/surefire-reports/TEST-*.xml"
127+
check_name: "Test Report (${{ matrix.database }})"
123128

124129
# Single required-check gate for branch protection.
125130
# Skipped (= "Success") when all test jobs pass or are legitimately skipped.

.github/workflows/playwright-sso-tests.yml

Lines changed: 222 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,53 @@
99
# See the License for the specific language governing permissions and
1010
# limitations under the License.
1111

12-
# This workflow executes SSO-specific end-to-end (e2e) tests using Playwright with MySQL as the database.
13-
#
12+
# This workflow executes SSO-specific end-to-end (e2e) tests using Playwright with PostgreSQL as the database.
13+
#
1414
# Purpose:
15-
# - Run SSO configuration tests for various authentication providers (Google, Azure AD, Okta, SAML, LDAP, etc.)
16-
# - Validate SSO provider selection, field visibility, and configuration workflows
17-
# - Tests are tagged with @sso and run in isolation from other Playwright tests
15+
# - Run SSO token renewal E2E tests using a mock OIDC provider on PRs
16+
# - Run SSO configuration tests for various providers (Google, Azure AD, Okta, etc.) via manual trigger
17+
# - Tests run in isolation from the regular sharded Playwright E2E tests
1818
#
1919
# Triggers:
20-
# - Manual trigger via workflow_dispatch
21-
# - Pull requests with "safe to test" label
22-
# - Excludes draft PRs
20+
# - Pull requests with "safe to test" label (mock-oidc only, Chromium + WebKit)
21+
# - Manual trigger via workflow_dispatch (any SSO provider, Chromium + WebKit)
2322
#
2423
# Test Location:
25-
# - openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/SSOConfiguration.spec.ts
26-
#
27-
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path
24+
# - openmetadata-ui/src/main/resources/ui/playwright/e2e/Auth/SSOAuthentication.spec.ts (mock-oidc)
2825

29-
name: SSO Authentication Tests (Nightly)
26+
name: SSO Playwright E2E Tests
3027

3128
on:
32-
# schedule:
33-
# # Run every night at 2 AM UTC
34-
# - cron: '0 2 * * *'
35-
workflow_dispatch: # Allow manual trigger
29+
pull_request_target:
30+
types:
31+
- labeled
32+
- opened
33+
- synchronize
34+
- reopened
35+
- ready_for_review
36+
paths:
37+
- "openmetadata-ui/src/main/resources/ui/src/components/Auth/**"
38+
- "openmetadata-ui/src/main/resources/ui/src/rest/auth-API*"
39+
- "openmetadata-ui/src/main/resources/ui/src/utils/AuthProvider*"
40+
- "openmetadata-ui/src/main/resources/ui/src/utils/TokenServiceUtil*"
41+
- "openmetadata-ui/src/main/resources/ui/src/utils/UserDataUtils*"
42+
- "openmetadata-ui/src/main/resources/ui/src/hooks/useSignIn*"
43+
- "openmetadata-ui/src/main/resources/ui/playwright/e2e/Auth/**"
44+
- "openmetadata-ui/src/main/resources/ui/playwright/utils/mockOidc*"
45+
- "openmetadata-ui/src/main/resources/ui/playwright.sso.config.ts"
46+
- "docker/development/mock-oidc-provider/**"
47+
- "docker/development/docker-compose.yml"
48+
- "docker/development/.env.sso-test"
49+
- ".github/workflows/playwright-sso-tests.yml"
50+
workflow_dispatch:
3651
inputs:
3752
sso_provider:
3853
description: "SSO Provider to test"
3954
required: true
40-
default: "google"
55+
default: "mock-oidc"
4156
type: choice
4257
options:
58+
- mock-oidc
4359
- google
4460
- okta
4561
- azure
@@ -49,9 +65,10 @@ on:
4965

5066
permissions:
5167
contents: read
68+
pull-requests: write
5269

5370
concurrency:
54-
group: sso-auth-tests-${{ github.workflow }}-${{ github.event.inputs.sso_provider || 'scheduled' }}
71+
group: sso-playwright-${{ github.event.pull_request.number || github.run_id }}
5572
cancel-in-progress: true
5673

5774
jobs:
@@ -63,7 +80,7 @@ jobs:
6380
strategy:
6481
fail-fast: false
6582
matrix:
66-
provider: ${{ github.event.inputs.sso_provider == 'all' && fromJSON('["google", "okta", "azure", "auth0"]') || github.event.inputs.sso_provider && fromJSON(format('["{0}"]', github.event.inputs.sso_provider)) || fromJSON('["google"]') }}
83+
provider: ${{ github.event_name == 'pull_request_target' && fromJSON('["mock-oidc"]') || github.event.inputs.sso_provider && fromJSON(format('["{0}"]', github.event.inputs.sso_provider)) || fromJSON('["mock-oidc"]') }}
6784

6885
steps:
6986
- name: Free Disk Space (Ubuntu)
@@ -93,7 +110,7 @@ jobs:
93110
github-token: "${{ secrets.GITHUB_TOKEN }}"
94111
valid-labels: "safe to test"
95112
pull-request-number: "${{ github.event.pull_request.number }}"
96-
disable-reviews: true # To not auto approve changes
113+
disable-reviews: true
97114

98115
- name: Checkout
99116
uses: actions/checkout@v4
@@ -109,13 +126,43 @@ jobs:
109126
restore-keys: |
110127
${{ runner.os }}-maven-
111128
129+
- name: Start Mock OIDC Provider
130+
if: ${{ matrix.provider == 'mock-oidc' }}
131+
run: |
132+
cd docker/development
133+
docker compose --profile sso-test build mock-oidc-provider
134+
docker compose --profile sso-test up -d mock-oidc-provider
135+
echo "Waiting for mock OIDC provider to be healthy..."
136+
for i in $(seq 1 30); do
137+
if curl -sf http://localhost:9090/health > /dev/null 2>&1; then
138+
echo "Mock OIDC provider is ready"
139+
break
140+
fi
141+
echo "Waiting... ($i/30)"
142+
sleep 2
143+
done
144+
curl -sf http://localhost:9090/.well-known/openid-configuration || echo "WARNING: Discovery endpoint not ready"
145+
112146
- name: Setup Openmetadata Test Environment
113147
uses: ./.github/actions/setup-openmetadata-test-environment
114148
with:
115149
python-version: "3.10"
116-
# Skip ingestion setup for SSO tests
117150
args: "-d postgresql -i false"
118151
ingestion_dependency: "all"
152+
env:
153+
AUTHENTICATION_PROVIDER: ${{ matrix.provider == 'mock-oidc' && 'custom-oidc' || 'basic' }}
154+
CUSTOM_OIDC_AUTHENTICATION_PROVIDER_NAME: ${{ matrix.provider == 'mock-oidc' && 'mock-oidc' || '' }}
155+
AUTHENTICATION_PUBLIC_KEYS: ${{ matrix.provider == 'mock-oidc' && '[http://localhost:9090/jwks,http://localhost:8585/api/v1/system/config/jwks]' || '[http://localhost:8585/api/v1/system/config/jwks]' }}
156+
AUTHENTICATION_AUTHORITY: ${{ matrix.provider == 'mock-oidc' && 'http://localhost:9090' || 'https://accounts.google.com' }}
157+
AUTHENTICATION_CLIENT_ID: ${{ matrix.provider == 'mock-oidc' && 'openmetadata-test' || '' }}
158+
AUTHENTICATION_CALLBACK_URL: ${{ matrix.provider == 'mock-oidc' && 'http://localhost:8585/callback' || '' }}
159+
OIDC_CLIENT_ID: ${{ matrix.provider == 'mock-oidc' && 'openmetadata-test' || '' }}
160+
OIDC_TYPE: ${{ matrix.provider == 'mock-oidc' && 'custom-oidc' || '' }}
161+
OIDC_CLIENT_SECRET: ${{ matrix.provider == 'mock-oidc' && 'openmetadata-test-secret' || '' }}
162+
OIDC_DISCOVERY_URI: ${{ matrix.provider == 'mock-oidc' && 'http://localhost:9090/.well-known/openid-configuration' || '' }}
163+
OIDC_CALLBACK: ${{ matrix.provider == 'mock-oidc' && 'http://localhost:8585/callback' || 'http://localhost:8585/callback' }}
164+
OIDC_SERVER_URL: ${{ matrix.provider == 'mock-oidc' && 'http://localhost:8585' || 'http://localhost:8585' }}
165+
AUTHENTICATION_CLIENT_TYPE: ${{ matrix.provider == 'mock-oidc' && 'confidential' || 'public' }}
119166

120167
- name: Setup Node.js
121168
uses: actions/setup-node@v4
@@ -127,11 +174,22 @@ jobs:
127174
run: yarn --ignore-scripts --frozen-lockfile
128175

129176
- name: Install Playwright Browsers
130-
run: npx playwright@1.51.1 install chromium --with-deps
177+
run: npx playwright@1.51.1 install chromium webkit --with-deps
178+
179+
- name: Run Mock OIDC Authentication Tests
180+
if: ${{ matrix.provider == 'mock-oidc' }}
181+
working-directory: openmetadata-ui/src/main/resources/ui
182+
run: npx playwright test --config=playwright.sso.config.ts --workers=1
183+
env:
184+
MOCK_OIDC_URL: http://localhost:9090
185+
PLAYWRIGHT_IS_OSS: true
186+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
187+
timeout-minutes: 60
131188

132189
- name: Run SSO Authentication Tests
190+
if: ${{ matrix.provider != 'mock-oidc' }}
133191
working-directory: openmetadata-ui/src/main/resources/ui
134-
run: npx playwright test playwright/e2e/Auth/SSOAuthentication.spec.ts --workers=1
192+
run: npx playwright test --config=playwright.sso.config.ts --workers=1
135193
env:
136194
SSO_PROVIDER_TYPE: ${{ matrix.provider }}
137195
SSO_USERNAME: ${{ secrets[format('{0}_SSO_USERNAME', upper(matrix.provider))] }}
@@ -145,21 +203,154 @@ jobs:
145203
uses: actions/upload-artifact@v4
146204
with:
147205
name: sso-auth-test-results-${{ matrix.provider }}
148-
path: openmetadata-ui/src/main/resources/ui/playwright/output/playwright-report
206+
path: |
207+
openmetadata-ui/src/main/resources/ui/playwright/output/sso-playwright-report
208+
openmetadata-ui/src/main/resources/ui/playwright/output/sso-test-results
149209
retention-days: 5
150210

211+
- name: Upload results JSON for summary
212+
uses: actions/upload-artifact@v4
213+
if: ${{ !cancelled() }}
214+
with:
215+
name: sso-results-json-${{ matrix.provider }}
216+
path: openmetadata-ui/src/main/resources/ui/playwright/output/sso-results.json
217+
retention-days: 1
218+
if-no-files-found: ignore
219+
151220
- name: Clean Up
152221
run: |
153222
cd ./docker/development
223+
docker compose --profile sso-test down --remove-orphans 2>/dev/null || true
154224
docker compose down --remove-orphans
155225
sudo rm -rf ${PWD}/docker-volume
156-
157-
notify:
226+
227+
sso-summary:
228+
if: ${{ !cancelled() && github.event_name == 'pull_request_target' }}
158229
needs: sso-auth-tests
159230
runs-on: ubuntu-latest
160-
if: failure()
161231
steps:
162-
- name: Send notification on failure
163-
run: |
164-
echo "SSO Authentication tests failed for one or more providers"
165-
# Add your notification logic here (Slack, email, etc.)
232+
- name: Download results JSON
233+
uses: actions/download-artifact@v4
234+
with:
235+
pattern: sso-results-json-*
236+
path: results
237+
238+
- name: Post SSO test summary as PR comment
239+
uses: actions/github-script@v7
240+
with:
241+
github-token: ${{ secrets.GITHUB_TOKEN }}
242+
script: |
243+
const fs = require('fs');
244+
const path = require('path');
245+
246+
const runId = '${{ github.run_id }}';
247+
const repo = context.repo;
248+
const prNumber = context.payload.pull_request?.number;
249+
if (!prNumber) return;
250+
251+
const artifactUrl = `https://github.com/${repo.owner}/${repo.repo}/actions/runs/${runId}`;
252+
const commentMarker = '<!-- sso-playwright-summary -->';
253+
254+
const allTests = [];
255+
const resultsDir = 'results';
256+
if (fs.existsSync(resultsDir)) {
257+
for (const dir of fs.readdirSync(resultsDir).sort()) {
258+
const jsonPath = path.join(resultsDir, dir, 'sso-results.json');
259+
if (!fs.existsSync(jsonPath)) continue;
260+
261+
const report = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
262+
263+
function collectTests(suite, filePath) {
264+
const file = suite.file || filePath || '';
265+
for (const spec of (suite.specs || [])) {
266+
for (const test of (spec.tests || [])) {
267+
const results = test.results || [];
268+
const lastResult = results[results.length - 1] || {};
269+
const firstResult = results[0] || {};
270+
allTests.push({
271+
title: spec.title,
272+
project: test.projectName || '',
273+
file: file,
274+
status: test.status,
275+
retries: results.length - 1,
276+
error: lastResult.error?.message || firstResult.error?.message || '',
277+
});
278+
}
279+
}
280+
for (const child of (suite.suites || [])) {
281+
collectTests(child, file);
282+
}
283+
}
284+
for (const suite of (report.suites || [])) {
285+
collectTests(suite, '');
286+
}
287+
}
288+
}
289+
290+
if (allTests.length === 0) {
291+
console.log('No SSO test results found');
292+
return;
293+
}
294+
295+
const passed = allTests.filter(t => t.status === 'expected');
296+
const failed = allTests.filter(t => t.status === 'unexpected');
297+
const flaky = allTests.filter(t => t.status === 'flaky');
298+
const skipped = allTests.filter(t => t.status === 'skipped');
299+
300+
const lines = [commentMarker];
301+
302+
if (failed.length > 0) {
303+
lines.push(`## 🔴 SSO Playwright Results — ${failed.length} failure(s)${flaky.length > 0 ? `, ${flaky.length} flaky` : ''}`);
304+
} else if (flaky.length > 0) {
305+
lines.push(`## 🟡 SSO Playwright Results — all passed (${flaky.length} flaky)`);
306+
} else {
307+
lines.push(`## ✅ SSO Playwright Results — all ${passed.length} tests passed`);
308+
}
309+
lines.push('');
310+
lines.push(`✅ ${passed.length} passed · ❌ ${failed.length} failed · 🟡 ${flaky.length} flaky · ⏭️ ${skipped.length} skipped`);
311+
lines.push('');
312+
313+
if (failed.length > 0) {
314+
lines.push('### Failures');
315+
lines.push('');
316+
for (const t of failed.slice(0, 20)) {
317+
lines.push(`<details><summary>❌ ${t.project} › ${t.title}</summary>`);
318+
lines.push('');
319+
lines.push('```');
320+
lines.push(t.error.substring(0, 1000));
321+
lines.push('```');
322+
lines.push('</details>');
323+
lines.push('');
324+
}
325+
}
326+
327+
if (flaky.length > 0) {
328+
lines.push(`<details><summary>🟡 ${flaky.length} flaky test(s)</summary>`);
329+
lines.push('');
330+
for (const t of flaky.slice(0, 20)) {
331+
lines.push(`- ${t.project} › ${t.title} (${t.retries} ${t.retries === 1 ? 'retry' : 'retries'})`);
332+
}
333+
lines.push('');
334+
lines.push('</details>');
335+
lines.push('');
336+
}
337+
338+
lines.push(`📦 [View run details](${artifactUrl})`);
339+
340+
const body = lines.join('\n');
341+
342+
let existingComment = null;
343+
for await (const response of github.paginate.iterator(
344+
github.rest.issues.listComments, { ...repo, issue_number: prNumber, per_page: 100 }
345+
)) {
346+
const found = response.data.find(c =>
347+
c.user?.login === 'github-actions[bot]' && c.body?.includes(commentMarker)
348+
);
349+
if (found) { existingComment = found; break; }
350+
}
351+
352+
if (existingComment) {
353+
await github.rest.issues.updateComment({ ...repo, comment_id: existingComment.id, body });
354+
} else {
355+
await github.rest.issues.createComment({ ...repo, issue_number: prNumber, body });
356+
}

.github/workflows/update-playwright-e2e-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
cache-dependency-path: openmetadata-ui/src/main/resources/ui/yarn.lock
4141

4242
- name: Install Yarn
43-
run: npm install -g yarn
43+
run: corepack enable
4444

4545
- name: Install Dependencies
4646
working-directory: openmetadata-ui/src/main/resources/ui

0 commit comments

Comments
 (0)