@grafana/create-plugin 6.2.0-canary.2233.19133609453.0 → 6.2.0-canary.2233.19424871609.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/CONTRIBUTING.md +3 -0
  3. package/dist/codemods/additions/additions.js +6 -8
  4. package/dist/codemods/additions/scripts/example-addition.js +19 -33
  5. package/dist/codemods/migrations/manager.js +13 -40
  6. package/dist/codemods/migrations/migrations.js +33 -25
  7. package/dist/codemods/migrations/scripts/004-eslint9-flat-config.js +1 -2
  8. package/dist/codemods/migrations/scripts/005-react-18-3.js +20 -0
  9. package/dist/codemods/migrations/scripts/example-migration.js +7 -3
  10. package/dist/codemods/runner.js +38 -0
  11. package/dist/codemods/schema-parser.js +20 -0
  12. package/dist/codemods/utils.js +7 -4
  13. package/dist/commands/add.command.js +24 -55
  14. package/dist/commands/update.command.js +7 -41
  15. package/dist/utils/utils.checks.js +40 -0
  16. package/dist/utils/utils.config.js +1 -16
  17. package/package.json +3 -2
  18. package/src/codemods/additions/additions.test.ts +12 -0
  19. package/src/codemods/additions/additions.ts +7 -21
  20. package/src/codemods/additions/scripts/example-addition.test.ts +14 -33
  21. package/src/codemods/additions/scripts/example-addition.ts +27 -44
  22. package/src/codemods/migrations/fixtures/migrations.ts +19 -18
  23. package/src/codemods/migrations/manager.test.ts +67 -73
  24. package/src/codemods/migrations/manager.ts +17 -50
  25. package/src/codemods/migrations/migrations.test.ts +10 -5
  26. package/src/codemods/migrations/migrations.ts +37 -34
  27. package/src/codemods/migrations/scripts/004-eslint9-flat-config.ts +2 -2
  28. package/src/codemods/migrations/scripts/005-react-18-3.test.ts +145 -0
  29. package/src/codemods/migrations/scripts/005-react-18-3.ts +19 -0
  30. package/src/codemods/migrations/scripts/example-migration.test.ts +1 -1
  31. package/src/codemods/migrations/scripts/example-migration.ts +20 -3
  32. package/src/codemods/runner.ts +57 -0
  33. package/src/codemods/schema-parser.ts +27 -0
  34. package/src/codemods/types.ts +9 -14
  35. package/src/codemods/{migrations/utils.test.ts → utils.test.ts} +8 -7
  36. package/src/codemods/utils.ts +13 -35
  37. package/src/commands/add.command.ts +26 -62
  38. package/src/commands/update.command.ts +8 -47
  39. package/src/migrations/migrations.ts +44 -0
  40. package/src/utils/utils.checks.ts +47 -0
  41. package/src/utils/utils.config.ts +1 -28
  42. package/templates/common/_package.json +7 -5
  43. package/templates/github/workflows/bundle-stats.yml +1 -1
  44. package/templates/github/workflows/ci.yml +11 -11
  45. package/templates/github/workflows/cp-update.yml +9 -14
  46. package/templates/github/workflows/is-compatible.yml +3 -3
  47. package/templates/github/workflows/release.yml +1 -1
  48. package/vitest.config.ts +12 -0
  49. package/dist/codemods/additions/manager.js +0 -115
  50. package/dist/codemods/additions/utils.js +0 -10
  51. package/dist/codemods/migrations/utils.js +0 -10
  52. package/src/codemods/additions/manager.ts +0 -145
  53. package/src/codemods/additions/utils.ts +0 -12
  54. package/src/codemods/migrations/utils.ts +0 -12
@@ -1,8 +1,3 @@
1
- /**
2
- * Shared utilities for codemods (migrations and additions).
3
- * These functions work with the Context class to modify plugin codebases.
4
- */
5
-
6
1
  import { dirname, join } from 'node:path';
7
2
  import { createRequire } from 'node:module';
8
3
  import { Context } from './context.js';
@@ -11,20 +6,9 @@ import chalk from 'chalk';
11
6
  import { output } from '../utils/utils.console.js';
