Skip to content

Commit

Permalink
atlasexec: expose cli error with exit code (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
masseelch authored Apr 30, 2024
1 parent 865efa3 commit 97e7fef
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 27 deletions.
55 changes: 32 additions & 23 deletions atlasexec/atlas.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@ func (c *Client) MigrateDown(ctx context.Context, params *MigrateDownParams) (*M
}
args = append(args, params.Vars.AsArgs()...)
r, err := c.runCommand(ctx, args)
if cliErr := (cliError{}); errors.As(err, &cliErr) && cliErr.stderr == "" {
r = strings.NewReader(cliErr.stdout)
if cliErr := (&Error{}); errors.As(err, &cliErr) && cliErr.Stderr == "" {
r = strings.NewReader(cliErr.Stdout)
err = nil
}
// NOTE: This command only support one result.
Expand Down Expand Up @@ -465,8 +465,8 @@ func (c *Client) MigrateLint(ctx context.Context, params *MigrateLintParams) (*S
return nil, err
}
r, err := c.runCommand(ctx, args)
if cliErr := (cliError{}); errors.As(err, &cliErr) && cliErr.stderr == "" {
r = strings.NewReader(cliErr.stdout)
if cliErr := (&Error{}); errors.As(err, &cliErr) && cliErr.Stderr == "" {
r = strings.NewReader(cliErr.Stdout)
err = nil
}
// NOTE: This command only support one result.
Expand All @@ -478,7 +478,7 @@ func (c *Client) MigrateLint(ctx context.Context, params *MigrateLintParams) (*S
var LintErr = errors.New("lint error")

// MigrateLintError runs the 'migrate lint' command, the output is written to params.Writer and reports
// if an error occurred. If the error is a setup error, a cliError is returned. If the error is a lint error,
// if an error occurred. If the error is a setup error, a Error is returned. If the error is a lint error,
// LintErr is returned.
func (c *Client) MigrateLintError(ctx context.Context, params *MigrateLintParams) error {
args, err := lintArgs(params)
Expand All @@ -487,17 +487,17 @@ func (c *Client) MigrateLintError(ctx context.Context, params *MigrateLintParams
}
r, err := c.runCommand(ctx, args)
var (
cliErr cliError
cliErr *Error
isCLI = errors.As(err, &cliErr)
)
// Setup errors.
if isCLI && cliErr.stderr != "" {
if isCLI && cliErr.Stderr != "" {
return cliErr
}
// Lint errors.
if isCLI && cliErr.stdout != "" {
if isCLI && cliErr.Stdout != "" {
err = LintErr
r = strings.NewReader(cliErr.stdout)
r = strings.NewReader(cliErr.Stdout)
}
// Unknown errors.
if err != nil && !isCLI {
Expand Down Expand Up @@ -572,10 +572,14 @@ func (c *Client) runCommand(ctx context.Context, args []string) (io.Reader, erro
cmd.Stderr = &stderr
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return nil, cliError{
stderr: strings.TrimSpace(stderr.String()),
stdout: strings.TrimSpace(stdout.String()),
cerr := &Error{
Stderr: strings.TrimSpace(stderr.String()),
Stdout: strings.TrimSpace(stdout.String()),
}
if exitErr := (&exec.ExitError{}); errors.As(err, &exitErr) {
cerr.err = exitErr
}
return nil, cerr
}
return &stdout, nil
}
Expand Down Expand Up @@ -629,17 +633,22 @@ func TempFile(content, ext string) (string, func() error, error) {
}, nil
}

type cliError struct {
stdout string
stderr string
type Error struct {
err *exec.ExitError
Stdout string
Stderr string
}

// Error implements the error interface.
func (e cliError) Error() string {
if e.stderr != "" {
return e.stderr
func (e *Error) Error() string {
if e.Stderr != "" {
return e.Stderr
}
return e.stdout
return e.Stdout
}

func (e *Error) Unwrap() error {
return e.err
}

func (v Vars) AsArgs() []string {
Expand Down Expand Up @@ -690,8 +699,8 @@ func jsonDecode[T any](r io.Reader, err error) ([]*T, error) {
case nil:
dst = append(dst, &m)
default:
return nil, cliError{
stdout: string(buf),
return nil, &Error{
Stdout: string(buf),
}
}
}
Expand All @@ -700,8 +709,8 @@ func jsonDecode[T any](r io.Reader, err error) ([]*T, error) {
func jsonDecodeErr[T any](fn func([]*T) error) func(io.Reader, error) ([]*T, error) {
return func(r io.Reader, err error) ([]*T, error) {
if err != nil {
if cliErr := (cliError{}); errors.As(err, &cliErr) && cliErr.stderr == "" {
d, err := jsonDecode[T](strings.NewReader(cliErr.stdout), nil)
if cliErr := (&Error{}); errors.As(err, &cliErr) && cliErr.Stderr == "" {
d, err := jsonDecode[T](strings.NewReader(cliErr.Stdout), nil)
if err == nil {
return nil, fn(d)
}
Expand Down
4 changes: 2 additions & 2 deletions atlasexec/atlas_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ type (
}
// MigrateDown contains a summary of a migration down attempt on a database.
MigrateDown struct {
Planned []File `json:"Planned,omitempty"` // Pending migration files
Reverted []*RevertedFile `json:"Reverted,omitempty"` // Applied files
Planned []File `json:"Planned,omitempty"` // Planned migration files
Reverted []*RevertedFile `json:"Reverted,omitempty"` // Reverted files
Current string `json:"Current,omitempty"` // Current migration version
Target string `json:"Target,omitempty"` // Target migration version
Total int `json:"Total,omitempty"` // Total number of migrations to revert
Expand Down
6 changes: 4 additions & 2 deletions atlasexec/atlas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ func Test_MigrateApply(t *testing.T) {
})
require.ErrorContains(t, err, `required flag "url" not set`)
require.Nil(t, got)
var exerr *exec.ExitError
require.ErrorAs(t, err, &exerr)
// Set the env var and try again
os.Setenv("DB_URL", "sqlite://file?_fk=1&cache=shared&mode=memory")
got, err = c.MigrateApply(context.Background(), &atlasexec.MigrateApplyParams{
Expand Down Expand Up @@ -837,7 +839,7 @@ func TestMigrateApply(t *testing.T) {
_, err := c.MigrateApply(context.Background(), tt.params)
require.Error(t, err)
// The script mock-args.sh exit with an error code.
// So, our atlasexec.MigrateApply should return a cliError.
// So, our atlasexec.MigrateApply should return a Error.
// Which contains all output from the script (both stdout and stderr).
require.Equal(t, tt.expect, err.Error())
})
Expand Down Expand Up @@ -909,7 +911,7 @@ func TestMigrateDown(t *testing.T) {
_, err := c.MigrateDown(context.Background(), tt.params)
require.Error(t, err)
// The script mock-args.sh exit with an error code.
// So, our atlasexec.MigrateApply should return a cliError.
// So, our atlasexec.MigrateApply should return a Error.
// Which contains all output from the script (both stdout and stderr).
require.Equal(t, tt.expect, err.Error())
})
Expand Down

0 comments on commit 97e7fef

Please sign in to comment.