@grafana/create-plugin 0.6.3 → 0.7.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 CHANGED
@@ -1,3 +1,15 @@
1
+ # v0.7.0 (Tue Nov 29 2022)
2
+
3
+ #### 🚀 Enhancement
4
+
5
+ - Create plugin: Introduce sign-plugin [#160](https://github.com/grafana/plugin-tools/pull/160) ([@jackw](https://github.com/jackw))
6
+
7
+ #### Authors: 1
8
+
9
+ - Jack Westbrook ([@jackw](https://github.com/jackw))
10
+
11
+ ---
12
+
1
13
  # v0.6.3 (Mon Nov 28 2022)
2
14
 
3
15
  #### 🐛 Bug Fix
@@ -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: [
@@ -120,7 +121,11 @@ function default_1(plop) {
120
121
  ? getActionsForTemplateFolder({ folderPath: constants_1.TEMPLATE_PATHS.isCompatibleWorkflow, exportPath: exportPath })
121
122
  : [];
122
123
  var readmeActions = getActionsForReadme({ exportPath: exportPath });
123
- return __spreadArray(__spreadArray(__spreadArray(__spreadArray([], pluginActions, true), ciWorkflowActions, true), readmeActions, true), isCompatibleWorkflowActions, true);
124
+ return __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], pluginActions, true), ciWorkflowActions, true), readmeActions, true), isCompatibleWorkflowActions, true), [
125
+ {
126
+ type: 'printSuccessMessage'
127
+ },
128
+ ], false);
124
129
  }
125
130
  });
126
131
  }
@@ -130,6 +135,7 @@ function getActionsForReadme(_a) {
130
135
  return [
131
136
  replacePatternWithTemplateInReadme('-- INSERT FRONTEND GETTING STARTED --', 'frontend-getting-started.md', exportPath),
132
137
  replacePatternWithTemplateInReadme('-- INSERT BACKEND GETTING STARTED --', 'backend-getting-started.md', exportPath),
138
+ replacePatternWithTemplateInReadme('-- INSERT DISTRIBUTING YOUR PLUGIN --', 'distributing-your-plugin.md', exportPath),
133
139
  ];
134
140
  }
135
141
  function replacePatternWithTemplateInReadme(pattern, partialsFile, exportPath) {
@@ -179,3 +185,14 @@ function getExportPath(pluginName, orgName, pluginType) {
179
185
  return path_1["default"].join(process.cwd(), (0, utils_handlebars_1.normalizeId)(pluginName, orgName, pluginType));
180
186
  }
181
187
  }
188
+ function printSuccessMessage(answers) {
189
+ var directory = (0, utils_handlebars_1.normalizeId)(answers.pluginName, answers.orgName, answers.pluginType);
190
+ var commands = __spreadArray(__spreadArray([
191
+ ' * `yarn install` to install frontend dependencies.',
192
+ ' * `docker-compose up` to start a grafana development server.',
193
+ ' * `yarn dev` to build (and watch) the plugin frontend code.'
194
+ ], (answers.hasBackend ? [' * `mage -v build:linux` to build the plugin backend code.'] : []), true), [
195
+ ' * Open http://localhost:3000 in your browser to create a dashboard to begin developing your plugin.',
196
+ ], false);
197
+ 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");
198
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafana/create-plugin",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "main": "index.js",
5
5
  "repository": {
6
6
  "directory": "packages/create-plugin",
@@ -60,5 +60,5 @@
60
60
  "engines": {
61
61
  "node": ">=16"
62
62
  },
63
- "gitHead": "f1dc565ab40f62006c023bc3eda23e8ebeed6ae7"
63
+ "gitHead": "a9672bf8dfb3c26bcda4b2eb82ab57d4f1f0601d"
64
64
  }
@@ -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: [
@@ -139,7 +141,15 @@ export default function (plop: NodePlopAPI) {
139
141
  // Replace conditional bits in the Readme files
140
142
  const readmeActions = getActionsForReadme({ exportPath });
141
143
 
142
- return [...pluginActions, ...ciWorkflowActions, ...readmeActions, ...isCompatibleWorkflowActions];
144
+ return [
145
+ ...pluginActions,
146
+ ...ciWorkflowActions,
147
+ ...readmeActions,
148
+ ...isCompatibleWorkflowActions,
149
+ {
150
+ type: 'printSuccessMessage',
151
+ },
152
+ ];
143
153
  },
144
154
  });
