项目文件夹

文件
Asim Aslam 3e885308a0 lint: clear the golangci-lint backlog and enforce a blocking lint in CI (#2995)
Fixes #2988. Brings 'golangci-lint run ./...' to zero issues (was ~373):

- errcheck: explicitly ignore fire-and-forget calls with '_ =' (and a small
  errcheck.exclude-functions list for response writes — json Encoder.Encode,
  http ResponseWriter.Write, fmt.Fprint*); genuine cases handled.
- unused: remove dead code (unexported decls and dead test helpers) and the
  imports they orphaned.
- staticcheck: ST1005 error strings, ST1016 receiver names, S1000/S1017/S1019/
  S1023 simplifications, SA4004/SA4006/SA4010 dead code, SA1021 net.IP.Equal,
  SA6002 (store *[]byte in sync.Pool).
- govet: fix a context leak (lostcancel) in internal/util/mdns and move
  t.Fatal/Fatalf out of goroutines (testinggoroutine) in tests.
- ineffassign, unconvert: mechanical fixes.

CI: the Lint workflow now runs a blocking full-tree 'golangci-lint run' on
pushes and PRs (dropped only-new-issues now that the tree is clean).

Verified: go build, go vet, test compilation, and unit tests for the
behaviourally-touched packages all pass.


Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 18:51:30 +01:00

205 行
5.3 KiB
Go

package microcli
import (
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"github.com/urfave/cli/v2"
"go-micro.dev/v6/client"
"go-micro.dev/v6/cmd"
"go-micro.dev/v6/codec/bytes"
"go-micro.dev/v6/registry"
"go-micro.dev/v6/cmd/micro/cli/new"
"go-micro.dev/v6/cmd/micro/cli/util"
// Import packages that register commands via init()
_ "go-micro.dev/v6/cmd/micro/cli/agent"
_ "go-micro.dev/v6/cmd/micro/cli/build"
_ "go-micro.dev/v6/cmd/micro/cli/deploy"
_ "go-micro.dev/v6/cmd/micro/cli/init"
_ "go-micro.dev/v6/cmd/micro/cli/remote"
)
func genProtoHandler(c *cli.Context) error {
cmd := exec.Command("find", ".", "-name", "*.proto", "-exec", "protoc", "--proto_path=.", "--micro_out=.", "--go_out=.", `{}`, `;`)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
func init() {
cmd.Register([]*cli.Command{
{
Name: "new",
Usage: "Create a new service",
ArgsUsage: "[name]",
UsageText: ` micro new helloworld # scaffold a single service
micro new --prompt "a todo list with tasks" # AI-design multiple services
micro new --prompt "add tags to the task service" # extend existing services`,
Action: new.Run,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "no-mcp",
Usage: "Disable MCP gateway integration in generated code",
},
&cli.BoolFlag{
Name: "proto",
Usage: "Use Protocol Buffers (requires protoc); default is reflection-based, no protoc needed",
},
&cli.StringFlag{
Name: "template",
Usage: "Service template: default, crud, pubsub, api",
},
&cli.StringFlag{
Name: "prompt",
Usage: "Describe the system to generate (uses AI to design & build services with real business logic)",
EnvVars: []string{"MICRO_NEW_PROMPT"},
},
&cli.StringFlag{
Name: "provider",
Usage: "AI provider for --prompt (anthropic, openai, gemini, atlascloud, groq, mistral, together)",
EnvVars: []string{"MICRO_AI_PROVIDER"},
},
&cli.StringFlag{
Name: "api_key",
Usage: "API key for --prompt (or set ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)",
EnvVars: []string{"MICRO_AI_API_KEY"},
},
},
},
{
Name: "gen",
Usage: "Generate various things",
Subcommands: []*cli.Command{
{
Name: "proto",
Usage: "Generate proto requires protoc and protoc-gen-micro",
Action: genProtoHandler,
},
},
},
{
Name: "services",
Usage: "List available services",
Action: func(ctx *cli.Context) error {
services, err := registry.ListServices()
if err != nil {
return err
}
for _, service := range services {
fmt.Println(service.Name)
}
return nil
},
},
{
Name: "call",
Usage: "Call a service",
Flags: []cli.Flag{
&cli.StringSliceFlag{
Name: "header",
Aliases: []string{"H"},
Usage: "Set request headers (can be used multiple times): --header 'Key:Value'",
},
&cli.StringSliceFlag{
Name: "metadata",
Aliases: []string{"m"},
Usage: "Set request metadata (can be used multiple times): --metadata 'Key:Value'",
},
},
Action: func(ctx *cli.Context) error {
args := ctx.Args()
if args.Len() < 2 {
return fmt.Errorf("usage: [service] [endpoint] [request]")
}
service := args.Get(0)
endpoint := args.Get(1)
request := `{}`
if args.Len() == 3 {
request = args.Get(2)
}
// Create context with metadata if provided
// Note: This is for the direct 'micro call' command.
// Dynamic service calls (e.g., 'micro helloworld call') are handled in CallService.
callCtx := context.TODO()
callCtx = util.AddMetadataToContext(callCtx, ctx.StringSlice("metadata"))
callCtx = util.AddMetadataToContext(callCtx, ctx.StringSlice("header"))
req := client.NewRequest(service, endpoint, &bytes.Frame{Data: []byte(request)})
var rsp bytes.Frame
err := client.Call(callCtx, req, &rsp)
if err != nil {
return err
}
fmt.Print(string(rsp.Data))
return nil
},
},
{
Name: "describe",
Usage: "Describe a service",
Action: func(ctx *cli.Context) error {
args := ctx.Args()
if args.Len() != 1 {
return fmt.Errorf("usage: [service]")
}
service := args.Get(0)
services, err := registry.GetService(service)
if err != nil {
return err
}
if len(services) == 0 {
return nil
}
b, _ := json.MarshalIndent(services[0], "", " ")
fmt.Println(string(b))
return nil
},
},
// Note: The following commands are registered in their respective packages:
// - status, logs, stop: remote/remote.go
// - build: build/build.go
// - deploy: deploy/deploy.go
// - init: init/init.go
}...)
cmd.App().Action = func(c *cli.Context) error {
if c.Args().Len() == 0 {
return nil
}
v, err := exec.LookPath("micro-" + c.Args().First())
if err == nil {
ce := exec.Command(v, c.Args().Slice()[1:]...)
ce.Stdout = os.Stdout
ce.Stderr = os.Stderr
return ce.Run()
}
command := c.Args().Get(0)
args := c.Args().Slice()
if srv, err := util.LookupService(command); err != nil {
return util.CliError(err)
} else if srv != nil && util.ShouldRenderHelp(args) {
return cli.Exit(util.FormatServiceUsage(srv, c), 0)
} else if srv != nil {
err := util.CallService(srv, args)
return util.CliError(err)
}
return nil
}
}