pkg/builder/builder.go
Rama main · réplica de lectura del repositorio original.
package builder
import (
"context"
"errors"
"io"
"io/fs"
"os"
pathspkg "path"
"runtime"
"slices"
"github.com/rs/zerolog"
"encore.dev/appruntime/exported/experiments"
"encr.dev/cli/daemon/apps"
"encr.dev/internal/optracker"
"encr.dev/internal/version"
"encr.dev/pkg/cueutil"
"encr.dev/pkg/fns"
"encr.dev/pkg/option"
"encr.dev/pkg/paths"
meta "encr.dev/proto/encore/parser/meta/v1"
)
var LocalBuildTags = []string{
"encore_local",
"encore_no_gcp", "encore_no_aws", "encore_no_azure",
"encore_no_datadog", "encore_no_prometheus",
}
// DebugMode specifies how to compile the application for debugging.
type DebugMode string
const (
DebugModeDisabled DebugMode = "disabled"
DebugModeEnabled DebugMode = "enabled"
DebugModeBreak DebugMode = "break"
)
// InstallMode selects which dependencies to install for TypeScript apps.
type InstallMode string
const (
// InstallAll installs every dependency. It is the default.
InstallAll InstallMode = "all"
// InstallProduction omits development dependencies, using each
// package manager's equivalent of npm's --omit=dev.
InstallProduction InstallMode = "production"
)
type BuildInfo struct {
BuildTags []string
CgoEnabled bool
StaticLink bool
DebugMode DebugMode
Environ []string
GOOS, GOARCH string
KeepOutput bool
Revision string
UncommittedChanges bool
// MainPkg is the path to the existing main package to use, if any.
MainPkg option.Option[paths.Pkg]
// Overrides to explicitly set the GoRoot and EncoreRuntime paths.
// if not set, they will be inferred from the current executable.
GoRoot option.Option[paths.FS]
EncoreRuntimes option.Option[paths.FS]
// UseLocalJSRuntime specifies whether to override the installed Encore version
// with the local JS runtime.
UseLocalJSRuntime bool
// Logger allows a custom logger to be used by the various phases of the builder.
Logger option.Option[zerolog.Logger]
// DisableSensitiveScrubbing, if true, disables scrubbing of sensitive fields.
// Used for local development.
DisableSensitiveScrubbing bool
}
func (b *BuildInfo) IsCrossBuild() bool {
return b.GOOS != runtime.GOOS || b.GOARCH != runtime.GOARCH
}
// DefaultBuildInfo returns a BuildInfo with default values.
// It can be modified afterwards.
func DefaultBuildInfo() BuildInfo {
return BuildInfo{
BuildTags: slices.Clone(LocalBuildTags),
CgoEnabled: true,
StaticLink: false,
DebugMode: DebugModeDisabled,
GOOS: runtime.GOOS,
GOARCH: runtime.GOARCH,
KeepOutput: false,
Revision: "",
UncommittedChanges: false,
// Use the local JS runtime if this is a development build.
UseLocalJSRuntime: version.Channel == version.DevBuild,
}
}
type PrepareParams struct {
Build BuildInfo
App *apps.Instance
WorkingDir string
Stderr option.Option[io.Writer]
// InstallMode selects which dependencies to install for TypeScript apps.
// The zero value means InstallAll. Ignored by the Go builder.
InstallMode InstallMode
}
type PrepareResult struct {
Data any
}
type ParseParams struct {
Build BuildInfo
App *apps.Instance
Experiments *experiments.Set
WorkingDir string
ParseTests bool
// Prepare is the result from calling Prepare().
// Required for TypeScript apps, ignored for Go apps.
Prepare *PrepareResult
// Optional writer to redirect stderr to.
Stderr option.Option[io.Writer]
}
type ParseResult struct {
Meta *meta.Data
Data any
}
type CompileParams struct {
Build BuildInfo
App *apps.Instance
Parse *ParseResult
OpTracker *optracker.OpTracker
Experiments *experiments.Set
WorkingDir string
// Override to explicitly allow the Encore version to be set.
EncoreVersion option.Option[string]
Environ []string
}
type ArtifactString string
func (a ArtifactString) Join(strs ...string) ArtifactString {
str := pathspkg.Join(strs...)
return ArtifactString(pathspkg.Join(string(a), str))
}
func (a ArtifactString) Expand(artifactDir paths.FS) string {
return os.Expand(string(a), func(key string) string {
if key == "ARTIFACT_DIR" {
return artifactDir.ToIO()
}
return ""
})
}
type ArtifactStrings []ArtifactString
func (a ArtifactStrings) Expand(artifactDir paths.FS) []string {
return fns.Map(a, func(a ArtifactString) string { return a.Expand(artifactDir) })
}
// CmdSpec is a specification for a command to run.
//
// The fields can refer to file paths within the artifact directory
// using the "${ARTIFACT_DIR}" placeholder (substituted with os.ExpandEnv).
// This is necessary when building docker images, as otherwise the file paths
// will refer to the wrong filesystem location in the built docker image.
type CmdSpec struct {
// The command to execute. Can either be a filesystem path
// or a path to a binary (using "${ARTIFACT_DIR}" as a placeholder).
Command ArtifactStrings `json:"command"`
// Additional env variables to pass in.
Env ArtifactStrings `json:"env"`
// PrioritizedFiles are file paths that should be prioritized when
// building a streamable docker image.
PrioritizedFiles ArtifactStrings `json:"prioritized_files"`
}
func (s *CmdSpec) Expand(artifactDir paths.FS) Cmd {
return Cmd{
Command: s.Command.Expand(artifactDir),
Env: s.Env.Expand(artifactDir),
}
}
// Cmd defines a command to run. It's like CmdSpec, but uses expanded paths
// instead of ArtifactStrings. A CmdSpec can be turned into a Cmd using Expand.
type Cmd struct {
// The command to execute, with arguments.
Command []string
// Additional env variables to pass in.
Env []string
}
type CompileResult struct {
OS string
Arch string
Outputs []BuildOutput
}
type BuildOutput interface {
GetArtifactDir() paths.FS
GetEntrypoints() []Entrypoint
}
type Entrypoint struct {
// How to run this entrypoint.
Cmd CmdSpec `json:"cmd"`
// Services hosted by this entrypoint.
Services []string `json:"services"`
// Gateways hosted by this entrypoint.
Gateways []string `json:"gateways"`
// Whether this entrypoint uses the new runtime config.
UseRuntimeConfigV2 bool `json:"use_runtime_config_v2"`
}
type GoBuildOutput struct {
// The folder containing the build artifacts.
// These artifacts are assumed to be relocatable.
ArtifactDir paths.FS `json:"artifact_dir"`
// The entrypoints that are part of this build output.
Entrypoints []Entrypoint `json:"entrypoints"`
}
func (o *GoBuildOutput) GetArtifactDir() paths.FS { return o.ArtifactDir }
func (o *GoBuildOutput) GetEntrypoints() []Entrypoint { return o.Entrypoints }
type JSBuildOutput struct {
// The folder containing the build artifacts.
// These artifacts are assumed to be relocatable.
ArtifactDir paths.FS `json:"artifact_dir"`
// The entrypoints that are part of this build output.
Entrypoints []Entrypoint `json:"entrypoints"`
// Whether the build output uses the local runtime on the builder,
// as opposed to installing a published release via e.g. 'npm install'.
UsesLocalRuntime bool `json:"uses_local_runtime"`
}
func (o *JSBuildOutput) GetArtifactDir() paths.FS { return o.ArtifactDir }
func (o *JSBuildOutput) GetEntrypoints() []Entrypoint { return o.Entrypoints }
type RunTestsParams struct {
Spec *TestSpecResult
// WorkingDir is the directory to invoke the test command from.
WorkingDir paths.FS
// Stdout and Stderr are where to redirect the command output.
Stdout, Stderr io.Writer
}
type TestSpecParams struct {
Compile CompileParams
// Env sets environment variables for "go test".
Env []string
// Args sets extra arguments for "go test".
Args []string
}
// ErrNoTests is reported by TestSpec when there aren't any tests to run.
var ErrNoTests = errors.New("no tests found")
type TestSpecResult struct {
Command string
Args []string
Environ []string
// For use by the builder when invoking RunTests.
BuilderData any
}
type GenUserFacingParams struct {
Build BuildInfo
App *apps.Instance
Parse *ParseResult
}
type ServiceConfigsParams struct {
Parse *ParseResult
CueMeta *cueutil.Meta
}
type ServiceConfigsResult struct {
Configs map[string]string
ConfigFiles fs.FS
}
type Impl interface {
Prepare(context.Context, PrepareParams) (*PrepareResult, error)
Parse(context.Context, ParseParams) (*ParseResult, error)
Compile(context.Context, CompileParams) (*CompileResult, error)
TestSpec(context.Context, TestSpecParams) (*TestSpecResult, error)
RunTests(context.Context, RunTestsParams) error
ServiceConfigs(context.Context, ServiceConfigsParams) (*ServiceConfigsResult, error)
GenUserFacing(context.Context, GenUserFacingParams) error
UseNewRuntimeConfig() bool
NeedsMeta() bool
Close() error
}