Skip to content

Commit f33ffe8

Browse files
authored
Run E2E against Grafana Cloud (#1400)
1 parent 69d1774 commit f33ffe8

File tree

7 files changed

+142
-14
lines changed

7 files changed

+142
-14
lines changed

.github/workflows/cron.yml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: cron Jobs
2+
3+
on:
4+
schedule:
5+
- cron: '0 9 * * *' # Daily at 09:00 UTC
6+
7+
defaults:
8+
run:
9+
shell: bash
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
bench-tests:
16+
name: Run E2E Tests with Grafana Bench
17+
runs-on: ubuntu-24.04
18+
timeout-minutes: 60
19+
20+
# ensure job never runs on forks
21+
if: ${{ github.event_name != 'schedule' || github.repository_owner == 'grafana' }}
22+
23+
# this job needs OIDC to fetch Vault secrets
24+
permissions:
25+
contents: read
26+
id-token: write
27+
28+
steps:
29+
- uses: actions/checkout@v6
30+
with:
31+
# Avoid leaving a token in the repo checkout; prefer explicit auth for publishing steps
32+
persist-credentials: false
33+
34+
- name: Get secrets from Vault
35+
id: get-secrets
36+
uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.3.0
37+
with:
38+
# Grafana auth (used by @grafana/plugin-e2e)
39+
# + Prometheus creds for Bench metrics reporting
40+
common_secrets: |
41+
PLAYWRIGHT_GRAFANA_PASSWORD=data-sources/e2e:grafana-pw
42+
PLAYWRIGHT_GRAFANA_USERNAME=data-sources/e2e:grafana-username
43+
PROMETHEUS_PASSWORD=grafana-bench:prometheus_token
44+
PROMETHEUS_URL=grafana-bench:prometheus_url
45+
PROMETHEUS_USER=grafana-bench:prometheus_user
46+
47+
# Repo-specific backend secrets (naming varies by datasource)
48+
repo_secrets: |
49+
DS_INSTANCE_HOST=ds-instance:host
50+
DS_INSTANCE_PASSWORD=ds-instance:password
51+
DS_INSTANCE_PORT=ds-instance:port
52+
DS_INSTANCE_USERNAME=ds-instance:username
53+
54+
# Keep secrets in step output; we’ll pass them to Bench explicitly
55+
export_env: false
56+
57+
- name: Wait for Grafana to be reachable
58+
uses: grafana/plugin-actions/wait-for-grafana@wait-for-grafana/v1.0.2
59+
with:
60+
# Use /login so “reachable” also implies the app is up
61+
url: "https://datasourcese2e.grafana-dev.net/login"
62+
timeout: 300 # 5 minutes
63+
interval: 10 # 10 seconds
64+
65+
- name: Run Grafana Bench tests
66+
run: |
67+
set -euo pipefail
68+
docker run \
69+
-e PROMETHEUS_URL="${{ fromJSON(steps.get-secrets.outputs.secrets).PROMETHEUS_URL }}" \
70+
-e PROMETHEUS_USER="${{ fromJSON(steps.get-secrets.outputs.secrets).PROMETHEUS_USER }}" \
71+
-e PROMETHEUS_PASSWORD="${{ fromJSON(steps.get-secrets.outputs.secrets).PROMETHEUS_PASSWORD }}" \
72+
--network=host \
73+
--rm \
74+
--volume "$PWD:/tests" \
75+
us-docker.pkg.dev/grafanalabs-global/docker-grafana-bench-prod/grafana-bench-playwright:v0.6.11 test \
76+
--grafana-admin-password "${{ fromJSON(steps.get-secrets.outputs.secrets).PLAYWRIGHT_GRAFANA_PASSWORD }}" \
77+
--grafana-admin-user "${{ fromJSON(steps.get-secrets.outputs.secrets).PLAYWRIGHT_GRAFANA_USERNAME }}" \
78+
--grafana-url "https://datasourcese2e.grafana-dev.net" \
79+
--grafana-version "rrc-instant" \
80+
--prometheus-metrics \
81+
--prometheus-strict-lint \
82+
--pw-execute "npm run e2e" \
83+
--pw-prepare "npm ci --no-audit --fund=false; npx playwright install" \
84+
--test-env 'CI=true,DS_INSTANCE_HOST=${{ fromJSON(steps.get-secrets.outputs.secrets).DS_INSTANCE_HOST }},DS_INSTANCE_PASSWORD=${{ fromJSON(steps.get-secrets.outputs.secrets).DS_INSTANCE_PASSWORD }},DS_INSTANCE_PORT=${{ fromJSON(steps.get-secrets.outputs.secrets).DS_INSTANCE_PORT }},DS_INSTANCE_USERNAME=${{ fromJSON(steps.get-secrets.outputs.secrets).DS_INSTANCE_USERNAME }},DS_PDC_NETWORK_NAME=datasources-pdc-network-aws-datasourcese2e' \
85+
--test-runner playwright \
86+
--test-verbose

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
environment: ${{ matrix.environment }}
4141
docs-only: ${{ fromJSON(github.event.inputs.docs-only) }}
4242
scopes: ${{ github.event.inputs.environment == 'cloud (recommended)' && 'grafana_cloud' || github.event.inputs.environment == 'on-prem (for emergencies fix to On Prem customers)' && 'universal' }}
43-
go-version: "1.24"
43+
go-version: "1.25"
4444
golangci-lint-version: "2.1.6"
4545
run-playwright: false
4646
github-draft-release: false

.github/workflows/push.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,29 @@ jobs:
1212
ci:
1313
name: CI
1414
uses: grafana/plugin-ci-workflows/.github/workflows/ci.yml@ci-cd-workflows/v5.1.0
15+
if: github.ref != 'refs/heads/main'
1516
permissions:
1617
contents: read
1718
id-token: write
1819
with:
20+
go-version: '1.25'
21+
golangci-lint-version: '2.1.6'
1922
plugin-version-suffix: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }}
20-
go-version: "1.24"
21-
golangci-lint-version: "2.1.6"
23+
24+
publish-latest-to-catalog:
25+
name: Publish `main` to Dev Catalog
26+
if: github.ref == 'refs/heads/main'
27+
uses: grafana/plugin-ci-workflows/.github/workflows/cd.yml@ci-cd-workflows/v5.1.0
28+
permissions:
29+
attestations: write
30+
contents: write
31+
id-token: write
32+
with:
33+
disable-docs-publishing: true
34+
disable-github-release: true
35+
environment: 'dev'
36+
go-version: '1.25'
37+
golangci-lint-version: '2.1.6'
38+
plugin-version-suffix: ${{ github.sha }}
39+
run-playwright: false
40+
scopes: grafana_cloud_instance_datasourcese2e

