Skip to content

Commit

Permalink
E2E: set up plugin-e2e (#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinwcyu authored Mar 22, 2024
1 parent f221aee commit 26dee8a
Show file tree
Hide file tree
Showing 14 changed files with 490 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .config/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ARG grafana_version=latest
ARG grafana_image=grafana-enterprise

FROM grafana/grafana:${grafana_version}
FROM grafana/${grafana_image}:${grafana_version}

# Make it as simple as possible to access the grafana instance for development purposes
# Do NOT enable these settings in a public facing / production grafana instance
Expand Down
161 changes: 161 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: CI

on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main

permissions:
contents: read
id-token: write

jobs:
build:
runs-on: ubuntu-latest
outputs:
plugin-id: ${{ steps.metadata.outputs.plugin-id }}
plugin-version: ${{ steps.metadata.outputs.plugin-version }}
archive: ${{ steps.metadata.outputs.archive }}
steps:
- uses: actions/checkout@v4

- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Check types
run: yarn typecheck

- name: Lint
run: yarn lint

- name: Unit tests
run: yarn test:ci

- name: Build frontend
run: yarn build

- name: Setup Go environment
uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Test backend
uses: magefile/mage-action@v3
with:
version: latest
args: coverage

- name: Build backend
uses: magefile/mage-action@v3
with:
version: latest
args: buildAll

- name: Get plugin metadata
id: metadata
run: |
sudo apt-get install jq
export GRAFANA_PLUGIN_ID=$(cat dist/plugin.json | jq -r .id)
export GRAFANA_PLUGIN_VERSION=$(cat dist/plugin.json | jq -r .info.version)
export GRAFANA_PLUGIN_ARTIFACT=${GRAFANA_PLUGIN_ID}-${GRAFANA_PLUGIN_VERSION}.zip
echo "plugin-id=${GRAFANA_PLUGIN_ID}" >> $GITHUB_OUTPUT
echo "plugin-version=${GRAFANA_PLUGIN_VERSION}" >> $GITHUB_OUTPUT
echo "archive=${GRAFANA_PLUGIN_ARTIFACT}" >> $GITHUB_OUTPUT
- name: Package plugin
id: package-plugin
run: |
mv dist ${{ steps.metadata.outputs.plugin-id }}
zip ${{ steps.metadata.outputs.archive }} ${{ steps.metadata.outputs.plugin-id }} -r
- name: Archive Build
uses: actions/upload-artifact@v4
with:
name: ${{ steps.metadata.outputs.plugin-id }}-${{ steps.metadata.outputs.plugin-version }}
path: ${{ steps.metadata.outputs.archive }}
retention-days: 5

resolve-versions:
name: Resolve Grafana images
runs-on: ubuntu-latest
timeout-minutes: 3
outputs:
matrix: ${{ steps.resolve-versions.outputs.matrix }}
steps:
- name: Resolve Grafana E2E versions
id: resolve-versions
uses: grafana/plugin-actions/e2e-version@main
with:
version-resolver-type: version-support-policy

playwright-tests:
needs: [resolve-versions, build]
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
GRAFANA_IMAGE: ${{fromJson(needs.resolve-versions.outputs.matrix)}}
name: ${{ matrix.GRAFANA_IMAGE.name }}@${{ matrix.GRAFANA_IMAGE.VERSION }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Install Playwright Browsers
run: yarn playwright install --with-deps chromium

- name: Download build
id: download-build
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.plugin-id }}-${{ needs.build.outputs.plugin-version }}

