Skip to content

Commit

Permalink
refactor: move logic from cmd/ftl/cmd_build* into buildengine (#974)
Browse files Browse the repository at this point in the history
This is just a pure move, with no logic changes.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
alecthomas and github-actions[bot] authored Feb 22, 2024
1 parent 1fadba2 commit 459b441
Show file tree
Hide file tree
Showing 18 changed files with 95 additions and 71 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ dist/
examples/**/go.work
examples/**/go.work.sum
**/_ftl
buildengine/.gitignore
30 changes: 26 additions & 4 deletions buildengine/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,39 @@ package buildengine

import (
"context"
"fmt"

"github.com/TBD54566975/ftl/backend/schema"
"github.com/TBD54566975/ftl/common/moduleconfig"
)

// A Module is a ModuleConfig with its dependencies populated.
type Module struct {
ModuleConfig
moduleconfig.ModuleConfig
Dependencies []string
}

// LoadModule loads a module from the given directory.
//
// A [Module] includes the module configuration as well as its dependencies
// extracted from source code.
func LoadModule(dir string) (Module, error) {
config, err := moduleconfig.LoadModuleConfig(dir)
if err != nil {
return Module{}, err
}
return UpdateDependencies(config)
}

// Build a module in the given directory given the schema and module config.
func Build(ctx context.Context, schema *schema.Schema, config Module) error {
panic("not implemented")
func Build(ctx context.Context /*schema *schema.Schema, */, module Module) error {
switch module.Language {
case "go":
return buildGo(ctx, module)

case "kotlin":
return buildKotlin(ctx, module)

default:
return fmt.Errorf("unknown language %q", module.Language)
}
}
11 changes: 6 additions & 5 deletions cmd/ftl/cmd_build_go.go → buildengine/build_go.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package buildengine

import (
"context"
Expand All @@ -10,20 +10,21 @@ import (
"github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect"
"github.com/TBD54566975/ftl/backend/schema"
"github.com/TBD54566975/ftl/go-runtime/compile"
"github.com/TBD54566975/ftl/internal/rpc"
)

func (b *buildCmd) buildGo(ctx context.Context, client ftlv1connect.ControllerServiceClient) error {
func buildGo(ctx context.Context, module Module) error {
client := rpc.ClientFromContext[ftlv1connect.ControllerServiceClient](ctx)
resp, err := client.GetSchema(ctx, connect.NewRequest(&ftlv1.GetSchemaRequest{}))
if err != nil {
return err
}
sch, err := schema.FromProto(resp.Msg.Schema)
if err != nil {
return err
return fmt.Errorf("failed to convert schema from proto: %w", err)
}
if err := compile.Build(ctx, b.ModuleDir, sch); err != nil {
if err := compile.Build(ctx, module.Dir, sch); err != nil {
return fmt.Errorf("failed to build module: %w", err)
}

return nil
}
18 changes: 10 additions & 8 deletions cmd/ftl/cmd_build_kotlin.go → buildengine/build_kotlin.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package buildengine

import (
"context"
Expand All @@ -9,28 +9,30 @@ import (
"github.com/beevik/etree"

"github.com/TBD54566975/ftl"
"github.com/TBD54566975/ftl/buildengine"
"github.com/TBD54566975/ftl/internal/exec"
"github.com/TBD54566975/ftl/internal/log"
)

func (b *buildCmd) buildKotlin(ctx context.Context, config buildengine.ModuleConfig) error {
func buildKotlin(ctx context.Context, module Module) error {
logger := log.FromContext(ctx)

if err := setPomProperties(logger, filepath.Join(b.ModuleDir, "..")); err != nil {
return fmt.Errorf("unable to update ftl.version in %s: %w", b.ModuleDir, err)
if err := SetPOMProperties(ctx, filepath.Join(module.Dir, "..")); err != nil {
return fmt.Errorf("unable to update ftl.version in %s: %w", module.Dir, err)
}

logger.Debugf("Using build command '%s'", config.Build)
err := exec.Command(ctx, log.Debug, b.ModuleDir, "bash", "-c", config.Build).RunBuffered(ctx)
logger.Debugf("Using build command '%s'", module.Build)
err := exec.Command(ctx, log.Debug, module.Dir, "bash", "-c", module.Build).RunBuffered(ctx)
if err != nil {
return fmt.Errorf("failed to build module: %w", err)
}

return nil
}

func setPomProperties(logger *log.Logger, baseDir string) error {
// SetPOMProperties updates the ftl.version and ftlEndpoint properties in the
// pom.xml file in the given base directory.
func SetPOMProperties(ctx context.Context, baseDir string) error {
logger := log.FromContext(ctx)
ftlVersion := ftl.Version
if ftlVersion == "dev" {
ftlVersion = "1.0-SNAPSHOT"
Expand Down
8 changes: 5 additions & 3 deletions buildengine/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import (

"golang.design/x/reflect"
"golang.org/x/exp/maps"

"github.com/TBD54566975/ftl/common/moduleconfig"
)

// UpdateAllDependencies calls UpdateDependencies on each module in the list.
func UpdateAllDependencies(modules []ModuleConfig) ([]Module, error) {
func UpdateAllDependencies(modules []moduleconfig.ModuleConfig) ([]Module, error) {
out := []Module{}
for _, module := range modules {
updated, err := UpdateDependencies(module)
Expand All @@ -32,7 +34,7 @@ func UpdateAllDependencies(modules []ModuleConfig) ([]Module, error) {

// UpdateDependencies finds the dependencies for an FTL module and returns a
// Module with those dependencies populated.
func UpdateDependencies(config ModuleConfig) (Module, error) {
func UpdateDependencies(config moduleconfig.ModuleConfig) (Module, error) {
dependencies, err := extractDependencies(config)
if err != nil {
return Module{}, err
Expand All @@ -41,7 +43,7 @@ func UpdateDependencies(config ModuleConfig) (Module, error) {
return Module{ModuleConfig: out, Dependencies: dependencies}, nil
}

func extractDependencies(config ModuleConfig) ([]string, error) {
func extractDependencies(config moduleconfig.ModuleConfig) ([]string, error) {
switch config.Language {
case "go":
return extractGoFTLImports(config.Module, config.Dir)
Expand Down
8 changes: 5 additions & 3 deletions buildengine/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,29 @@ import (
"os"
"path/filepath"
"sort"

"github.com/TBD54566975/ftl/common/moduleconfig"
)

// DiscoverModules recursively loads all modules under the given directories.
//
// If no directories are provided, the current working directory is used.
func DiscoverModules(dirs ...string) ([]ModuleConfig, error) {
func DiscoverModules(dirs ...string) ([]moduleconfig.ModuleConfig, error) {
if len(dirs) == 0 {
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
dirs = []string{cwd}
}
out := []ModuleConfig{}
out := []moduleconfig.ModuleConfig{}
for _, dir := range dirs {
err := WalkDir(dir, func(path string, d fs.DirEntry) error {
if filepath.Base(path) != "ftl.toml" {
return nil
}
moduleDir := filepath.Dir(path)
config, err := LoadModuleConfig(moduleDir)
config, err := moduleconfig.LoadModuleConfig(moduleDir)
if err != nil {
return err
}
Expand Down
4 changes: 3 additions & 1 deletion buildengine/discover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import (
"testing"

"github.com/alecthomas/assert/v2"

"github.com/TBD54566975/ftl/common/moduleconfig"
)

func TestDiscoverModules(t *testing.T) {
modules, err := DiscoverModules("testdata/modules")
assert.NoError(t, err)
expected := []ModuleConfig{
expected := []moduleconfig.ModuleConfig{
{
Dir: "testdata/modules/alpha",
Language: "go",
Expand Down
4 changes: 3 additions & 1 deletion buildengine/filehash.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"path/filepath"

"github.com/bmatcuk/doublestar/v4"

"github.com/TBD54566975/ftl/common/moduleconfig"
)

type FileChangeType rune
Expand Down Expand Up @@ -63,7 +65,7 @@ func CompareFileHashes(oldFiles, newFiles FileHashes) (FileChangeType, string, b

// ComputeFileHashes computes the SHA256 hash of all (non-git-ignored) files in
// the given directory.
func ComputeFileHashes(config ModuleConfig) (FileHashes, error) {
func ComputeFileHashes(config moduleconfig.ModuleConfig) (FileHashes, error) {
fileHashes := make(FileHashes)
err := WalkDir(config.Dir, func(srcPath string, entry fs.DirEntry) error {
for _, pattern := range config.Watch {
Expand Down
22 changes: 12 additions & 10 deletions buildengine/topological_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@ import (
"testing"

"github.com/alecthomas/assert/v2"

"github.com/TBD54566975/ftl/common/moduleconfig"
)

func TestBuildOrder(t *testing.T) {
modules := []Module{
{
ModuleConfig: ModuleConfig{Module: "alpha"},
ModuleConfig: moduleconfig.ModuleConfig{Module: "alpha"},
Dependencies: []string{"beta", "gamma"},
},
{
ModuleConfig: ModuleConfig{Module: "beta"},
ModuleConfig: moduleconfig.ModuleConfig{Module: "beta"},
Dependencies: []string{"kappa"},
},
{
ModuleConfig: ModuleConfig{Module: "gamma"},
ModuleConfig: moduleconfig.ModuleConfig{Module: "gamma"},
Dependencies: []string{"kappa"},
},
{
ModuleConfig: ModuleConfig{Module: "kappa"},
ModuleConfig: moduleconfig.ModuleConfig{Module: "kappa"},
},
{
ModuleConfig: ModuleConfig{Module: "delta"},
ModuleConfig: moduleconfig.ModuleConfig{Module: "delta"},
},
}

Expand All @@ -33,15 +35,15 @@ func TestBuildOrder(t *testing.T) {

expected := [][]Module{
{
{ModuleConfig: ModuleConfig{Module: "delta"}},
{ModuleConfig: ModuleConfig{Module: "kappa"}},
{ModuleConfig: moduleconfig.ModuleConfig{Module: "delta"}},
{ModuleConfig: moduleconfig.ModuleConfig{Module: "kappa"}},
},
{
{ModuleConfig: ModuleConfig{Module: "beta"}, Dependencies: []string{"kappa"}},
{ModuleConfig: ModuleConfig{Module: "gamma"}, Dependencies: []string{"kappa"}},
{ModuleConfig: moduleconfig.ModuleConfig{Module: "beta"}, Dependencies: []string{"kappa"}},
{ModuleConfig: moduleconfig.ModuleConfig{Module: "gamma"}, Dependencies: []string{"kappa"}},
},
{
{ModuleConfig: ModuleConfig{Module: "alpha"}, Dependencies: []string{"beta", "gamma"}},
{ModuleConfig: moduleconfig.ModuleConfig{Module: "alpha"}, Dependencies: []string{"beta", "gamma"}},
},
}
assert.Equal(t, expected, graph)
Expand Down
3 changes: 2 additions & 1 deletion buildengine/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/alecthomas/types/pubsub"

"github.com/TBD54566975/ftl/common/moduleconfig"
"github.com/TBD54566975/ftl/internal/log"
"github.com/TBD54566975/ftl/internal/maps"
)
Expand Down Expand Up @@ -60,7 +61,7 @@ func Watch(ctx context.Context, period time.Duration, dirs ...string) *pubsub.To
logger.Tracef("error discovering modules: %v", err)
continue
}
moduleConfigsByDir := maps.FromSlice(moduleConfigs, func(config ModuleConfig) (string, ModuleConfig) {
moduleConfigsByDir := maps.FromSlice(moduleConfigs, func(config moduleconfig.ModuleConfig) (string, moduleconfig.ModuleConfig) {
return config.Module, config
})

Expand Down
3 changes: 2 additions & 1 deletion buildengine/watch_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package buildengine
package buildengine_test

import (
"context"
Expand All @@ -10,6 +10,7 @@ import (

"github.com/alecthomas/assert/v2"

. "github.com/TBD54566975/ftl/buildengine"
"github.com/TBD54566975/ftl/internal/log"
)

Expand Down
28 changes: 6 additions & 22 deletions cmd/ftl/cmd_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package main

import (
"context"
"fmt"
"time"

"github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect"
"github.com/TBD54566975/ftl/buildengine"
"github.com/TBD54566975/ftl/internal/log"
)
Expand All @@ -14,36 +12,22 @@ type buildCmd struct {
ModuleDir string `arg:"" help:"Directory containing ftl.toml" type:"existingdir" default:"."`
}

func (b *buildCmd) Run(ctx context.Context, client ftlv1connect.ControllerServiceClient) error {
func (b *buildCmd) Run(ctx context.Context) error {
logger := log.FromContext(ctx)

startTime := time.Now()
// Load the TOML file.
var err error
config, err := buildengine.LoadModuleConfig(b.ModuleDir)

module, err := buildengine.LoadModule(b.ModuleDir)
if err != nil {
return err
}
logger.Infof("Building %s module '%s'", module.Language, module.Module)

logger.Infof("Building %s module '%s'", config.Language, config.Module)

switch config.Language {
case "kotlin":
err = b.buildKotlin(ctx, config)

case "go":
err = b.buildGo(ctx, client)

default:
return fmt.Errorf("unable to build, unknown language %q", config.Language)
}

err = buildengine.Build(ctx, module)
if err != nil {
return err
}

duration := time.Since(startTime)
formattedDuration := fmt.Sprintf("%.2fs", duration.Seconds())
logger.Infof("Successfully built module '%s' in %s", config.Module, formattedDuration)
logger.Infof("Successfully built module '%s' in %.2fs", module.Module, time.Since(startTime).Seconds())
return nil
}
Loading

0 comments on commit 459b441

Please sign in to comment.