Migrate the Grafana plugin build from grafana-toolkit to create-plugin - #118
Migrate the Grafana plugin build from grafana-toolkit to create-plugin#118PDGGK wants to merge 2 commits into
Conversation
@grafana/toolkit was archived by Grafana and no longer receives updates, so the plugin could not be built with a supported toolchain. This moves the frontend build to @grafana/create-plugin: webpack, SWC/Jest, the flat ESLint config, Playwright for e2e, and a package-lock.json replacing the yarn.lock. The generated .config directory is checked in as create-plugin intends and is not hand-edited; it can be refreshed with 'npx @grafana/create-plugin update'. The plugin's own CI workflow is updated in the same change, because it is what the migration breaks: it pinned Node 14, installed with 'yarn install --frozen-lockfile' and keyed both caches on yarn.lock, which this change removes. It now reads the Node version from the plugin's .nvmrc, caches on package-lock.json and runs 'npm ci && npm run build'. The Go backend step is untouched. grafanaDependency moves from >=9.3.0 to >=12.3.0. The plugin builds and is tested against the @grafana/data, @grafana/ui and @grafana/runtime 13.1.0 packages the new toolchain pulls in. Those are webpack externals resolved from the host Grafana at runtime, so an API present in the 13.1.0 types but absent on an older host fails at runtime rather than at build time, which is exactly why the declared floor should be the one we build and test against. The stricter ESLint config reports two errors in the tree-model query editors, where an array is mutated in place and the same reference is then handed to onChange. Both are changed to pass a new array instead. The same append, and two splice-based removals, remain a few lines away where the rule does not flag them; those are left for a separate change with tests rather than altering untested UI behaviour here. docker-compose.yaml also starts a standalone IoTDB alongside Grafana and ./provisioning wires the datasource to it, so 'npm run server' brings up a working plugin against a real server rather than an empty Grafana. Signed-off-by: Zihan Dai <99155080+PDGGK@users.noreply.github.com>
|
Thanks for taking this on — moving off the archived Three things below. The first is blocking; the second is a suggestion that would have caught the first automatically; the third needs a call from the PMC rather than from you or me. 1. Blocking:
|
The migration removed yarn.lock and moved the plugin to Node 22 and a webpack config loaded through ts-node, but connectors/grafana-plugin/pom.xml still drove frontend-maven-plugin with install-node-and-yarn, Node 16.13.1 and Yarn 1.22.17. That is a second consumer of the toolchain this change replaces, alongside the workflow already updated here, so mvn -Pwith-grafana-plugin package would have broken on master straight after the merge. The Maven executions now install Node from the same version the plugin declares and run npm ci and npm run build. ci rather than install so the lockfile stays authoritative and a drifted dependency set fails the build instead of resolving silently. Note that .npmrc sets ignore-scripts=true, which applies to the Maven-driven install as well. The reason this was not caught is that no CI job builds this module through Maven at all: grafana-plugin is not part of the with-all-connectors profile that compile-check.yml uses, and the Jenkinsfile's plain mvn clean install does not activate with-grafana-plugin either. The green build check is this workflow, which exercises the npm path directly, so it was verifying its own new path. A second job now runs the Maven entrypoint, which also covers the antrun execution bound to the package phase that invokes backend-compile.sh -- that one is not skipped by -DskipTests despite its execution id. Signed-off-by: Zihan Dai <99155080+PDGGK@users.noreply.github.com>
|
Thanks — item 1 is a real break and I had missed it in exactly the way you describe. Pushed as The pom. Verified locally: Item 2. Added as a second job in One thing worth recording from getting that job green: the antrun execution has Item 3. Agreed that both belong to the PMC rather than to this PR, and I will raise them on One observation I am deliberately not folding in, since it is pre-existing and this PR does not touch the file: |
Why
@grafana/toolkitwas archived by Grafana and no longer receives updates, sonpm run buildwas pinned to an unmaintained toolchain. This migrates the plugin's frontend build to@grafana/create-plugin, which is the supported replacement.What changed
Build toolchain.
grafana-toolkit plugin:build/test/devare replaced by webpack, SWC/Jest, the flat ESLint config and Playwright, all driven from the generated.config/directory..config/is checked in ascreate-pluginintends, carries its own "do not edit" notice, and can be refreshed later withnpx @grafana/create-plugin update.Lockfile.
yarn.lockis removed in favour ofpackage-lock.json, matching the npm-based scripts the new toolchain generates.grafanaDependencymoves from>=9.3.0to>=12.3.0. This is the one compatibility decision in the change, so to be explicit about it: the plugin builds and is tested against@grafana/data,@grafana/uiand@grafana/runtime13.1.0. Those packages are webpack externals (.config/bundler/externals.ts), resolved from the host Grafana at runtime rather than bundled — so an API that exists in the 13.1.0 types but not on an older host does not fail the build, it fails at runtime in the user's Grafana with no bundled fallback. Declaring>=12.3.0, the floorcreate-plugindeclares for this SDK generation, states the range we can actually stand behind. If keeping a lower floor matters more, that is worth saying now — it would mean pinning the@grafana/*packages down instead.Two ESLint errors fixed. The stricter config flags
react-hooks/immutabilityin the tree-model query editors, where an array is mutated in place and the same reference is then passed toonChange— so a consumer comparing by reference sees no change. Both now pass a new array instead.To be plain about what this leaves behind:
FromValue.tsxandSelectValue.tsxstill contain the identical append (prefixPath[prefixPath.length] = ''; onChange(prefixPath)) a few lines below the corrected one, where the rule does not flag it, plus twosplice-based removals with the same shape. I left them because these components have no test coverage and a toolchain migration is the wrong place to change untested UI behaviour — but I am happy to fix the remaining sites in a separate change with tests.CI workflow updated in the same change.
.github/workflows/grafana-plugin.ymltriggers onconnectors/grafana-plugin/**, pinsnode-version: "14.x", installs withyarn install --frozen-lockfileand keys both caches onhashFiles('**/yarn.lock'). Since this change removesyarn.lock, that workflow would fail at install, and Node 14 cannot run the new toolchain in any case. It now takes the Node version from the plugin's.nvmrc— so it cannot drift away from the toolchain again — usessetup-node's npm cache keyed onpackage-lock.json, and runsnpm ci && npm run build. The Go/backend step is unchanged.Development environment.
docker-compose.yamlnow also starts a standalone IoTDB next to Grafana, andprovisioning/wires the datasource to it (REST on 18080 for the tree-model modes, native Thrift on 6667 for the table-model mode).npm run servertherefore brings up a Grafana with the plugin loaded and a server to query, instead of an empty instance.One known rough edge in the generated config:
.config/supervisord/supervisord.confwaits for a backend binary matchinggpx_iotdb*, derived from the plugin name, whileplugin.jsondeclaresexecutable: gpx_apache_iotdb_datasource. That only affectsDEVELOPMENT=true(the delve path); with the defaultDEVELOPMENT=falsethe entrypoint runs Grafana directly, which is the path verified below. I have not hand-edited it, since.config/is generated and regenerated bycreate-plugin update.Verification
Toolchain:
typecheck,lint(0 errors; 9 remaining warnings are pre-existing deprecation notices),test:ci(13 tests) andbuildall pass. The exact command chain the updated workflow runs —npm ci && npm run build— was run from a clean install to confirmpackage-lock.jsonandpackage.jsonare in sync, sincenpm cifails hard if they are not.End to end against real servers, not just a green build: the plugin was loaded into Grafana 13.1.0 from
docker compose up, with a realapache/iotdb:2.0.8behind it. Grafana registers the plugin (Plugin registered pluginId=apache-iotdb-datasource), the provisioned datasource connects, and a table-model queryrenders in a panel with the row-major result correctly pivoted into one series per tag value, and the same data shown in the table view.