The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/build/e2e/main.go

174 lines
4.0 KiB

package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"path"
"dagger.io/dagger"
"github.com/urfave/cli/v3"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
if err := NewApp().Run(ctx, os.Args); err != nil {
cancel()
fmt.Println(err)
os.Exit(1)
}
}
func NewApp() *cli.Command {
return &cli.Command{
Name: "e2e",
Usage: "Run the E2E tests for Grafana",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "suite",
Usage: "E2E test suite path (e.g. e2e/various-suite)",
Validator: mustBeDir("suite"),
TakesFile: true,
Required: true,
},
&cli.StringFlag{
Name: "grafana-dir",
Usage: "Path to the grafana/grafana clone directory",
Value: ".",
Validator: mustBeDir("grafana-dir"),
TakesFile: true,
},
&cli.StringFlag{
Name: "package",
Usage: "Path to the grafana tar.gz package",
Value: "grafana.tar.gz",
Validator: mustBeFile("package", false),
TakesFile: true,
},
&cli.StringFlag{
Name: "license",
Usage: "Path to the Grafana Enterprise license file (optional)",
Validator: mustBeFile("license", true),
TakesFile: true,
},
&cli.StringFlag{
Name: "flags",
Usage: "Flags to pass through to the e2e runner",
},
&cli.BoolFlag{
Name: "image-renderer",
Usage: "Install the image renderer plugin",
Value: false,
},
},
Action: run,
}
}
func run(ctx context.Context, cmd *cli.Command) error {
grafanaDir := cmd.String("grafana-dir")
suite := cmd.String("suite")
targzPath := cmd.String("package")
licensePath := cmd.String("license")
imageRenderer := cmd.Bool("image-renderer")
runnerFlags := cmd.String("flags")
d, err := dagger.Connect(ctx)
if err != nil {
return fmt.Errorf("failed to connect to Dagger: %w", err)
}
yarnCache := d.CacheVolume("yarn")
log.Println("grafana dir:", grafanaDir)
log.Println("targz:", targzPath)
log.Println("license path:", licensePath)
grafana := d.Host().Directory(".", dagger.HostDirectoryOpts{
Exclude: []string{"node_modules", "*.tar.gz"},
})
targz := d.Host().File(targzPath)
var license *dagger.File
if licensePath != "" {
license = d.Host().File(licensePath)
}
svc, err := GrafanaService(ctx, d, GrafanaServiceOpts{
GrafanaDir: grafana,
GrafanaTarGz: targz,
YarnCache: yarnCache,
License: license,
InstallImageRenderer: imageRenderer,
})
if err != nil {
return fmt.Errorf("failed to create Grafana service: %w", err)
}
videosDir := path.Join("/src", suite, "videos")
// *spec.ts.mp4
c := RunSuite(d, svc, grafana, yarnCache, suite, runnerFlags)
c, err = c.Sync(ctx)
if err != nil {
return fmt.Errorf("failed to run e2e test suite: %w", err)
}
code, err := c.ExitCode(ctx)
if err != nil {
return fmt.Errorf("failed to get exit code of e2e test suite: %w", err)
}
log.Println("exit code:", code)
// No sync error; export the videos dir
if _, err := c.Directory(videosDir).Export(ctx, "videos"); err != nil {
return fmt.Errorf("failed to export videos directory: %w", err)
}
if code != 0 {
return fmt.Errorf("e2e tests failed with exit code %d", code)
}
log.Println("e2e tests completed successfully")
return nil
}
func mustBeFile(arg string, emptyOk bool) func(string) error {
return func(s string) error {
if s == "" {
if emptyOk {
return nil
}
return cli.Exit(arg+" cannot be empty", 1)
}
stat, err := os.Stat(s)
if err != nil {
return cli.Exit(arg+" does not exist or cannot be read: "+s, 1)
}
if stat.IsDir() {
return cli.Exit(arg+" must be a file, not a directory: "+s, 1)
}
return nil
}
}
func mustBeDir(arg string) func(string) error {
return func(s string) error {
if s == "" {
return cli.Exit(arg+" cannot be empty", 1)
}
stat, err := os.Stat(s)
if err != nil {
return cli.Exit(arg+" does not exist or cannot be read: "+s, 1)
}
if !stat.IsDir() {
return cli.Exit(arg+" must be a directory: "+s, 1)
}
return nil
}
}