From b9be0bcb6c24626735aac8173f0f300303418077 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 5 May 2026 17:17:18 +0200 Subject: [PATCH 1/7] fix(create-plugin): replace deprecated baseUrl with paths in tsconfig template --- packages/create-plugin/templates/common/.config/tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/create-plugin/templates/common/.config/tsconfig.json b/packages/create-plugin/templates/common/.config/tsconfig.json index 0f74a86deb..ed5f242e09 100644 --- a/packages/create-plugin/templates/common/.config/tsconfig.json +++ b/packages/create-plugin/templates/common/.config/tsconfig.json @@ -9,7 +9,9 @@ "alwaysStrict": true, "declaration": false, "rootDir": "../src", - "baseUrl": "../src", + "paths": { + "*": ["../src/*"] + }, "typeRoots": ["../node_modules/@types"], "resolveJsonModule": true }, From 125c3e19c63a8b1a365eb71681187052db3029c5 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 5 May 2026 17:17:24 +0200 Subject: [PATCH 2/7] feat(create-plugin): add migration 008 to replace tsconfig baseUrl with paths --- .../src/codemods/migrations/migrations.ts | 7 ++ .../008-remove-tsconfig-baseurl.test.ts | 91 +++++++++++++++++++ .../scripts/008-remove-tsconfig-baseurl.ts | 32 +++++++ 3 files changed, 130 insertions(+) create mode 100644 packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.test.ts create mode 100644 packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.ts diff --git a/packages/create-plugin/src/codemods/migrations/migrations.ts b/packages/create-plugin/src/codemods/migrations/migrations.ts index 1bcbff8df9..ce145d1358 100644 --- a/packages/create-plugin/src/codemods/migrations/migrations.ts +++ b/packages/create-plugin/src/codemods/migrations/migrations.ts @@ -50,6 +50,13 @@ export default [ 'Add setupTests.d.ts for @testing-library/jest-dom types and remove @types/testing-library__jest-dom npm package.', scriptPath: import.meta.resolve('./scripts/007-remove-testing-library-types.js'), }, + { + name: '008-remove-tsconfig-baseurl', + version: '7.3.1', + description: + 'Replace deprecated baseUrl compiler option in .config/tsconfig.json with an equivalent paths catch-all.', + scriptPath: import.meta.resolve('./scripts/008-remove-tsconfig-baseurl.js'), + }, // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It is only used above to force migrations to run // for those written before the switch to updates as migrations. ] satisfies Migration[]; diff --git a/packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.test.ts b/packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.test.ts new file mode 100644 index 0000000000..7c00ea99d3 --- /dev/null +++ b/packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.test.ts @@ -0,0 +1,91 @@ +import { describe, expect, it } from 'vitest'; +import { parse } from 'jsonc-parser'; +import migrate from './008-remove-tsconfig-baseurl.js'; +import { Context } from '../../context.js'; + +const SCAFFOLD_TSCONFIG = `/* + * ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY \`@grafana/create-plugin\`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️ + */ +{ + "compilerOptions": { + "alwaysStrict": true, + "rootDir": "../src", + "baseUrl": "../src", + "typeRoots": ["../node_modules/@types"], + "resolveJsonModule": true + }, + "extends": "@grafana/tsconfig" +} +`; + +describe('008-remove-tsconfig-baseurl', () => { + it('should remove baseUrl and add paths catch-all, preserving comment header and rootDir', () => { + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', SCAFFOLD_TSCONFIG); + + const result = migrate(context); + const content = result.getFile('.config/tsconfig.json') || ''; + const config = parse(content) as { compilerOptions: Record }; + + expect(config.compilerOptions['baseUrl']).toBeUndefined(); + expect(config.compilerOptions['paths']).toEqual({ '*': ['../src/*'] }); + expect(config.compilerOptions['rootDir']).toBe('../src'); + expect(content).toContain('DO NOT EDIT THIS FILE DIRECTLY'); + }); + + it('should be idempotent', async () => { + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', SCAFFOLD_TSCONFIG); + + await expect(migrate).toBeIdempotent(context); + }); + + it('should not modify file when baseUrl is already absent', () => { + const context = new Context('/virtual'); + const content = `{ + "compilerOptions": { + "rootDir": "../src", + "paths": { "*": ["../src/*"] } + } +} +`; + context.addFile('.config/tsconfig.json', content); + + const result = migrate(context); + + expect(result.getFile('.config/tsconfig.json')).toBe(content); + }); + + it('should not modify anything when .config/tsconfig.json does not exist', () => { + const context = new Context('/virtual'); + + const result = migrate(context); + + expect(result.hasChanges()).toBe(false); + }); + + it('should merge paths["*"] into an existing paths object without overwriting other entries', () => { + const context = new Context('/virtual'); + context.addFile( + '.config/tsconfig.json', + `{ + "compilerOptions": { + "rootDir": "../src", + "baseUrl": "../src", + "paths": { + "@components/*": ["../src/components/*"] + } + } +} +` + ); + + const result = migrate(context); + const content = result.getFile('.config/tsconfig.json') || ''; + const config = parse(content) as { compilerOptions: { paths: Record } }; + + expect(config.compilerOptions.paths['@components/*']).toEqual(['../src/components/*']); + expect(config.compilerOptions.paths['*']).toEqual(['../src/*']); + expect(config.compilerOptions).not.toHaveProperty('baseUrl'); + }); +}); diff --git a/packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.ts b/packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.ts new file mode 100644 index 0000000000..8aee220b4d --- /dev/null +++ b/packages/create-plugin/src/codemods/migrations/scripts/008-remove-tsconfig-baseurl.ts @@ -0,0 +1,32 @@ +import { modify, applyEdits } from 'jsonc-parser'; +import type { Context } from '../../context.js'; + +export default function migrate(context: Context) { + if (!context.doesFileExist('.config/tsconfig.json')) { + return context; + } + + const content = context.getFile('.config/tsconfig.json') || ''; + + if (!content.includes('"baseUrl"')) { + return context; + } + + const formattingOptions = { formattingOptions: { insertSpaces: true, tabSize: 2 } }; + + // applyEdits accepts Edit[] and modify returns Edit[], but both modify calls must operate on + // the same base string to produce correct offsets. Chaining them sequentially is safer since + // removing baseUrl shifts positions in compilerOptions before we add paths. + const contentWithoutBaseUrl = applyEdits( + content, + modify(content, ['compilerOptions', 'baseUrl'], undefined, formattingOptions) + ); + const contentWithPaths = applyEdits( + contentWithoutBaseUrl, + modify(contentWithoutBaseUrl, ['compilerOptions', 'paths', '*'], ['../src/*'], formattingOptions) + ); + + context.updateFile('.config/tsconfig.json', contentWithPaths); + + return context; +} From dd5c24a60d2b43c631ddcacb17ccb98ce2ac5ed0 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Tue, 5 May 2026 17:28:50 +0200 Subject: [PATCH 3/7] fix(create-plugin): clarify migration 008 description with purpose not just action --- packages/create-plugin/src/codemods/migrations/migrations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-plugin/src/codemods/migrations/migrations.ts b/packages/create-plugin/src/codemods/migrations/migrations.ts index ce145d1358..4e20f96191 100644 --- a/packages/create-plugin/src/codemods/migrations/migrations.ts +++ b/packages/create-plugin/src/codemods/migrations/migrations.ts @@ -54,7 +54,7 @@ export default [ name: '008-remove-tsconfig-baseurl', version: '7.3.1', description: - 'Replace deprecated baseUrl compiler option in .config/tsconfig.json with an equivalent paths catch-all.', + 'Fix TypeScript 6 compatibility: baseUrl is deprecated in TS6 (error TS5101) and must be replaced with an equivalent paths entry to preserve non-relative import resolution.', scriptPath: import.meta.resolve('./scripts/008-remove-tsconfig-baseurl.js'), }, // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It is only used above to force migrations to run From 1ca9860a50058b1b08b5c52763ef08992bc844de Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Wed, 6 May 2026 10:15:37 +0200 Subject: [PATCH 4/7] feat(create-plugin): add migration to update ts-node compilerOptions Updates module, moduleResolution, and target inside ts-node compilerOptions in scaffolded plugins' .config/tsconfig.json so they remain compatible with the latest @grafana/tsconfig (TypeScript 5/6). --- .../scripts/009-ts-node-nodenext.test.ts | 105 ++++++++++++++++++ .../scripts/009-ts-node-nodenext.ts | 37 ++++++ 2 files changed, 142 insertions(+) create mode 100644 packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.test.ts create mode 100644 packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.ts diff --git a/packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.test.ts b/packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.test.ts new file mode 100644 index 0000000000..dc93c6eb80 --- /dev/null +++ b/packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.test.ts @@ -0,0 +1,105 @@ +import { describe, expect, it } from 'vitest'; +import migrate from './009-ts-node-nodenext.js'; +import { Context } from '../../context.js'; + +const SCAFFOLDED_TSCONFIG = `/* + * ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY \`@grafana/create-plugin\`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️ + * + * In order to extend the configuration follow the steps in + * https://grafana.com/developers/plugin-tools/how-to-guides/extend-configurations#extend-the-typescript-config + */ +{ + "compilerOptions": { + "alwaysStrict": true, + "declaration": false, + "rootDir": "../src", + "paths": { + "*": ["../src/*"] + }, + "typeRoots": ["../node_modules/@types"], + "resolveJsonModule": true + }, + "ts-node": { + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "target": "es5", + "esModuleInterop": true + }, + "transpileOnly": true + }, + "include": ["../src", "./types"], + "extends": "@grafana/tsconfig" +} +`; + +describe('009-ts-node-nodenext', () => { + it('should update module, moduleResolution, and target inside ts-node compilerOptions', () => { + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', SCAFFOLDED_TSCONFIG); + + const result = migrate(context); + const updated = result.getFile('.config/tsconfig.json') || ''; + + expect(updated).toContain('"module": "nodenext"'); + expect(updated).toContain('"moduleResolution": "nodenext"'); + expect(updated).toContain('"target": "es2022"'); + expect(updated).not.toContain('"module": "commonjs"'); + expect(updated).not.toContain('"moduleResolution": "node"'); + expect(updated).not.toContain('"target": "es5"'); + }); + + it('should preserve the JSONC comment header', () => { + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', SCAFFOLDED_TSCONFIG); + + const result = migrate(context); + const updated = result.getFile('.config/tsconfig.json') || ''; + + expect(updated).toContain('THIS FILE WAS SCAFFOLDED BY'); + expect(updated.startsWith('/*')).toBe(true); + }); + + it('should be idempotent', async () => { + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', SCAFFOLDED_TSCONFIG); + + await expect(migrate).toBeIdempotent(context); + }); + + it('should be a no-op when the file is already migrated', () => { + const alreadyMigrated = SCAFFOLDED_TSCONFIG.replace('"module": "commonjs"', '"module": "nodenext"') + .replace('"moduleResolution": "node"', '"moduleResolution": "nodenext"') + .replace('"target": "es5"', '"target": "es2022"'); + + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', alreadyMigrated); + + const result = migrate(context); + + expect(result.getFile('.config/tsconfig.json')).toBe(alreadyMigrated); + }); + + it('should be a no-op when .config/tsconfig.json does not exist', () => { + const context = new Context('/virtual'); + + const result = migrate(context); + + expect(result.hasChanges()).toBe(false); + }); + + it('should leave user-customised values untouched and only update keys at known-old values', () => { + const partiallyCustomised = SCAFFOLDED_TSCONFIG.replace('"target": "es5"', '"target": "es2020"'); + + const context = new Context('/virtual'); + context.addFile('.config/tsconfig.json', partiallyCustomised); + + const result = migrate(context); + const updated = result.getFile('.config/tsconfig.json') || ''; + + expect(updated).toContain('"module": "nodenext"'); + expect(updated).toContain('"moduleResolution": "nodenext"'); + expect(updated).toContain('"target": "es2020"'); + expect(updated).not.toContain('"target": "es2022"'); + }); +}); diff --git a/packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.ts b/packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.ts new file mode 100644 index 0000000000..8537ccfdd0 --- /dev/null +++ b/packages/create-plugin/src/codemods/migrations/scripts/009-ts-node-nodenext.ts @@ -0,0 +1,37 @@ +import { applyEdits, modify } from 'jsonc-parser'; +import type { Context } from '../../context.js'; + +const TSCONFIG_PATH = '.config/tsconfig.json'; + +const FORMATTING_OPTIONS = { + formattingOptions: { insertSpaces: true, tabSize: 2 }, +}; + +const UPDATES: Array<{ key: string; oldValue: string; newValue: string }> = [ + { key: 'module', oldValue: 'commonjs', newValue: 'nodenext' }, + { key: 'moduleResolution', oldValue: 'node', newValue: 'nodenext' }, + { key: 'target', oldValue: 'es5', newValue: 'es2022' }, +]; + +export default function migrate(context: Context) { + if (!context.doesFileExist(TSCONFIG_PATH)) { + return context; + } + + const original = context.getFile(TSCONFIG_PATH) || ''; + let next = original; + + for (const { key, oldValue, newValue } of UPDATES) { + const oldPattern = `"${key}": "${oldValue}"`; + if (!next.includes(oldPattern)) { + continue; + } + next = applyEdits(next, modify(next, ['ts-node', 'compilerOptions', key], newValue, FORMATTING_OPTIONS)); + } + + if (next !== original) { + context.updateFile(TSCONFIG_PATH, next); + } + + return context; +} From c977975ebd83baf2721e05fb9cb2d699b0aa66e5 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Wed, 6 May 2026 10:15:59 +0200 Subject: [PATCH 5/7] feat(create-plugin): register 009-ts-node-nodenext migration --- .../create-plugin/src/codemods/migrations/migrations.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/create-plugin/src/codemods/migrations/migrations.ts b/packages/create-plugin/src/codemods/migrations/migrations.ts index 4e20f96191..de8c6f1b1d 100644 --- a/packages/create-plugin/src/codemods/migrations/migrations.ts +++ b/packages/create-plugin/src/codemods/migrations/migrations.ts @@ -57,6 +57,13 @@ export default [ 'Fix TypeScript 6 compatibility: baseUrl is deprecated in TS6 (error TS5101) and must be replaced with an equivalent paths entry to preserve non-relative import resolution.', scriptPath: import.meta.resolve('./scripts/008-remove-tsconfig-baseurl.js'), }, + { + name: '009-ts-node-nodenext', + version: '7.3.1', + description: + 'Fix ts-node compatibility with the latest @grafana/tsconfig: outdated module/moduleResolution/target overrides break TypeScript 5/6 builds, replaced with nodenext/nodenext/es2022.', + scriptPath: import.meta.resolve('./scripts/009-ts-node-nodenext.js'), + }, // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It is only used above to force migrations to run // for those written before the switch to updates as migrations. ] satisfies Migration[]; From b528d0cd5ec9ec8cabe7d93c1a13309d0cb55385 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Wed, 6 May 2026 10:16:13 +0200 Subject: [PATCH 6/7] fix(create-plugin): update scaffolded ts-node compilerOptions Update module, moduleResolution, and target to nodenext/nodenext/es2022 so newly scaffolded plugins are compatible with the latest @grafana/tsconfig (TypeScript 5/6). --- .../create-plugin/templates/common/.config/tsconfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-plugin/templates/common/.config/tsconfig.json b/packages/create-plugin/templates/common/.config/tsconfig.json index ed5f242e09..385a2234ce 100644 --- a/packages/create-plugin/templates/common/.config/tsconfig.json +++ b/packages/create-plugin/templates/common/.config/tsconfig.json @@ -17,9 +17,9 @@ }, "ts-node": { "compilerOptions": { - "module": "commonjs", - "moduleResolution": "node", - "target": "es5", + "module": "nodenext", + "moduleResolution": "nodenext", + "target": "es2022", "esModuleInterop": true }, "transpileOnly": true From 7e38a5ae5b99c5409ccde035ef6678ca1e56e230 Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Wed, 6 May 2026 10:16:47 +0200 Subject: [PATCH 7/7] ci: re-enable test-updates job The grafana/grafana NPM package publishing issue that caused this job to fail has been resolved, so the job can run again. It exercises the create-plugin update command end-to-end on a 5.27.1-scaffolded plugin, validating every registered migration in sequence. --- .github/workflows/ci.yml | 151 +++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ba109048c..c78fd94e23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -174,82 +174,81 @@ jobs: GRAFANA_ACCESS_POLICY_TOKEN: ${{ fromJSON(steps.get-secrets.outputs.secrets).GRAFANA_ACCESS_POLICY_TOKEN }} run: sign-plugin --rootUrls http://www.example.com --signatureType private working-directory: ./${{ env.WORKING_DIR }} - # Temporarily disable to prevent failures due to NPM package publishing in grafana/grafana. Put back to 5.27.1 once resolved. - # test-updates: - # name: Test create-plugin update command - # runs-on: ubuntu-x64 - # if: "!contains(github.event.head_commit.message, 'ci skip') && !contains(github.event.head_commit.message, 'skip ci')" - # needs: [test] - # env: - # WORKING_DIR: 'myorg-nobackend-panel' - # steps: - # - name: Setup nodejs - # uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 - # with: - # node-version: '24' - - # - name: Scaffold plugin using the earliest create-plugin version mentioned in migrations - # run: npx -y @grafana/create-plugin@5.27.1 --plugin-name='no-backend' --org-name='myorg' --plugin-type='panel' - - # - name: Install generated plugin dependencies - # run: npm install --no-audit - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Download packed artifacts - # uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - # with: - # name: packed-artifacts - # path: ./packed-artifacts - - # - name: Install npm packages globally - # run: for file in *.tgz; do npm install -g "$file"; done - # working-directory: ./packed-artifacts - - # - name: Test create-plugin update command - # run: npx create-plugin update --force - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Lint plugin frontend - # run: npm run lint - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Typecheck plugin frontend - # run: npm run typecheck - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Build plugin frontend - # run: npm run build - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Test plugin frontend - # run: npm run test:ci - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Install playwright dependencies - # run: npm exec playwright install --with-deps chromium - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Start grafana server for e2e tests (10.4.0) - # run: | - # ANONYMOUS_AUTH_ENABLED=false docker compose build --no-cache - # docker compose up -d - # env: - # GRAFANA_VERSION: '10.4.0' - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Wait for grafana server (10.4.0) - # uses: grafana/plugin-actions/wait-for-grafana@752a92aaebfcd83121acc27293c93b7013d30deb # wait-for-grafana/v1.0.1 - # with: - # url: http://localhost:3000/login - - # - name: Run e2e tests (10.4.0) - # id: run-e2e-tests-min-version - # run: npm run e2e - # working-directory: ./${{ env.WORKING_DIR }} - - # - name: Stop grafana docker (10.4.0) - # run: docker compose down - # working-directory: ./${{ env.WORKING_DIR }} + test-updates: + name: Test create-plugin update command + runs-on: ubuntu-x64 + if: "!contains(github.event.head_commit.message, 'ci skip') && !contains(github.event.head_commit.message, 'skip ci')" + needs: [test] + env: + WORKING_DIR: 'myorg-nobackend-panel' + steps: + - name: Setup nodejs + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + with: + node-version: '24' + + - name: Scaffold plugin using the earliest create-plugin version mentioned in migrations + run: npx -y @grafana/create-plugin@5.27.1 --plugin-name='no-backend' --org-name='myorg' --plugin-type='panel' + + - name: Install generated plugin dependencies + run: npm install --no-audit + working-directory: ./${{ env.WORKING_DIR }} + + - name: Download packed artifacts + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: packed-artifacts + path: ./packed-artifacts + + - name: Install npm packages globally + run: for file in *.tgz; do npm install -g "$file"; done + working-directory: ./packed-artifacts + + - name: Test create-plugin update command + run: npx create-plugin update --force + working-directory: ./${{ env.WORKING_DIR }} + + - name: Lint plugin frontend + run: npm run lint + working-directory: ./${{ env.WORKING_DIR }} + + - name: Typecheck plugin frontend + run: npm run typecheck + working-directory: ./${{ env.WORKING_DIR }} + + - name: Build plugin frontend + run: npm run build + working-directory: ./${{ env.WORKING_DIR }} + + - name: Test plugin frontend + run: npm run test:ci + working-directory: ./${{ env.WORKING_DIR }} + + - name: Install playwright dependencies + run: npm exec playwright install --with-deps chromium + working-directory: ./${{ env.WORKING_DIR }} + + - name: Start grafana server for e2e tests (10.4.0) + run: | + ANONYMOUS_AUTH_ENABLED=false docker compose build --no-cache + docker compose up -d + env: + GRAFANA_VERSION: '10.4.0' + working-directory: ./${{ env.WORKING_DIR }} + + - name: Wait for grafana server (10.4.0) + uses: grafana/plugin-actions/wait-for-grafana@752a92aaebfcd83121acc27293c93b7013d30deb # wait-for-grafana/v1.0.1 + with: + url: http://localhost:3000/login + + - name: Run e2e tests (10.4.0) + id: run-e2e-tests-min-version + run: npm run e2e + working-directory: ./${{ env.WORKING_DIR }} + + - name: Stop grafana docker (10.4.0) + run: docker compose down + working-directory: ./${{ env.WORKING_DIR }} generate-plugins: name: Test plugin scaffolding