Skip to content

Commit

Permalink
refactor: refactors to project.RunTarget() (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmgilman authored Sep 14, 2024
1 parent 887a6ee commit 80b759e
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 78 deletions.
1 change: 1 addition & 0 deletions forge/cli/blueprint.cue
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ project: {
"darwin/arm64",
]
}
test: retries: 3
}
}
31 changes: 11 additions & 20 deletions forge/cli/cmd/cmds/run.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package cmds

import (
"fmt"
"log/slog"
"strings"

"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/earthly"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/earthfile"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/executor"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/secrets"
)
Expand All @@ -21,40 +19,33 @@ type RunCmd struct {
}

func (c *RunCmd) Run(logger *slog.Logger) error {
if !strings.Contains(c.Path, "+") {
return fmt.Errorf("invalid Earthfile+Target pair: %s", c.Path)
ref, err := earthfile.ParseEarthfileRef(c.Path)
if err != nil {
return err
}

earthfileDir := strings.Split(c.Path, "+")[0]
target := strings.Split(c.Path, "+")[1]

project, err := loadProject(earthfileDir, logger)
project, err := loadProject(ref.Path, logger)
if err != nil {
return err
}

logger.Info("Executing Earthly target", "project", project.Path, "target", ref.Target)
localExec := executor.NewLocalExecutor(
logger,
executor.WithRedirect(),
)

opts := generateOpts(target, c, &project.Blueprint)
earthlyExec := earthly.NewEarthlyExecutor(
earthfileDir,
target,
result, err := project.RunTarget(
ref.Target,
c.CI,
c.Local,
localExec,
secrets.NewDefaultSecretStore(),
logger,
opts...,
generateOpts(c)...,
)

logger.Info("Executing Earthly target", "earthfile", earthfileDir, "target", target)
result, err := earthlyExec.Run()
if err != nil {
return err
}

printJson(result, c.Pretty)

return nil
}
2 changes: 1 addition & 1 deletion forge/cli/cmd/cmds/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type ScanCmd struct {

func (c *ScanCmd) Run(logger *slog.Logger) error {
walker := walker.NewDefaultFSWalker(logger)
loader := project.NewDefaultProjectLoader(loadRuntimes(logger), logger)
loader := project.NewDefaultProjectLoader(project.GetDefaultRuntimes(logger), logger)

var rootPath string
if c.Absolute {
Expand Down
57 changes: 5 additions & 52 deletions forge/cli/cmd/cmds/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"log/slog"

"github.com/input-output-hk/catalyst-forge/blueprint/schema"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/earthly"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/project"
)
Expand All @@ -22,50 +21,11 @@ func enumerate(data map[string][]string) []string {
return result
}

// generateOpts generates the options for the Earthly executor based on the configuration file and flags.
func generateOpts(target string, flags *RunCmd, config *schema.Blueprint) []earthly.EarthlyExecutorOption {
// generateOpts generates the options for the Earthly executor based on command
// flags.
func generateOpts(flags *RunCmd) []earthly.EarthlyExecutorOption {
var opts []earthly.EarthlyExecutorOption

if config != nil {
if _, ok := config.Project.CI.Targets[target]; ok {
targetConfig := config.Project.CI.Targets[target]

if len(targetConfig.Args) > 0 {
var args []string
for k, v := range targetConfig.Args {
args = append(args, fmt.Sprintf("--%s", k), v)
}

opts = append(opts, earthly.WithTargetArgs(args...))
}

// We only run multiple platforms in CI mode to avoid issues with local builds.
if targetConfig.Platforms != nil && flags.CI {
opts = append(opts, earthly.WithPlatforms(targetConfig.Platforms...))
}

if targetConfig.Privileged != nil && *targetConfig.Privileged {
opts = append(opts, earthly.WithPrivileged())
}

if targetConfig.Retries != nil {
opts = append(opts, earthly.WithRetries(*targetConfig.Retries))
}

if len(targetConfig.Secrets) > 0 {
opts = append(opts, earthly.WithSecrets(targetConfig.Secrets))
}
}

if config.Global.CI.Providers.Earthly.Satellite != nil && !flags.Local {
opts = append(opts, earthly.WithSatellite(*config.Global.CI.Providers.Earthly.Satellite))
}

if len(config.Global.CI.Secrets) > 0 {
opts = append(opts, earthly.WithSecrets(config.Global.CI.Secrets))
}
}

if flags != nil {
if flags.Artifact != "" {
opts = append(opts, earthly.WithArtifact(flags.Artifact))
Expand All @@ -80,7 +40,7 @@ func generateOpts(target string, flags *RunCmd, config *schema.Blueprint) []eart
opts = append(opts, earthly.WithPlatforms(flags.Platform...))
}

if flags.TargetArgs != nil && len(flags.TargetArgs) > 0 && flags.TargetArgs[0] != "" {
if len(flags.TargetArgs) > 0 && flags.TargetArgs[0] != "" {
opts = append(opts, earthly.WithTargetArgs(flags.TargetArgs...))
}
}
Expand All @@ -90,17 +50,10 @@ func generateOpts(target string, flags *RunCmd, config *schema.Blueprint) []eart

// loadProject loads the project from the given root path.
func loadProject(rootPath string, logger *slog.Logger) (project.Project, error) {
loader := project.NewDefaultProjectLoader(loadRuntimes(logger), logger)
loader := project.NewDefaultProjectLoader(project.GetDefaultRuntimes(logger), logger)
return loader.Load(rootPath)
}

// loadRuntimes loads the all runtime data collectors.
func loadRuntimes(logger *slog.Logger) []project.RuntimeData {
return []project.RuntimeData{
project.NewGitRuntime(logger),
}
}

// printJson prints the given data as a JSON string.
func printJson(data interface{}, pretty bool) {
var out []byte
Expand Down
22 changes: 22 additions & 0 deletions forge/cli/pkg/earthfile/earthfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package earthfile

import (
"context"
"fmt"
"strings"

"github.com/earthly/earthly/ast"
"github.com/earthly/earthly/ast/spec"
Expand All @@ -13,6 +15,12 @@ type Earthfile struct {
spec spec.Earthfile
}

// EarthfileRef represents a reference to an Earthfile and a target.
type EarthfileRef struct {
Path string
Target string
}

// Targets returns the names of the targets in the Earthfile.
func (e Earthfile) Targets() []string {
var targetNames []string
Expand Down Expand Up @@ -52,6 +60,20 @@ func ParseEarthfile(ctx context.Context, earthfile walker.FileSeeker) (Earthfile
}, nil
}

// ParseEarthfileRef parses an Earthfile+Target pair.
func ParseEarthfileRef(ref string) (EarthfileRef, error) {
parts := strings.Split(ref, "+")

if len(parts) != 2 {
return EarthfileRef{}, fmt.Errorf("invalid Earthfile+Target pair: %s", ref)
}

return EarthfileRef{
Path: parts[0],
Target: parts[1],
}, nil
}

// namedReader is a FileSeeker that also provides the name of the file.
// This is used to interopt with the Earthly AST parser.
type namedReader struct {
Expand Down
1 change: 1 addition & 0 deletions forge/cli/pkg/project/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func (p *DefaultProjectLoader) Load(projectPath string) (Project, error) {
Path: projectPath,
Repo: repo,
RepoRoot: gitRoot,
logger: p.logger,
rawBlueprint: rbp,
}, nil
}
Expand Down
77 changes: 72 additions & 5 deletions forge/cli/pkg/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package project

import (
"fmt"
"log/slog"
"path/filepath"
"strings"

gg "github.com/go-git/go-git/v5"
"github.com/input-output-hk/catalyst-forge/blueprint/pkg/blueprint"
"github.com/input-output-hk/catalyst-forge/blueprint/schema"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/earthfile"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/earthly"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/executor"
"github.com/input-output-hk/catalyst-forge/forge/cli/pkg/secrets"
)

type TagInfo struct {
Expand All @@ -25,14 +29,10 @@ type Project struct {
Repo *gg.Repository
RepoRoot string
Tags TagInfo
logger *slog.Logger
rawBlueprint blueprint.RawBlueprint
}

// Raw returns the raw blueprint.
func (p *Project) Raw() blueprint.RawBlueprint {
return p.rawBlueprint
}

// GetRelativePath returns the relative path of the project from the repo root.
func (p *Project) GetRelativePath() (string, error) {
var projectPath, repoRoot string
Expand Down Expand Up @@ -67,3 +67,70 @@ func (p *Project) GetRelativePath() (string, error) {

return relPath, nil
}

// Raw returns the raw blueprint.
func (p *Project) Raw() blueprint.RawBlueprint {
return p.rawBlueprint
}

func (p *Project) RunTarget(
target string,
ci bool,
local bool,
exec executor.Executor,
store secrets.SecretStore,
opts ...earthly.EarthlyExecutorOption,
) (map[string]earthly.EarthlyExecutionResult, error) {
return earthly.NewEarthlyExecutor(
p.Path,
target,
exec,
store,
p.logger,
append(p.generateOpts(target, ci, local), opts...)...,
).Run()
}

func (p *Project) generateOpts(target string, ci, local bool) []earthly.EarthlyExecutorOption {
var opts []earthly.EarthlyExecutorOption

if _, ok := p.Blueprint.Project.CI.Targets[target]; ok {
targetConfig := p.Blueprint.Project.CI.Targets[target]

if len(targetConfig.Args) > 0 {
var args []string
for k, v := range targetConfig.Args {
args = append(args, fmt.Sprintf("--%s", k), v)
}

opts = append(opts, earthly.WithTargetArgs(args...))
}

// We only run multiple platforms in CI mode to avoid issues with local builds.
if targetConfig.Platforms != nil && ci {
opts = append(opts, earthly.WithPlatforms(targetConfig.Platforms...))
}

if targetConfig.Privileged != nil && *targetConfig.Privileged {
opts = append(opts, earthly.WithPrivileged())
}

if targetConfig.Retries != nil {
opts = append(opts, earthly.WithRetries(*targetConfig.Retries))
}

if len(targetConfig.Secrets) > 0 {
opts = append(opts, earthly.WithSecrets(targetConfig.Secrets))
}
}

if p.Blueprint.Global.CI.Providers.Earthly.Satellite != nil && !local {
opts = append(opts, earthly.WithSatellite(*p.Blueprint.Global.CI.Providers.Earthly.Satellite))
}

if len(p.Blueprint.Global.CI.Secrets) > 0 {
opts = append(opts, earthly.WithSecrets(p.Blueprint.Global.CI.Secrets))
}

return opts
}
8 changes: 8 additions & 0 deletions forge/cli/pkg/project/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,16 @@ func (g *GitRuntime) Load(project *Project) map[string]string {
return data
}

// NewGitRuntime creates a new GitRuntime.
func NewGitRuntime(logger *slog.Logger) *GitRuntime {
return &GitRuntime{
logger: logger,
}
}

// GetDefaultRuntimes returns the default runtime data loaders.
func GetDefaultRuntimes(logger *slog.Logger) []RuntimeData {
return []RuntimeData{
NewGitRuntime(logger),
}
}

0 comments on commit 80b759e

Please sign in to comment.