cspell.config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"CHSQL",
1919
"ClickHouse",
2020
"closedate",
21+
"combobox",
2122
"commitish",
2223
"concats",
2324
"createddate",
@@ -78,9 +79,9 @@
7879
"timerange",
7980
"timeseries",
8081
"timespan",
81-
"toggleTip",
8282
"TLSCA",
8383
"TLSSSL",
84+
"toggleTip",
8485
"Toggletip",
8586
"totime",
8687
"traceid",

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

playwright.config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { dirname } from 'path';
2+
13
import { defineConfig, devices } from '@playwright/test';
24
import type { PluginOptions } from '@grafana/plugin-e2e';
35

@@ -42,14 +44,14 @@ export default defineConfig<PluginOptions>({
4244
projects: [
4345
{
4446
name: 'auth',
45-
testDir: 'node_modules/@grafana/plugin-e2e/dist/auth',
47+
testDir: `${dirname(require.resolve('@grafana/plugin-e2e'))}/auth`,
4648
testMatch: [/.*\.js/],
4749
},
4850
{
4951
name: 'run-tests',
5052
use: {
5153
...devices['Desktop Chrome'],
52-
storageState: 'playwright/.auth/admin.json',
54+
storageState: `playwright/.auth/${process.env.GRAFANA_ADMIN_USER || 'admin'}.json`,
5355
},
5456
dependencies: ['auth'],
5557
},

tests/e2e/configEditor.spec.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,44 @@
11
import { expect, test } from '@grafana/plugin-e2e';
2+
import { Page } from '@playwright/test';
23

34
const PLUGIN_UID = 'grafana-clickhouse-datasource';
4-
const CLICKHOUSE_DB_URL = Boolean(process.env.CI) ? 'clickhouse-server' : 'localhost';
5+
6+
// Determine ClickHouse DB URL based on environment
7+
function resolveClickhouseUrl(env = process.env) {
8+
const { CI, DS_INSTANCE_HOST } = env;
9+
return CI ? (DS_INSTANCE_HOST || 'clickhouse-server') : 'localhost';
10+
}
11+
12+
// Configure Private Data Source Connect if network name is provided
13+
async function configurePDC(page: Page, networkName: string) {
14+
await page.getByRole('combobox', { name: 'Private data source connect' }).click();
15+
await page.getByText(networkName).click();
16+
}
517

618
test.describe('Config Editor', () => {
719
test('invalid credentials should return an error', async ({ createDataSourceConfigPage, page }) => {
820
const configPage = await createDataSourceConfigPage({ type: PLUGIN_UID });
9-
await page.getByPlaceholder('Server address').fill(CLICKHOUSE_DB_URL);
21+
await page.getByPlaceholder('Server address').fill(resolveClickhouseUrl());
1022
await expect(configPage.saveAndTest()).not.toBeOK();
23+
await configPage.deleteDataSource();
1124
});
1225

1326
test('valid credentials should display a success alert on the page', async ({ createDataSourceConfigPage, page }) => {
1427
const configPage = await createDataSourceConfigPage({ type: PLUGIN_UID });
1528

16-
await page.getByPlaceholder('Server address').fill(CLICKHOUSE_DB_URL);
17-
await page.getByPlaceholder('9000').fill('9000');
18-
await page.getByPlaceholder('default').fill('default');
29+
await page.getByPlaceholder('Server address').fill(resolveClickhouseUrl());
30+
await page.getByPlaceholder('9000').fill(process.env.DS_INSTANCE_PORT ?? '9000');
31+
await page.getByPlaceholder('default').fill(process.env.DS_INSTANCE_USERNAME ?? 'default');
32+
await page.getByPlaceholder('password').fill(process.env.DS_INSTANCE_PASSWORD ?? '');
33+
34+
if (process.env.DS_PDC_NETWORK_NAME) {
35+
await configurePDC(page, process.env.DS_PDC_NETWORK_NAME);
36+
}
1937

2038
await configPage.saveAndTest();
2139
await expect(configPage).toHaveAlert('success', { hasNotText: 'Datasource updated' });
2240

23-
await page.pause();
41+
await configPage.deleteDataSource();
2442
});
2543

2644
test('mandatory fields should show error if left empty', async ({ createDataSourceConfigPage, page }) => {
@@ -35,5 +53,7 @@ test.describe('Config Editor', () => {
3553
await expect(page.getByText('Port is required')).toBeVisible();
3654

3755
await expect(configPage.saveAndTest()).not.toBeOK();
56+
57+
await configPage.deleteDataSource();
3858
});
3959
});

0 commit comments

Comments
 (0)