Skip to content

Commit

Permalink
Add E2E workflow (#20)
Browse files Browse the repository at this point in the history
* Add E2E workflow

* Update e2e.yml

* Update e2e.yml

* Update e2e.yml

* Update docker-compose.yml

* Update e2e.yml

* Update tests

* Update e2e.yml

* Update env

* Updates
  • Loading branch information
mikhail-vl authored Oct 9, 2024
1 parent 54e08f9 commit 543d68a
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 5 deletions.
54 changes: 54 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: E2E

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

jobs:
tests:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Start Grafana
run: docker compose up -d grafana

- name: Wait Grafana Started
run: sleep 5

- name: Create Engine Service Account
id: serviceAccount
run: |
source ./test/generate-token.sh
echo "grafana-token=${GRAFANA_TOKEN}" >> $GITHUB_OUTPUT
- name: Insert env variables
run: echo "GRAFANA_TOKEN=${{ steps.serviceAccount.outputs.grafana-token }}" >> .env

- name: Start Platform
run: docker compose up -d

- name: Run e2e tests
run: cp .env test && docker compose -f test/docker-compose.yml build && docker compose -f test/docker-compose.yml up --exit-code-from test

- name: Stop Platform
run: docker compose down

- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: test/playwright-report/
retention-days: 30
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
### Features / Enhancements

- Updated Business Intelligence 1.8.0 (#18)
- Updated Business Intelligence 2.0.0 (#12)
- Updated Business Intelligence 2.0.0 (#19)
- Add E2E workflow (#20)
- [Manager] Removed create annotations metric and replace calculation to execution (#131)
- [Manager] Added evaluation apply mode (#132)
- [Manager] Added percentage of values evaluation (#133)
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Business Intelligence

![Grafana](https://img.shields.io/badge/Grafana-11.2-orange)
![E2E](https://github.com/volkovlabs/business-intelligence/workflows/E2E/badge.svg)

## Introduction

The Business Intelligence provides an accessible platform for business users.
Expand All @@ -14,7 +17,7 @@ The Business Intelligence provides an accessible platform for business users.
## Highlights

- Manage alerts based on panel queries with thresholds with Business Alerting
- High performance Business Engine with HA support
- High performance Business Engine with HA

## Includes

Expand Down
3 changes: 0 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ services:
ports:
- 3000:3000
volumes:
- ./grafana:/var/lib/grafana
- ./volkovlabs-manager-app:/var/lib/grafana/plugins/volkovlabs-manager-app
- ./provisioning:/etc/grafana/provisioning

Expand All @@ -16,8 +15,6 @@ services:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
volumes:
- ./database:/var/lib/postgresql/data

engine:
depends_on:
Expand Down
Binary file modified img/unscripted-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions test/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Get the latest version of Playwright
FROM mcr.microsoft.com/playwright:focal

# Set the work directory for the application
WORKDIR app

# COPY the needed files to the app folder in Docker image
COPY playwright.config.ts .

# Install the dependencies in Node environment
RUN npm install @grafana/plugin-e2e

# Install browsers
RUN npx playwright install --with-deps chromium

# Run tests
CMD ["npx", "playwright", "test"]
8 changes: 8 additions & 0 deletions test/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
test:
build:
context: .
env_file: .env
volumes:
- ./playwright-report:/app/playwright-report
network_mode: host
21 changes: 21 additions & 0 deletions test/general.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { test, expect } from "@grafana/plugin-e2e";
import { EngineServerHelper } from "./utils";

test.describe("General", () => {
test("Check grafana version", async ({ grafanaVersion }) => {
console.log("Grafana version: ", grafanaVersion);
expect(grafanaVersion).toEqual(grafanaVersion);
});

test("Check engine health", async () => {
const engine = new EngineServerHelper();

await engine.checkHealth();
});

test("Check engine has access to grafana dashboard", async () => {
const engine = new EngineServerHelper();

await engine.checkDashboardAccess("bd0aabe4-3d2d-4d2e-a34d-d6260b06e10b");
});
});
19 changes: 19 additions & 0 deletions test/generate-token.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

# Generate a new token
serviceAccount=$(curl -s -X POST -H "Content-Type: application/json" -d '{"name": "business-engine", "role": "Editor"}' http://admin:admin@localhost:3000/api/serviceaccounts)

echo "Service Account: $serviceAccount"

serviceAccountId=$(echo "$serviceAccount" | jq '.id')

echo "Request: http://admin:admin@localhost:3000/api/serviceaccounts/${serviceAccountId}/tokens"

# create the service account token with the service account id 1 - /serviceaccounts/{id} returned from the previous step
token=$(curl -s -X POST -H "Content-Type: application/json" -d '{"name": "engine"}' http://admin:admin@localhost:3000/api/serviceaccounts/${serviceAccountId}/tokens)

echo "Token: $token"

export GRAFANA_TOKEN=$(echo "$token" | jq '.key')
exec "$@"

73 changes: 73 additions & 0 deletions test/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { dirname } from "path";
import { defineConfig, devices } from "@playwright/test";

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

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
/**
* Directory with tests
*/
testDir: "./",

/**
* Run tests in files in parallel
*/
fullyParallel: true,

/**
* Number of retry.
*/
retries: 6,

/**
* Number of workers.
*/
workers: 1,

/**
* Reporter to use. See https://playwright.dev/docs/test-reporters
*/
reporter: [["html", { open: "never" }]],

/**
* 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: process.env.E2E_GRAFANA_URL || "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: "auth",
testDir: pluginE2eAuth,
testMatch: [/.*\.js/],
},
{
name: "run-tests",
use: {
...devices["Desktop Chrome"],

/**
* @grafana/plugin-e2e writes the auth state to this file,
* the path should not be modified
*/
storageState: "playwright/.auth/admin.json",
},
dependencies: ["auth"],
},
],
});
1 change: 1 addition & 0 deletions test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './server';
57 changes: 57 additions & 0 deletions test/utils/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { expect, request } from "@playwright/test";

/**
* Engine Server Helper
*/
export class EngineServerHelper {
private readonly url = process.env.E2E_ENGINE_URL || "http://localhost:3001";
private readonly token = process.env.ENGINE_TOKEN;

/**
* Request
*/
private async request<TResult>(
path: string,
options?: RequestInit
): Promise<TResult> {
try {
const context = await request.newContext({
baseURL: this.url,
});

const response = await context.fetch(`${this.url}${path}`, {
...options,
headers: {
Authorization: `Bearer ${this.token}`,
},
});

return (await response.json()) as TResult;
} catch (error) {
console.error("Request Error", error);
throw error;
}
}

/**
* Check Health
*/
public async checkHealth() {
const result = await this.request<{ message: "string" }>("/health");

return expect(result).toEqual({
message: "pong",
});
}

/**
* Check dashboard access
*/
public async checkDashboardAccess(id: string) {
const result = await this.request<{ uid: "string" }>(
`/grafana/dashboards/uid/${id}`
);

return expect(result.uid).toEqual(id);
}
}

0 comments on commit 543d68a

Please sign in to comment.