12
7
  import { getPackageManagerSilentInstallCmd, getPackageManagerWithFallback } from '../utils/utils.packageManager.js';
13
8
  import { execSync } from 'node:child_process';
14
- import { clean, coerce, gt } from 'semver';
15
-
16
- /**
17
- * Generic metadata type for printChanges
18
- */
19
- type ChangeMetadata = {
20
- description: string;
21
- };
9
+ import { clean, coerce, gt, gte } from 'semver';
22
10
 
23
- /**
24
- * Prints changes made to the context in a formatted way.
25
- * Works with both migrations and additions.
26
- */
27
- export function printChanges(context: Context, key: string, meta: ChangeMetadata) {
11
+ export function printChanges(context: Context, key: string, description: string) {
28
12
  const changes = context.listChanges();
29
13
  const lines = [];
30
14
 
@@ -39,7 +23,7 @@ export function printChanges(context: Context, key: string, meta: ChangeMetadata
39
23
  }
40
24
 
41
25
  output.addHorizontalLine('gray');
42
- output.logSingleLine(`${key} (${meta.description})`);
26
+ output.logSingleLine(`${key} (${description})`);
43
27
 
44
28
  if (lines.length === 0) {
45
29
  output.logSingleLine('No changes were made');
@@ -48,9 +32,6 @@ export function printChanges(context: Context, key: string, meta: ChangeMetadata
48
32
  }
49
33
  }
50
34
 
51
- /**
52
- * Writes all changes from the context to the filesystem.
53
- */
54
35
  export function flushChanges(context: Context) {
55
36
  const basePath = context.basePath;
56
37
  const changes = context.listChanges();
@@ -122,9 +103,6 @@ export async function formatFiles(context: Context) {
122
103
  // (This runs for each codemod used in an update)
123
104
  let packageJsonInstallCache: string;
124
105
 
125
- /**
126
- * Installs NPM dependencies if package.json has changed.
127
- */
128
106
  export function installNPMDependencies(context: Context) {
129
107
  const hasPackageJsonChanges = Object.entries(context.listChanges()).some(
130
108
  ([filePath, { changeType }]) => filePath === 'package.json' && changeType === 'update'
@@ -152,9 +130,6 @@ export function installNPMDependencies(context: Context) {
152
130
  }
153
131
  }
154
132
 
155
- /**
156
- * Reads and parses a JSON file from the context.
157
- */
158
133
  export function readJsonFile<T extends object = any>(context: Context, path: string): T {
159
134
  if (!context.doesFileExist(path)) {
160
135
  throw new Error(`Cannot find ${path}`);
@@ -166,9 +141,6 @@ export function readJsonFile<T extends object = any>(context: Context, path: str
166
141
  }
167
142
  }
168
143
 
169
- /**
170
- * Adds or updates dependencies in package.json, preventing downgrades.
171
- */
172
144
  export function addDependenciesToPackageJson(
173
145
  context: Context,
174
146
  dependencies: Record<string, string>,
@@ -233,9 +205,6 @@ export function addDependenciesToPackageJson(
233
205
  context.updateFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2));
234
206
  }
235
207
 
236
- /**
237
- * Removes dependencies from package.json.
238
- */
239
208
  export function removeDependenciesFromPackageJson(
240
209
  context: Context,
241
210
  dependencies: string[],
@@ -276,8 +245,13 @@ const DIST_TAGS = {
276
245
 
277
246
  /**
278
247
  * Compares two version strings to determine if the incoming version is greater
248
+ *
249
+ * @param incomingVersion - The incoming version to compare.
250
+ * @param existingVersion - The existing version to compare.
251
+ * @param orEqualTo - Whether to check for greater than or equal to (>=) instead of just greater than (>).
252
+ *
279
253
  */
280
- export function isVersionGreater(incomingVersion: string, existingVersion: string): boolean {
254
+ export function isVersionGreater(incomingVersion: string, existingVersion: string, orEqualTo = false) {
281
255
  const incomingIsDistTag = incomingVersion in DIST_TAGS;
282
256
  const existingIsDistTag = existingVersion in DIST_TAGS;
283
257
 
@@ -301,6 +275,10 @@ export function isVersionGreater(incomingVersion: string, existingVersion: strin
301
275
  return true;
302
276
  }
303
277
 
278
+ if (orEqualTo) {
279
+ return gte(incomingSemver, existingSemver);
280
+ }
281
+
304
282
  return gt(incomingSemver, existingSemver);
305
283
  }
306
284
 
@@ -1,7 +1,7 @@
1
- import { getAdditionFlags, getAvailableAdditions, runAdditionByName } from '../codemods/additions/manager.js';
2
- import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
3
-
4
- import { isPluginDirectory } from '../utils/utils.plugin.js';
1
+ import defaultAdditions from '../codemods/additions/additions.js';
2
+ import { runCodemod } from '../codemods/runner.js';
3
+ import { getPackageManagerExecCmd, getPackageManagerFromUserAgent } from '../utils/utils.packageManager.js';
4
+ import { performPreCodemodChecks } from '../utils/utils.checks.js';
5
5
  import minimist from 'minimist';
6
6
  import { output } from '../utils/utils.console.js';
7
7
 
@@ -13,10 +13,27 @@ export const add = async (argv: minimist.ParsedArgs) => {
13
13
  process.exit(1);
14
14
  }
15
15
 
16
- await performPreAddChecks(argv);
16
+ await performPreCodemodChecks(argv);
17
17
 
18
18
  try {
19
- await runAdditionByName(subCommand, argv);
19
+ const addition = defaultAdditions.find((addition) => addition.name === subCommand);
20
+ if (!addition) {
21
+ const additionsList = defaultAdditions.map((addition) => addition.name);
22
+ throw new Error(`Unknown addition: ${subCommand}\n\nAvailable additions: ${additionsList.join(', ')}`);
23
+ }
24
+
25
+ output.log({
26
+ title: `Running addition: ${addition.name}`,
27
+ body: [addition.description],
28
+ });
29
+
30
+ // filter out minimist internal properties (_ and $0) before passing to codemod
31
+ const { _, $0, ...codemodOptions } = argv;
32
+ await runCodemod(addition, codemodOptions);
33
+
34
+ output.success({
35
+ title: `Successfully added ${addition.name} to your plugin.`,
36
+ });
20
37
  } catch (error) {
21
38
  if (error instanceof Error) {
22
39
  output.error({
@@ -29,69 +46,16 @@ export const add = async (argv: minimist.ParsedArgs) => {
29
46
  };
30
47
 
31
48
  async function showAdditionsHelp() {
32
- const availableAdditions = getAvailableAdditions();
33
- const additionsList = await Promise.all(
34
- Object.values(availableAdditions).map(async (addition) => {
35
- let info = `${addition.name} - ${addition.description}`;
36
- const flags = await getAdditionFlags(addition);
37
- if (flags.length > 0) {
38
- const flagDocs = flags.map((flag) => {
39
- const req = flag.required ? ' (required)' : ' (optional)';
40
- return ` --${flag.name}: ${flag.description}${req}`;
41
- });
42
- info += '\n' + flagDocs.join('\n');
43
- }
44
- return info;
45
- })
46
- );
49
+ const additionsList = defaultAdditions.map((addition) => addition.name);
50
+ const { packageManagerName, packageManagerVersion } = getPackageManagerFromUserAgent();
47
51
 
48
52
  output.error({
49
53
  title: 'No addition specified',
50
54
  body: [
51
- 'Usage: npx @grafana/create-plugin add <addition-name> [options]',
55
+ `Usage: ${getPackageManagerExecCmd(packageManagerName, packageManagerVersion)} add <addition-name> [options]`,
52
56
  '',
53
57
  'Available additions:',
54
58
  ...output.bulletList(additionsList),
55
59
  ],
56
60
  });
57
61
  }
58
-
59
- async function performPreAddChecks(argv: minimist.ParsedArgs) {
60
- if (!(await isGitDirectory()) && !argv.force) {
61
- output.error({
62
- title: 'You are not inside a git directory',
63
- body: [
64
- `In order to proceed please run ${output.formatCode('git init')} in the root of your project and commit your changes.`,
65
- `(This check is necessary to make sure that the changes are easy to revert and don't interfere with any changes you currently have.`,
66
- `In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
67
- ],
68
- });
69
-
70
- process.exit(1);
71
- }
72
-
73
- if (!(await isGitDirectoryClean()) && !argv.force) {
74
- output.error({
75
- title: 'Please clean your repository working tree before adding features.',
76
- body: [
77
- 'Commit your changes or stash them.',
78
- `(This check is necessary to make sure that the changes are easy to revert and don't mess with any changes you currently have.`,
79
- `In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
80
- ],
81
- });
82
-
83
- process.exit(1);
84
- }
85
-
86
- if (!isPluginDirectory() && !argv.force) {
87
- output.error({
88
- title: 'Are you inside a plugin directory?',
89
- body: [
90
- `We couldn't find a "src/plugin.json" file under your current directory.`,
91
- `(Please make sure to run this command from the root of your plugin folder. In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
92
- ],
93
- });
94
-
95
- process.exit(1);
96
- }
97
- }
@@ -5,18 +5,17 @@ import {
5
5
  getPackageManagerWithFallback,
6
6
  } from '../utils/utils.packageManager.js';
7
7
  import { gte, lt } from 'semver';
8
- import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
8
+ import { performPreCodemodChecks } from '../utils/utils.checks.js';
9
9
 
10
10
  import { CURRENT_APP_VERSION } from '../utils/utils.version.js';
11
11
  import { LEGACY_UPDATE_CUTOFF_VERSION } from '../constants.js';
12
12
  import { getConfig } from '../utils/utils.config.js';
13
- import { isPluginDirectory } from '../utils/utils.plugin.js';
14
13
  import minimist from 'minimist';
15
14
  import { output } from '../utils/utils.console.js';
16
15
  import { spawnSync } from 'node:child_process';
17
16
 
18
17
  export const update = async (argv: minimist.ParsedArgs) => {
19
- await performPreUpdateChecks(argv);
18
+ await performPreCodemodChecks(argv);
20
19
  const { version } = getConfig();
21
20
 
22
21
  if (lt(version, LEGACY_UPDATE_CUTOFF_VERSION)) {
@@ -32,9 +31,13 @@ export const update = async (argv: minimist.ParsedArgs) => {
32
31
  process.exit(0);
33
32
  }
34
33
 
35
- const commitEachMigration = argv.commit;
36
34
  const migrations = getMigrationsToRun(version, CURRENT_APP_VERSION);
37
- await runMigrations(migrations, { commitEachMigration });
35
+ // filter out minimist internal properties (_ and $0) before passing to codemod
36
+ const { _, $0, ...codemodOptions } = argv;
37
+ await runMigrations(migrations, {
38
+ commitEachMigration: !!argv.commit,
39
+ codemodOptions,
40
+ });
38
41
  output.success({
39
42
  title: `Successfully updated create-plugin from ${version} to ${CURRENT_APP_VERSION}.`,
40
43
  });
@@ -49,48 +52,6 @@ export const update = async (argv: minimist.ParsedArgs) => {
49
52
  }
50
53
  };
51
54
 
52
- async function performPreUpdateChecks(argv: minimist.ParsedArgs) {
53
- if (!(await isGitDirectory()) && !argv.force) {
54
- output.error({
55
- title: 'You are not inside a git directory',
56
- body: [
57
- `In order to proceed please run ${output.formatCode('git init')} in the root of your project and commit your changes.`,
58
- `(This check is necessary to make sure that the updates are easy to revert and don't interfere with any changes you currently have.`,
59
- `In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
60
- ],
61
- });
62
-
63
- process.exit(1);
64
- }
65
-
66
- if (!(await isGitDirectoryClean()) && !argv.force) {
67
- output.error({
68
- title: 'Please clean your repository working tree before updating.',
69
- body: [
70
- 'Commit your changes or stash them.',
71
- `(This check is necessary to make sure that the updates are easy to revert and don't mess with any changes you currently have.`,
72
- `In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
73
- ],
74
- });
75
-
76
- process.exit(1);
77
- }
78
-
79
- if (!isPluginDirectory() && !argv.force) {
80
- output.error({
81
- title: 'Are you inside a plugin directory?',
82
- body: [
83
- `We couldn't find a "src/plugin.json" file under your current directory.`,
84
- `(Please make sure to run this command from the root of your plugin folder. In case you want to proceed as is please use the ${output.formatCode(
85
- '--force'
86
- )} flag.)`,
87
- ],
88
- });
89
-
90
- process.exit(1);
91
- }
92
- }
93
-
94
55
  /**
95
56
  * Prepares a plugin for migrations by running the legacy update command and installing dependencies.
96
57
  * This is a one time operation that ensures the plugin configs are "as expected" by the new migration system.
@@ -0,0 +1,44 @@
1
+ import { LEGACY_UPDATE_CUTOFF_VERSION } from '../constants.js';
2
+
3
+ export type MigrationMeta = {
4
+ version: string;
5
+ description: string;
6
+ migrationScript: string;
7
+ };
8
+
9
+ type Migrations = {
10
+ migrations: Record<string, MigrationMeta>;
11
+ };
12
+
13
+ // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It was used to force migrations to run
14
+ // for those written before the switch to updates as migrations.
15
+ export default {
16
+ migrations: {
17
+ '001-update-grafana-compose-extend': {
18
+ version: LEGACY_UPDATE_CUTOFF_VERSION,
19
+ description: 'Update ./docker-compose.yaml to extend from ./.config/docker-compose-base.yaml.',
20
+ migrationScript: './scripts/001-update-grafana-compose-extend.js',
21
+ },
22
+ '002-update-is-compatible-workflow': {
23
+ version: LEGACY_UPDATE_CUTOFF_VERSION,
24
+ description:
25
+ 'Update ./.github/workflows/is-compatible.yml to use is-compatible github action instead of calling levitate directly',
26
+ migrationScript: './scripts/002-update-is-compatible-workflow.js',
27
+ },
28
+ '003-update-eslint-deprecation-rule': {
29
+ version: LEGACY_UPDATE_CUTOFF_VERSION,
30
+ description: 'Replace deprecated eslint-plugin-deprecation with @typescript-eslint/no-deprecated rule.',
31
+ migrationScript: './scripts/003-update-eslint-deprecation-rule.js',
32
+ },
33
+ '004-eslint9-flat-config': {
34
+ version: LEGACY_UPDATE_CUTOFF_VERSION,
35
+ description: 'Migrate eslint config to flat config format and update devDependencies to latest versions.',
36
+ migrationScript: './scripts/004-eslint9-flat-config.js',
37
+ },
38
+ '005-react-18-3': {
39
+ version: '6.1.9',
40
+ description: 'Update React and ReactDOM 18.x versions to ^18.3.0 to surface React 19 compatibility issues.',
41
+ migrationScript: './scripts/005-react-18-3.js',
42
+ },
43
+ },
44
+ } as Migrations;
@@ -0,0 +1,47 @@
1
+ import minimist from 'minimist';
2
+ import { isGitDirectory, isGitDirectoryClean } from './utils.git.js';
3
+ import { isPluginDirectory } from './utils.plugin.js';
4
+ import { output } from './utils.console.js';
5
+
6
+ /**
7
+ * Ensures git directory exists, is clean, and we're in a plugin directory
8
+ */
9
+ export async function performPreCodemodChecks(argv: minimist.ParsedArgs): Promise<void> {
10
+ if (!(await isGitDirectory()) && !argv.force) {
11
+ output.error({
12
+ title: 'You are not inside a git directory',
13
+ body: [
14
+ `In order to proceed please run ${output.formatCode('git init')} in the root of your project and commit your changes.`,
15
+ `(This check is necessary to make sure that changes are easy to revert and don't interfere with any changes you currently have.`,
16
+ `In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
17
+ ],
18
+ });
19
+
20
+ process.exit(1);
21
+ }
22
+
23
+ if (!(await isGitDirectoryClean()) && !argv.force) {
24
+ output.error({
25
+ title: 'Please clean your repository working tree before making changes.',
26
+ body: [
27
+ 'Commit your changes or stash them.',
28
+ `(This check is necessary to make sure that changes are easy to revert and don't mess with any changes you currently have.`,
29
+ `In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
30
+ ],
31
+ });
32
+
33
+ process.exit(1);
34
+ }
35
+
36
+ if (!isPluginDirectory() && !argv.force) {
37
+ output.error({
38
+ title: 'Are you inside a plugin directory?',
39
+ body: [
40
+ `We couldn't find a "src/plugin.json" file under your current directory.`,
41
+ `(Please make sure to run this command from the root of your plugin folder. In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
42
+ ],
43
+ });
44
+
45
+ process.exit(1);
46
+ }
47
+ }
@@ -1,6 +1,4 @@
1
1
  import { argv, commandName } from './utils.cli.js';
2
-
3
- import type { AdditionFeatureName } from '../codemods/additions/additions.js';
4
2
  import { CURRENT_APP_VERSION } from './utils.version.js';
5
3
  import { DEFAULT_FEATURE_FLAGS } from '../constants.js';
6
4
  import fs from 'node:fs';
@@ -10,7 +8,7 @@ import path from 'node:path';
10
8
  import { writeFile } from 'node:fs/promises';
11
9
  import { EOL } from 'node:os';
12
10
 
13
- type CoreFeatureFlags = {
11
+ type FeatureFlags = {
14
12
  bundleGrafanaUI?: boolean;
15
13
 
16
14
  // If set to true, the plugin will be scaffolded with React Router v6. Defaults to true.
@@ -21,16 +19,6 @@ type CoreFeatureFlags = {
21
19
  useExperimentalUpdates?: boolean;
22
20
  };
23
21
 
24
- type AdditionFeatureFlags = {
25
- [K in AdditionFeatureName]?: boolean;
26
- };
27
-
28
- export type FeatureFlags = CoreFeatureFlags & AdditionFeatureFlags;
29
-
30
- export function isFeatureEnabled(features: FeatureFlags, featureName: AdditionFeatureName): boolean {
31
- return features[featureName] === true;
32
- }
33
-
34
22
  export type CreatePluginConfig = UserConfig & {
35
23
  version: string;
36
24
  };
@@ -144,18 +132,3 @@ export async function setRootConfig(configOverride: Partial<CreatePluginConfig>
144
132
 
145
133
  return updatedConfig;
146
134
  }
147
-
148
- export async function setFeatureFlag(featureName: string, enabled = true): Promise<void> {
149
- const userConfig = getUserConfig() || { features: {} };
150
- const userConfigPath = path.resolve(process.cwd(), '.cprc.json');
151
-
152
- const updatedConfig = {
153
- ...userConfig,
154
- features: {
155
- ...userConfig.features,
156
- [featureName]: enabled,
157
- },
158
- };
159
-
160
- await writeFile(userConfigPath, JSON.stringify(updatedConfig, null, 2) + EOL);
161
- }
@@ -16,7 +16,7 @@
16
16
  "author": "{{ sentenceCase orgName }}",
17
17
  "license": "Apache-2.0",
18
18
  "devDependencies": {
19
- "@grafana/eslint-config": "^8.2.0",
19
+ "@grafana/eslint-config": "^9.0.0",
20
20
  "@grafana/plugin-e2e": "^3.0.1",
21
21
  "@grafana/tsconfig": "^2.0.1",
22
22
  "@playwright/test": "^1.52.0",{{#if useExperimentalRspack}}
@@ -29,7 +29,9 @@
29
29
  "@testing-library/jest-dom": "6.1.4",
30
30
  "@testing-library/react": "14.0.0",
31
31
  "@types/jest": "^29.5.0",
32
- "@types/node": "^20.8.7",{{#if isAppType}}{{#unless useReactRouterV6}}
32
+ "@types/node": "^20.8.7",
33
+ "@types/react": "^18.3.0",
34
+ "@types/react-dom": "^18.3.0",{{#if isAppType}}{{#unless useReactRouterV6}}
33
35
  "@types/react-router-dom": "^{{ reactRouterVersion }}",{{/unless}}{{/if}}
34
36
  "@types/testing-library__jest-dom": "5.14.8",
35
37
  "@typescript-eslint/eslint-plugin": "^8.3.0",
@@ -40,7 +42,7 @@
40
42
  "eslint-config-prettier": "^8.8.0",
41
43
  "eslint-plugin-jsdoc": "^51.2.3",
42
44
  "eslint-plugin-react": "^7.37.5",
43
- "eslint-plugin-react-hooks": "^5.2.0",
45
+ "eslint-plugin-react-hooks": "^7.0.0",
44
46
  "eslint-webpack-plugin": "^5.0.0",{{#unless useExperimentalRspack}}
45
47
  "fork-ts-checker-webpack-plugin": "^8.0.0",{{/unless}}
46
48
  "glob": "^10.2.7",
@@ -77,8 +79,8 @@
77
79
  "@grafana/ui": "^12.2.1",
78
80
  "@grafana/schema": "^12.2.1",{{#if_eq pluginType "scenesapp" }}
79
81
  "@grafana/scenes": "{{ scenesVersion }}",{{/if_eq}}
80
- "react": "18.2.0",
81
- "react-dom": "18.2.0"{{#if isAppType}},
82
+ "react": "^18.3.0",
83
+ "react-dom": "^18.3.0"{{#if isAppType}},
82
84
  "react-router-dom": "^{{ reactRouterVersion }}",
83
85
  "rxjs": "7.8.2"{{/if}}
84
86
  },
@@ -20,7 +20,7 @@ jobs:
20
20
 
21
21
  steps:
22
22
  - name: Checkout repository
23
- uses: actions/checkout@v4
23
+ uses: actions/checkout@v5
24
24
  with:
25
25
  persist-credentials: false
26
26
 
@@ -25,16 +25,16 @@ jobs:
25
25
  env:
26
26
  GRAFANA_ACCESS_POLICY_TOKEN: $\{{ secrets.GRAFANA_ACCESS_POLICY_TOKEN }}
27
27
  steps:
28
- - uses: actions/checkout@v4
28
+ - uses: actions/checkout@v5
29
29
  with:
30
30
  persist-credentials: false
31
31
  {{#if_eq packageManagerName "pnpm"}}
32
32
  # pnpm action uses the packageManager field in package.json to
33
33
  # understand which version to install.
34
- - uses: pnpm/action-setup@v3
34
+ - uses: pnpm/action-setup@v4
35
35
  {{/if_eq}}
36
36
  - name: Setup Node.js environment
37
- uses: actions/setup-node@v4
37
+ uses: actions/setup-node@v6
38
38
  with:
39
39
  node-version: '22'
40
40
  cache: '{{ packageManagerName }}'
@@ -61,7 +61,7 @@ jobs:
61
61
 
62
62
  - name: Setup Go environment
63
63
  if: steps.check-for-backend.outputs.has-backend == 'true'
64
- uses: actions/setup-go@v5
64
+ uses: actions/setup-go@v6
65
65
  with:
66
66
  go-version: '1.22'
67
67
 
@@ -122,7 +122,7 @@ jobs:
122
122
  ARCHIVE: $\{{ steps.metadata.outputs.archive }}
123
123
 
124
124
  - name: Archive Build
125
- uses: actions/upload-artifact@v4
125
+ uses: actions/upload-artifact@v5
126
126
  with:
127
127
  name: $\{{ steps.metadata.outputs.plugin-id }}-$\{{ steps.metadata.outputs.plugin-version }}
128
128
  path: $\{{ steps.metadata.outputs.plugin-id }}
@@ -140,7 +140,7 @@ jobs:
140
140
  matrix: $\{{ steps.resolve-versions.outputs.matrix }}
141
141
  steps:
142
142
  - name: Checkout
143
- uses: actions/checkout@v4
143
+ uses: actions/checkout@v5
144
144
  with:
145
145
  persist-credentials: false
146
146
 
@@ -162,12 +162,12 @@ jobs:
162
162
  name: e2e test $\{{ matrix.GRAFANA_IMAGE.name }}@$\{{ matrix.GRAFANA_IMAGE.VERSION }}
163
163
  runs-on: ubuntu-latest
164
164
  steps:
165
- - uses: actions/checkout@v4
165
+ - uses: actions/checkout@v5
166
166
  with:
167
167
  persist-credentials: false
168
168
 
169
169
  - name: Download plugin
170
- uses: actions/download-artifact@v4
170
+ uses: actions/download-artifact@v6
171
171
  with:
172
172
  path: dist
173
173
  name: $\{{ needs.build.outputs.plugin-id }}-$\{{ needs.build.outputs.plugin-version }}
@@ -180,10 +180,10 @@ jobs:
180
180
  {{#if_eq packageManagerName "pnpm"}}
181
181
  # pnpm action uses the packageManager field in package.json to
182
182
  # understand which version to install.
183
- - uses: pnpm/action-setup@v3
183
+ - uses: pnpm/action-setup@v4
184
184
  {{/if_eq}}
185
185
  - name: Setup Node.js environment
186
- uses: actions/setup-node@v4
186
+ uses: actions/setup-node@v6
187
187
  with:
188
188
  node-version: '22'
189
189
  cache: '{{ packageManagerName }}'
@@ -242,7 +242,7 @@ jobs:
242
242
  needs: [playwright-tests]
243
243
  runs-on: ubuntu-latest
244
244
  steps:
245
- - uses: actions/checkout@v4
245
+ - uses: actions/checkout@v5
246
246
  with:
247
247
  # required for playwright-gh-pages
248
248
  persist-credentials: true
@@ -1,3 +1,4 @@
1
+ {{!-- /* 🚨 The `${{ }}` Github workflow expressions need to be escaped so they are not being interpreted by Handlebars. (this comment is going to be removed after scaffolding) 🚨 */ --}}
1
2
  name: Create Plugin Update
2
3
 
3
4
  on:
@@ -5,22 +6,16 @@ on:
5
6
  schedule:
6
7
  - cron: '0 0 1 * *' # run once a month on the 1st day
7
8
 
8
- # To use the default github token with the following elevated permissions make sure to check:
9
- # **Allow GitHub Actions to create and approve pull requests** in https://github.com/ORG_NAME/REPO_NAME/settings/actions.
10
- # Alternatively create a fine-grained personal access token for your repository with
11
- # `contents: read and write` and `pull requests: read and write` and pass it to the action.
12
-
13
- permissions:
14
- contents: write
15
- pull-requests: write
9
+ # To use this workflow please create a fine-grained personal access token for your repository with:
10
+ # `contents: read and write`
11
+ # `pull requests: read and write`
12
+ # `workflows: read and write`
16
13
 
17
14
  jobs:
18
15
  release:
19
16
  runs-on: ubuntu-latest
20
17
  steps:
21
- - uses: grafana/plugin-actions/create-plugin-update@create-plugin-update/v1.1.0
22
- # Uncomment to use a fine-grained personal access token instead of default github token
23
- # (For more info on how to generate the token see https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
24
- # with:
25
- # Make sure to save the token in your repository secrets
26
- # token: ${{ secrets.GH_PAT_TOKEN }}
18
+ - uses: grafana/plugin-actions/create-plugin-update@create-plugin-update/v2.0.1
19
+ with:
20
+ # Make sure to save the token in your repository secrets as `GH_PAT_TOKEN`
21
+ token: $\{{ secrets.GH_PAT_TOKEN }}
@@ -7,18 +7,18 @@ jobs:
7
7
  permissions:
8
8
  contents: read
9
9
  steps:
10
- - uses: actions/checkout@v4
10
+ - uses: actions/checkout@v5
11
11
  with:
12
12
  persist-credentials: false
13
13
 
14
14
  {{#if_eq packageManagerName "pnpm"}}
15
15
  # pnpm action uses the packageManager field in package.json to
16
16
  # understand which version to install.
17
- - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
17
+ - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
18
18
  {{/if_eq}}
19
19
 
20
20
  - name: Setup Node.js environment
21
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
21
+ uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
22
22
  with:
23
23
  node-version: '22'
24
24
  cache: '{{ packageManagerName }}'
@@ -16,7 +16,7 @@ jobs:
16
16
  contents: write
17
17
  runs-on: ubuntu-latest
18
18
  steps:
19
- - uses: actions/checkout@v4
19
+ - uses: actions/checkout@v5
20
20
  with:
21
21
  persist-credentials: false
22
22