diff --git a/.golangci.yml b/.golangci.yml index ed140f8b5f..0642ccd592 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,15 +8,14 @@ output: linters: enable-all: true disable: - - maligned - - megacheck + - mnd # So annoying + - execinquery - lll - typecheck # `go build` catches this, and it doesn't currently work with Go 1.11 modules - goimports # horrendously slow with go modules :( - dupl # has never been actually useful - gochecknoglobals - gochecknoinits - - interfacer # author deprecated it because it provides bad suggestions - funlen - whitespace - godox @@ -25,22 +24,18 @@ linters: - gomnd - gocognit - gocyclo - - scopelint - godot - nestif - testpackage - - goerr113 - gci - gofumpt - - exhaustivestruct - nlreturn - forbidigo - cyclop - paralleltest - - ifshort # so annoying - - golint - tagliatelle - gomoddirectives + - err113 - varnamelen - ireturn - containedctx @@ -48,14 +43,10 @@ linters: - contextcheck - nonamedreturns - exhaustruct - - nosnakecase - nosprintfhostport - nilerr - goconst - prealloc - - deadcode # doesn't support generics - - varcheck # doesn't support generics - - structcheck # doesn't support generics - rowserrcheck # doesn't support generics - wastedassign # doesn't support generics - goprintffuncname @@ -143,3 +134,4 @@ issues: - "^dot-imports:" - "fmt.Errorf can be replaced with errors.New" - "fmt.Sprintf can be replaced with string concatenation" + - "strings.Title has been deprecated" diff --git a/backend/controller/controller.go b/backend/controller/controller.go index a6975bbbaa..6c6c575890 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -8,8 +8,6 @@ import ( "math/rand" "net/http" "net/url" - "reflect" - "runtime" "sort" "strings" "sync" @@ -1625,46 +1623,6 @@ func (s *Service) getActiveSchema(ctx context.Context) (*schema.Schema, error) { }) } -func runWithRetries(ctx context.Context, success, failure time.Duration, fn func(ctx context.Context) error) { - name := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() - name = name[strings.LastIndex(name, ".")+1:] - name = strings.TrimSuffix(name, "-fm") - - ctx = log.ContextWithLogger(ctx, log.FromContext(ctx).Scope(name)) - failureRetry := backoff.Backoff{ - Min: failure, - Max: failure * 2, - Jitter: true, - Factor: 2, - } - failed := false - logger := log.FromContext(ctx) - for { - err := fn(ctx) - if err != nil { - next := failureRetry.Duration() - logger.Errorf(err, "Failed, retrying in %s", next) - select { - case <-time.After(next): - case <-ctx.Done(): - return - } - } else { - if failed { - logger.Debugf("Recovered") - failed = false - } - failureRetry.Reset() - logger.Tracef("Success, next run in %s", success) - select { - case <-time.After(success): - case <-ctx.Done(): - return - } - } - } -} - func extractIngressRoutingEntries(req *ftlv1.CreateDeploymentRequest) []dal.IngressRoutingEntry { var ingressRoutes []dal.IngressRoutingEntry for _, decl := range req.Schema.Decls { diff --git a/backend/schema/normalise.go b/backend/schema/normalise.go index 2506671b2d..0da2d5df87 100644 --- a/backend/schema/normalise.go +++ b/backend/schema/normalise.go @@ -36,14 +36,3 @@ func Normalise[T Node](n T) T { }) return ni //nolint:forcetypeassert } - -func normaliseSlice[T Node](in []T) []T { - if in == nil { - return nil - } - var out []T - for _, n := range in { - out = append(out, Normalise(n)) - } - return out -} diff --git a/backend/schema/validate.go b/backend/schema/validate.go index 9d2a2e87e8..970ec14a74 100644 --- a/backend/schema/validate.go +++ b/backend/schema/validate.go @@ -598,8 +598,12 @@ func validateVerbMetadata(scopes Scopes, module *Module, n *Verb) (merr []error) func validateIngressRequestOrResponse(scopes Scopes, module *Module, n *Verb, reqOrResp string, r Type) (fieldType Type, body Symbol, merr []error) { rref, _ := r.(*Ref) resp, sym := ResolveTypeAs[*Data](scopes, r) - m, _ := sym.Module.Get() - if sym == nil || m == nil || m.Name != "builtin" || resp.Name != "Http"+strings.Title(reqOrResp) { + invalid := sym == nil + if !invalid { + m, _ := sym.Module.Get() + invalid = m == nil || m.Name != "builtin" || resp.Name != "Http"+strings.Title(reqOrResp) + } + if invalid { merr = append(merr, errorf(r, "ingress verb %s: %s type %s must be builtin.HttpRequest", n.Name, reqOrResp, r)) return } diff --git a/bin/.golangci-lint-1.57.1.pkg b/bin/.golangci-lint-1.59.1.pkg similarity index 100% rename from bin/.golangci-lint-1.57.1.pkg rename to bin/.golangci-lint-1.59.1.pkg diff --git a/bin/golangci-lint b/bin/golangci-lint index 32d0089f14..99e329692a 120000 --- a/bin/golangci-lint +++ b/bin/golangci-lint @@ -1 +1 @@ -.golangci-lint-1.57.1.pkg \ No newline at end of file +.golangci-lint-1.59.1.pkg \ No newline at end of file diff --git a/cmd/ftl-controller/main.go b/cmd/ftl-controller/main.go index e6506a78fd..52854fe39a 100644 --- a/cmd/ftl-controller/main.go +++ b/cmd/ftl-controller/main.go @@ -52,20 +52,18 @@ func main() { configProviders := []cf.Provider[cf.Configuration]{cf.NewDBConfigProvider(dal)} configResolver := cf.NewDBConfigResolver(dal) cm, err := cf.New[cf.Configuration](ctx, configResolver, configProviders) - if err != nil { - kctx.Fatalf(err.Error()) - } + kctx.FatalIfErrorf(err) + ctx = cf.ContextWithConfig(ctx, cm) // The FTL controller currently only supports AWS Secrets Manager as a secrets provider. awsConfig, err := config.LoadDefaultConfig(ctx) + kctx.FatalIfErrorf(err) asmClient := secretsmanager.NewFromConfig(awsConfig) secretsResolver := cf.ASM{Client: *asmClient} secretsProviders := []cf.Provider[cf.Secrets]{cf.ASM{Client: *asmClient}} sm, err := cf.New[cf.Secrets](ctx, secretsResolver, secretsProviders) - if err != nil { - kctx.Fatalf(err.Error()) - } + kctx.FatalIfErrorf(err) ctx = cf.ContextWithSecrets(ctx, sm) err = controller.Start(ctx, cli.ControllerConfig, scaling.NewK8sScaling()) diff --git a/cmd/ftl/cmd_download.go b/cmd/ftl/cmd_download.go index 65fd3e3bbd..d340efbc2d 100644 --- a/cmd/ftl/cmd_download.go +++ b/cmd/ftl/cmd_download.go @@ -2,14 +2,10 @@ package main import ( "context" - "os" - "path/filepath" - ftlv1 "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1" "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect" "github.com/TBD54566975/ftl/internal/download" "github.com/TBD54566975/ftl/internal/model" - "github.com/TBD54566975/ftl/internal/sha256" ) type downloadCmd struct { @@ -20,38 +16,3 @@ type downloadCmd struct { func (d *downloadCmd) Run(ctx context.Context, client ftlv1connect.ControllerServiceClient) error { return download.Artefacts(ctx, client, d.Deployment, d.Dest) } - -func (d *downloadCmd) getLocalArtefacts() ([]*ftlv1.DeploymentArtefact, error) { - haveArtefacts := []*ftlv1.DeploymentArtefact{} - dest, err := filepath.Abs(d.Dest) - if err != nil { - return nil, err - } - err = filepath.Walk(dest, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - sum, err := sha256.SumFile(path) - if err != nil { - return err - } - - relPath, err := filepath.Rel(dest, path) - if err != nil { - return err - } - haveArtefacts = append(haveArtefacts, &ftlv1.DeploymentArtefact{ - Path: relPath, - Digest: sum.String(), - Executable: info.Mode()&0111 != 0, - }) - return nil - }) - if err != nil { - return nil, err - } - return haveArtefacts, nil -} diff --git a/cmd/ftl/cmd_ps.go b/cmd/ftl/cmd_ps.go index ae9f6fa448..a166ca7269 100644 --- a/cmd/ftl/cmd_ps.go +++ b/cmd/ftl/cmd_ps.go @@ -3,13 +3,12 @@ package main import ( "context" "fmt" - "os" "sort" "strings" "connectrpc.com/connect" - "github.com/golang/protobuf/jsonpb" "golang.org/x/exp/maps" + jsonpb "google.golang.org/protobuf/encoding/protojson" ftlv1 "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1" "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect" @@ -26,13 +25,13 @@ func (s *psCmd) Run(ctx context.Context, client ftlv1connect.ControllerServiceCl return err } if s.JSON { - marshaller := jsonpb.Marshaler{Indent: " "} + marshaller := jsonpb.MarshalOptions{Indent: " "} for _, process := range status.Msg.Processes { - err = marshaller.Marshal(os.Stdout, process) + data, err := marshaller.Marshal(process) if err != nil { return err } - fmt.Println() + fmt.Printf("%s\n", data) } return nil } @@ -65,19 +64,19 @@ func (s *psCmd) Run(ctx context.Context, client ftlv1connect.ControllerServiceCl key = fmt.Sprintf("%s-%s", key, strings.ToLower(runner.Key[len(runner.Key)-5:])) runnerKey = runner.Key endpoint = runner.Endpoint - labels, err := (&jsonpb.Marshaler{}).MarshalToString(runner.Labels) + labels, err := jsonpb.Marshal(runner.Labels) if err != nil { return err } - runnerLabels = labels + runnerLabels = string(labels) } args := []any{key, fmt.Sprintf("%d/%d", i+1, first.MinReplicas), "live", runnerKey, endpoint} if s.Verbose > 1 { - labels, err := (&jsonpb.Marshaler{}).MarshalToString(first.Labels) + labels, err := jsonpb.Marshal(first.Labels) if err != nil { return err } - args = append(args, labels, runnerLabels) + args = append(args, string(labels), runnerLabels) } fmt.Printf(format, args...) } diff --git a/cmd/ftl/cmd_status.go b/cmd/ftl/cmd_status.go index 8a35c63b9e..0eb8beb6c1 100644 --- a/cmd/ftl/cmd_status.go +++ b/cmd/ftl/cmd_status.go @@ -2,10 +2,10 @@ package main import ( "context" - "os" + "fmt" "connectrpc.com/connect" - "github.com/golang/protobuf/jsonpb" + jsonpb "google.golang.org/protobuf/encoding/protojson" ftlv1 "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1" "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect" @@ -30,7 +30,11 @@ func (s *statusCmd) Run(ctx context.Context, client ftlv1connect.ControllerServi deployment.Schema = nil } } - return (&jsonpb.Marshaler{ - Indent: " ", - }).Marshal(os.Stdout, status.Msg) + marshaler := jsonpb.MarshalOptions{Indent: " "} + data, err := marshaler.Marshal(status.Msg) + if err != nil { + return fmt.Errorf("failed to marshal status: %w", err) + } + fmt.Printf("%s\n", data) + return nil } diff --git a/go-runtime/compile/schema.go b/go-runtime/compile/schema.go index bd8aee88e6..c61bd4c635 100644 --- a/go-runtime/compile/schema.go +++ b/go-runtime/compile/schema.go @@ -1615,10 +1615,3 @@ func isIotaEnum(node ast.Node) bool { return false } } - -func exportedName(name string) string { - if name == "" { - return "" - } - return string(unicode.ToUpper(rune(name[0]))) + name[1:] -} diff --git a/go-runtime/schema/common/common.go b/go-runtime/schema/common/common.go index a04800b5a3..901bca8340 100644 --- a/go-runtime/schema/common/common.go +++ b/go-runtime/schema/common/common.go @@ -266,8 +266,6 @@ func GetTypeForNode(node ast.Node, info *types.Info) types.Type { if obj := info.ObjectOf(n); obj != nil { return obj.Type() } - case ast.Expr: - return info.TypeOf(n) case *ast.AssignStmt: if len(n.Lhs) > 0 { return info.TypeOf(n.Lhs[0]) @@ -296,6 +294,8 @@ func GetTypeForNode(node ast.Node, info *types.Info) types.Type { return t } } + case ast.Expr: + return info.TypeOf(n) } return nil } diff --git a/go-runtime/schema/common/fact.go b/go-runtime/schema/common/fact.go index ca3306d345..2b47232e22 100644 --- a/go-runtime/schema/common/fact.go +++ b/go-runtime/schema/common/fact.go @@ -77,13 +77,6 @@ func MarkSchemaDecl(pass *analysis.Pass, obj types.Object, decl schema.Decl) { pass.ExportObjectFact(obj, fact) } -// markSchemaDeclIncluded marks the given decl as included in the schema. -func markSchemaDeclIncluded(pass *analysis.Pass, obj types.Object) { - for _, f := range GetFactsForObject[*ExtractedDecl](pass, obj) { - f.ShouldInclude = true - } -} - // MarkFailedExtraction marks the given object as having failed extraction. func MarkFailedExtraction(pass *analysis.Pass, obj types.Object) { fact := newFact(pass) diff --git a/internal/container/container.go b/internal/container/container.go index b2f1c6681d..1956cd4a69 100644 --- a/internal/container/container.go +++ b/internal/container/container.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/image" "github.com/docker/docker/client" "github.com/docker/go-connections/nat" @@ -41,15 +42,15 @@ func DoesExist(ctx context.Context, name string) (bool, error) { } // Pull pulls the given image. -func Pull(ctx context.Context, image string) error { +func Pull(ctx context.Context, imageName string) error { cli, err := dockerClient.Get(ctx) if err != nil { return err } - reader, err := cli.ImagePull(ctx, image, types.ImagePullOptions{}) + reader, err := cli.ImagePull(ctx, imageName, image.PullOptions{}) if err != nil { - return fmt.Errorf("failed to pull %s image: %w", image, err) + return fmt.Errorf("failed to pull %s image: %w", imageName, err) } defer reader.Close() diff --git a/internal/cron/pattern.go b/internal/cron/pattern.go index 6d2e191751..0c199b6592 100644 --- a/internal/cron/pattern.go +++ b/internal/cron/pattern.go @@ -231,7 +231,6 @@ func Parse(text string) (Pattern, error) { // A helper struct to build up a cron pattern with a short syntax. type shortState struct { - position int seenNonZero bool components []Component err error diff --git a/internal/rpc/context.go b/internal/rpc/context.go index 791dcdd0d0..28583740c0 100644 --- a/internal/rpc/context.go +++ b/internal/rpc/context.go @@ -283,14 +283,14 @@ func (v versionInterceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc log.FromContext(ctx).Warnf("%s", err) } } else { - resp.Header().Set("X-FTL-Version", ftl.Version) + resp.Header().Set("X-Ftl-Version", ftl.Version) } return resp, nil } } func (v versionInterceptor) checkVersion(header http.Header) error { - version := header.Get("X-FTL-Version") + version := header.Get("X-Ftl-Version") if semver.Compare(ftl.Version, version) < 0 { return fmt.Errorf("FTL client (%s) is older than server (%s), consider upgrading: https://github.com/TBD54566975/ftl/releases", ftl.Version, version) } diff --git a/internal/rpc/headers/headers.go b/internal/rpc/headers/headers.go index d124af756d..f084b778c1 100644 --- a/internal/rpc/headers/headers.go +++ b/internal/rpc/headers/headers.go @@ -12,13 +12,13 @@ import ( // Headers used by the internal RPC system. const ( - DirectRoutingHeader = "FTL-Direct" + DirectRoutingHeader = "Ftl-Direct" // VerbHeader is the header used to pass the module.verb of the current request. // // One header will be present for each hop in the request path. - VerbHeader = "FTL-Verb" + VerbHeader = "Ftl-Verb" // RequestIDHeader is the header used to pass the inbound request ID. - RequestIDHeader = "FTL-Request-ID" + RequestIDHeader = "Ftl-Request-Id" ) func IsDirectRouted(header http.Header) bool {