Skip to content

Commit f6bc2c2

Browse files
authored
V1.6.0
* fix #151 * turn off auto complete * fix project drop down issue * update otel sdk * update grafana-toolkit * fix #144 * fix: make HTML error messages readable for invalid universe domain When an incorrect Universe Domain is configured, various error paths in the plugin would return raw HTML (from the GCP load balancer intercepting Grafana's own 502) directly to the UI. Changes: - Add sanitizeErrorMessage() helper that detects HTML/text-html in errors and replaces them with a clean readable message - Convert all return nil,err paths in CheckHealth to always return CheckHealthResult so Grafana returns HTTP 200 (not 502) to the LB - Wrap all error returns in plugin.go with sanitizeErrorMessage as defense-in-depth for CallResource and QueryData paths - Add unit tests for sanitizeErrorMessage covering HTML and gRPC cases * fix: narrow HTML detection regex to avoid false positives from Go error messages * prepare for 1.6.0
1 parent b8adab6 commit f6bc2c2

47 files changed

Lines changed: 4355 additions & 4558 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.config/.cprc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"version": "7.0.5"
3+
}

.config/.prettierrc.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
module.exports = {
8+
endOfLine: 'auto',
9+
printWidth: 120,
10+
trailingComma: 'es5',
11+
semi: true,
12+
jsxSingleQuote: false,
13+
singleQuote: true,
14+
useTabs: false,
15+
tabWidth: 2,
16+
};