- name: Unpack build
run: |
unzip ${{ needs.build.outputs.archive }}
mv ${{ needs.build.outputs.plugin-id }} dist
- name: Start Grafana
shell: bash
run: |
docker compose pull
docker compose up --detach --wait --wait-timeout 60
env:
GRAFANA_IMAGE: ${{ matrix.GRAFANA_IMAGE.NAME }}
GRAFANA_VERSION: ${{ matrix.GRAFANA_IMAGE.VERSION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Run Playwright tests
id: run-tests
run: npm run playwright:test
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Publish report to GCS
if: ${{ (always() && steps.run-tests.outcome == 'success') || (failure() && steps.run-tests.outcome == 'failure') && github.event.organization.login == 'grafana' }}
uses: grafana/plugin-actions/publish-report@main
with:
grafana-version: ${{ matrix.GRAFANA_IMAGE.VERSION }}
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,15 @@ e2e-results/
# vscode
.vscode
__debug_bin

# E2E tests
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
.env
.env.*
# ignore all provisioning files except for e2e placeholders.
provisioning/datasources/*
!provisioning/datasources/*.e2e.yaml
38 changes: 38 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@ To build X-Ray data source locally you should follow the steps below.
## Frontend

1. Install dependencies

```BASH
yarn install
```

2. Build plugin in development mode or run in watch mode

```BASH
yarn dev
```

or

```BASH
yarn watch
```

3. Build plugin in production mode

```BASH
yarn build
```
Expand All @@ -31,20 +37,52 @@ go get -u github.com/grafana/grafana-plugin-sdk-go
```

2. Build backend plugin binaries for Linux, Windows and Darwin:

```BASH
mage -v
```

3. List all available Mage targets for additional commands:

```BASH
mage -l
```

4. Watch all go sources, rebuild on change and reload plugin in running Grafana (need [Bra installed](https://github.com/unknwon/bra)):

```BASH
bra run
```

## Testing

### E2E Tests

1. Add a `.env` file to the project root with `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` defined

```
AWS_ACCESS_KEY_ID="REPLACE_WITH_AWS_ACCESS_KEY_ID"
AWS_SECRET_ACCESS_KEY="REPLACE_WITH_AWS_SECRET_KEY"
```

2. Ensure you have the `AWS X-Ray E2E` data source provisioned in the `provisioning/datasources` directory

3. Start the server

```sh
yarn server
```

4. Run the tests

```sh
yarn playwright:test

# Optionally show the report, the report automatically shows if any tests fail
yarn playwright:report

```

## Learn more

- [Build a data source backend plugin tutorial](https://grafana.com/tutorials/build-a-data-source-backend-plugin)
Expand Down
5 changes: 4 additions & 1 deletion cspell.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@
"opentelemetry",
"httptrace",
"otelhttptrace",
"otelgrpc"
"otelgrpc",
"healthcheck",
"combobox",
"menuitemcheckbox"
]
}
18 changes: 17 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@ version: '3.0'
services:
grafana:
container_name: 'grafana-x-ray-datasource'
platform: 'linux/amd64'
build:
context: ./.config
args:
grafana_version: ${GRAFANA_VERSION:-9.3.2}
grafana_image: ${GRAFANA_IMAGE:-grafana-enterprise}
grafana_version: ${GRAFANA_VERSION:-latest}
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
healthcheck:
test: curl -f http://localhost:3000 || exit 1
# TODO: Uncomment start_period and start_interval when the ubuntu-latest
# image in gh actions uses docker engine version >25 and remove
# interval, timeout, and retries. Version >25 is required for
# start_period and start_interval to work properly https://github.com/moby/moby/pull/46764
# start_period: 30s
# start_interval: 500ms
interval: 500ms
timeout: 30s
retries: 60
ports:
- 3000:3000/tcp
volumes:
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"lint:fix": "yarn lint --fix",
"server": "docker-compose up --build",
"spellcheck": "cspell -c cspell.config.json \"**/*.{ts,tsx,js,go,md,mdx,yml,yaml,json,scss,css}\"",
"playwright:test": "yarn playwright test",
"playwright:report": "yarn playwright show-report",
"test": "jest --watch --onlyChanged",
"test:ci": "jest --maxWorkers 4",
"test:coverage": "jest --coverage",
Expand All @@ -23,9 +25,11 @@
"@grafana/aws-sdk": "0.3.0",
"@grafana/data": "9.3.2",
"@grafana/eslint-config": "^6.0.1",
"@grafana/plugin-e2e": "^0.21.0",
"@grafana/runtime": "9.3.2",
"@grafana/tsconfig": "^1.2.0-rc1",
"@grafana/ui": "9.3.2",
"@playwright/test": "^1.41.2",
"@swc/core": "^1.2.144",
"@swc/helpers": "^0.3.6",
"@swc/jest": "^0.2.20",
Expand All @@ -42,6 +46,7 @@
"copy-webpack-plugin": "^10.0.0",
"cspell": "8.0.0",
"css-loader": "6.7.1",
"dotenv": "^16.4.5",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^46.7.0",
Expand Down
49 changes: 49 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { dirname } from 'path';
import { defineConfig, devices } from '@playwright/test';
import dotenv from 'dotenv';

dotenv.config();

const pluginE2EAuth = `${dirname(require.resolve('@grafana/plugin-e2e'))}/auth`;

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{
name: 'authenticate',
testDir: pluginE2EAuth,
testMatch: [/.*\.js/],
},
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
storageState: 'playwright/.auth/admin.json',
},
dependencies: ['authenticate'],
},
],
});
Loading

0 comments on commit 26dee8a

Please sign in to comment.