Files
Kevin Minehart 13f4cf162e CI: move grafana-build into pkg/build (#105640)
* move grafana-build into pkg/build
2025-05-20 10:48:00 -05:00

163 lines
3.6 KiB
Go

package pipeline
import (
"context"
"errors"
"fmt"
"log/slog"
"sync"
"dagger.io/dagger"
"github.com/grafana/grafana/pkg/build/daggerbuild/cliutil"
)
var (
ErrorUnexpectedType = errors.New("unexpected type in state")
)
type StateHandler interface {
String(context.Context, Argument) (string, error)
Int64(context.Context, Argument) (int64, error)
Bool(context.Context, Argument) (bool, error)
File(context.Context, Argument) (*dagger.File, error)
Directory(context.Context, Argument) (*dagger.Directory, error)
CacheVolume(context.Context, Argument) (*dagger.CacheVolume, error)
}
// State stores the overall state of the application. Externally, it is read-only.
// It starts every run completely empty. As arguments are needed by other arguments, their ValueFuncs are called
// when fetched from the state and then stored for future re-use.
type State struct {
Data sync.Map
Log *slog.Logger
// These two fields are only here so that the state can call the ValueFunc of each argument if it's not already available in the state.
CLIContext cliutil.CLIContext
Client *dagger.Client
Platform dagger.Platform
}
func (s *State) ArgumentOpts() *ArgumentOpts {
return &ArgumentOpts{
Log: s.Log,
CLIContext: s.CLIContext,
Client: s.Client,
State: s,
Platform: s.Platform,
}
}
func (s *State) String(ctx context.Context, arg Argument) (string, error) {
if v, ok := s.Data.Load(arg.Name); ok {
str, ok := v.(string)
if !ok {
return "", fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name)
}
return str, nil
}
str, err := arg.String(ctx, s.ArgumentOpts())
if err != nil {
return "", err
}
s.Data.Store(arg.Name, str)
return str, nil
}
func (s *State) Int64(ctx context.Context, arg Argument) (int64, error) {
if v, ok := s.Data.Load(arg.Name); ok {
val, ok := v.(int64)
if !ok {
return 0, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name)
}
return val, nil
}
val, err := arg.Int64(ctx, s.ArgumentOpts())
if err != nil {
return 0, err
}
s.Data.Store(arg.Name, val)
return val, nil
}
func (s *State) Bool(ctx context.Context, arg Argument) (bool, error) {
if v, ok := s.Data.Load(arg.Name); ok {
val, ok := v.(bool)
if !ok {
return false, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name)
}
return val, nil
}
val, err := arg.Bool(ctx, s.ArgumentOpts())
if err != nil {
return false, err
}
s.Data.Store(arg.Name, val)
return val, nil
}
func (s *State) File(ctx context.Context, arg Argument) (*dagger.File, error) {
if v, ok := s.Data.Load(arg.Name); ok {
val, ok := v.(*dagger.File)
if !ok {
return nil, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name)
}
return val, nil
}
f, err := arg.File(ctx, s.ArgumentOpts())
if err != nil {
return nil, err
}
s.Data.Store(arg.Name, f)
return f, nil
}
func (s *State) Directory(ctx context.Context, arg Argument) (*dagger.Directory, error) {
if v, ok := s.Data.Load(arg.Name); ok {
val, ok := v.(*dagger.Directory)
if !ok {
return nil, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name)
}
return val, nil
}
dir, err := arg.Directory(ctx, s.ArgumentOpts())
if err != nil {
return nil, err
}
s.Data.Store(arg.Name, dir)
return dir, nil
}
func (s *State) CacheVolume(ctx context.Context, arg Argument) (*dagger.CacheVolume, error) {
if v, ok := s.Data.Load(arg.Name); ok {
val, ok := v.(*dagger.CacheVolume)
if !ok {
return nil, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name)
}
return val, nil
}
dir, err := arg.CacheVolume(ctx, s.ArgumentOpts())
if err != nil {
return nil, err
}
s.Data.Store(arg.Name, dir)
return dir, nil
}