@grafana/create-plugin 0.5.4 → 0.6.0-canary.160.e62f4fc.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.
- package/CHANGELOG.md +0 -50
- package/dist/commands/generate.plopfile.js +18 -1
- package/dist/utils/tests/utils.handlebars.test.js +0 -6
- package/dist/utils/utils.handlebars.js +1 -1
- package/package.json +2 -2
- package/src/commands/generate.plopfile.ts +34 -0
- package/src/utils/tests/utils.handlebars.test.ts +0 -10
- package/src/utils/utils.handlebars.ts +1 -1
- package/templates/_partials/distributing-your-plugin.md +38 -0
- package/templates/app/README.md +2 -0
- package/templates/backend/pkg/plugin/datasource.go +2 -6
- package/templates/common/.config/README.md +4 -25
- package/templates/common/.config/jest.config.js +3 -6
- package/templates/common/.config/{jest/mocks → mocks}/react-inlinesvg.tsx +0 -0
- package/templates/common/package.json +19 -18
- package/templates/datasource/README.md +2 -0
- package/templates/github/ci/.github/workflows/ci.yml +12 -27
- package/templates/github/ci/.github/workflows/release.yml +37 -69
- package/templates/github/is-compatible/.github/workflows/is-compatible.yml +3 -2
- package/templates/panel/README.md +2 -0
- package/templates/common/.config/jest/utils.js +0 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,53 +1,3 @@
|
|
|
1
|
-
# v0.5.4 (Fri Nov 18 2022)
|
|
2
|
-
|
|
3
|
-
#### 🐛 Bug Fix
|
|
4
|
-
|
|
5
|
-
- Create-plugin: Fix failing jest config [#151](https://github.com/grafana/plugin-tools/pull/151) ([@jackw](https://github.com/jackw))
|
|
6
|
-
|
|
7
|
-
#### Authors: 1
|
|
8
|
-
|
|
9
|
-
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# v0.5.3 (Thu Nov 17 2022)
|
|
14
|
-
|
|
15
|
-
#### 🐛 Bug Fix
|
|
16
|
-
|
|
17
|
-
- Create-Plugin: Transform known ES modules in jest config [#145](https://github.com/grafana/plugin-tools/pull/145) ([@jackw](https://github.com/jackw))
|
|
18
|
-
|
|
19
|
-
#### Authors: 1
|
|
20
|
-
|
|
21
|
-
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
# v0.5.2 (Thu Nov 17 2022)
|
|
26
|
-
|
|
27
|
-
#### 🐛 Bug Fix
|
|
28
|
-
|
|
29
|
-
- Create-Plugin: Bump dependencies to support node 18 [#144](https://github.com/grafana/plugin-tools/pull/144) ([@jackw](https://github.com/jackw))
|
|
30
|
-
- Create-Plugin: Backend template: Switch from Info to Debug level [#146](https://github.com/grafana/plugin-tools/pull/146) ([@xnyo](https://github.com/xnyo))
|
|
31
|
-
|
|
32
|
-
#### Authors: 2
|
|
33
|
-
|
|
34
|
-
- Giuseppe Guerra ([@xnyo](https://github.com/xnyo))
|
|
35
|
-
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
# v0.5.1 (Mon Nov 14 2022)
|
|
40
|
-
|
|
41
|
-
#### 🐛 Bug Fix
|
|
42
|
-
|
|
43
|
-
- Fix: include uppercase characters when normalising plugin id [#142](https://github.com/grafana/plugin-tools/pull/142) ([@jackw](https://github.com/jackw))
|
|
44
|
-
|
|
45
|
-
#### Authors: 1
|
|
46
|
-
|
|
47
|
-
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
1
|
# v0.5.0 (Mon Nov 07 2022)
|
|
52
2
|
|
|
53
3
|
:tada: This release contains work from a new contributor! :tada:
|
|
@@ -31,6 +31,7 @@ var constants_1 = require("../constants");
|
|
|
31
31
|
function default_1(plop) {
|
|
32
32
|
plop.setHelper('if_eq', utils_handlebars_1.ifEq);
|
|
33
33
|
plop.setHelper('normalize_id', utils_handlebars_1.normalizeId);
|
|
34
|
+
plop.setActionType('printSuccessMessage', printSuccessMessage);
|
|
34
35
|
plop.setGenerator('create-plugin', {
|
|
35
36
|
description: 'used to scaffold a grafana plugin',
|
|
36
37
|
prompts: [
|
|
@@ -111,7 +112,11 @@ function default_1(plop) {
|
|
|
111
112
|
? getActionsForTemplateFolder({ folderPath: constants_1.TEMPLATE_PATHS.isCompatibleWorkflow, exportPath: exportPath })
|
|
112
113
|
: [];
|
|
113
114
|
var readmeActions = getActionsForReadme({ exportPath: exportPath });
|
|
114
|
-
return __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], commonActions, true), pluginTypeSpecificActions, true), backendActions, true), ciWorkflowActions, true), readmeActions, true), isCompatibleWorkflowActions, true)
|
|
115
|
+
return __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], commonActions, true), pluginTypeSpecificActions, true), backendActions, true), ciWorkflowActions, true), readmeActions, true), isCompatibleWorkflowActions, true), [
|
|
116
|
+
{
|
|
117
|
+
type: 'printSuccessMessage'
|
|
118
|
+
},
|
|
119
|
+
], false);
|
|
115
120
|
}
|
|
116
121
|
});
|
|
117
122
|
}
|
|
@@ -121,6 +126,7 @@ function getActionsForReadme(_a) {
|
|
|
121
126
|
return [
|
|
122
127
|
replacePatternWithTemplateInReadme('-- INSERT FRONTEND GETTING STARTED --', 'frontend-getting-started.md', exportPath),
|
|
123
128
|
replacePatternWithTemplateInReadme('-- INSERT BACKEND GETTING STARTED --', 'backend-getting-started.md', exportPath),
|
|
129
|
+
replacePatternWithTemplateInReadme('-- INSERT DISTRIBUTING YOUR PLUGIN --', 'distributing-your-plugin.md', exportPath),
|
|
124
130
|
];
|
|
125
131
|
}
|
|
126
132
|
function replacePatternWithTemplateInReadme(pattern, partialsFile, exportPath) {
|
|
@@ -170,3 +176,14 @@ function getExportPath(pluginName, orgName, pluginType) {
|
|
|
170
176
|
return path_1["default"].join(process.cwd(), (0, utils_handlebars_1.normalizeId)(pluginName, orgName, pluginType));
|
|
171
177
|
}
|
|
172
178
|
}
|
|
179
|
+
function printSuccessMessage(answers) {
|
|
180
|
+
var directory = (0, utils_handlebars_1.normalizeId)(answers.pluginName, answers.orgName, answers.pluginType);
|
|
181
|
+
var commands = __spreadArray(__spreadArray([
|
|
182
|
+
' * `yarn install` to install frontend dependencies.',
|
|
183
|
+
' * `docker-compose up` to start a grafana development server.',
|
|
184
|
+
' * `yarn dev` to build (and watch) the plugin frontend code.'
|
|
185
|
+
], (answers.hasBackend ? [' * `mage -v build:linux` to build the plugin backend code.'] : []), true), [
|
|
186
|
+
' * Open http://localhost:3000/dashboard/new in your browser to create a dashboard to begin developing your plugin.',
|
|
187
|
+
], false);
|
|
188
|
+
return "\n Congratulations on scaffolding a Grafana ".concat(answers.pluginName, " plugin! \uD83D\uDE80\n\n ## What's next?\n Navigate into ./").concat(directory, " and run the following commands to get started:\n").concat(commands.map(function (command) { return command; }).join('\n'), "\n\n View the README.md for futher information.\n Learn more about Grafana Plugins at https://grafana.com/docs/grafana/latest/plugins/developing/development/\n\n");
|
|
189
|
+
}
|
|
@@ -22,11 +22,5 @@ describe('Handlebars helpers', function () {
|
|
|
22
22
|
var actual = (0, utils_handlebars_1.normalizeId)(pluginName, orgName, type);
|
|
23
23
|
expect(actual).toEqual("myorg-myplugin-".concat(type));
|
|
24
24
|
});
|
|
25
|
-
test.each([constants_1.PLUGIN_TYPES.app, constants_1.PLUGIN_TYPES.datasource, constants_1.PLUGIN_TYPES.panel])('should handle uppercase characters', function (type) {
|
|
26
|
-
var pluginName = "MyPlugin";
|
|
27
|
-
var orgName = 'MyOrg';
|
|
28
|
-
var actual = (0, utils_handlebars_1.normalizeId)(pluginName, orgName, type);
|
|
29
|
-
expect(actual).toEqual("myorg-myplugin-".concat(type));
|
|
30
|
-
});
|
|
31
25
|
});
|
|
32
26
|
});
|
|
@@ -39,7 +39,7 @@ var ifEq = function (a, b, options) {
|
|
|
39
39
|
exports.ifEq = ifEq;
|
|
40
40
|
var normalizeId = function (pluginName, orgName, type) {
|
|
41
41
|
var re = new RegExp("-?".concat(type, "$"), 'i');
|
|
42
|
-
var nameRegex = new RegExp('[^0-9a-
|
|
42
|
+
var nameRegex = new RegExp('[^0-9a-z]', 'g');
|
|
43
43
|
var newPluginName = pluginName.replace(re, '').replace(nameRegex, '');
|
|
44
44
|
var newOrgName = orgName.replace(nameRegex, '');
|
|
45
45
|
return changeCase.lowerCase(newOrgName) + '-' + changeCase.lowerCase(newPluginName) + "-".concat(type);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/create-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-canary.160.e62f4fc.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"directory": "packages/create-plugin",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"engines": {
|
|
60
60
|
"node": ">=16"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "e62f4fc1fe115ff39cb9cd7f224515c8660cd797"
|
|
63
63
|
}
|
|
@@ -27,6 +27,8 @@ export default function (plop: NodePlopAPI) {
|
|
|
27
27
|
plop.setHelper('if_eq', ifEq);
|
|
28
28
|
plop.setHelper('normalize_id', normalizeId);
|
|
29
29
|
|
|
30
|
+
plop.setActionType('printSuccessMessage', printSuccessMessage);
|
|
31
|
+
|
|
30
32
|
plop.setGenerator('create-plugin', {
|
|
31
33
|
description: 'used to scaffold a grafana plugin',
|
|
32
34
|
prompts: [
|
|
@@ -131,6 +133,9 @@ export default function (plop: NodePlopAPI) {
|
|
|
131
133
|
...ciWorkflowActions,
|
|
132
134
|
...readmeActions,
|
|
133
135
|
...isCompatibleWorkflowActions,
|
|
136
|
+
{
|
|
137
|
+
type: 'printSuccessMessage',
|
|
138
|
+
},
|
|
134
139
|
];
|
|
135
140
|
},
|
|
136
141
|
});
|
|
@@ -148,6 +153,11 @@ function getActionsForReadme({ exportPath }: { exportPath: string }): ModifyActi
|
|
|
148
153
|
'backend-getting-started.md',
|
|
149
154
|
exportPath
|
|
150
155
|
),
|
|
156
|
+
replacePatternWithTemplateInReadme(
|
|
157
|
+
'-- INSERT DISTRIBUTING YOUR PLUGIN --',
|
|
158
|
+
'distributing-your-plugin.md',
|
|
159
|
+
exportPath
|
|
160
|
+
),
|
|
151
161
|
];
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -221,3 +231,27 @@ function getExportPath(pluginName: string, orgName: string, pluginType: PLUGIN_T
|
|
|
221
231
|
return path.join(process.cwd(), normalizeId(pluginName, orgName, pluginType));
|
|
222
232
|
}
|
|
223
233
|
}
|
|
234
|
+
|
|
235
|
+
function printSuccessMessage(answers: CliArgs) {
|
|
236
|
+
const directory = normalizeId(answers.pluginName, answers.orgName, answers.pluginType);
|
|
237
|
+
|
|
238
|
+
const commands = [
|
|
239
|
+
' * `yarn install` to install frontend dependencies.',
|
|
240
|
+
' * `docker-compose up` to start a grafana development server.',
|
|
241
|
+
' * `yarn dev` to build (and watch) the plugin frontend code.',
|
|
242
|
+
...(answers.hasBackend ? [' * `mage -v build:linux` to build the plugin backend code.'] : []),
|
|
243
|
+
' * Open http://localhost:3000/dashboard/new in your browser to create a dashboard to begin developing your plugin.',
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
return `
|
|
247
|
+
Congratulations on scaffolding a Grafana ${answers.pluginName} plugin! 🚀
|
|
248
|
+
|
|
249
|
+
## What's next?
|
|
250
|
+
Navigate into ./${directory} and run the following commands to get started:
|
|
251
|
+
${commands.map((command) => command).join('\n')}
|
|
252
|
+
|
|
253
|
+
View the README.md for futher information.
|
|
254
|
+
Learn more about Grafana Plugins at https://grafana.com/docs/grafana/latest/plugins/developing/development/
|
|
255
|
+
|
|
256
|
+
`;
|
|
257
|
+
}
|
|
@@ -31,15 +31,5 @@ describe('Handlebars helpers', () => {
|
|
|
31
31
|
expect(actual).toEqual(`myorg-myplugin-${type}`);
|
|
32
32
|
}
|
|
33
33
|
);
|
|
34
|
-
|
|
35
|
-
test.each([PLUGIN_TYPES.app, PLUGIN_TYPES.datasource, PLUGIN_TYPES.panel])(
|
|
36
|
-
'should handle uppercase characters',
|
|
37
|
-
(type: PLUGIN_TYPES) => {
|
|
38
|
-
const pluginName = `MyPlugin`;
|
|
39
|
-
const orgName = 'MyOrg';
|
|
40
|
-
const actual = normalizeId(pluginName, orgName, type);
|
|
41
|
-
expect(actual).toEqual(`myorg-myplugin-${type}`);
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
34
|
});
|
|
45
35
|
});
|
|
@@ -12,7 +12,7 @@ export const ifEq = (a: any, b: any, options: HelperOptions) => {
|
|
|
12
12
|
|
|
13
13
|
export const normalizeId = (pluginName: string, orgName: string, type: PLUGIN_TYPES) => {
|
|
14
14
|
const re = new RegExp(`-?${type}$`, 'i');
|
|
15
|
-
const nameRegex = new RegExp('[^0-9a-
|
|
15
|
+
const nameRegex = new RegExp('[^0-9a-z]', 'g');
|
|
16
16
|
|
|
17
17
|
const newPluginName = pluginName.replace(re, '').replace(nameRegex, '');
|
|
18
18
|
const newOrgName = orgName.replace(nameRegex, '');
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Distributing your plugin
|
|
2
|
+
|
|
3
|
+
When distributing a Grafana plugin either within the community or privately the plugin must be signed so the Grafana application can verify its authenticity. This can be done with the `@grafana/sign-plugin` package.
|
|
4
|
+
|
|
5
|
+
_Note: It's not necessary to sign a plugin during development. The docker development environment that is scaffolded with `@grafana/create-plugin` caters for running the plugin without a signature._
|
|
6
|
+
|
|
7
|
+
## Initial steps
|
|
8
|
+
|
|
9
|
+
Before signing a plugin please read the Grafana [plugin publishing and signing criteria](https://grafana.com/docs/grafana/latest/developers/plugins/publishing-and-signing-criteria/) documentation carefully.
|
|
10
|
+
|
|
11
|
+
`@grafana/create-plugin` has added the necessary commands and workflows to make signing and distributing a plugin via the grafana plugins catalog as straightforward as possible.
|
|
12
|
+
|
|
13
|
+
Before signing a plugin for the first time please consult the Grafana [plugin signature levels](https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/#plugin-signature-levels) documentation to understand the differences between the types of signature level.
|
|
14
|
+
|
|
15
|
+
1. Create a [Grafana Cloud account](https://grafana.com/signup).
|
|
16
|
+
2. Make sure that the first part of the plugin ID matches the slug of your Grafana Cloud account.
|
|
17
|
+
- _You can find the plugin ID in the plugin.json file inside your plugin directory. For example, if your account slug is `acmecorp`, you need to prefix the plugin ID with `acmecorp-`._
|
|
18
|
+
3. Create a Grafana Cloud API key with the `PluginPublisher` role.
|
|
19
|
+
4. Keep a record of this API key as it will be required for signing a plugin
|
|
20
|
+
|
|
21
|
+
## Signing a plugin
|
|
22
|
+
|
|
23
|
+
### Using Github actions release workflow
|
|
24
|
+
|
|
25
|
+
If the plugin is using the github actions supplied with `@grafana/create-plugin` signing a plugin is included out of the box. The [release workflow](./.github/workflows/release.yml) can prepare everything to make submitting your plugin to Grafana as easy as possible. Before being able to sign the plugin however a secret needs adding to the Github repository.
|
|
26
|
+
|
|
27
|
+
1. Please navigate to "settings > secrets > actions" within your repo to create secrets.
|
|
28
|
+
2. Click "New repository secret"
|
|
29
|
+
3. Name the secret "GRAFANA_API_KEY"
|
|
30
|
+
4. Paste your Grafana Cloud API key in the Secret field
|
|
31
|
+
5. Click "Add secret"
|
|
32
|
+
|
|
33
|
+
#### Push a version tag
|
|
34
|
+
|
|
35
|
+
To trigger the workflow we need to push a version tag to github. This can be achieved with the following steps:
|
|
36
|
+
|
|
37
|
+
1. Run `npm version <major|minor|patch>`
|
|
38
|
+
2. Run `git push origin main --follow-tags`
|
package/templates/app/README.md
CHANGED
|
@@ -11,6 +11,8 @@ App plugins can let you create a custom out-of-the-box monitoring experience by
|
|
|
11
11
|
-- INSERT FRONTEND GETTING STARTED --
|
|
12
12
|
{{#if hasBackend}}-- INSERT BACKEND GETTING STARTED --{{/if}}
|
|
13
13
|
|
|
14
|
+
-- INSERT DISTRIBUTING YOUR PLUGIN --
|
|
15
|
+
|
|
14
16
|
## Learn more
|
|
15
17
|
|
|
16
18
|
Below you can find source code for existing app plugins and other related documentation.
|
|
@@ -44,9 +44,7 @@ func (d *Datasource) Dispose() {
|
|
|
44
44
|
// The QueryDataResponse contains a map of RefID to the response for each query, and each response
|
|
45
45
|
// contains Frames ([]*Frame).
|
|
46
46
|
func (d *Datasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
47
|
-
|
|
48
|
-
// (like the *backend.QueryDataRequest)
|
|
49
|
-
log.DefaultLogger.Debug("QueryData called", "numQueries", len(req.Queries))
|
|
47
|
+
log.DefaultLogger.Info("QueryData called", "request", req)
|
|
50
48
|
|
|
51
49
|
// create response struct
|
|
52
50
|
response := backend.NewQueryDataResponse()
|
|
@@ -96,9 +94,7 @@ func (d *Datasource) query(_ context.Context, pCtx backend.PluginContext, query
|
|
|
96
94
|
// datasource configuration page which allows users to verify that
|
|
97
95
|
// a datasource is working as expected.
|
|
98
96
|
func (d *Datasource) CheckHealth(_ context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
|
99
|
-
|
|
100
|
-
// (like the *backend.QueryDataRequest)
|
|
101
|
-
log.DefaultLogger.Debug("CheckHealth called")
|
|
97
|
+
log.DefaultLogger.Info("CheckHealth called", "request", req)
|
|
102
98
|
|
|
103
99
|
var status = backend.HealthStatusOk
|
|
104
100
|
var message = "Data source is working"
|
|
@@ -16,12 +16,11 @@ to issues around working with the project.
|
|
|
16
16
|
Edit the `.eslintrc` file in the project root in order to extend the ESLint configuration.
|
|
17
17
|
|
|
18
18
|
**Example:**
|
|
19
|
-
|
|
20
19
|
```json
|
|
21
20
|
{
|
|
22
21
|
"extends": "./.config/.eslintrc",
|
|
23
22
|
"rules": {
|
|
24
|
-
|
|
23
|
+
"react/prop-types": "off"
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
```
|
|
@@ -33,11 +32,10 @@ Edit the `.eslintrc` file in the project root in order to extend the ESLint conf
|
|
|
33
32
|
Edit the `.prettierrc.js` file in the project root in order to extend the Prettier configuration.
|
|
34
33
|
|
|
35
34
|
**Example:**
|
|
36
|
-
|
|
37
35
|
```javascript
|
|
38
36
|
module.exports = {
|
|
39
37
|
// Prettier configuration provided by Grafana scaffolding
|
|
40
|
-
...require(
|
|
38
|
+
...require("./.config/.prettierrc.js"),
|
|
41
39
|
|
|
42
40
|
semi: false,
|
|
43
41
|
};
|
|
@@ -52,23 +50,7 @@ There are two configuration in the project root that belong to Jest: `jest-setup
|
|
|
52
50
|
**`jest-setup.js`:** A file that is run before each test file in the suite is executed. We are using it to
|
|
53
51
|
set up the Jest DOM for the testing library and to apply some polyfills. ([link to Jest docs](https://jestjs.io/docs/configuration#setupfilesafterenv-array))
|
|
54
52
|
|
|
55
|
-
**`jest.config.js`:** The main Jest configuration file that
|
|
56
|
-
|
|
57
|
-
#### ESM errors with Jest
|
|
58
|
-
|
|
59
|
-
A common issue found with the current jest config involves importing an npm package which only offers an ESM build. These packages cause jest to error with `SyntaxError: Cannot use import statement outside a module`. To work around this we provide a list of known packages to pass to the `[transformIgnorePatterns](https://jestjs.io/docs/configuration#transformignorepatterns-arraystring)` jest configuration property. If need be this can be extended in the following way:
|
|
60
|
-
|
|
61
|
-
```javascript
|
|
62
|
-
process.env.TZ = 'UTC';
|
|
63
|
-
const { grafanaESModules, nodeModulesToTransform } = require('./jest/utils');
|
|
64
|
-
|
|
65
|
-
module.exports = {
|
|
66
|
-
// Jest configuration provided by Grafana
|
|
67
|
-
...require('./.config/jest.config'),
|
|
68
|
-
// Inform jest to only transform specific node_module packages.
|
|
69
|
-
transformIgnorePatterns: [nodeModulesToTransform([...grafanaESModules, 'packageName'])],
|
|
70
|
-
};
|
|
71
|
-
```
|
|
53
|
+
**`jest.config.js`:** The main Jest configuration file that is extending our basic Grafana-tailored setup. ([link to Jest docs](https://jestjs.io/docs/configuration))
|
|
72
54
|
|
|
73
55
|
---
|
|
74
56
|
|
|
@@ -77,7 +59,6 @@ module.exports = {
|
|
|
77
59
|
Edit the `tsconfig.json` file in the project root in order to extend the TypeScript configuration.
|
|
78
60
|
|
|
79
61
|
**Example:**
|
|
80
|
-
|
|
81
62
|
```json
|
|
82
63
|
{
|
|
83
64
|
"extends": "./.config/tsconfig.json",
|
|
@@ -99,7 +80,6 @@ Create a new config file that is going to extend the basic one provided by Grafa
|
|
|
99
80
|
It can live in the project root, e.g. `webpack.config.ts`.
|
|
100
81
|
|
|
101
82
|
#### 2. Merge the basic config provided by Grafana and your custom setup
|
|
102
|
-
|
|
103
83
|
We are going to use [`webpack-merge`](https://github.com/survivejs/webpack-merge) for this.
|
|
104
84
|
|
|
105
85
|
```typescript
|
|
@@ -120,6 +100,7 @@ const config = async (env): Promise<Configuration> => {
|
|
|
120
100
|
};
|
|
121
101
|
|
|
122
102
|
export default config;
|
|
103
|
+
|
|
123
104
|
```
|
|
124
105
|
|
|
125
106
|
#### 3. Update the `package.json` to use the new Webpack config
|
|
@@ -127,14 +108,12 @@ export default config;
|
|
|
127
108
|
We need to update the `scripts` in the `package.json` to use the extended Webpack configuration.
|
|
128
109
|
|
|
129
110
|
**Update for `build`:**
|
|
130
|
-
|
|
131
111
|
```diff
|
|
132
112
|
-"build": "webpack -c ./.config/webpack/webpack.config.ts --env production",
|
|
133
113
|
+"build": "webpack -c ./webpack.config.ts --env production",
|
|
134
114
|
```
|
|
135
115
|
|
|
136
116
|
**Update for `dev`:**
|
|
137
|
-
|
|
138
117
|
```diff
|
|
139
118
|
-"dev": "webpack -w -c ./.config/webpack/webpack.config.ts --env development",
|
|
140
119
|
+"dev": "webpack -w -c ./webpack.config.ts --env development",
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const path = require('path');
|
|
8
|
-
const { grafanaESModules, nodeModulesToTransform } = require('./jest/utils');
|
|
9
8
|
|
|
10
9
|
module.exports = {
|
|
11
10
|
moduleNameMapper: {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"\\.(css|scss|sass)$": "identity-obj-proxy",
|
|
12
|
+
"react-inlinesvg": path.resolve(__dirname, "mocks", "react-inlinesvg.tsx"),
|
|
14
13
|
},
|
|
15
14
|
modulePaths: ['<rootDir>/src'],
|
|
16
15
|
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
|
|
@@ -36,7 +35,5 @@ module.exports = {
|
|
|
36
35
|
},
|
|
37
36
|
],
|
|
38
37
|
},
|
|
39
|
-
|
|
40
|
-
// ES module without it being transformed first. ./config/README.md#esm-errors-with-jest
|
|
41
|
-
transformIgnorePatterns: [nodeModulesToTransform(grafanaESModules)],
|
|
38
|
+
transformIgnorePatterns: [],
|
|
42
39
|
};
|
|
File without changes
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"lint:fix": "yarn lint --fix",
|
|
13
13
|
"e2e": "yarn cypress install && yarn grafana-e2e run",
|
|
14
14
|
"e2e:update": "yarn cypress install && yarn grafana-e2e run --update-screenshots",
|
|
15
|
-
"server": "docker-compose up --build"
|
|
15
|
+
"server": "docker-compose up --build",
|
|
16
|
+
"sign": "npx --yes @grafana/sign-plugin"
|
|
16
17
|
},
|
|
17
18
|
"author": "{{ sentenceCase orgName }}",
|
|
18
19
|
"license": "Apache-2.0",
|
|
@@ -20,40 +21,40 @@
|
|
|
20
21
|
"@babel/core": "^7.16.7",
|
|
21
22
|
"@grafana/e2e": "{{ grafanaVersion }}",
|
|
22
23
|
"@grafana/e2e-selectors": "{{ grafanaVersion }}",
|
|
23
|
-
"@grafana/eslint-config": "^5.
|
|
24
|
+
"@grafana/eslint-config": "^2.5.0",
|
|
24
25
|
"@grafana/tsconfig": "^1.2.0-rc1",
|
|
25
26
|
"@swc/core": "^1.2.144",
|
|
26
|
-
"@swc/helpers": "^0.
|
|
27
|
+
"@swc/helpers": "^0.3.6",
|
|
27
28
|
"@swc/jest": "^0.2.20",
|
|
28
29
|
"@testing-library/jest-dom": "^5.16.2",
|
|
29
|
-
"@testing-library/react": "^
|
|
30
|
+
"@testing-library/react": "^12.1.3",
|
|
30
31
|
"@types/glob": "^8.0.0",
|
|
31
|
-
"@types/jest": "^
|
|
32
|
-
"@types/lodash": "
|
|
32
|
+
"@types/jest": "^27.4.1",
|
|
33
|
+
"@types/lodash": "latest",{{#if_eq pluginType "app"}}
|
|
33
34
|
"@types/react-router-dom": "^5.3.3",{{/if_eq}}
|
|
34
|
-
"@types/node": "^
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
36
|
-
"@typescript-eslint/parser": "^
|
|
37
|
-
"copy-webpack-plugin": "^
|
|
38
|
-
"css-loader": "
|
|
39
|
-
"eslint": "
|
|
35
|
+
"@types/node": "^17.0.19",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
|
37
|
+
"@typescript-eslint/parser": "^4.33.0",
|
|
38
|
+
"copy-webpack-plugin": "^10.0.0",
|
|
39
|
+
"css-loader": "6.7.1",
|
|
40
|
+
"eslint": "^7.32.0",
|
|
40
41
|
"eslint-config-prettier": "^8.3.0",
|
|
41
|
-
"eslint-plugin-jsdoc": "^
|
|
42
|
+
"eslint-plugin-jsdoc": "^36.1.0",
|
|
42
43
|
"eslint-plugin-prettier": "^4.0.0",
|
|
43
44
|
"eslint-plugin-react": "^7.26.1",
|
|
44
45
|
"eslint-plugin-react-hooks": "^4.2.0",
|
|
45
46
|
"eslint-webpack-plugin": "^3.1.1",
|
|
46
|
-
"fork-ts-checker-webpack-plugin": "^7.2.0",
|
|
47
47
|
"glob": "^8.0.3",
|
|
48
48
|
"identity-obj-proxy": "3.0.0",
|
|
49
49
|
"jest": "27.5.0",
|
|
50
|
+
"fork-ts-checker-webpack-plugin": "^7.2.0",
|
|
50
51
|
"prettier": "^2.5.0",
|
|
51
52
|
"replace-in-file-webpack-plugin": "^1.0.6",
|
|
52
|
-
"sass": "1.
|
|
53
|
-
"sass-loader": "13.
|
|
53
|
+
"sass": "1.55.0",
|
|
54
|
+
"sass-loader": "13.1.0",
|
|
54
55
|
"style-loader": "3.3.1",
|
|
55
|
-
"swc-loader": "^0.
|
|
56
|
-
"tsconfig-paths": "^
|
|
56
|
+
"swc-loader": "^0.1.15",
|
|
57
|
+
"tsconfig-paths": "^3.12.0",
|
|
57
58
|
"ts-node": "^10.5.0",
|
|
58
59
|
"typescript": "^4.4.0",
|
|
59
60
|
"webpack": "^5.69.1",
|
|
@@ -11,6 +11,8 @@ Grafana supports a wide range of data sources, including Prometheus, MySQL, and
|
|
|
11
11
|
-- INSERT FRONTEND GETTING STARTED --
|
|
12
12
|
{{#if hasBackend}}-- INSERT BACKEND GETTING STARTED --{{/if}}
|
|
13
13
|
|
|
14
|
+
-- INSERT DISTRIBUTING YOUR PLUGIN --
|
|
15
|
+
|
|
14
16
|
## Learn more
|
|
15
17
|
|
|
16
18
|
Below you can find source code for existing app plugins and other related documentation.
|
|
@@ -10,6 +10,7 @@ on:
|
|
|
10
10
|
branches:
|
|
11
11
|
- master
|
|
12
12
|
- main
|
|
13
|
+
|
|
13
14
|
jobs:
|
|
14
15
|
build:
|
|
15
16
|
runs-on: ubuntu-latest
|
|
@@ -19,34 +20,18 @@ jobs:
|
|
|
19
20
|
- name: Setup Node.js environment
|
|
20
21
|
uses: actions/setup-node@v3
|
|
21
22
|
with:
|
|
22
|
-
node-version: '16
|
|
23
|
-
|
|
24
|
-
- name: Get yarn cache directory path
|
|
25
|
-
id: yarn-cache-dir-path
|
|
26
|
-
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
|
27
|
-
|
|
28
|
-
- name: Cache yarn cache
|
|
29
|
-
uses: actions/cache@v3
|
|
30
|
-
id: cache-yarn-cache
|
|
31
|
-
with:
|
|
32
|
-
path: $\{{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
33
|
-
key: $\{{ runner.os }}-yarn-$\{{ hashFiles('**/yarn.lock') }}
|
|
34
|
-
restore-keys: |
|
|
35
|
-
$\{{ runner.os }}-yarn-
|
|
36
|
-
|
|
37
|
-
- name: Cache node_modules
|
|
38
|
-
id: cache-node-modules
|
|
39
|
-
uses: actions/cache@v3
|
|
40
|
-
with:
|
|
41
|
-
path: node_modules
|
|
42
|
-
key: $\{{ runner.os }}-$\{{ matrix.node-version }}-nodemodules-$\{{ hashFiles('**/yarn.lock') }}
|
|
43
|
-
restore-keys: |
|
|
44
|
-
$\{{ runner.os }}-$\{{ matrix.node-version }}-nodemodules-
|
|
45
|
-
|
|
23
|
+
node-version: '16'
|
|
24
|
+
cache: 'yarn'
|
|
46
25
|
- name: Install dependencies
|
|
47
|
-
run: yarn install --
|
|
26
|
+
run: yarn install --immutable --prefer-offline
|
|
48
27
|
|
|
49
|
-
- name:
|
|
28
|
+
- name: Check types
|
|
29
|
+
run: yarn typecheck
|
|
30
|
+
- name: Lint
|
|
31
|
+
run: yarn lint
|
|
32
|
+
- name: Unit tests
|
|
33
|
+
run: yarn test:ci
|
|
34
|
+
- name: Build frontend
|
|
50
35
|
run: yarn build
|
|
51
36
|
|
|
52
37
|
- name: Start grafana docker
|
|
@@ -55,7 +40,7 @@ jobs:
|
|
|
55
40
|
- name: Run e2e tests
|
|
56
41
|
run: yarn e2e
|
|
57
42
|
|
|
58
|
-
- name:
|
|
43
|
+
- name: Stop grafana docker
|
|
59
44
|
run: docker-compose down
|
|
60
45
|
|
|
61
46
|
- name: Check for backend
|
|
@@ -4,52 +4,29 @@ name: Release
|
|
|
4
4
|
on:
|
|
5
5
|
push:
|
|
6
6
|
tags:
|
|
7
|
-
- 'v
|
|
7
|
+
- 'v*' # Run workflow on version tags, e.g. v1.0.0.
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
release:
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
|
-
|
|
12
|
+
env:
|
|
13
|
+
GRAFANA_API_KEY: $\{{ secrets.GRAFANA_API_KEY }} # Requires a Grafana API key from Grafana.com.
|
|
13
14
|
steps:
|
|
14
15
|
- uses: actions/checkout@v3
|
|
15
16
|
|
|
16
17
|
- name: Setup Node.js environment
|
|
17
18
|
uses: actions/setup-node@v3
|
|
18
19
|
with:
|
|
19
|
-
node-version: '16
|
|
20
|
+
node-version: '16'
|
|
21
|
+
cache: 'yarn'
|
|
20
22
|
|
|
21
23
|
- name: Setup Go environment
|
|
22
24
|
uses: actions/setup-go@v3
|
|
23
25
|
with:
|
|
24
26
|
go-version: '1.19'
|
|
25
27
|
|
|
26
|
-
- name: Get yarn cache directory path
|
|
27
|
-
id: yarn-cache-dir-path
|
|
28
|
-
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
|
29
|
-
|
|
30
|
-
- name: Cache yarn cache
|
|
31
|
-
uses: actions/cache@v3
|
|
32
|
-
id: cache-yarn-cache
|
|
33
|
-
with:
|
|
34
|
-
path: $\{{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
35
|
-
key: $\{{ runner.os }}-yarn-$\{{ hashFiles('**/yarn.lock') }}
|
|
36
|
-
restore-keys: |
|
|
37
|
-
$\{{ runner.os }}-yarn-
|
|
38
|
-
|
|
39
|
-
- name: Cache node_modules
|
|
40
|
-
id: cache-node-modules
|
|
41
|
-
uses: actions/cache@v3
|
|
42
|
-
with:
|
|
43
|
-
path: node_modules
|
|
44
|
-
key: $\{{ runner.os }}-$\{{ matrix.node-version }}-nodemodules-$\{{ hashFiles('**/yarn.lock') }}
|
|
45
|
-
restore-keys: |
|
|
46
|
-
$\{{ runner.os }}-$\{{ matrix.node-version }}-nodemodules-
|
|
47
|
-
|
|
48
28
|
- name: Install dependencies
|
|
49
|
-
run: yarn install --
|
|
50
|
-
if: |
|
|
51
|
-
steps.cache-yarn-cache.outputs.cache-hit != 'true' ||
|
|
52
|
-
steps.cache-node-modules.outputs.cache-hit != 'true'
|
|
29
|
+
run: yarn install --immutable --prefer-offline
|
|
53
30
|
|
|
54
31
|
- name: Build and test frontend
|
|
55
32
|
run: yarn build
|
|
@@ -76,10 +53,15 @@ jobs:
|
|
|
76
53
|
version: latest
|
|
77
54
|
args: buildAll
|
|
78
55
|
|
|
56
|
+
- name: Warn missing Grafana API key
|
|
57
|
+
run: |
|
|
58
|
+
echo Please generate a Grafana API key: https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/#generate-an-api-key
|
|
59
|
+
echo Once done please go to \"settings \> secrets \> actions\" to add it as GRAFANA_API_KEY
|
|
60
|
+
if: $\{{ env.GRAFANA_API_KEY == '' }}
|
|
61
|
+
|
|
79
62
|
- name: Sign plugin
|
|
80
63
|
run: yarn sign
|
|
81
|
-
env
|
|
82
|
-
GRAFANA_API_KEY: $\{{ secrets.GRAFANA_API_KEY }} # Requires a Grafana API key from Grafana.com.
|
|
64
|
+
if: $\{{ env.GRAFANA_API_KEY != '' }}
|
|
83
65
|
|
|
84
66
|
- name: Get plugin metadata
|
|
85
67
|
id: metadata
|
|
@@ -117,49 +99,35 @@ jobs:
|
|
|
117
99
|
md5sum $\{{ steps.metadata.outputs.archive }} > $\{{ steps.metadata.outputs.archive-checksum }}
|
|
118
100
|
echo "checksum=$(cat ./$\{{ steps.metadata.outputs.archive-checksum }} | cut -d' ' -f1)" >> $GITHUB_OUTPUT
|
|
119
101
|
|
|
120
|
-
- name:
|
|
102
|
+
- name: Validate plugin
|
|
121
103
|
run: |
|
|
122
104
|
git clone https://github.com/grafana/plugin-validator
|
|
123
105
|
pushd ./plugin-validator/pkg/cmd/plugincheck2
|
|
124
106
|
go install
|
|
125
107
|
popd
|
|
126
|
-
plugincheck2 -config ./plugin-validator/config/
|
|
108
|
+
plugincheck2 -config ./plugin-validator/config/default.yaml $\{{ steps.metadata.outputs.archive }}
|
|
127
109
|
|
|
128
|
-
- name: Create release
|
|
129
|
-
|
|
130
|
-
uses: actions/create-release@v1
|
|
131
|
-
env:
|
|
132
|
-
GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
|
|
110
|
+
- name: Create Github release
|
|
111
|
+
uses: softprops/action-gh-release@v1
|
|
133
112
|
with:
|
|
134
|
-
tag_name: $\{{ github.ref }}
|
|
135
|
-
release_name: Release $\{{ github.ref }}
|
|
136
|
-
body_path: $\{{ steps.changelog.outputs.path }}
|
|
137
113
|
draft: true
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
asset_name: $\{{ steps.metadata.outputs.archive-checksum }}
|
|
159
|
-
asset_content_type: text/plain
|
|
160
|
-
|
|
161
|
-
- name: Publish to Grafana.com
|
|
162
|
-
run: |
|
|
163
|
-
echo A draft release has been created for your plugin. Please review and publish it. Then submit your plugin to grafana.com/plugins by opening a PR to https://github.com/grafana/grafana-plugin-repository with the following entry:
|
|
164
|
-
echo
|
|
165
|
-
echo '{ "id": "$\{{ steps.metadata.outputs.plugin-id }}", "type": "$\{{ steps.metadata.outputs.plugin-type }}", "url": "https://github.com/$\{{ github.repository }}", "versions": [ { "version": "$\{{ steps.metadata.outputs.plugin-version }}", "commit": "$\{{ github.sha }}", "url": "https://github.com/$\{{ github.repository }}", "download": { "any": { "url": "https://github.com/$\{{ github.repository }}/releases/download/v$\{{ steps.metadata.outputs.plugin-version }}/$\{{ steps.metadata.outputs.archive }}", "md5": "$\{{ steps.package-plugin.outputs.checksum }}" } } } ] }' | jq .
|
|
114
|
+
generate_release_notes: true
|
|
115
|
+
files: |
|
|
116
|
+
./$\{{ steps.metadata.outputs.archive }}
|
|
117
|
+
./$\{{ steps.metadata.outputs.archive-checksum }}
|
|
118
|
+
body: |
|
|
119
|
+
**This Github draft release has been created for your plugin.**
|
|
120
|
+
|
|
121
|
+
_Note: if this is the first release for your plugin please consult the [distributing-your-plugin section](https://github.com/$\{{github.repository}}/blob/main/README.md#distributing-your-plugin) of the README_
|
|
122
|
+
|
|
123
|
+
If you would like to submit this release to Grafana please consider the following steps:
|
|
124
|
+
|
|
125
|
+
- Check the Validate plugin step in the [release workflow](https://github.com/$\{{github.repository}}/commit/$\{{github.sha}}/checks/$\{{github.run_id}}) for any warnings that need attention
|
|
126
|
+
- Navigate to https://grafana.com/auth/sign-in/ to sign into your account
|
|
127
|
+
- Once logged in click **My Plugins** in the admin navigation
|
|
128
|
+
- Click the **Submit Plugin** button
|
|
129
|
+
- Fill in the Plugin Submission form:
|
|
130
|
+
- Paste this [.zip asset link](https://github.com/$\{{ github.repository }}/releases/download/v$\{{ steps.metadata.outputs.plugin-version }}/$\{{ steps.metadata.outputs.archive }}) in the Plugin URL field
|
|
131
|
+
- Paste this [.zip.md5 link](https://github.com/$\{{ github.repository }}/releases/download/v$\{{ steps.metadata.outputs.plugin-version }}/$\{{ steps.metadata.outputs.archive-checksum }}) in the MD5 field
|
|
132
|
+
|
|
133
|
+
Once done please remove these instructions and publish this release.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: Latest Grafana API compatibility check
|
|
2
|
-
on: [
|
|
2
|
+
on: [pull_request]
|
|
3
3
|
|
|
4
4
|
jobs:
|
|
5
5
|
compatibilitycheck:
|
|
@@ -9,8 +9,9 @@ jobs:
|
|
|
9
9
|
- uses: actions/setup-node@v3
|
|
10
10
|
with:
|
|
11
11
|
node-version: '16'
|
|
12
|
+
cache: 'yarn'
|
|
12
13
|
- name: Install dependencies
|
|
13
|
-
run: yarn install
|
|
14
|
+
run: yarn install --immutable --prefer-offline
|
|
14
15
|
- name: Build plugin
|
|
15
16
|
run: yarn build
|
|
16
17
|
- name: Compatibility check
|
|
@@ -13,6 +13,8 @@ Use panel plugins when you want to do things like visualize data returned by dat
|
|
|
13
13
|
-- INSERT FRONTEND GETTING STARTED --
|
|
14
14
|
{{#if hasBackend}}-- INSERT BACKEND GETTING STARTED --{{/if}}
|
|
15
15
|
|
|
16
|
+
-- INSERT DISTRIBUTING YOUR PLUGIN --
|
|
17
|
+
|
|
16
18
|
## Learn more
|
|
17
19
|
|
|
18
20
|
Below you can find source code for existing app plugins and other related documentation.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
|
|
3
|
-
*
|
|
4
|
-
* In order to extend the configuration follow the steps in .config/README.md
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
* This utility function is useful in combination with jest `transformIgnorePatterns` config
|
|
9
|
-
* to transform specific packages (e.g.ES modules) in a projects node_modules folder.
|
|
10
|
-
*/
|
|
11
|
-
const nodeModulesToTransform = (moduleNames) => `node_modules\/(?!(${moduleNames.join('|')})\/)`;
|
|
12
|
-
|
|
13
|
-
// Array of known nested grafana package dependencies that only bundle an ESM version
|
|
14
|
-
const grafanaESModules = ['ol', 'react-colorful'];
|
|
15
|
-
|
|
16
|
-
module.exports = {
|
|
17
|
-
nodeModulesToTransform,
|
|
18
|
-
grafanaESModules
|
|
19
|
-
}
|