working dagger
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { test, expect } from '@grafana/plugin-e2e';
|
||||
|
||||
test(
|
||||
'Scenario test: Can login successfully',
|
||||
'Scenario test: Can actually login successfully',
|
||||
{
|
||||
tag: ['@scenarios'],
|
||||
},
|
||||
|
||||
@@ -20,4 +20,13 @@ else
|
||||
./scripts/grafana-server/wait-for-grafana
|
||||
fi
|
||||
|
||||
PORT=3001 HOST=localhost yarn playwright test
|
||||
# Wait for health endpoint to be ready
|
||||
echo "Waiting for Grafana health endpoint..."
|
||||
while ! curl -s "http://localhost:3001/api/health" > /dev/null; do
|
||||
sleep 1
|
||||
done
|
||||
echo "Grafana health endpoint is ready"
|
||||
|
||||
|
||||
# PORT=3001 HOST=localhost yarn playwright test
|
||||
PORT=3001 HOST=localhost yarn playwright test --grep @panels
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
type Deps struct {
|
||||
NodeVersion string
|
||||
PlaywrightVersion string
|
||||
}
|
||||
|
||||
func GetVersions(ctx context.Context, src *dagger.Directory) (Deps, error) {
|
||||
nvmrc, err := src.File(".nvmrc").Contents(ctx)
|
||||
if err != nil {
|
||||
return Deps{}, err
|
||||
}
|
||||
pkgJSON, err := src.File("package.json").Contents(ctx)
|
||||
if err != nil {
|
||||
return Deps{}, err
|
||||
}
|
||||
|
||||
// parse JSON in-Go, no jq needed
|
||||
var pkg struct {
|
||||
DevDependencies map[string]string `json:"devDependencies"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(pkgJSON), &pkg); err != nil {
|
||||
return Deps{}, err
|
||||
}
|
||||
|
||||
return Deps{
|
||||
NodeVersion: strings.TrimSpace(strings.TrimPrefix(nvmrc, "v")),
|
||||
PlaywrightVersion: strings.TrimSpace(pkg.DevDependencies["@playwright/test"]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func RunTest(
|
||||
ctx context.Context,
|
||||
d *dagger.Client,
|
||||
grafanaService *dagger.Service,
|
||||
) (*dagger.Container, error) {
|
||||
|
||||
grafanaDir := "." // TODO: arg
|
||||
|
||||
nxCache := d.CacheVolume("nx-cache")
|
||||
|
||||
// Minimal files needed to run yarn install
|
||||
yarnHostSrc := d.Host().Directory(grafanaDir, dagger.HostDirectoryOpts{
|
||||
Include: []string{
|
||||
"package.json",
|
||||
"yarn.lock",
|
||||
".yarnrc.yml",
|
||||
".yarn",
|
||||
"packages/*/package.json",
|
||||
"public/app/plugins/*/*/package.json",
|
||||
"e2e/test-plugins/*/package.json",
|
||||
".nvmrc",
|
||||
},
|
||||
})
|
||||
|
||||
// Files needed to run e2e tests. Above files will be copied into the test runner container as well.
|
||||
e2eHostSrc := d.Host().Directory(".", dagger.HostDirectoryOpts{
|
||||
Include: []string{
|
||||
"public/app/types/*.d.ts",
|
||||
"public/app/core/icons/cached.json",
|
||||
|
||||
// packages we use in playwright tests
|
||||
"packages", // TODO: do we need all of this?
|
||||
"e2e/test-plugins",
|
||||
"public/app/plugins", // TODO: do we need all of this?
|
||||
|
||||
// e2e files
|
||||
"e2e-playwright",
|
||||
"playwright.config.ts",
|
||||
},
|
||||
Exclude: []string{
|
||||
"**/dist",
|
||||
},
|
||||
})
|
||||
|
||||
deps, err := GetVersions(ctx, yarnHostSrc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeBase := WithNode(d, deps.NodeVersion)
|
||||
playwrightBase := WithPlaywright(d, nodeBase, deps.PlaywrightVersion)
|
||||
|
||||
e2eContainer := WithYarnInstall(d, playwrightBase, yarnHostSrc).
|
||||
WithWorkdir("/src").
|
||||
WithDirectory("/src", e2eHostSrc).
|
||||
WithMountedCache(".nx", nxCache).
|
||||
WithExec([]string{"yarn", "e2e:plugin:build"}).
|
||||
WithEnvVariable("HOST", grafanaHost).
|
||||
WithEnvVariable("PORT", fmt.Sprint(grafanaPort)).
|
||||
WithServiceBinding(grafanaHost, grafanaService).
|
||||
WithEnvVariable("PLAYWRIGHT_HTML_OPEN", "never").
|
||||
WithExec([]string{"yarn", "e2e:playwright"}, dagger.ContainerWithExecOpts{
|
||||
Expect: dagger.ReturnTypeAny,
|
||||
})
|
||||
|
||||
// TODO: wrap in conditional arg
|
||||
_, err = e2eContainer.Directory("/src/playwright-report").Export(ctx, "./dist/playwright-report")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = e2eContainer.Directory("/src/test-results").Export(ctx, "./dist/test-results")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e2eContainer, nil
|
||||
}
|
||||
|
||||
func WithNode(d *dagger.Client, version string) *dagger.Container {
|
||||
nodeImage := fmt.Sprintf("node:%s-slim", strings.TrimPrefix(version, "v"))
|
||||
return d.Container().From(nodeImage)
|
||||
}
|
||||
|
||||
func WithPlaywright(d *dagger.Client, base *dagger.Container, version string) *dagger.Container {
|
||||
brCache := d.CacheVolume("playwright-browsers")
|
||||
return base.
|
||||
WithEnvVariable("PLAYWRIGHT_BROWSERS_PATH", "/playwright-cache").
|
||||
WithMountedCache("/playwright-cache", brCache).
|
||||
WithExec([]string{"npx", "-y", "playwright@" + version, "install", "--with-deps"})
|
||||
}
|
||||
|
||||
func WithYarnInstall(d *dagger.Client, base *dagger.Container, yarnHostSrc *dagger.Directory) *dagger.Container {
|
||||
yarnCache := d.CacheVolume("yarn-cache")
|
||||
|
||||
return base.
|
||||
WithWorkdir("/src").
|
||||
WithMountedCache("/.yarn", yarnCache).
|
||||
WithEnvVariable("YARN_CACHE_FOLDER", "/.yarn").
|
||||
|
||||
// It's important to copy all files here because the whole src directory is then copied into the test runner container
|
||||
WithDirectory("/src", yarnHostSrc).
|
||||
WithExec([]string{"corepack", "enable"}).
|
||||
WithExec([]string{"corepack", "install"}).
|
||||
WithExec([]string{"yarn", "install", "--immutable"})
|
||||
}
|
||||
@@ -118,26 +118,26 @@ func run(ctx context.Context, cmd *cli.Command) error {
|
||||
|
||||
c, runErr := RunTest(ctx, d, svc)
|
||||
if runErr != nil {
|
||||
return fmt.Errorf("failed to run a11y test suite: %w", runErr)
|
||||
return fmt.Errorf("failed to run e2e test suite: %w", runErr)
|
||||
}
|
||||
|
||||
c, syncErr := c.Sync(ctx)
|
||||
if syncErr != nil {
|
||||
return fmt.Errorf("failed to sync a11y test suite: %w", syncErr)
|
||||
return fmt.Errorf("failed to sync e2e test suite: %w", syncErr)
|
||||
}
|
||||
|
||||
code, codeErr := c.ExitCode(ctx)
|
||||
if codeErr != nil {
|
||||
return fmt.Errorf("failed to get exit code of a11y test suite: %w", codeErr)
|
||||
return fmt.Errorf("failed to get exit code of e2e test suite: %w", codeErr)
|
||||
}
|
||||
|
||||
if code == 0 {
|
||||
log.Printf("a11y tests passed with exit code %d", code)
|
||||
log.Printf("e2e tests passed with exit code %d", code)
|
||||
} else {
|
||||
return fmt.Errorf("a11y tests failed with exit code %d", code)
|
||||
return fmt.Errorf("e2e tests failed with exit code %d", code)
|
||||
}
|
||||
|
||||
log.Println("a11y tests completed successfully")
|
||||
log.Println("e2e tests completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// NodeVersionContainer returns a container whose `stdout` will return the node version from the '.nvmrc' file in the directory 'src'.
|
||||
func NodeVersion(d *dagger.Client, src *dagger.File) *dagger.Container {
|
||||
return d.Container().From("alpine:3").
|
||||
WithMountedFile("/src/.nvmrc", src).
|
||||
WithWorkdir("/src").
|
||||
WithExec([]string{"cat", ".nvmrc"})
|
||||
}
|
||||
|
||||
func NodeImage(version string) string {
|
||||
return fmt.Sprintf("node:%s-slim", strings.TrimPrefix(strings.TrimSpace(version), "v"))
|
||||
}
|
||||
|
||||
func RunTest(
|
||||
ctx context.Context,
|
||||
d *dagger.Client,
|
||||
grafanaService *dagger.Service,
|
||||
) (*dagger.Container, error) {
|
||||
|
||||
// Explicitly only the files u'sed by e2e tests
|
||||
hostSrc := d.Host().Directory(".", dagger.HostDirectoryOpts{
|
||||
Include: []string{
|
||||
// Include all files for a valid yarn workspace install
|
||||
"package.json",
|
||||
"yarn.lock",
|
||||
".yarnrc.yml",
|
||||
".yarn",
|
||||
"packages/*/package.json",
|
||||
"public/app/plugins/*/*/package.json",
|
||||
"e2e/test-plugins/*/package.json",
|
||||
".nvmrc",
|
||||
"public/app/types/*.d.ts",
|
||||
|
||||
// packages we use in playwright tests
|
||||
"packages",
|
||||
|
||||
// e2e files
|
||||
"e2e-playwright",
|
||||
},
|
||||
Exclude: []string{
|
||||
"packages/*/dist",
|
||||
},
|
||||
})
|
||||
|
||||
nodeVersion, err := NodeVersion(d, hostSrc.File(".nvmrc")).Stdout(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
yarnCache := d.CacheVolume("yarn-cache")
|
||||
yarnCacheDir := "/yarn-cache"
|
||||
|
||||
pa11yContainer := d.Container().From(NodeImage(nodeVersion)).
|
||||
WithExec([]string{"npx", "-y", "playwright@1.52.0", "install", "--with-deps"}). // TODO: sync version from package.json
|
||||
WithWorkdir("/src").
|
||||
WithDirectory("/src", hostSrc).
|
||||
WithMountedCache(yarnCacheDir, yarnCache).
|
||||
WithExec([]string{"corepack", "enable"}).
|
||||
WithExec([]string{"corepack", "install"}).
|
||||
WithEnvVariable("YARN_CACHE_FOLDER", yarnCacheDir).
|
||||
WithExec([]string{"yarn", "config", "get", "cacheFolder"}).
|
||||
WithExec([]string{"yarn", "install", "--immutable"}).
|
||||
// WithExec([]string{"yarn", "e2e:plugin:build"}).
|
||||
WithEnvVariable("HOST", grafanaHost).
|
||||
WithEnvVariable("PORT", fmt.Sprint(grafanaPort)).
|
||||
WithExec([]string{"yarn", "packages:build"}).
|
||||
WithExec([]string{"yarn", "e2e:playwright"})
|
||||
|
||||
return pa11yContainer, nil
|
||||
}
|
||||
@@ -12,7 +12,10 @@ export default defineConfig<PluginOptions>({
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: 'html',
|
||||
reporter: [
|
||||
['list'], // for terminal
|
||||
['html'], // pretty
|
||||
],
|
||||
use: {
|
||||
baseURL: `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}`,
|
||||
trace: 'retain-on-failure',
|
||||
|
||||
Reference in New Issue
Block a user