CI: Move e2e test pipeline from Drone to GitHub Actions (#103134)

* Add e2e dagger pipeline

* various-suite not various suite

* upload videos dir

* produce e2e videos even on failure

* nil ref

* sync doesn't return container

* fix quotes

* try without flags first?

* try without quoting?

* use two dashes in flags

* update CODEOWNERS

* make update-workspace

* go work sync

* make update-workspace

* add newline
This commit is contained in:
Kevin Minehart
2025-04-02 13:31:47 -05:00
committed by GitHub
parent 0e1cb44ad9
commit 88d54892bd
55 changed files with 815 additions and 541 deletions
+72
View File
@@ -0,0 +1,72 @@
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"dagger.io/dagger"
)
func main() {
var (
ctx = context.Background()
grafanaPath = flag.String("grafana-dir", ".", "Path to cloned grafana repo")
targzPath = flag.String("package", "grafana.tar.gz", "Path to grafana tar.gz package")
suite = flag.String("suite", "", "e2e suite name (used in arg to run-suite script)")
)
flag.Parse()
d, err := dagger.Connect(ctx)
if err != nil {
panic(err)
}
yarnCache := d.CacheVolume("yarn")
log.Println("grafana dir:", *grafanaPath)
log.Println("targz:", *targzPath)
grafana := d.Host().Directory(".", dagger.HostDirectoryOpts{
Exclude: []string{".git", "node_modules", "*.tar.gz"},
})
targz := d.Host().File("grafana.tar.gz")
svc, err := GrafanaService(ctx, d, GrafanaServiceOpts{
GrafanaDir: grafana,
GrafanaTarGz: targz,
YarnCache: yarnCache,
})
if err != nil {
panic(err)
}
videosDir := fmt.Sprintf("/src/e2e/%s/videos", *suite)
// *spec.ts.mp4
c := RunSuite(d, svc, grafana, yarnCache, *suite)
c, err = c.Sync(ctx)
if err != nil {
log.Fatalf("error running dagger: %s", err)
}
code, err := c.ExitCode(ctx)
if err != nil {
log.Fatalf("error getting exit code: %s", err)
}
log.Println("exit code:", code)
// No sync error; export the videos dir
if _, err := c.Directory(videosDir).Export(ctx, "videos"); err != nil {
log.Fatalf("error getting videos: %s", err)
}
if code != 0 {
log.Printf("tests failed: exit code %d", code)
}
os.Exit(code)
}
+22
View File
@@ -0,0 +1,22 @@
package main
import (
"fmt"
"dagger.io/dagger"
)
func RunSuite(d *dagger.Client, svc *dagger.Service, src *dagger.Directory, cache *dagger.CacheVolume, suite string) *dagger.Container {
return WithYarnCache(WithGrafanaFrontend(d.Container().From("cypress/included:13.1.0"), src), cache).
WithWorkdir("/src").
WithEnvVariable("HOST", "grafana").
WithEnvVariable("PORT", "3001").
WithServiceBinding("grafana", svc).
WithExec([]string{"yarn", "install", "--immutable"}).
WithExec([]string{
"/bin/bash", "-c",
fmt.Sprintf("./e2e/run-suite %s true", suite),
}, dagger.ContainerWithExecOpts{
Expect: dagger.ReturnTypeAny,
})
}
+91
View File
@@ -0,0 +1,91 @@
package main
import (
"context"
"fmt"
"log"
"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"))
}
type GrafanaServiceOpts struct {
GrafanaDir *dagger.Directory
GrafanaTarGz *dagger.File
YarnCache *dagger.CacheVolume
}
func Frontend(src *dagger.Directory) *dagger.Directory {
return src.
WithoutFile("go.mod").
WithoutFile("go.sum").
WithoutFile("go.work").
WithoutFile("go.work.sum").
WithoutDirectory(".github").
WithoutDirectory("docs").
WithoutDirectory("pkg").
WithoutDirectory("apps").
WithoutDirectory("videos")
}
func WithGrafanaFrontend(c *dagger.Container, src *dagger.Directory) *dagger.Container {
return c.WithDirectory("/src", Frontend(src), dagger.ContainerWithDirectoryOpts{
Exclude: []string{
"*drone*",
"*.go",
"*.md",
},
})
}
func WithYarnCache(c *dagger.Container, cache *dagger.CacheVolume) *dagger.Container {
return c.
WithWorkdir("/src").
WithMountedCache("/yarn/cache", cache)
}
func GrafanaService(ctx context.Context, d *dagger.Client, opts GrafanaServiceOpts) (*dagger.Service, error) {
log.Println("getting node version")
nodeVersion, err := NodeVersion(d, opts.GrafanaDir.File(".nvmrc")).Stdout(ctx)
if err != nil {
return nil, err
}
log.Println("done getting node version")
src := WithYarnCache(
WithGrafanaFrontend(d.Container().From(NodeImage(nodeVersion)), opts.GrafanaDir),
opts.YarnCache,
).WithEnvVariable("YARN_CACHE_FOLDER", "/yarn/cache").
WithExec([]string{"yarn", "install", "--immutable"}).
WithExec([]string{"yarn", "e2e:plugin:build"})
svc := d.Container().From("alpine").
WithExec([]string{"apk", "add", "bash"}).
WithMountedFile("/src/grafana.tar.gz", opts.GrafanaTarGz).
WithExec([]string{"mkdir", "-p", "/src/grafana"}).
WithExec([]string{"tar", "--strip-components=1", "-xzf", "/src/grafana.tar.gz", "-C", "/src/grafana"}).
WithDirectory("/src/grafana/devenv", src.Directory("/src/devenv")).
WithDirectory("/src/grafana/e2e", src.Directory("/src/e2e")).
WithDirectory("/src/grafana/scripts", src.Directory("/src/scripts")).
WithDirectory("/src/grafana/tools", src.Directory("/src/tools")).
WithWorkdir("/src/grafana").
WithEnvVariable("GF_APP_MODE", "development").
WithEnvVariable("GF_SERVER_HTTP_PORT", "3001").
WithEnvVariable("GF_SERVER_ROUTER_LOGGING", "1").
WithExposedPort(3001).
AsService(dagger.ContainerAsServiceOpts{Args: []string{"bash", "-x", "scripts/grafana-server/start-server"}})
return svc, nil
}