From b8f0b9b23e7b3fe7ff57938598c168a93c1028da Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 17:09:53 +0000 Subject: [PATCH 01/10] Resolve RC client version from server_version, not v3 VERSION The Generic CLI suite resolved the expected pmm-admin version for a `pmm3-rc` client by curl-ing Percona-Lab/pmm-submodules v3 VERSION. The moment an RC branches, that file is bumped to the next dev version, so during RC testing the client reports 3.9.0 while the test expects 3.9.1 -> every Generic leg failed on `pmm-admin --version` / `summary --version`. Resolve the expected version from `pmm-admin status --json` (server_version) for `pmm3-rc` too, reusing the existing feature-build path, so the reference tracks the artifact under test rather than the moving v3 line. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- cli/tests/generic.spec.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cli/tests/generic.spec.ts b/cli/tests/generic.spec.ts index bab005d2f..66670bf05 100644 --- a/cli/tests/generic.spec.ts +++ b/cli/tests/generic.spec.ts @@ -16,13 +16,14 @@ test.describe('PMM Client "Generic" CLI tests', { tag: '@generic' }, () => { }); let PMM_VERSION = `${process.env.CLIENT_VERSION}`; - if (/^https?:/.test(PMM_VERSION)) { - // An explicit build URL (feature build) carries the version of the branch it was built - // from, which may predate the latest bump on v3. The server under test comes from that - // same build, so it is the only valid reference for the client's version. + if (/^https?:/.test(PMM_VERSION) || /pmm3-rc/.test(PMM_VERSION)) { + // An explicit build URL (feature build) or a release-candidate client carries the version of + // the branch/artifact it was built from, which may predate the latest bump on v3: the moment + // an RC branches, v3 VERSION already moves ahead to the next dev version. The server under test + // comes from that same build, so it is the only valid reference for the client's version. PMM_VERSION = JSON.parse(cli.execute('sudo pmm-admin status --json').stdout).pmm_agent_status?.server_version; if (!PMM_VERSION) throw new Error('Could not read server version from "pmm-admin status --json"'); - } else if (/latest-tarball|3-dev-latest|pmm3-rc/.test(PMM_VERSION)) { + } else if (/latest-tarball|3-dev-latest/.test(PMM_VERSION)) { // TODO: refactor to use docker hub API to remove file-update dependency // See: https://github.com/Percona-QA/package-testing/blob/master/playbooks/pmm2-client_integration_upgrade_custom_path.yml#L41 PMM_VERSION = cli.execute('curl -s https://raw.githubusercontent.com/Percona-Lab/pmm-submodules/v3/VERSION') From d7b0626c52b592c6182befebea48f440a37acf2c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 19:56:33 +0000 Subject: [PATCH 02/10] Gate MongoDB Unused Indexes dashboard test to PMM 3.10.0+ The Unused Indexes dashboard ships from PMM Server 3.10.0, but the rc-testing-suite runs pmm-qa main against older RC images (e.g. 3.9.0-rc), where the dashboard/nav item does not exist, so PMM-T2262 fails with "element(s) not found". Add a small server-version gate (read from DOCKER_VERSION) and skip the spec when the server predates 3.10.0. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- e2e_tests/helpers/version.helper.ts | 28 +++++++++++++++++++ .../mongo/mongodbUnusedIndexes.test.ts | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 e2e_tests/helpers/version.helper.ts diff --git a/e2e_tests/helpers/version.helper.ts b/e2e_tests/helpers/version.helper.ts new file mode 100644 index 000000000..bee38889a --- /dev/null +++ b/e2e_tests/helpers/version.helper.ts @@ -0,0 +1,28 @@ +/** + * PMM Server version gate for e2e tests. + * + * Some specs exercise features that exist only from a given PMM Server release. The + * rc-testing-suite runs the pmm-qa `main` tests against older RC images, so a spec that is + * ahead of the image under test must skip instead of failing. The server version is read + * from DOCKER_VERSION (the image under test, e.g. "perconalab/pmm-server:3.9.0-rc"), which the + * RC and nightly workflows always pass; dev/unknown tags carry no semver and are treated as + * newest (never skipped). + */ +export const getServerVersion = (): string | null => { + const match = (process.env.DOCKER_VERSION ?? '').match(/(\d+)\.(\d+)\.(\d+)/); + + return match ? `${match[1]}.${match[2]}.${match[3]}` : null; +}; + +export const serverVersionBelow = (minVersion: string): boolean => { + const current = getServerVersion(); + if (!current) return false; + + const [a, b, c] = current.split('.').map(Number); + const [x, y, z] = minVersion.split('.').map(Number); + + if (a !== x) return a < x; + if (b !== y) return b < y; + + return c < z; +}; diff --git a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts index 6b9347a31..2e5634c96 100644 --- a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts +++ b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts @@ -1,6 +1,7 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import { Timeouts } from '@helpers/timeouts'; +import { serverVersionBelow } from '@helpers/version.helper'; const collection = 'users'; @@ -11,6 +12,7 @@ pmmTest.beforeEach(async ({ grafanaHelper }) => { pmmTest( 'PMM-T2262 Verify MongoDB Unused Indexes dashboard @nightly @dashboards @pmm-psmdb-integration', async ({ api, dashboard, mongoDbHelper, page, urlHelper }) => { + pmmTest.skip(serverVersionBelow('3.10.0'), 'MongoDB Unused Indexes dashboard is available from PMM Server 3.10.0'); const database = `pmm_qa_unused_indexes_${Date.now()}`; const service = await api.inventoryApi.getServiceDetailsByPartialName('rs101'); const unusedIndexes = dashboard.mongo.unusedIndexes; From 2235a84f3ebb0ca0381fceb8c9ed72d011b5354c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 20:04:26 +0000 Subject: [PATCH 03/10] Gate 3.10.0-only e2e specs against older RC images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These specs cover features that ship from PMM Server 3.10.0 and are absent in 3.9.x (incl. the 3.9.1 patch RC), so they fail when the rc-testing-suite runs pmm-qa main against a 3.9.x image: - RTA table/session URL-state persistence (PMM-T2265/T2266/T2267) — useTableUrlState, percona/pmm#5537 - Update-notification snooze (PMM-T2263) — percona/pmm#5694 - Left-menu traversal expecting the 3.10 mongo-unused-indexes nav item (PMM-T2202) Skip each via the shared serverVersionBelow('3.10.0') gate; they keep running on 3.10.0+ dev/RC builds. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- e2e_tests/tests/helpCenter.test.ts | 2 ++ e2e_tests/tests/navigation.test.ts | 2 ++ e2e_tests/tests/qan/rta/overview.test.ts | 3 +++ e2e_tests/tests/qan/rta/session.test.ts | 2 ++ 4 files changed, 9 insertions(+) diff --git a/e2e_tests/tests/helpCenter.test.ts b/e2e_tests/tests/helpCenter.test.ts index f4bd53e7e..e9aa6c7e0 100644 --- a/e2e_tests/tests/helpCenter.test.ts +++ b/e2e_tests/tests/helpCenter.test.ts @@ -2,6 +2,7 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import apiEndpoints from '@helpers/apiEndpoints'; import { Timeouts } from '@helpers/timeouts'; +import { serverVersionBelow } from '@helpers/version.helper'; pmmTest.beforeEach(async ({ grafanaHelper, page }) => { await grafanaHelper.authorize(); @@ -164,6 +165,7 @@ pmmTest('PMM-T2134 Verify Update check @new-navigation', async ({ helpPage, mock pmmTest( 'PMM-T2263 Verify update notification remains snoozed after refresh @new-navigation', async ({ helpPage, mocks, page }) => { + pmmTest.skip(serverVersionBelow('3.10.0'), 'Update-notification snooze is available from PMM Server 3.10.0'); const snoozeDuration = Timeouts.ONE_MINUTE; const updateVersion = `test-update-${Date.now()}`; const snooze = await mocks.mockSnoozedUpdate(updateVersion); diff --git a/e2e_tests/tests/navigation.test.ts b/e2e_tests/tests/navigation.test.ts index 8954628fc..18ca233af 100644 --- a/e2e_tests/tests/navigation.test.ts +++ b/e2e_tests/tests/navigation.test.ts @@ -2,6 +2,7 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import { type NestedLocators } from '@pages/base.page'; import { Timeouts } from '@helpers/timeouts'; +import { serverVersionBelow } from '@helpers/version.helper'; pmmTest.beforeEach(async ({ grafanaHelper, page }) => { await grafanaHelper.authorize(); @@ -148,6 +149,7 @@ pmmTest('PMM-T2201 verify node persistence @new-navigation', async ({ leftNaviga pmmTest( 'PMM-T2202 Traverse all the menu items in left menu sidebar @new-navigation', async ({ leftNavigation }) => { + pmmTest.skip(serverVersionBelow('3.10.0'), 'Left-menu traversal includes nav items added in PMM Server 3.10.0'); await pmmTest.step('Traverse menu items', async () => { await leftNavigation.verifyAllMenuItems(); }); diff --git a/e2e_tests/tests/qan/rta/overview.test.ts b/e2e_tests/tests/qan/rta/overview.test.ts index 86d9fb439..910c97061 100644 --- a/e2e_tests/tests/qan/rta/overview.test.ts +++ b/e2e_tests/tests/qan/rta/overview.test.ts @@ -2,6 +2,7 @@ import { readFile } from 'node:fs/promises'; import pmmTest from '@fixtures/pmmTest'; import { Timeouts } from '@helpers/timeouts'; import { expect } from '@playwright/test'; +import { serverVersionBelow } from '@helpers/version.helper'; let sortedHostNames: string[]; @@ -245,6 +246,7 @@ pmmTest('PMM-T2252 Verify RTA overview CSV export @rta', async ({ page, queryAna pmmTest( 'PMM-T2265 Verify RTA overview table state is stored in the URL and restored after refresh @rta', async ({ page, queryAnalytics }) => { + pmmTest.skip(serverVersionBelow('3.10.0'), 'RTA table URL-state persistence is available from PMM Server 3.10.0'); const { rta } = queryAnalytics; const expectedServiceIds = new URL(page.url()).searchParams.getAll('serviceIds'); @@ -286,6 +288,7 @@ pmmTest( pmmTest( 'PMM-T2266 Verify RTA elapsed-time decimal filter and URL restoration @rta', async ({ page, queryAnalytics }) => { + pmmTest.skip(serverVersionBelow('3.10.0'), 'RTA elapsed-time filter URL restoration is available from PMM Server 3.10.0'); const { rta } = queryAnalytics; const durationParameterName = 'overview.f.queryExecutionDurationMs'; let decimalMaximum = ''; diff --git a/e2e_tests/tests/qan/rta/session.test.ts b/e2e_tests/tests/qan/rta/session.test.ts index 854d4a129..babfacd48 100644 --- a/e2e_tests/tests/qan/rta/session.test.ts +++ b/e2e_tests/tests/qan/rta/session.test.ts @@ -1,6 +1,7 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import { Timeouts } from '@helpers/timeouts'; +import { serverVersionBelow } from '@helpers/version.helper'; let rs101ServiceId: string; let rs102ServiceId: string; @@ -55,6 +56,7 @@ pmmTest('PMM-T2182 Verify overview loads when session exists @rta', async ({ api pmmTest( 'PMM-T2267 Verify RTA sessions page size is stored in the URL and restored after refresh @rta', async ({ mocks, page, queryAnalytics }) => { + pmmTest.skip(serverVersionBelow('3.10.0'), 'RTA sessions URL-state persistence is available from PMM Server 3.10.0'); const { rta } = queryAnalytics; await pmmTest.step('Set up mocked sessions', async () => { From 9d27f146b01e3b7585d20a2c407028e2075f5e51 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 21:37:43 +0000 Subject: [PATCH 04/10] Fix PMM-T2227 tarball-upgrade version assertion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1175 made the post-upgrade check assert PMM_VERSION, which for the compatibility legs is the pinned matrix.version (e.g. 3.7.0) — but the test always upgrades to pmm-client-latest.tar.gz (dev HEAD, e.g. 3.9.1-v3), so every compat Generic leg failed asserting the old pinned version. Assert against the version the upgrade tarball actually installs instead: verify the reported version changed (upgrade happened) and, for the default dev-latest tarball, that it matches the build under test (v3 VERSION). This keeps the exact-version coverage without tying it to the leg's source version. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- cli/tests/generic.spec.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cli/tests/generic.spec.ts b/cli/tests/generic.spec.ts index 66670bf05..43cf49db4 100644 --- a/cli/tests/generic.spec.ts +++ b/cli/tests/generic.spec.ts @@ -602,8 +602,15 @@ test.describe('PMM Client "Generic" CLI tests', { tag: '@generic' }, () => { const newAdminStatus = await cli.exec(`docker exec ${containerName} pmm-admin status`); const newVersion = await cli.exec(`docker exec ${containerName} pmm-admin version | grep "Version:"`); + const upgradedVersion = process.env.PMM_CLIENT_VERSION?.includes('http') + ? '' + : cli.execute('curl -s https://raw.githubusercontent.com/Percona-Lab/pmm-submodules/v3/VERSION').stdout.trim(); + await newPid.outNotContains(oldPid.stdout); await newAdminStatus.outContains('Connected'); - await newVersion.outContains(PMM_VERSION); + expect(newVersion.stdout.trim()).not.toEqual(oldVersion.stdout.trim()); + if (upgradedVersion) { + await newVersion.outContains(upgradedVersion); + } }); }); From caab41d5ffb9ad483ae30fbe49c402bf82dbc853 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 15 Aug 2026 01:09:51 +0000 Subject: [PATCH 05/10] Inline version gate helper and trim comments Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- cli/tests/generic.spec.ts | 5 +---- e2e_tests/helpers/version.helper.ts | 31 ++++++++--------------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/cli/tests/generic.spec.ts b/cli/tests/generic.spec.ts index 43cf49db4..aa51b7195 100644 --- a/cli/tests/generic.spec.ts +++ b/cli/tests/generic.spec.ts @@ -17,10 +17,7 @@ test.describe('PMM Client "Generic" CLI tests', { tag: '@generic' }, () => { let PMM_VERSION = `${process.env.CLIENT_VERSION}`; if (/^https?:/.test(PMM_VERSION) || /pmm3-rc/.test(PMM_VERSION)) { - // An explicit build URL (feature build) or a release-candidate client carries the version of - // the branch/artifact it was built from, which may predate the latest bump on v3: the moment - // an RC branches, v3 VERSION already moves ahead to the next dev version. The server under test - // comes from that same build, so it is the only valid reference for the client's version. + // Feature-build / RC clients trail v3 VERSION once an RC branches; take the version from the server. PMM_VERSION = JSON.parse(cli.execute('sudo pmm-admin status --json').stdout).pmm_agent_status?.server_version; if (!PMM_VERSION) throw new Error('Could not read server version from "pmm-admin status --json"'); } else if (/latest-tarball|3-dev-latest/.test(PMM_VERSION)) { diff --git a/e2e_tests/helpers/version.helper.ts b/e2e_tests/helpers/version.helper.ts index bee38889a..2a22bdc69 100644 --- a/e2e_tests/helpers/version.helper.ts +++ b/e2e_tests/helpers/version.helper.ts @@ -1,28 +1,13 @@ -/** - * PMM Server version gate for e2e tests. - * - * Some specs exercise features that exist only from a given PMM Server release. The - * rc-testing-suite runs the pmm-qa `main` tests against older RC images, so a spec that is - * ahead of the image under test must skip instead of failing. The server version is read - * from DOCKER_VERSION (the image under test, e.g. "perconalab/pmm-server:3.9.0-rc"), which the - * RC and nightly workflows always pass; dev/unknown tags carry no semver and are treated as - * newest (never skipped). - */ -export const getServerVersion = (): string | null => { - const match = (process.env.DOCKER_VERSION ?? '').match(/(\d+)\.(\d+)\.(\d+)/); - - return match ? `${match[1]}.${match[2]}.${match[3]}` : null; -}; - export const serverVersionBelow = (minVersion: string): boolean => { - const current = getServerVersion(); - if (!current) return false; + const match = (process.env.DOCKER_VERSION ?? '').match(/(\d+)\.(\d+)\.(\d+)/); + if (!match) return false; - const [a, b, c] = current.split('.').map(Number); - const [x, y, z] = minVersion.split('.').map(Number); + const current = match.slice(1).map(Number); + const min = minVersion.split('.').map(Number); - if (a !== x) return a < x; - if (b !== y) return b < y; + for (let i = 0; i < 3; i++) { + if (current[i] !== min[i]) return current[i] < min[i]; + } - return c < z; + return false; }; From 5354cabe3108ac8b6c7cfc107b5d73de0d278749 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 15 Aug 2026 01:19:35 +0000 Subject: [PATCH 06/10] Fail closed when the upgrade version lookup fails If the curl to v3 VERSION failed or returned empty, upgradedVersion was '' and the exact-version assertion was silently skipped, letting the test pass on any changed version. Require a successful, non-empty lookup instead. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- cli/tests/generic.spec.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cli/tests/generic.spec.ts b/cli/tests/generic.spec.ts index aa51b7195..c16ed9d75 100644 --- a/cli/tests/generic.spec.ts +++ b/cli/tests/generic.spec.ts @@ -599,9 +599,13 @@ test.describe('PMM Client "Generic" CLI tests', { tag: '@generic' }, () => { const newAdminStatus = await cli.exec(`docker exec ${containerName} pmm-admin status`); const newVersion = await cli.exec(`docker exec ${containerName} pmm-admin version | grep "Version:"`); - const upgradedVersion = process.env.PMM_CLIENT_VERSION?.includes('http') - ? '' - : cli.execute('curl -s https://raw.githubusercontent.com/Percona-Lab/pmm-submodules/v3/VERSION').stdout.trim(); + const versionLookup = process.env.PMM_CLIENT_VERSION?.includes('http') + ? undefined + : cli.execute('curl --fail --silent --show-error https://raw.githubusercontent.com/Percona-Lab/pmm-submodules/v3/VERSION'); + if (versionLookup && (versionLookup.code !== 0 || !versionLookup.stdout.trim())) { + throw new Error('Could not read the expected upgrade version from v3 VERSION'); + } + const upgradedVersion = versionLookup?.stdout.trim() ?? ''; await newPid.outNotContains(oldPid.stdout); await newAdminStatus.outContains('Connected'); From 52d777980d55a542b87de18def7cbf1cee408030 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 15 Aug 2026 01:24:05 +0000 Subject: [PATCH 07/10] Detect PMM version from the server API, not DOCKER_VERSION DOCKER_VERSION is not always set, so the version gate could not tell which build was under test. Add ServerApi.getPmmVersion() (GET /v1/version) as in percona/pmm-qa#1094 and reduce the helper to a pure semver comparison; the 3.10.0 gates now read the running server's version. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- e2e_tests/api/server.api.ts | 32 ++++++++++++++++++- e2e_tests/helpers/apiEndpoints.ts | 1 + e2e_tests/helpers/version.helper.ts | 19 +++++------ .../mongo/mongodbUnusedIndexes.test.ts | 2 +- e2e_tests/tests/helpCenter.test.ts | 4 +-- e2e_tests/tests/navigation.test.ts | 4 +-- e2e_tests/tests/qan/rta/overview.test.ts | 8 ++--- e2e_tests/tests/qan/rta/session.test.ts | 4 +-- 8 files changed, 51 insertions(+), 23 deletions(-) diff --git a/e2e_tests/api/server.api.ts b/e2e_tests/api/server.api.ts index 04138b8eb..e5be08b58 100644 --- a/e2e_tests/api/server.api.ts +++ b/e2e_tests/api/server.api.ts @@ -1,10 +1,40 @@ -import { APIRequestContext } from '@playwright/test'; +import { APIRequestContext, expect } from '@playwright/test'; +import GrafanaHelper from '@helpers/grafana.helper'; import { Timeouts } from '@helpers/timeouts'; import apiEndpoints from '@helpers/apiEndpoints'; +interface PmmVersion { + major: number; + minor: number; + patch: number; + version: string; +} + +interface VersionResponse { + version: string; +} + export default class ServerApi { constructor(private request: APIRequestContext) {} + getPmmVersion = async (): Promise => { + const response = await this.request.get(apiEndpoints.server.version, { + headers: GrafanaHelper.getAuthHeader(), + }); + + expect(response.status()).toEqual(200); + + const data = (await response.json()) as VersionResponse; + const [versionMajor, versionMinor, versionPatch] = data.version.split('.'); + + return { + major: parseInt(versionMajor), + minor: parseInt(versionMinor), + patch: parseInt(versionPatch), + version: data.version, + }; + }; + waitForReady = async (overallTimeoutMs: Timeouts = Timeouts.ONE_MINUTE): Promise => { const pollIntervalMs = Timeouts.FIVE_SECONDS; const deadline = Date.now() + overallTimeoutMs; diff --git a/e2e_tests/helpers/apiEndpoints.ts b/e2e_tests/helpers/apiEndpoints.ts index 0bebe6fae..4d02c19e7 100644 --- a/e2e_tests/helpers/apiEndpoints.ts +++ b/e2e_tests/helpers/apiEndpoints.ts @@ -35,6 +35,7 @@ const apiEndpoints = { readyz: '/v1/server/readyz', settings: '/v1/server/settings', updates: '**/v1/server/updates?force=**', + version: '/v1/version', }, users: { me: '**/v1/users/me', diff --git a/e2e_tests/helpers/version.helper.ts b/e2e_tests/helpers/version.helper.ts index 2a22bdc69..bef6d1c1a 100644 --- a/e2e_tests/helpers/version.helper.ts +++ b/e2e_tests/helpers/version.helper.ts @@ -1,13 +1,10 @@ -export const serverVersionBelow = (minVersion: string): boolean => { - const match = (process.env.DOCKER_VERSION ?? '').match(/(\d+)\.(\d+)\.(\d+)/); - if (!match) return false; +export const serverVersionBelow = ( + version: { major: number; minor: number; patch: number }, + minVersion: string, +): boolean => { + const [major, minor, patch] = minVersion.split('.').map(Number); + if (version.major !== major) return version.major < major; + if (version.minor !== minor) return version.minor < minor; - const current = match.slice(1).map(Number); - const min = minVersion.split('.').map(Number); - - for (let i = 0; i < 3; i++) { - if (current[i] !== min[i]) return current[i] < min[i]; - } - - return false; + return version.patch < patch; }; diff --git a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts index 2e5634c96..958bf3a34 100644 --- a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts +++ b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts @@ -12,7 +12,7 @@ pmmTest.beforeEach(async ({ grafanaHelper }) => { pmmTest( 'PMM-T2262 Verify MongoDB Unused Indexes dashboard @nightly @dashboards @pmm-psmdb-integration', async ({ api, dashboard, mongoDbHelper, page, urlHelper }) => { - pmmTest.skip(serverVersionBelow('3.10.0'), 'MongoDB Unused Indexes dashboard is available from PMM Server 3.10.0'); + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'MongoDB Unused Indexes dashboard is available from PMM Server 3.10.0'); const database = `pmm_qa_unused_indexes_${Date.now()}`; const service = await api.inventoryApi.getServiceDetailsByPartialName('rs101'); const unusedIndexes = dashboard.mongo.unusedIndexes; diff --git a/e2e_tests/tests/helpCenter.test.ts b/e2e_tests/tests/helpCenter.test.ts index e9aa6c7e0..ee0c06fe0 100644 --- a/e2e_tests/tests/helpCenter.test.ts +++ b/e2e_tests/tests/helpCenter.test.ts @@ -164,8 +164,8 @@ pmmTest('PMM-T2134 Verify Update check @new-navigation', async ({ helpPage, mock pmmTest( 'PMM-T2263 Verify update notification remains snoozed after refresh @new-navigation', - async ({ helpPage, mocks, page }) => { - pmmTest.skip(serverVersionBelow('3.10.0'), 'Update-notification snooze is available from PMM Server 3.10.0'); + async ({ api, helpPage, mocks, page }) => { + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'Update-notification snooze is available from PMM Server 3.10.0'); const snoozeDuration = Timeouts.ONE_MINUTE; const updateVersion = `test-update-${Date.now()}`; const snooze = await mocks.mockSnoozedUpdate(updateVersion); diff --git a/e2e_tests/tests/navigation.test.ts b/e2e_tests/tests/navigation.test.ts index 18ca233af..0b8d6e2a9 100644 --- a/e2e_tests/tests/navigation.test.ts +++ b/e2e_tests/tests/navigation.test.ts @@ -148,8 +148,8 @@ pmmTest('PMM-T2201 verify node persistence @new-navigation', async ({ leftNaviga pmmTest( 'PMM-T2202 Traverse all the menu items in left menu sidebar @new-navigation', - async ({ leftNavigation }) => { - pmmTest.skip(serverVersionBelow('3.10.0'), 'Left-menu traversal includes nav items added in PMM Server 3.10.0'); + async ({ api, leftNavigation }) => { + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'Left-menu traversal includes nav items added in PMM Server 3.10.0'); await pmmTest.step('Traverse menu items', async () => { await leftNavigation.verifyAllMenuItems(); }); diff --git a/e2e_tests/tests/qan/rta/overview.test.ts b/e2e_tests/tests/qan/rta/overview.test.ts index 910c97061..98d1d932f 100644 --- a/e2e_tests/tests/qan/rta/overview.test.ts +++ b/e2e_tests/tests/qan/rta/overview.test.ts @@ -245,8 +245,8 @@ pmmTest('PMM-T2252 Verify RTA overview CSV export @rta', async ({ page, queryAna pmmTest( 'PMM-T2265 Verify RTA overview table state is stored in the URL and restored after refresh @rta', - async ({ page, queryAnalytics }) => { - pmmTest.skip(serverVersionBelow('3.10.0'), 'RTA table URL-state persistence is available from PMM Server 3.10.0'); + async ({ api, page, queryAnalytics }) => { + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'RTA table URL-state persistence is available from PMM Server 3.10.0'); const { rta } = queryAnalytics; const expectedServiceIds = new URL(page.url()).searchParams.getAll('serviceIds'); @@ -287,8 +287,8 @@ pmmTest( pmmTest( 'PMM-T2266 Verify RTA elapsed-time decimal filter and URL restoration @rta', - async ({ page, queryAnalytics }) => { - pmmTest.skip(serverVersionBelow('3.10.0'), 'RTA elapsed-time filter URL restoration is available from PMM Server 3.10.0'); + async ({ api, page, queryAnalytics }) => { + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'RTA elapsed-time filter URL restoration is available from PMM Server 3.10.0'); const { rta } = queryAnalytics; const durationParameterName = 'overview.f.queryExecutionDurationMs'; let decimalMaximum = ''; diff --git a/e2e_tests/tests/qan/rta/session.test.ts b/e2e_tests/tests/qan/rta/session.test.ts index babfacd48..c56821e86 100644 --- a/e2e_tests/tests/qan/rta/session.test.ts +++ b/e2e_tests/tests/qan/rta/session.test.ts @@ -55,8 +55,8 @@ pmmTest('PMM-T2182 Verify overview loads when session exists @rta', async ({ api pmmTest( 'PMM-T2267 Verify RTA sessions page size is stored in the URL and restored after refresh @rta', - async ({ mocks, page, queryAnalytics }) => { - pmmTest.skip(serverVersionBelow('3.10.0'), 'RTA sessions URL-state persistence is available from PMM Server 3.10.0'); + async ({ api, mocks, page, queryAnalytics }) => { + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'RTA sessions URL-state persistence is available from PMM Server 3.10.0'); const { rta } = queryAnalytics; await pmmTest.step('Set up mocked sessions', async () => { From 4e36b427c62bb6de21c838ab313224e18e993598 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 15:06:52 +0000 Subject: [PATCH 08/10] Gate version-specific specs with a min-pmm-version annotation Move the 3.10.0 skip logic out of each test body into a single pmmTest.beforeEach that reads a `min-pmm-version` annotation and skips when the running server (GET /v1/version) is below it. Tests now only declare the version they need; no per-test skip code or fixture plumbing, and nothing to edit when a version ships. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- e2e_tests/fixtures/pmmTest.ts | 8 ++++++++ .../tests/dashboards/mongo/mongodbUnusedIndexes.test.ts | 3 +-- e2e_tests/tests/helpCenter.test.ts | 5 ++--- e2e_tests/tests/navigation.test.ts | 5 ++--- e2e_tests/tests/qan/rta/overview.test.ts | 9 ++++----- e2e_tests/tests/qan/rta/session.test.ts | 5 ++--- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/e2e_tests/fixtures/pmmTest.ts b/e2e_tests/fixtures/pmmTest.ts index 7109bbdb4..ef9291b5f 100644 --- a/e2e_tests/fixtures/pmmTest.ts +++ b/e2e_tests/fixtures/pmmTest.ts @@ -22,6 +22,7 @@ import apiEndpoints from '@helpers/apiEndpoints'; import SettingsPage from '@pages/ha/settings.page'; import UpdatesPage from '@pages/updates.page'; import DownloadsPage from '@pages/downloads.page'; +import { serverVersionBelow } from '@helpers/version.helper'; const pmmTest = base.extend<{ settingsPage: SettingsPage; @@ -155,4 +156,11 @@ const pmmTest = base.extend<{ vacuumDashboardPage: async ({ page }, use) => await use(new VacuumDashboard(page)), }); +pmmTest.beforeEach(async ({ api }, testInfo) => { + const minVersion = testInfo.annotations.find((annotation) => annotation.type === 'min-pmm-version')?.description; + if (!minVersion) return; + + pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), minVersion), `Requires PMM Server ${minVersion}+`); +}); + export default pmmTest; diff --git a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts index 958bf3a34..36af166df 100644 --- a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts +++ b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts @@ -1,7 +1,6 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import { Timeouts } from '@helpers/timeouts'; -import { serverVersionBelow } from '@helpers/version.helper'; const collection = 'users'; @@ -11,8 +10,8 @@ pmmTest.beforeEach(async ({ grafanaHelper }) => { pmmTest( 'PMM-T2262 Verify MongoDB Unused Indexes dashboard @nightly @dashboards @pmm-psmdb-integration', + { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ api, dashboard, mongoDbHelper, page, urlHelper }) => { - pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'MongoDB Unused Indexes dashboard is available from PMM Server 3.10.0'); const database = `pmm_qa_unused_indexes_${Date.now()}`; const service = await api.inventoryApi.getServiceDetailsByPartialName('rs101'); const unusedIndexes = dashboard.mongo.unusedIndexes; diff --git a/e2e_tests/tests/helpCenter.test.ts b/e2e_tests/tests/helpCenter.test.ts index ee0c06fe0..63a44a152 100644 --- a/e2e_tests/tests/helpCenter.test.ts +++ b/e2e_tests/tests/helpCenter.test.ts @@ -2,7 +2,6 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import apiEndpoints from '@helpers/apiEndpoints'; import { Timeouts } from '@helpers/timeouts'; -import { serverVersionBelow } from '@helpers/version.helper'; pmmTest.beforeEach(async ({ grafanaHelper, page }) => { await grafanaHelper.authorize(); @@ -164,8 +163,8 @@ pmmTest('PMM-T2134 Verify Update check @new-navigation', async ({ helpPage, mock pmmTest( 'PMM-T2263 Verify update notification remains snoozed after refresh @new-navigation', - async ({ api, helpPage, mocks, page }) => { - pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'Update-notification snooze is available from PMM Server 3.10.0'); + { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, + async ({ helpPage, mocks, page }) => { const snoozeDuration = Timeouts.ONE_MINUTE; const updateVersion = `test-update-${Date.now()}`; const snooze = await mocks.mockSnoozedUpdate(updateVersion); diff --git a/e2e_tests/tests/navigation.test.ts b/e2e_tests/tests/navigation.test.ts index 0b8d6e2a9..bd894d650 100644 --- a/e2e_tests/tests/navigation.test.ts +++ b/e2e_tests/tests/navigation.test.ts @@ -2,7 +2,6 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import { type NestedLocators } from '@pages/base.page'; import { Timeouts } from '@helpers/timeouts'; -import { serverVersionBelow } from '@helpers/version.helper'; pmmTest.beforeEach(async ({ grafanaHelper, page }) => { await grafanaHelper.authorize(); @@ -148,8 +147,8 @@ pmmTest('PMM-T2201 verify node persistence @new-navigation', async ({ leftNaviga pmmTest( 'PMM-T2202 Traverse all the menu items in left menu sidebar @new-navigation', - async ({ api, leftNavigation }) => { - pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'Left-menu traversal includes nav items added in PMM Server 3.10.0'); + { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, + async ({ leftNavigation }) => { await pmmTest.step('Traverse menu items', async () => { await leftNavigation.verifyAllMenuItems(); }); diff --git a/e2e_tests/tests/qan/rta/overview.test.ts b/e2e_tests/tests/qan/rta/overview.test.ts index 98d1d932f..ca4b1162c 100644 --- a/e2e_tests/tests/qan/rta/overview.test.ts +++ b/e2e_tests/tests/qan/rta/overview.test.ts @@ -2,7 +2,6 @@ import { readFile } from 'node:fs/promises'; import pmmTest from '@fixtures/pmmTest'; import { Timeouts } from '@helpers/timeouts'; import { expect } from '@playwright/test'; -import { serverVersionBelow } from '@helpers/version.helper'; let sortedHostNames: string[]; @@ -245,8 +244,8 @@ pmmTest('PMM-T2252 Verify RTA overview CSV export @rta', async ({ page, queryAna pmmTest( 'PMM-T2265 Verify RTA overview table state is stored in the URL and restored after refresh @rta', - async ({ api, page, queryAnalytics }) => { - pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'RTA table URL-state persistence is available from PMM Server 3.10.0'); + { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, + async ({ page, queryAnalytics }) => { const { rta } = queryAnalytics; const expectedServiceIds = new URL(page.url()).searchParams.getAll('serviceIds'); @@ -287,8 +286,8 @@ pmmTest( pmmTest( 'PMM-T2266 Verify RTA elapsed-time decimal filter and URL restoration @rta', - async ({ api, page, queryAnalytics }) => { - pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'RTA elapsed-time filter URL restoration is available from PMM Server 3.10.0'); + { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, + async ({ page, queryAnalytics }) => { const { rta } = queryAnalytics; const durationParameterName = 'overview.f.queryExecutionDurationMs'; let decimalMaximum = ''; diff --git a/e2e_tests/tests/qan/rta/session.test.ts b/e2e_tests/tests/qan/rta/session.test.ts index c56821e86..e7b88c1f6 100644 --- a/e2e_tests/tests/qan/rta/session.test.ts +++ b/e2e_tests/tests/qan/rta/session.test.ts @@ -1,7 +1,6 @@ import pmmTest from '@fixtures/pmmTest'; import { expect } from '@playwright/test'; import { Timeouts } from '@helpers/timeouts'; -import { serverVersionBelow } from '@helpers/version.helper'; let rs101ServiceId: string; let rs102ServiceId: string; @@ -55,8 +54,8 @@ pmmTest('PMM-T2182 Verify overview loads when session exists @rta', async ({ api pmmTest( 'PMM-T2267 Verify RTA sessions page size is stored in the URL and restored after refresh @rta', - async ({ api, mocks, page, queryAnalytics }) => { - pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), '3.10.0'), 'RTA sessions URL-state persistence is available from PMM Server 3.10.0'); + { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, + async ({ mocks, page, queryAnalytics }) => { const { rta } = queryAnalytics; await pmmTest.step('Set up mocked sessions', async () => { From e2bd71eca7bf5b09b7ebdfa08654a0e8ed22c19a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 16:20:55 +0000 Subject: [PATCH 09/10] Move version gates to a central registry, off the tests Keep the runtime server-version gate but drive it from a single versionGates map (PMM-T id -> min version) resolved in pmmTest.beforeEach. The specs themselves carry nothing: gate or retire one by editing one line in the registry. Being a runtime gate, the same spec skips on an older server and runs on 3.10.0+, so it stays correct across concurrent patch/minor branches with no per-branch edits. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_012DpJQhfD6qKwZWwsiP671T Signed-off-by: Claude --- e2e_tests/fixtures/pmmTest.ts | 4 +++- e2e_tests/helpers/versionGates.ts | 9 +++++++++ .../tests/dashboards/mongo/mongodbUnusedIndexes.test.ts | 1 - e2e_tests/tests/helpCenter.test.ts | 1 - e2e_tests/tests/navigation.test.ts | 1 - e2e_tests/tests/qan/rta/overview.test.ts | 2 -- e2e_tests/tests/qan/rta/session.test.ts | 1 - 7 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 e2e_tests/helpers/versionGates.ts diff --git a/e2e_tests/fixtures/pmmTest.ts b/e2e_tests/fixtures/pmmTest.ts index ef9291b5f..159a079a4 100644 --- a/e2e_tests/fixtures/pmmTest.ts +++ b/e2e_tests/fixtures/pmmTest.ts @@ -23,6 +23,7 @@ import SettingsPage from '@pages/ha/settings.page'; import UpdatesPage from '@pages/updates.page'; import DownloadsPage from '@pages/downloads.page'; import { serverVersionBelow } from '@helpers/version.helper'; +import { minPmmVersion } from '@helpers/versionGates'; const pmmTest = base.extend<{ settingsPage: SettingsPage; @@ -157,7 +158,8 @@ const pmmTest = base.extend<{ }); pmmTest.beforeEach(async ({ api }, testInfo) => { - const minVersion = testInfo.annotations.find((annotation) => annotation.type === 'min-pmm-version')?.description; + const testId = testInfo.title.match(/PMM-T\d+/)?.[0]; + const minVersion = testId ? minPmmVersion[testId] : undefined; if (!minVersion) return; pmmTest.skip(serverVersionBelow(await api.serverApi.getPmmVersion(), minVersion), `Requires PMM Server ${minVersion}+`); diff --git a/e2e_tests/helpers/versionGates.ts b/e2e_tests/helpers/versionGates.ts new file mode 100644 index 000000000..503a830dc --- /dev/null +++ b/e2e_tests/helpers/versionGates.ts @@ -0,0 +1,9 @@ +// Specs keyed by their PMM-T id skip when the running server is below this version. +export const minPmmVersion: Record = { + 'PMM-T2202': '3.10.0', + 'PMM-T2262': '3.10.0', + 'PMM-T2263': '3.10.0', + 'PMM-T2265': '3.10.0', + 'PMM-T2266': '3.10.0', + 'PMM-T2267': '3.10.0', +}; diff --git a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts index 36af166df..6b9347a31 100644 --- a/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts +++ b/e2e_tests/tests/dashboards/mongo/mongodbUnusedIndexes.test.ts @@ -10,7 +10,6 @@ pmmTest.beforeEach(async ({ grafanaHelper }) => { pmmTest( 'PMM-T2262 Verify MongoDB Unused Indexes dashboard @nightly @dashboards @pmm-psmdb-integration', - { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ api, dashboard, mongoDbHelper, page, urlHelper }) => { const database = `pmm_qa_unused_indexes_${Date.now()}`; const service = await api.inventoryApi.getServiceDetailsByPartialName('rs101'); diff --git a/e2e_tests/tests/helpCenter.test.ts b/e2e_tests/tests/helpCenter.test.ts index 63a44a152..f4bd53e7e 100644 --- a/e2e_tests/tests/helpCenter.test.ts +++ b/e2e_tests/tests/helpCenter.test.ts @@ -163,7 +163,6 @@ pmmTest('PMM-T2134 Verify Update check @new-navigation', async ({ helpPage, mock pmmTest( 'PMM-T2263 Verify update notification remains snoozed after refresh @new-navigation', - { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ helpPage, mocks, page }) => { const snoozeDuration = Timeouts.ONE_MINUTE; const updateVersion = `test-update-${Date.now()}`; diff --git a/e2e_tests/tests/navigation.test.ts b/e2e_tests/tests/navigation.test.ts index bd894d650..8954628fc 100644 --- a/e2e_tests/tests/navigation.test.ts +++ b/e2e_tests/tests/navigation.test.ts @@ -147,7 +147,6 @@ pmmTest('PMM-T2201 verify node persistence @new-navigation', async ({ leftNaviga pmmTest( 'PMM-T2202 Traverse all the menu items in left menu sidebar @new-navigation', - { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ leftNavigation }) => { await pmmTest.step('Traverse menu items', async () => { await leftNavigation.verifyAllMenuItems(); diff --git a/e2e_tests/tests/qan/rta/overview.test.ts b/e2e_tests/tests/qan/rta/overview.test.ts index ca4b1162c..86d9fb439 100644 --- a/e2e_tests/tests/qan/rta/overview.test.ts +++ b/e2e_tests/tests/qan/rta/overview.test.ts @@ -244,7 +244,6 @@ pmmTest('PMM-T2252 Verify RTA overview CSV export @rta', async ({ page, queryAna pmmTest( 'PMM-T2265 Verify RTA overview table state is stored in the URL and restored after refresh @rta', - { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ page, queryAnalytics }) => { const { rta } = queryAnalytics; const expectedServiceIds = new URL(page.url()).searchParams.getAll('serviceIds'); @@ -286,7 +285,6 @@ pmmTest( pmmTest( 'PMM-T2266 Verify RTA elapsed-time decimal filter and URL restoration @rta', - { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ page, queryAnalytics }) => { const { rta } = queryAnalytics; const durationParameterName = 'overview.f.queryExecutionDurationMs'; diff --git a/e2e_tests/tests/qan/rta/session.test.ts b/e2e_tests/tests/qan/rta/session.test.ts index e7b88c1f6..854d4a129 100644 --- a/e2e_tests/tests/qan/rta/session.test.ts +++ b/e2e_tests/tests/qan/rta/session.test.ts @@ -54,7 +54,6 @@ pmmTest('PMM-T2182 Verify overview loads when session exists @rta', async ({ api pmmTest( 'PMM-T2267 Verify RTA sessions page size is stored in the URL and restored after refresh @rta', - { annotation: { type: 'min-pmm-version', description: '3.10.0' } }, async ({ mocks, page, queryAnalytics }) => { const { rta } = queryAnalytics; From 58f6747e5131b3f1af98c936b9a53c555a7df2df Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 17:45:58 +0000 Subject: [PATCH 10/10] Gate PMM-T2268 QAN URL-state test to PMM 3.10.0+ PMM-T2268 (added in #1139) exercises the useTableUrlState / debounced-search feature from PMM-14848 (percona/pmm#5537), merged to main on 2026-08-11 and shipping in 3.10.0. Like its sibling specs T2265-T2267 it fails against pre-3.10.0 RC images, so add it to the central version registry. Signed-off-by: Claude --- e2e_tests/helpers/versionGates.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e_tests/helpers/versionGates.ts b/e2e_tests/helpers/versionGates.ts index 503a830dc..ba6900129 100644 --- a/e2e_tests/helpers/versionGates.ts +++ b/e2e_tests/helpers/versionGates.ts @@ -6,4 +6,5 @@ export const minPmmVersion: Record = { 'PMM-T2265': '3.10.0', 'PMM-T2266': '3.10.0', 'PMM-T2267': '3.10.0', + 'PMM-T2268': '3.10.0', };