mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 08:09:27 +00:00
ci: make merge-reports-to-TestDino non-blocking for playwright_summary (#11457)
## Summary - In `playwright_summary`, `merge_and_upload_reports` result of `failure` is now treated as non-blocking (same as `success`/`skipped`) - The Playwright summary check will pass even if the TestDino merge/upload job fails (e.g. network issues, bad token, API outage) - Actual test results (`build_binary`, `ui_integration_tests`) still gate the summary as before ## Why The TestDino upload is observability/reporting infrastructure — it should never cause a PR's required check to fail when the tests themselves passed. Previously a transient TestDino failure would block merges. ## Test plan - [ ] Verify `playwright_summary` passes when `merge_and_upload_reports` succeeds (existing behavior) - [ ] Verify `playwright_summary` passes when `merge_and_upload_reports` fails (new behavior) - [ ] Verify `playwright_summary` still fails when `ui_integration_tests` fails (unchanged) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
90f2d4e33e
commit
cb4c799476
@@ -52,10 +52,11 @@ jobs:
|
||||
sort_key: ([.title | scan("[0-9]+")] | map(tonumber))
|
||||
}) |
|
||||
map(select(.sort_key | length > 0)) |
|
||||
. as $ms |
|
||||
(($ms | map(select(.due_ts == null or .due_ts >= now)) | sort_by(.sort_key) | .[0].title) //
|
||||
($ms | sort_by(.due_ts) | .[-1].title) //
|
||||
empty)')
|
||||
sort_by(.sort_key) |
|
||||
if length == 0 then empty
|
||||
elif (.[0].due_ts != null and .[0].due_ts < now) then (.[1].title // .[0].title)
|
||||
else .[0].title
|
||||
end')
|
||||
|
||||
if [ -n "$MILESTONE" ]; then
|
||||
gh pr edit "$NUMBER" -m "$MILESTONE" \
|
||||
@@ -127,10 +128,11 @@ jobs:
|
||||
sort_key: ([.title | scan("[0-9]+")] | map(tonumber))
|
||||
}) |
|
||||
map(select(.sort_key | length > 0)) |
|
||||
. as $ms |
|
||||
(($ms | map(select(.due_ts == null or .due_ts >= now)) | sort_by(.sort_key) | .[0].title) //
|
||||
($ms | sort_by(.due_ts) | .[-1].title) //
|
||||
empty)')
|
||||
sort_by(.sort_key) |
|
||||
if length == 0 then empty
|
||||
elif (.[0].due_ts != null and .[0].due_ts < now) then (.[1].title // .[0].title)
|
||||
else .[0].title
|
||||
end')
|
||||
|
||||
if [ -n "$MILESTONE" ]; then
|
||||
gh issue edit "$NUMBER" -m "$MILESTONE" \
|
||||
|
||||
@@ -1027,7 +1027,7 @@ jobs:
|
||||
UI_OK=true
|
||||
fi
|
||||
|
||||
if [ "${{ needs.merge_and_upload_reports.result }}" == "success" ] || [ "${{ needs.merge_and_upload_reports.result }}" == "skipped" ]; then
|
||||
if [ "${{ needs.merge_and_upload_reports.result }}" == "success" ] || [ "${{ needs.merge_and_upload_reports.result }}" == "skipped" ] || [ "${{ needs.merge_and_upload_reports.result }}" == "failure" ]; then
|
||||
MERGE_OK=true
|
||||
fi
|
||||
|
||||
|
||||
@@ -62,3 +62,4 @@ tests/ui-testing/seed-mcp.spec.js
|
||||
tests/ui-testing/docs/test_generator/audit-reports/cloud-compatibility-audit-2026-03-05.md
|
||||
tests/ui-testing/scripts/check-topology.js
|
||||
v0.70.0_release_gap_report.pdf
|
||||
tests/ui-testing/.env.old
|
||||
|
||||
@@ -2,6 +2,7 @@ import { expect } from '@playwright/test';
|
||||
const { waitUtils } = require('../../playwright-tests/utils/wait-helpers.js');
|
||||
const testLogger = require('../../playwright-tests/utils/test-logger.js');
|
||||
const { getAuthHeaders, getOrgIdentifier } = require('../../playwright-tests/utils/cloud-auth.js');
|
||||
const MonacoEditorHelper = require('../../playwright-tests/utils/MonacoEditorHelper.js');
|
||||
|
||||
export class SanityPage {
|
||||
constructor(page) {
|
||||
@@ -288,14 +289,13 @@ export class SanityPage {
|
||||
|
||||
const queryEditor = this.page.locator(this.queryEditorContent);
|
||||
await expect(queryEditor).toBeVisible({ timeout: 10000 });
|
||||
|
||||
await queryEditor.getByRole('code').click();
|
||||
await this.page.keyboard.press(process.platform === "darwin" ? "Meta+A" : "Control+A");
|
||||
await this.page.keyboard.press("Backspace");
|
||||
await this.page.waitForTimeout(300);
|
||||
await queryEditor.locator('.inputarea').fill('SELECT * FROM "e2e_automate" ORDER BY _timestamp DESC limit 5');
|
||||
|
||||
await this.page.waitForLoadState('domcontentloaded');
|
||||
|
||||
// Use MonacoEditorHelper to replace editor content via keyboard events.
|
||||
// .fill() on Monaco's .inputarea appends instead of replacing, producing an
|
||||
// invalid concatenated query that causes the server to abort the stream.
|
||||
const monacoHelper = new MonacoEditorHelper(this.page);
|
||||
await monacoHelper.setContent(queryEditor, 'SELECT * FROM "e2e_automate" ORDER BY _timestamp DESC limit 5');
|
||||
|
||||
const limitSearchPromise = this.page.waitForResponse(resp => resp.url().includes('/_search'), { timeout: 30000 });
|
||||
await this.page.locator(this.refreshButton).click({ force: true });
|
||||
await limitSearchPromise;
|
||||
|
||||
@@ -311,7 +311,9 @@ test.describe("Dashboard Table Chart - Core Features", () => {
|
||||
);
|
||||
|
||||
// First apply: execute the query with VRL so the new field is generated
|
||||
const streamPromise1 = waitForStreamComplete(page);
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
await streamPromise1;
|
||||
await pm.chartTypeSelector.waitForTableDataLoad();
|
||||
|
||||
// Now enable dynamic columns so the VRL-created field appears as a column
|
||||
@@ -319,7 +321,9 @@ test.describe("Dashboard Table Chart - Core Features", () => {
|
||||
await pm.dashboardPanelConfigs.selectDynamicColumns();
|
||||
|
||||
// Second apply: re-render table with dynamic columns enabled
|
||||
const streamPromise2 = waitForStreamComplete(page);
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
await streamPromise2;
|
||||
await pm.chartTypeSelector.waitForTableDataLoad();
|
||||
|
||||
// Verify the VRL-created field appears as a column in the table
|
||||
|
||||
@@ -1035,11 +1035,11 @@ test.describe("Dashboard Table Chart Pagination Feature - PromQL Tables", () =>
|
||||
const queryEditor = page.locator('[data-test="dashboard-panel-query-editor"]');
|
||||
await queryEditor.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
// Focus on the editor and enter a simple PromQL query using keyboard.type for reliable Monaco input
|
||||
// Use .inputarea.fill() to directly set Monaco's textarea value — same pattern as
|
||||
// the passing custom SQL test (line 934). keyboard.type() leaves autocomplete open
|
||||
// and doesn't reliably trigger Vue's reactive model update, causing "Query-1 is empty".
|
||||
await queryEditor.getByRole('code').click();
|
||||
await page.keyboard.press('Control+a');
|
||||
await page.keyboard.type('cpu_usage{}');
|
||||
await page.keyboard.press('Escape'); // Dismiss any Monaco autocomplete suggestions
|
||||
await queryEditor.locator('.inputarea').fill('cpu_usage{}');
|
||||
|
||||
// Apply
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
@@ -1070,8 +1070,10 @@ test.describe("Dashboard Table Chart Pagination Feature - PromQL Tables", () =>
|
||||
|
||||
testLogger.info('Verified pagination works for PromQL table chart');
|
||||
|
||||
// Clean up - save panel first before navigating back
|
||||
await pm.dashboardPanelActions.savePanel();
|
||||
// The router guard (onBeforeRouteLeave) fires window.confirm when leaving with
|
||||
// unsaved changes. Accept it so navigation to ViewDashboard completes.
|
||||
page.once('dialog', dialog => dialog.accept());
|
||||
await page.locator('[data-test="dashboard-panel-discard"]').click();
|
||||
await pm.dashboardCreate.backToDashboardList();
|
||||
await deleteDashboard(page, dashboardName);
|
||||
});
|
||||
|
||||
@@ -78,15 +78,28 @@ const test = baseTest.extend({
|
||||
},
|
||||
|
||||
// Enhanced page fixture
|
||||
page: async ({ context }, use) => {
|
||||
page: async ({ context }, use, testInfo) => {
|
||||
const page = await context.newPage();
|
||||
|
||||
|
||||
// Add wait helpers to page
|
||||
page.waitHelpers = waitUtils.create(page);
|
||||
|
||||
|
||||
testLogger.debug('New page created with global session and wait helpers');
|
||||
|
||||
|
||||
await use(page);
|
||||
|
||||
// On failure, click "Click for error details" before the framework takes its auto-screenshot.
|
||||
// This ensures the expanded error dialog is visible in the failure screenshot.
|
||||
if (testInfo.status === 'failed' || testInfo.status === 'timedOut') {
|
||||
try {
|
||||
const errorBtn = page.getByRole('button', { name: /click for error details/i });
|
||||
const isVisible = await errorBtn.isVisible({ timeout: 2000 }).catch(() => false);
|
||||
if (isVisible) {
|
||||
await errorBtn.click({ force: true }).catch(() => {});
|
||||
await page.waitForTimeout(800);
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user