Skip to content

Commit

Permalink
Add k6-gleam plugin
Browse files Browse the repository at this point in the history
Signed-off-by: Thanabodee Charoenpiriyakij <[email protected]>
  • Loading branch information
wingyplus committed May 13, 2024
1 parent f67af89 commit fa56e22
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 21 deletions.
4 changes: 0 additions & 4 deletions examples/basic_k6/runner.mjs

This file was deleted.

17 changes: 0 additions & 17 deletions src/k6/build.gleam

This file was deleted.

1 change: 1 addition & 0 deletions xk6-gleam/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/k6
52 changes: 52 additions & 0 deletions xk6-gleam/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module github.com/tsloughter/k6_gleam/k6-gleam

go 1.22.2

require (
github.com/BurntSushi/toml v1.3.2
github.com/grafana/k6pack v0.1.5
go.k6.io/k6 v0.51.0
)

require (
github.com/evanw/esbuild v0.20.2 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.33.1 // indirect
)

require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/dlclark/regexp2 v1.9.0 // indirect
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mstoykov/atlas v0.0.0-20220811071828-388f114305dd // indirect
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e // indirect
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.1.2 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/guregu/null.v3 v3.3.0 // indirect
)
224 changes: 224 additions & 0 deletions xk6-gleam/go.sum

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions xk6-gleam/internal/gleam/gleam.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package gleam

import (
"os"
"os/exec"
"path/filepath"

"github.com/BurntSushi/toml"
)

// Build run build command.
func Build() error {
// Ensure always build with js target.
cmd := exec.Command("gleam", "build", "--target", "javascript")
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
return cmd.Run()
}

// ProjectName returns a project name defined in `gleam.toml`.
func ProjectName(cwd string) (string, error) {
tm, err := os.ReadFile(filepath.Join(cwd, "gleam.toml"))
if err != nil {
return "", err
}

gleamToml := struct {
Name string `toml:"name"`
}{}
if err := toml.Unmarshal(tm, &gleamToml); err != nil {
return "", err
}

return gleamToml.Name, nil
}
119 changes: 119 additions & 0 deletions xk6-gleam/loader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package k6_gleam

import (
"os"
"path/filepath"
"strings"

"github.com/grafana/k6pack"
"github.com/sirupsen/logrus"
"github.com/tsloughter/k6_gleam/k6-gleam/internal/gleam"
)

func init() {
redirectStdin()
}

// Copied from https://github.com/grafana/xk6-ts/blob/master/loader.go#L17
func isRunCommand(args []string) (bool, int) {
argn := len(args)

scriptIndex := argn - 1
if scriptIndex < 0 {
return false, scriptIndex
}

var runIndex int

for idx := 0; idx < argn; idx++ {
arg := args[idx]
if arg == "run" && runIndex == 0 {
runIndex = idx

break
}
}

if runIndex == 0 {
return false, -1
}

return true, scriptIndex
}

// Uses script from `run` sub-command and transpile gleam into js and load it back
// to `k6` using stdin option.
func redirectStdin() {
isRun, scriptIndex := isRunCommand(os.Args)
if !isRun {
return
}

// TODO: detect .gleam extension.
filename := os.Args[scriptIndex]

logrus.Infof("Get script named %s", filename)
logrus.Info("Build a gleam project...")

if err := gleam.Build(); err != nil {
logrus.WithError(err).Fatal()
}

cwd, err := os.Getwd()
if err != nil {
logrus.WithError(err).Fatal()
}

logrus.Info("Bundling...")

filename, contents, err := jsBuildFile(cwd, filename)
if err != nil {
logrus.WithError(err).Fatal()
}

opts := k6pack.Options{
Filename: filename,
SourceRoot: cwd,
}

jsScript, err := k6pack.Pack(string(addRuntime(contents)), &opts)
if err != nil {
logrus.WithError(err).Fatal()
}

os.Args[scriptIndex] = "-"

reader, writer, err := os.Pipe()
if err != nil {
logrus.WithError(err).Fatal()
}

os.Stdin = reader

go func() {
_, werr := writer.Write(jsScript)
writer.Close()

if err != nil {
logrus.WithError(werr).Fatal("stdin redirect failed")
}
}()
}

func addRuntime(source []byte) []byte {
runtime := "\nexport default main;\n"
return append(source, []byte(runtime)...)
}

// Convert gleam input filename into javascript file path.
func jsBuildFile(cwd, gleamFilename string) (filename string, contents []byte, err error) {
filename = filepath.Base(gleamFilename)
projName, err := gleam.ProjectName(cwd)
if err != nil {
return "", nil, err
}
// TODO: support more than dev?
filename = filepath.Join(cwd, "build", "dev", "javascript", projName, strings.TrimRight(filename, ".gleam")+".mjs")
contents, err = os.ReadFile(filename)
return
}
9 changes: 9 additions & 0 deletions xk6-gleam/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package k6_gleam

import "go.k6.io/k6/js/modules"

type extension struct{}

func init() {
modules.Register("k6/x/gleam", extension{})
}

0 comments on commit fa56e22

Please sign in to comment.