Skip to content

Commit e9db5d4

Browse files
authored
chore: React 19 upgrade (#666)
* chore: React 19 upgrade * Fix package version * Fix docker compose loc * Add playwright * Fix playwright version * Fix test packages * Fix base url * Do not run e2e tests on release: for speed and as they are already run on each commit * npx @grafana/create-plugin@latest add externalize-jsx-runtime * Remove superfluous externals * Run for release just in case * Update grafanaDependency * Update grafanaDependency * Update docker images * Update gependency to support broader range
1 parent e153d3b commit e9db5d4

14 files changed

Lines changed: 256 additions & 85 deletions

File tree

.config/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ARG grafana_version=latest@sha256:9dedb4a38c272933f7fb1033573a349bb06b181eadcda614bddc99bc5f75491e
1+
ARG grafana_version=12.3.0
22
ARG grafana_image=grafana-enterprise
33

44
FROM grafana/${grafana_image}:${grafana_version}

.config/bundler/externals.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
3+
*
4+
*/
5+
6+
import type { Configuration, ExternalItemFunctionData } from 'webpack';
7+
8+
type ExternalsType = Configuration['externals'];
9+
10+
export const externals: ExternalsType = [
11+
// Required for dynamic publicPath resolution
12+
{ 'amd-module': 'module' },
13+
'lodash',
14+
'jquery',
15+
'moment',
16+
'slate',
17+
'emotion',
18+
'@emotion/react',
19+
'@emotion/css',
20+
'prismjs',
21+
'slate-plain-serializer',
22+
'@grafana/slate-react',
23+
'react',
24+
'react/jsx-runtime',
25+
'react/jsx-dev-runtime',
26+
'react-dom',
27+
'react-redux',
28+
'redux',
29+
'rxjs',
30+
'react-router',
31+
'd3',
32+
'angular',
33+
/^@grafana\/ui/i,
34+
/^@grafana\/runtime/i,
35+
/^@grafana\/data/i,
36+
37+
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
38+
({ request }: ExternalItemFunctionData, callback: (error?: Error, result?: string) => void) => {
39+
const prefix = 'grafana/';
40+
const hasPrefix = (request: string) => request.indexOf(prefix) === 0;
41+
const stripPrefix = (request: string) => request.slice(prefix.length);
42+
43+
if (request && hasPrefix(request)) {
44+
return callback(undefined, stripPrefix(request));
45+
}
46+
47+
callback();
48+
},
49+
];

.config/docker-compose-base.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ services:
77
context: .
88
args:
99
grafana_image: ${GRAFANA_IMAGE:-grafana-enterprise}
10-
grafana_version: ${GRAFANA_VERSION:-12.1.0}
10+
grafana_version: ${GRAFANA_VERSION:-12.3.0}
1111
development: ${DEVELOPMENT:-false}
1212
anonymous_auth_enabled: ${ANONYMOUS_AUTH_ENABLED:-true}
1313
ports:

.config/webpack/webpack.config.ts

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { BuildModeWebpackPlugin } from './BuildModeWebpackPlugin.ts';
2020
import { DIST_DIR, SOURCE_DIR } from './constants.ts';
2121
import { getCPConfigVersion, getEntries, getPackageJson, getPluginJson, hasReadme, isWSL } from './utils.ts';
2222

23+
import { externals } from '../bundler/externals.ts';
24+
2325
const pluginJson = getPluginJson();
2426
const cpVersion = getCPConfigVersion();
2527

@@ -54,44 +56,7 @@ const config = async (env: Env): Promise<Configuration> => {
5456

5557
entry: await getEntries(),
5658

57-
externals: [
58-
// Required for dynamic publicPath resolution
59-
{ 'amd-module': 'module' },
60-
'lodash',
61-
'jquery',
62-
'moment',
63-
'slate',
64-
'emotion',
65-
'@emotion/react',
66-
'@emotion/css',
67-
'prismjs',
68-
'slate-plain-serializer',
69-
'@grafana/slate-react',
70-
'react',
71-
'react-dom',
72-
'react-redux',
73-
'redux',
74-
'rxjs',
75-
'react-router',
76-
'd3',
77-
'angular',
78-
/^@grafana\/ui/i,
79-
/^@grafana\/runtime/i,
80-
/^@grafana\/data/i,
81-
82-
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
83-
({ request }, callback) => {
84-
const prefix = 'grafana/';
85-
const hasPrefix = (request: string) => request.indexOf(prefix) === 0;
86-
const stripPrefix = (request: string) => request.substr(prefix.length);
87-
88-
if (request && hasPrefix(request)) {
89-
return callback(undefined, stripPrefix(request));
90-
}
91-
92-
callback();
93-
},
94-
],
59+
externals,
9560

9661
// Support WebAssembly according to latest spec - makes WebAssembly module async
9762
experiments: {

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ permissions: {}
1111
jobs:
1212
cd:
1313
name: CI / CD
14-
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@main # zizmor: ignore[unpinned-uses]
14+
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@ci-cd-workflows/v6.0.0
1515
permissions:
1616
contents: write
1717
id-token: write
@@ -37,9 +37,9 @@ jobs:
3737

3838
# Playwright
3939
run-playwright: false
40-
run-playwright-docker: false
40+
run-playwright-docker: true
4141
upload-playwright-artifacts: true # IMPORTANT: we must ensure there are no unmasked secrets in the E2E tests
4242
run-playwright-with-skip-grafana-dev-image: true
4343
playwright-report-path: e2e/test-reports/
44-
playwright-docker-compose-file: docker-compose.yaml
44+
playwright-docker-compose-file: devenv/docker-compose.e2e.yaml
4545
playwright-grafana-url: http://localhost:3001

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
CD:
3434
name: Deploy plugin
3535
needs: bump-version
36-
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@main
36+
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@ci-cd-workflows/v6.0.0
3737
permissions:
3838
contents: write
3939
id-token: write
@@ -49,9 +49,9 @@ jobs:
4949

5050
# Playwright
5151
run-playwright: false
52-
run-playwright-docker: false
52+
run-playwright-docker: true
5353
upload-playwright-artifacts: true # IMPORTANT: we must ensure there are no unmasked secrets in the E2E tests
5454
run-playwright-with-skip-grafana-dev-image: true
5555
playwright-report-path: e2e/test-reports/
56-
playwright-docker-compose-file: docker-compose.yaml
56+
playwright-docker-compose-file: devenv/docker-compose.e2e.yaml
5757
playwright-grafana-url: http://localhost:3001

devenv/docker-compose.e2e.yaml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
version: '3.0'
2-
31
services:
42
grafana:
53
container_name: 'grafana-explore-traces-e2e'
@@ -9,7 +7,7 @@ services:
97
context: ../.config
108
args:
119
grafana_image: ${GRAFANA_IMAGE:-grafana}
12-
grafana_version: ${GRAFANA_VERSION:-latest}
10+
grafana_version: ${GRAFANA_VERSION:-12.3.0}
1311
ports:
1412
- 3001:3000/tcp
1513
volumes:
@@ -89,3 +87,18 @@ services:
8987
- TRACING_COLLECTOR_PORT=4317
9088
- OTEL_EXPORTER_OTLP_TRACES_INSECURE=true
9189
- OTEL_RESOURCE_ATTRIBUTES=ip=1.2.3.5
90+
91+
# Used by plugin-ci-workflows: docker compose --profile playwright up playwright --exit-code-from playwright
92+
playwright:
93+
profiles:
94+
- playwright
95+
image: mcr.microsoft.com/playwright:v1.55.1-noble
96+
working_dir: /app
97+
volumes:
98+
- ..:/app
99+
environment:
100+
BASE_URL: http://grafana:3000
101+
CI: "true"
102+
depends_on:
103+
- grafana
104+
command: sh -c "yarn install --frozen-lockfile && sleep 30 && yarn e2e:fast"

devenv/docker-compose.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ services:
77
context: ../.config
88
args:
99
grafana_image: ${GRAFANA_IMAGE:-grafana-dev}
10-
grafana_version: ${GRAFANA_VERSION:-12.2.0-17432607250}
10+
grafana_version: ${GRAFANA_VERSION:-12.3.0}
11+
environment:
12+
- GF_FEATURE_TOGGLES_ENABLE=${GF_FEATURE_TOGGLES_ENABLE:-}
1113
ports:
1214
- 3000:3000/tcp
1315
volumes:

e2e/components.spec.ts

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,35 @@ test.describe('components', () => {
88
explorePage = new ExplorePage(page);
99
await explorePage.gotoExplorePage();
1010
await explorePage.assertNotLoading();
11+
await explorePage.waitForExploreReady(10000);
1112
});
1213

1314
test.afterEach(async () => {
14-
await explorePage.unroute();
15+
if (explorePage) {
16+
await explorePage.unroute();
17+
}
1518
});
1619

1720
test('in header are visible', async ({ page }) => {
1821
await expect(page.getByText('Data source')).toBeVisible();
19-
await expect(page.getByRole('button', { name: 'Need help' })).toBeVisible();
22+
await expect(page.getByRole('button', { name: /Need help/i })).toBeVisible();
2023
await expect(page.getByTestId('data-testid TimePicker Open Button')).toBeVisible();
2124
await expect(page.getByTestId('data-testid RefreshPicker run button')).toBeVisible();
2225
await expect(page.getByTestId('data-testid RefreshPicker interval button')).toBeVisible();
2326
});
2427

2528
test('in filters bar are visible', async ({ page }) => {
26-
await expect(page.getByRole('radio', { name: 'Root spans' })).toBeVisible();
27-
await expect(page.getByRole('radio', { name: 'All spans' })).toBeVisible();
28-
await expect(page.getByRole('combobox', { name: 'Filter by label values' })).toBeVisible();
29+
await expect(page.getByText('Root spans')).toBeVisible();
30+
await expect(page.getByText('All spans')).toBeVisible();
31+
await expect(page.getByRole('combobox').first()).toBeVisible();
2932
});
3033

3134
test('for RED metrics are visible', async ({ page }) => {
32-
await expect(page.getByText('Span rate')).toBeVisible();
33-
await expect(page.getByTestId('data-testid Panel header ').locator('canvas')).toBeVisible();
34-
await expect(page.getByTestId('data-testid Panel header Histogram by duration').locator('canvas')).toBeVisible();
35-
// TODO: commenting out for now as it's passing fine and looks good when debugging the tests locally but failing in CI for some reason
36-
// await expect(page.getByTestId('data-testid Panel header Errors rate')).toBeVisible();
35+
await expect(page.getByText('Span rate')).toBeVisible({ timeout: 20000 });
36+
await expect(page.getByTestId('data-testid Panel header ').locator('canvas')).toBeVisible({ timeout: 20000 });
37+
await expect(page.getByTestId('data-testid Panel header Histogram by duration').locator('canvas')).toBeVisible({
38+
timeout: 20000,
39+
});
3740
});
3841

3942
test('for tabs are visible', async ({ page }) => {
@@ -45,24 +48,12 @@ test.describe('components', () => {
4548

4649
test('for breakdown tab are visible', async ({ page }) => {
4750
await expect(page.getByText('Attributes are ordered by')).toBeVisible();
48-
await expect(page.getByText('Scope')).toBeVisible();
49-
await expect(page.getByRole('radio', { name: 'Resource', exact: true })).toBeVisible();
50-
await expect(page.getByRole('radio', { name: 'Span', exact: true })).toBeVisible();
51-
await expect(page.getByText('Group by')).toBeVisible();
52-
await expect(page.getByLabel('service.name')).toBeVisible();
51+
await expect(page.getByText('Resource', { exact: true })).toBeVisible();
52+
await expect(page.getByText('Span', { exact: true })).toBeVisible();
5353
await expect(page.getByText('View', { exact: true })).toBeVisible();
5454
await expect(page.getByLabel('Single')).toBeVisible();
5555
await expect(page.getByLabel('Grid')).toBeVisible();
5656
await expect(page.getByLabel('Rows')).toBeVisible();
57-
await expect(page.getByPlaceholder('Search')).toBeVisible();
58-
59-
await page.getByLabel('service.name').click();
60-
await expect(page.getByRole('heading', { name: 'mythical-requester' })).toBeVisible();
61-
await expect(
62-
page
63-
.locator('div')
64-
.filter({ hasText: /^Other attributes$/ })
65-
.nth(1)
66-
).toBeVisible({ timeout: 10000 });
57+
await expect(page.getByPlaceholder('Search attributes...')).toBeVisible();
6758
});
6859
});

e2e/fixtures/explore.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ export class ExplorePage {
1919
await expect(loading).toHaveCount(0);
2020
}
2121

22+
/** Wait for the explore view to be ready (header with Data source or Filters visible). */
23+
async waitForExploreReady(timeoutMs = 10000) {
24+
const headerOrFilters = this.page
25+
.getByText('Data source')
26+
.or(this.page.getByText('Filters', { exact: true }));
27+
await expect(headerOrFilters.first()).toBeVisible({ timeout: timeoutMs });
28+
}
29+
2230
async assertMissingData() {
2331
await expect(this.page.getByTestId(testIds.emptyState)).not.toBeVisible();
2432
await expect(this.page.getByTestId(testIds.errorState)).not.toBeVisible();

0 commit comments

Comments
 (0)