145
155
  }
@@ -156,6 +166,11 @@ function getActionsForReadme({ exportPath }: { exportPath: string }): ModifyActi
156
166
  'backend-getting-started.md',
157
167
  exportPath
158
168
  ),
169
+ replacePatternWithTemplateInReadme(
170
+ '-- INSERT DISTRIBUTING YOUR PLUGIN --',
171
+ 'distributing-your-plugin.md',
172
+ exportPath
173
+ ),
159
174
  ];
160
175
  }
161
176
 
@@ -229,3 +244,27 @@ function getExportPath(pluginName: string, orgName: string, pluginType: PLUGIN_T
229
244
  return path.join(process.cwd(), normalizeId(pluginName, orgName, pluginType));
230
245
  }
231
246
  }
247
+
248
+ function printSuccessMessage(answers: CliArgs) {
249
+ const directory = normalizeId(answers.pluginName, answers.orgName, answers.pluginType);
250
+
251
+ const commands = [
252
+ ' * `yarn install` to install frontend dependencies.',
253
+ ' * `docker-compose up` to start a grafana development server.',
254
+ ' * `yarn dev` to build (and watch) the plugin frontend code.',
255
+ ...(answers.hasBackend ? [' * `mage -v build:linux` to build the plugin backend code.'] : []),
256
+ ' * Open http://localhost:3000 in your browser to create a dashboard to begin developing your plugin.',
257
+ ];
258
+
259
+ return `
260
+ Congratulations on scaffolding a Grafana ${answers.pluginName} plugin! 🚀
261
+
262
+ ## What's next?
263
+ Navigate into ./${directory} and run the following commands to get started:
264
+ ${commands.map((command) => command).join('\n')}
265
+
266
+ View the README.md for futher information.
267
+ Learn more about Grafana Plugins at https://grafana.com/docs/grafana/latest/plugins/developing/development/
268
+
269
+ `;
270
+ }
@@ -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`
@@ -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.
@@ -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",
@@ -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.x'
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 --frozen-lockfile
26
+ run: yarn install --immutable --prefer-offline
48
27
 
49
- - name: Build and test frontend
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: stop grafana docker
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*.*.*' # Run workflow on version tags, e.g. v1.0.0.
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.x'
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 --frozen-lockfile;
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 follow the instructions found here: https://github.com/$\{{github.repository}}/blob/main/README.md#using-github-actions-release-workflow
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: Lint plugin
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/publishing.yaml $\{{ steps.metadata.outputs.archive }}
108
+ plugincheck2 -config ./plugin-validator/config/default.yaml $\{{ steps.metadata.outputs.archive }}
127
109
 
128
- - name: Create release
129
- id: create_release
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
- - name: Add plugin to release
140
- id: upload-plugin-asset
141
- uses: actions/upload-release-asset@v1
142
- env:
143
- GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
144
- with:
145
- upload_url: $\{{ steps.create_release.outputs.upload_url }}
146
- asset_path: ./$\{{ steps.metadata.outputs.archive }}
147
- asset_name: $\{{ steps.metadata.outputs.archive }}
148
- asset_content_type: application/zip
149
-
150
- - name: Add checksum to release
151
- id: upload-checksum-asset
152
- uses: actions/upload-release-asset@v1
153
- env:
154
- GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
155
- with:
156
- upload_url: $\{{ steps.create_release.outputs.upload_url }}
157
- asset_path: ./$\{{ steps.metadata.outputs.archive-checksum }}
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: [push, pull_request]
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.