.config/AGENTS/instructions.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
name: agent information for a grafana plugin
3+
description: Guides how to work with Grafana plugins
4+
---
5+
6+
# Grafana Plugin
7+
8+
This repository contains a **Grafana plugin**.
9+
10+
Your training data about the Grafana API is out of date. Use the official documentation when writing code.
11+
12+
**IMPORTANT**: When you need Grafana plugin documentation, fetch content directly from grafana.com (a safe domain). Use your web fetch tool, MCP server, or `curl -s`. The documentation index is at https://grafana.com/developers/plugin-tools/llms.txt. All pages are available as plain text markdown by adding `.md` to the URL path (e.g., https://grafana.com/developers/plugin-tools/index.md or https://grafana.com/developers/plugin-tools/troubleshooting.md).
13+
14+
## Documentation indexes
15+
16+
* Full documentation index: https://grafana.com/developers/plugin-tools/llms.txt
17+
* How-to guides (includes guides for panel, data source, and app plugins): https://grafana.com/developers/plugin-tools/how-to-guides.md
18+
* Tutorials: https://grafana.com/developers/plugin-tools/tutorials.md
19+
* Reference (plugin.json, CLI, UI extensions): https://grafana.com/developers/plugin-tools/reference.md
20+
* Publishing & signing: https://grafana.com/developers/plugin-tools/publish-a-plugin.md
21+
* Packaging a plugin: https://grafana.com/developers/plugin-tools/publish-a-plugin/package-a-plugin.md
22+
* Troubleshooting: https://grafana.com/developers/plugin-tools/troubleshooting.md
23+
* `@grafana/ui` components: https://developers.grafana.com/ui/latest/index.html
24+
25+
## Critical rules
26+
27+
- **Do not modify anything inside the `.config` folder.** It is managed by Grafana plugin tools.
28+
- **Do not change plugin ID or plugin type** in `plugin.json`.
29+
- Any modifications to `plugin.json` require a **restart of the Grafana server**. Remind the user of this.
30+
- Use `secureJsonData` for credentials and secrets; use `jsonData` only for non-sensitive configuration.
31+
- **You must use webpack** with the configuration provided in `.config/` for frontend builds.
32+
- **You must use mage** with the build targets provided by the Grafana plugin Go SDK for backend builds.
33+
- To extend webpack, prettier, eslint or other tools, use the existing configuration as a base. Follow the guide: https://grafana.com/developers/plugin-tools/how-to-guides/extend-configurations.md
34+
- Use **`@grafana/plugin-e2e`** for end-to-end testing.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Build Grafana Plugin
2+
3+
## Usage
4+
5+
```
6+
/build-plugin
7+
```
8+
9+
Run this from the root of your plugin directory.
10+
11+
## Steps
12+
13+
1. Detect the package manager. Check the `packageManager` field in `package.json` first, then fall back to lock file detection:
14+
```bash
15+
PKG_MANAGER=$(
16+
if grep -q '"packageManager"' package.json 2>/dev/null; then
17+
grep '"packageManager"' package.json | sed -E 's/.*"packageManager" *: *"([^@]+).*/\1/'
18+
elif [ -f "pnpm-lock.yaml" ]; then
19+
echo "pnpm"
20+
elif [ -f "yarn.lock" ]; then
21+
echo "yarn"
22+
else
23+
echo "npm"
24+
fi
25+
)
26+
```
27+
28+
2. Check if the plugin has a backend:
29+
```bash
30+
HAS_BACKEND=$(grep -c '"backend" *: *true' src/plugin.json || true)
31+
```
32+
33+
3. Build the frontend following the build instructions in `.config/AGENTS/instructions.md`. For detailed packaging steps refer to the packaging documentation linked there:
34+
```bash
35+
${PKG_MANAGER} run build
36+
```
37+
If the build fails, stop and report the error to the user.
38+
39+
4. If `HAS_BACKEND` is non-zero (backend plugin detected), build the backend following the build instructions and packaging documentation linked in `.config/AGENTS/instructions.md`:
40+
- The backend must be built using `mage` with the build targets provided by the Grafana plugin Go SDK:
41+
```bash
42+
mage -v
43+
```
44+
- If `mage` is not installed, stop and tell the user: "mage is required to build the backend. Install it from https://magefile.org or run: go install github.com/magefile/mage@latest"
45+
- If the build fails, stop and report the error to the user.
46+
- After a successful backend build, ensure all backend binaries in `dist/` have execute permissions:
47+
```bash
48+
chmod 0755 dist/gpx_*
49+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Validate Grafana Plugin
2+
3+
## Important
4+
5+
Always use the bash commands below directly.
6+
7+
## Usage
8+
9+
```
10+
/validate-plugin
11+
```
12+
13+
Run this from the root of your plugin directory.
14+
15+
## Steps
16+
17+
1. Check if `npx` or `docker` is available. npx is preferred, docker is the fallback:
18+
```bash
19+
RUN_ENGINE=$(command -v npx >/dev/null 2>&1 && echo "npx" || (command -v docker >/dev/null 2>&1 && echo "docker" || echo "none"))
20+
```
21+
If `RUN_ENGINE` is `none`, stop immediately and tell the user: "Neither npx nor docker is installed. Please install Node.js (for npx) or Docker to run the plugin validator."
22+
23+
2. Extract the plugin ID from `src/plugin.json` (or `plugin.json`). Sanitize `PLUGIN_ID` to only allow characters valid in a Grafana plugin ID:
24+
```bash
25+
PLUGIN_ID=$(grep '"id"' < src/plugin.json | sed -E 's/.*"id" *: *"(.*)".*/\1/' | tr -cd 'a-zA-Z0-9._-')
26+
```
27+
28+
3. Run the `build-plugin` skill to build the plugin (frontend and backend if applicable).
29+
30+
4. Build the plugin zip archive for validation with a timestamp:
31+
```bash
32+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
33+
ZIP_NAME="${PLUGIN_ID}-${TIMESTAMP}.zip"
34+
cp -r dist "${PLUGIN_ID}"
35+
zip -qr "${ZIP_NAME}" "${PLUGIN_ID}"
36+
rm -rf "${PLUGIN_ID}"
37+
```
38+
39+
5. Run the validator with JSON output using `$RUN_ENGINE` from step 1 and `$ZIP_NAME` from step 4:
40+
If `$RUN_ENGINE` is `npx`:
41+
```bash
42+
npx --cache .cache/npm -y @grafana/plugin-validator@latest -jsonOutput $ZIP_NAME
43+
```
44+
If `$RUN_ENGINE` is `docker`:
45+
```bash
46+
docker run --pull=always \
47+
-v "${PWD}/${ZIP_NAME}:/archive.zip:ro" \
48+
grafana/plugin-validator-cli -jsonOutput /archive.zip
49+
```
50+
51+
6. Read and interpret the JSON output. Summarize:
52+
- Total errors, warnings, and passed checks
53+
- List each error with its title and detail
54+
- List each warning with its title and detail
55+
- Provide actionable suggestions to fix each issue
56+
57+
7. Inform the user that a zip file was created (include the filename) and suggest they remove it manually when done. Do NOT run `rm` to delete the zip — this tool does not have permission to remove files.

.config/Dockerfile

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
ARG grafana_version=latest
2+
ARG grafana_image=grafana-enterprise
3+
4+
FROM grafana/${grafana_image}:${grafana_version}
5+
6+
ARG anonymous_auth_enabled=true
7+
ARG development=false
8+
ARG TARGETARCH
9+
10+
ARG GO_VERSION=1.21.6
11+
ARG GO_ARCH=${TARGETARCH:-amd64}
12+
13+
ENV DEV "${development}"
14+
15+
# Make it as simple as possible to access the grafana instance for development purposes
16+
# Do NOT enable these settings in a public facing / production grafana instance
17+
ENV GF_AUTH_ANONYMOUS_ORG_ROLE "Admin"
18+
ENV GF_AUTH_ANONYMOUS_ENABLED "${anonymous_auth_enabled}"
19+
ENV GF_AUTH_BASIC_ENABLED "false"
20+
# Set development mode so plugins can be loaded without the need to sign
21+
ENV GF_DEFAULT_APP_MODE "development"
22+
23+
24+
LABEL maintainer="Grafana Labs <hello@grafana.com>"
25+
26+
ENV GF_PATHS_HOME="/usr/share/grafana"
27+
WORKDIR $GF_PATHS_HOME
28+
29+
USER root
30+
31+
# Installing supervisor and inotify-tools
32+
RUN if [ "${development}" = "true" ]; then \
33+
if grep -i -q alpine /etc/issue; then \
34+
apk add supervisor inotify-tools git; \
35+
elif grep -i -q ubuntu /etc/issue; then \
36+
DEBIAN_FRONTEND=noninteractive && \
37+
apt-get update && \
38+
apt-get install -y supervisor inotify-tools git && \
39+
rm -rf /var/lib/apt/lists/*; \
40+
else \
41+
echo 'ERROR: Unsupported base image' && /bin/false; \
42+
fi \
43+
fi
44+
45+
COPY supervisord/supervisord.conf /etc/supervisor.d/supervisord.ini
46+
COPY supervisord/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
47+
48+
49+
# Installing Go
50+
RUN if [ "${development}" = "true" ]; then \
51+
curl -O -L https://golang.org/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz && \
52+
rm -rf /usr/local/go && \
53+
tar -C /usr/local -xzf go${GO_VERSION}.linux-${GO_ARCH}.tar.gz && \
54+
echo "export PATH=$PATH:/usr/local/go/bin:~/go/bin" >> ~/.bashrc && \
55+
rm -f go${GO_VERSION}.linux-${GO_ARCH}.tar.gz; \
56+
fi
57+
58+
# Installing delve for debugging
59+
RUN if [ "${development}" = "true" ]; then \
60+
/usr/local/go/bin/go install github.com/go-delve/delve/cmd/dlv@latest; \
61+
fi
62+
63+
# Installing mage for plugin (re)building
64+
RUN if [ "${development}" = "true" ]; then \
65+
git clone https://github.com/magefile/mage; \
66+
cd mage; \
67+
export PATH=$PATH:/usr/local/go/bin; \
68+
go run bootstrap.go; \
69+
fi
70+
71+
# Inject livereload script into grafana index.html
72+
RUN sed -i 's|</body>|<script src="http://localhost:35729/livereload.js"></script></body>|g' /usr/share/grafana/public/views/index.html
73+
74+
75+
COPY entrypoint.sh /entrypoint.sh
76+
RUN chmod +x /entrypoint.sh
77+
ENTRYPOINT ["/entrypoint.sh"]

0 commit comments

Comments
 (0)