mukan-ignite/ignite/pkg/debugger/server.go
Mukan Erkin Törük 26b204bd04
Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
feat: fork Ignite CLI v29 as Mukan Ignite — remove cosmos-sdk restrictions
2026-05-11 03:31:37 +03:00

184 lines
4.2 KiB
Go

package debugger
import (
"context"
"net"
"github.com/go-delve/delve/pkg/logflags"
"github.com/go-delve/delve/pkg/terminal"
"github.com/go-delve/delve/service"
"github.com/go-delve/delve/service/debugger"
"github.com/go-delve/delve/service/rpc2"
"github.com/go-delve/delve/service/rpccommon"
"golang.org/x/sync/errgroup"
"github.com/ignite/cli/v29/ignite/pkg/errors"
)
const (
// DefaultAddress defines the default debug server address.
DefaultAddress = "127.0.0.1:30500"
// DefaultWorkingDir defines the default directory to use as
// working dir when running the app binary that will be debugged.
DefaultWorkingDir = "."
)
// Option configures debugging.
type Option func(*debuggerOptions)
type debuggerOptions struct {
disconnectChan chan struct{}
address, workingDir string
listener net.Listener
binaryArgs []string
clientRunHook, serverStartHook func()
}
// Address sets the address for the debug server.
func Address(address string) Option {
return func(o *debuggerOptions) {
o.address = address
}
}
// DisconnectChannel sets the channel used by the server to signal when the client disconnects.
func DisconnectChannel(c chan struct{}) Option {
return func(o *debuggerOptions) {
o.disconnectChan = c
}
}
// Listener sets a custom listener to serve requests.
func Listener(l net.Listener) Option {
return func(o *debuggerOptions) {
o.listener = l
}
}
// WorkingDir sets the working directory of the new process.
func WorkingDir(path string) Option {
return func(o *debuggerOptions) {
o.workingDir = path
}
}
// BinaryArgs sets command line argument for the new process.
func BinaryArgs(args ...string) Option {
return func(o *debuggerOptions) {
o.binaryArgs = args
}
}
// ClientRunHook sets a function to be executed right before debug client is run.
func ClientRunHook(fn func()) Option {
return func(o *debuggerOptions) {
o.clientRunHook = fn
}
}
// ServerStartHook sets a function to be executed right before debug server starts.
func ServerStartHook(fn func()) Option {
return func(o *debuggerOptions) {
o.serverStartHook = fn
}
}
// Start starts a debug server.
func Start(ctx context.Context, binaryPath string, options ...Option) (err error) {
o := applyDebuggerOptions(options...)
listener := o.listener
if listener == nil {
var c net.ListenConfig
listener, err = c.Listen(ctx, "tcp", o.address)
if err != nil {
return err
}
defer listener.Close()
}
if err = disableDelveLogging(); err != nil {
return err
}
server := rpccommon.NewServer(&service.Config{
Listener: listener,
AcceptMulti: false,
APIVersion: 2,
CheckLocalConnUser: true,
DisconnectChan: o.disconnectChan,
ProcessArgs: append([]string{binaryPath}, o.binaryArgs...),
Debugger: debugger.Config{
WorkingDir: o.workingDir,
Backend: "default",
},
})
if o.serverStartHook != nil {
o.serverStartHook()
}
if err = server.Run(); err != nil {
return errors.Errorf("failed to run debug server: %w", err)
}
defer server.Stop() //nolint:errcheck
// Wait until the context is done or the connected client disconnects
select {
case <-ctx.Done():
case <-o.disconnectChan:
}
return nil
}
// Run runs a debug client.
func Run(ctx context.Context, binaryPath string, options ...Option) error {
listener, conn := service.ListenerPipe()
defer listener.Close()
o := applyDebuggerOptions(options...)
options = append(options, Listener(listener))
g, ctx := errgroup.WithContext(ctx)
// Start the debugger server
g.Go(func() error {
return Start(ctx, binaryPath, options...)
})
// Start the debug client
g.Go(func() error {
client := rpc2.NewClientFromConn(conn)
term := terminal.New(client, nil)
if o.clientRunHook != nil {
o.clientRunHook()
}
_, err := term.Run()
return err
})
return g.Wait()
}
func applyDebuggerOptions(options ...Option) debuggerOptions {
o := debuggerOptions{
address: DefaultAddress,
workingDir: DefaultWorkingDir,
disconnectChan: make(chan struct{}),
}
for _, apply := range options {
apply(&o)
}
return o
}
func disableDelveLogging() error {
return logflags.Setup(false, "", "")
}