From d2217b57a7e66df780a4a8223d3dc071c873527b Mon Sep 17 00:00:00 2001 From: pablochacin Date: Mon, 20 Jan 2025 10:07:06 +0100 Subject: [PATCH] Mock k6foundry (#110) * make k6foundry configurable * mock foundry in tests Signed-off-by: Pablo Chacin --- .golangci.yml | 1 + .goreleaser.yaml | 98 +++++++++++++++++++++++ pkg/builder/builder.go | 22 +++++- pkg/builder/builder_test.go | 99 ++++++++++-------------- pkg/builder/testdata/catalog.json | 5 -- pkg/builder/testdata/deps/k6/cmd/k6.go | 4 - pkg/builder/testdata/deps/k6/go.mod | 3 - pkg/builder/testdata/deps/k6ext/go.mod | 3 - pkg/builder/testdata/deps/k6ext/main.go | 1 - pkg/builder/testdata/deps/k6ext2/go.mod | 3 - pkg/builder/testdata/deps/k6ext2/main.go | 1 - pkg/server/server_test.go | 2 - 12 files changed, 162 insertions(+), 80 deletions(-) create mode 100644 .goreleaser.yaml delete mode 100644 pkg/builder/testdata/catalog.json delete mode 100644 pkg/builder/testdata/deps/k6/cmd/k6.go delete mode 100644 pkg/builder/testdata/deps/k6/go.mod delete mode 100644 pkg/builder/testdata/deps/k6ext/go.mod delete mode 100644 pkg/builder/testdata/deps/k6ext/main.go delete mode 100644 pkg/builder/testdata/deps/k6ext2/go.mod delete mode 100644 pkg/builder/testdata/deps/k6ext2/main.go diff --git a/.golangci.yml b/.golangci.yml index 991b2de..bb0eb1e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -27,6 +27,7 @@ issues: - gosec - noctx - gochecknoglobals + - revive - path: js\/modules\/k6\/http\/.*_test\.go linters: # k6/http module's tests are quite complex because they often have several nested levels. diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..6108f7c --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,98 @@ +project_name: k6build +version: 2 +env: + - IMAGE_OWNER=ghcr.io/grafana +before: + hooks: + - go mod tidy +builds: + - env: + - CGO_ENABLED=0 + goos: ["darwin", "linux", "windows"] + goarch: ["amd64", "arm64"] + ldflags: + - "-s -w -X main.version={{.Version}} -X main.appname={{.ProjectName}}" + dir: cmd/k6build +source: + enabled: true + name_template: "{{ .ProjectName }}_{{ .Version }}_source" + +archives: + - id: bundle + format: tar.gz + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt" + +snapshot: + name_template: "{{ incpatch .Version }}-next+{{.ShortCommit}}{{if .IsGitDirty}}.dirty{{else}}{{end}}" + +changelog: + sort: asc + abbrev: -1 + filters: + exclude: + - "^chore:" + - "^docs:" + - "^test:" + +dockers: + - id: amd64 + dockerfile: Dockerfile.goreleaser + use: buildx + image_templates: + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:latest-amd64" + + build_flag_templates: + - "--platform=linux/amd64" + - "--pull" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.licenses=AGPL-3.0-only" + - id: arm64 + dockerfile: Dockerfile.goreleaser + use: buildx + image_templates: + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-arm64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}-arm64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:latest-arm64" + + build_flag_templates: + - "--platform=linux/arm64" + - "--pull" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.licenses=AGPL-3.0-only" + +docker_manifests: + - id: tag + name_template: "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:{{ .Tag }}" + image_templates: + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-arm64" + - id: major + name_template: "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}" + image_templates: + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}-arm64" + - id: major-minor + name_template: "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}" + image_templates: + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64" + - id: latest + name_template: "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:latest" + image_templates: + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:latest-amd64" + - "{{ .Env.IMAGE_OWNER }}/{{ .ProjectName }}:latest-arm64" diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index f652a04..669a49d 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -40,6 +40,19 @@ var ( // GoOpts defines the options for the go build environment type GoOpts = k6foundry.GoOpts +// Foundry is a function that creates a Foundry Builder +type Foundry interface { + NewBuilder(ctx context.Context, opts k6foundry.NativeBuilderOpts) (k6foundry.Builder, error) +} + +// FoundryFunction defines a function that implements the Foundry interface +type FoundryFunction func(context.Context, k6foundry.NativeBuilderOpts) (k6foundry.Builder, error) + +// NewBuilder implements the Foundry interface +func (f FoundryFunction) NewBuilder(ctx context.Context, opts k6foundry.NativeBuilderOpts) (k6foundry.Builder, error) { + return f(ctx, opts) +} + // Opts defines the options for configuring the builder type Opts struct { // Allow semvers with build metadata @@ -55,6 +68,7 @@ type Config struct { Opts Opts Catalog catalog.Catalog Store store.ObjectStore + Foundry Foundry } // Builder implements the BuildService interface @@ -63,6 +77,7 @@ type Builder struct { catalog catalog.Catalog store store.ObjectStore mutexes sync.Map + foundry Foundry } // New returns a new instance of Builder given a BuilderConfig @@ -75,10 +90,15 @@ func New(_ context.Context, config Config) (*Builder, error) { return nil, k6build.NewWrappedError(ErrInitializingBuilder, errors.New("store cannot be nil")) } + foundry := config.Foundry + if foundry == nil { + foundry = FoundryFunction(k6foundry.NewNativeBuilder) + } return &Builder{ catalog: config.Catalog, opts: config.Opts, store: config.Store, + foundry: foundry, }, nil } @@ -180,7 +200,7 @@ func (b *Builder) Build( //nolint:funlen builderOpts.Stderr = os.Stderr } - builder, err := k6foundry.NewNativeBuilder(ctx, builderOpts) + builder, err := b.foundry.NewBuilder(ctx, builderOpts) if err != nil { return k6build.Artifact{}, k6build.NewWrappedError(ErrInitializingBuilder, err) } diff --git a/pkg/builder/builder_test.go b/pkg/builder/builder_test.go index 37def33..381d981 100644 --- a/pkg/builder/builder_test.go +++ b/pkg/builder/builder_test.go @@ -4,7 +4,8 @@ import ( "context" "errors" "fmt" - "net/http/httptest" + "io" + "strings" "sync" "testing" @@ -12,7 +13,6 @@ import ( "github.com/grafana/k6build/pkg/catalog" "github.com/grafana/k6build/pkg/store/file" "github.com/grafana/k6foundry" - "github.com/grafana/k6foundry/pkg/testutils/goproxy" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -21,52 +21,47 @@ import ( // DependencyComp compares two dependencies for ordering func DependencyComp(a, b catalog.Module) bool { return a.Path < b.Path } -// SetupTestBuilder setups a local build service for testing -func SetupTestBuilder(t *testing.T) (*Builder, error) { - modules := []struct { - path string - version string - source string - }{ - { - path: "go.k6.io/k6", - version: "v0.1.0", - source: "testdata/deps/k6", - }, - { - path: "go.k6.io/k6", - version: "v0.2.0", - source: "testdata/deps/k6", - }, - { - path: "go.k6.io/k6ext", - version: "v0.1.0", - source: "testdata/deps/k6ext", - }, - { - path: "go.k6.io/k6ext", - version: "v0.2.0", - source: "testdata/deps/k6ext", - }, - { - path: "go.k6.io/k6ext2", - version: "v0.1.0", - source: "testdata/deps/k6ext2", - }, - } +type mockBuilder struct { + opts k6foundry.NativeBuilderOpts +} - // creates a goproxy that serves the given modules - proxy := goproxy.NewGoProxy() - for _, m := range modules { - err := proxy.AddModVersion(m.path, m.version, m.source) - if err != nil { - return nil, fmt.Errorf("setup %w", err) - } +// Mocks the Faundry's Build method +// Returns the build info for the given platform, k6 version and modules +func (m *mockBuilder) Build( + _ context.Context, + platform k6foundry.Platform, + k6Version string, + mods []k6foundry.Module, + buildOpts []string, + out io.Writer, +) (*k6foundry.BuildInfo, error) { + modVersions := make(map[string]string) + for _, mod := range mods { + modVersions[mod.Path] = mod.Version } + return &k6foundry.BuildInfo{ + Platform: platform.String(), + ModVersions: modVersions, + }, nil +} + +func MockFoundryFactory(_ context.Context, opts k6foundry.NativeBuilderOpts) (k6foundry.Builder, error) { + return &mockBuilder{ + opts: opts, + }, nil +} - goproxySrv := httptest.NewServer(proxy) +const catalogJSON = ` +{ +"k6": {"module": "go.k6.io/k6", "versions": ["v0.1.0", "v0.2.0"]}, +"k6/x/ext": {"module": "go.k6.io/k6ext", "versions": ["v0.1.0", "v0.2.0"]}, +"k6/x/ext2": {"module": "go.k6.io/k6ext2", "versions": ["v0.1.0"]} +} +` - catalog, err := catalog.NewCatalogFromFile("testdata/catalog.json") +// SetupTestBuilder setups a local build service for testing +func SetupTestBuilder(t *testing.T) (*Builder, error) { + catalog, err := catalog.NewCatalogFromJSON(strings.NewReader(catalogJSON)) if err != nil { return nil, fmt.Errorf("setting up test builder %w", err) } @@ -77,20 +72,10 @@ func SetupTestBuilder(t *testing.T) (*Builder, error) { } return New(context.Background(), Config{ - Opts: Opts{ - GoOpts: k6foundry.GoOpts{ - CopyGoEnv: true, - Env: map[string]string{ - "GOPROXY": goproxySrv.URL, - "GONOPROXY": "none", - "GOPRIVATE": "go.k6.io", - "GONOSUMDB": "go.k6.io", - }, - TmpCache: true, - }, - }, + Opts: Opts{}, Catalog: catalog, Store: store, + Foundry: FoundryFunction(MockFoundryFactory), }) } @@ -325,7 +310,7 @@ func TestIdempotentBuild(t *testing.T) { }) } -// TestConcurrentBuilds tests that is sage to build the same artifact concurrently and that +// TestConcurrentBuilds tests that is safe to build the same artifact concurrently and that // concurrent builds of different artifacts are not affected. // The test uses a local test setup backed by a file object store. // Attempting to write the same artifact twice will return an error. diff --git a/pkg/builder/testdata/catalog.json b/pkg/builder/testdata/catalog.json deleted file mode 100644 index 0032653..0000000 --- a/pkg/builder/testdata/catalog.json +++ /dev/null @@ -1,5 +0,0 @@ -{ -"k6": {"module": "go.k6.io/k6", "versions": ["v0.1.0", "v0.2.0"]}, -"k6/x/ext": {"module": "go.k6.io/k6ext", "versions": ["v0.1.0", "v0.2.0"]}, -"k6/x/ext2": {"module": "go.k6.io/k6ext2", "versions": ["v0.1.0"]} -} \ No newline at end of file diff --git a/pkg/builder/testdata/deps/k6/cmd/k6.go b/pkg/builder/testdata/deps/k6/cmd/k6.go deleted file mode 100644 index 05b72b0..0000000 --- a/pkg/builder/testdata/deps/k6/cmd/k6.go +++ /dev/null @@ -1,4 +0,0 @@ -package cmd - -func Execute() { -} diff --git a/pkg/builder/testdata/deps/k6/go.mod b/pkg/builder/testdata/deps/k6/go.mod deleted file mode 100644 index b7a7a45..0000000 --- a/pkg/builder/testdata/deps/k6/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module go.k6.io/k6 - -go 1.17 \ No newline at end of file diff --git a/pkg/builder/testdata/deps/k6ext/go.mod b/pkg/builder/testdata/deps/k6ext/go.mod deleted file mode 100644 index 5fcf581..0000000 --- a/pkg/builder/testdata/deps/k6ext/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module go.k6.io/k6ext - -go 1.17 \ No newline at end of file diff --git a/pkg/builder/testdata/deps/k6ext/main.go b/pkg/builder/testdata/deps/k6ext/main.go deleted file mode 100644 index c40a730..0000000 --- a/pkg/builder/testdata/deps/k6ext/main.go +++ /dev/null @@ -1 +0,0 @@ -package k6ext diff --git a/pkg/builder/testdata/deps/k6ext2/go.mod b/pkg/builder/testdata/deps/k6ext2/go.mod deleted file mode 100644 index 6cb06d5..0000000 --- a/pkg/builder/testdata/deps/k6ext2/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module go.k6.io/k6ext2 - -go 1.17 \ No newline at end of file diff --git a/pkg/builder/testdata/deps/k6ext2/main.go b/pkg/builder/testdata/deps/k6ext2/main.go deleted file mode 100644 index c7840a4..0000000 --- a/pkg/builder/testdata/deps/k6ext2/main.go +++ /dev/null @@ -1 +0,0 @@ -package k6ext2 diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index bb6d542..582398f 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -29,7 +29,6 @@ func (f buildFunction) Build( return f(ctx, platform, k6Constrains, deps) } -//nolint:revive func buildOk( ctx context.Context, platform string, @@ -41,7 +40,6 @@ func buildOk( }, nil } -//nolint:revive func buildErr( ctx context.Context, platform string,