Skip to content

Commit

Permalink
Merge branch 'version/0-43-0-RC1' into mitchell/dx-2213
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchell-as committed Nov 2, 2023
2 parents 301fe30 + ef12da9 commit 0034f49
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 25 deletions.
4 changes: 3 additions & 1 deletion cmd/state/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ func run(args []string, isInteractive bool, cfg *config.Instance, out output.Out
if childCmd != nil {
cmdName = childCmd.JoinedSubCommandNames() + " "
}
err = errs.AddTips(err, locale.Tl("err_tip_run_help", "Run → [ACTIONABLE]`state {{.V0}}--help`[/RESET] for general help", cmdName))
if !out.Type().IsStructured() {
err = errs.AddTips(err, locale.Tl("err_tip_run_help", "Run → [ACTIONABLE]`state {{.V0}}--help`[/RESET] for general help", cmdName))
}
errors.ReportError(err, cmds.Command(), an)
}

Expand Down
9 changes: 5 additions & 4 deletions internal/output/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ func (f *JSON) Fprint(writer io.Writer, value interface{}) {
}

type StructuredError struct {
Error string `json:"error"`
Error string `json:"error"`
Tips []string `json:"tips,omitempty"`
}

// Error will marshal and print the given value to the error writer
Expand Down Expand Up @@ -120,11 +121,11 @@ func toStructuredError(v interface{}) StructuredError {
case StructuredError:
return vv
case error:
return StructuredError{locale.JoinedErrorMessage(vv)}
return StructuredError{Error: locale.JoinedErrorMessage(vv)}
case string:
return StructuredError{vv}
return StructuredError{Error: vv}
}
message := fmt.Sprintf("Not a recognized error format: %v", v)
multilog.Error(message)
return StructuredError{message}
return StructuredError{Error: message}
}
2 changes: 1 addition & 1 deletion internal/output/mediator.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func mediatorValue(v interface{}, format Format) interface{} {
if vt, ok := v.(StructuredMarshaller); ok {
return vt.MarshalStructured(format)
}
return StructuredError{locale.Tr("err_no_structured_output", string(format))}
return StructuredError{Error: locale.Tr("err_no_structured_output", string(format))}
}
if vt, ok := v.(Marshaller); ok {
return vt.MarshalOutput(format)
Expand Down
2 changes: 1 addition & 1 deletion internal/output/mediator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func Test_mediatorValue(t *testing.T) {
"unstructured",
JSONFormatName,
},
StructuredError{locale.Tr("err_no_structured_output", string(JSONFormatName))},
StructuredError{Error: locale.Tr("err_no_structured_output", string(JSONFormatName))},
},
}
for _, tt := range tests {
Expand Down
31 changes: 19 additions & 12 deletions internal/runbits/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,7 @@ func (o *OutputError) MarshalOutput(f output.Format) interface{} {
}

// Concatenate error tips
errorTips := []string{}
err := o.error
for _, err := range errs.Unpack(err) {
if v, ok := err.(ErrorTips); ok {
for _, tip := range v.ErrorTips() {
if !funk.Contains(errorTips, tip) {
errorTips = append(errorTips, tip)
}
}
}
}
errorTips := getErrorTips(o.error)
errorTips = append(errorTips, locale.Tl("err_help_forum", "Ask For Help → [ACTIONABLE]{{.V0}}[/RESET]", constants.ForumsURL))

// Print tips
Expand All @@ -92,6 +82,23 @@ func (o *OutputError) MarshalOutput(f output.Format) interface{} {
return strings.Join(outLines, "\n")
}

func getErrorTips(err error) []string {
errorTips := []string{}
for _, err := range errs.Unpack(err) {
v, ok := err.(ErrorTips)
if !ok {
continue
}
for _, tip := range v.ErrorTips() {
if funk.Contains(errorTips, tip) {
continue
}
errorTips = append(errorTips, tip)
}
}
return errorTips
}

func (o *OutputError) MarshalStructured(f output.Format) interface{} {
var userFacingError errs.UserFacingError
var message string
Expand All @@ -100,7 +107,7 @@ func (o *OutputError) MarshalStructured(f output.Format) interface{} {
} else {
message = locale.JoinedErrorMessage(o.error)
}
return output.StructuredError{message}
return output.StructuredError{message, getErrorTips(o.error)}
}

func trimError(msg string) string {
Expand Down
18 changes: 13 additions & 5 deletions internal/updater/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,45 @@ package updater
import (
"crypto/sha256"
"fmt"
"io/ioutil"

"github.com/ActiveState/cli/internal/analytics"
anaConst "github.com/ActiveState/cli/internal/analytics/constants"
"github.com/ActiveState/cli/internal/analytics/dimensions"
"github.com/ActiveState/cli/internal/errs"
"github.com/ActiveState/cli/internal/fileutils"
"github.com/ActiveState/cli/internal/httpreq"
"github.com/ActiveState/cli/internal/logging"
"github.com/ActiveState/cli/internal/retryhttp"
"github.com/ActiveState/cli/internal/rtutils/ptr"
)

const CfgUpdateTag = "update_tag"

type Fetcher struct {
httpreq *httpreq.Client
an analytics.Dispatcher
retryhttp *retryhttp.Client
an analytics.Dispatcher
}

func NewFetcher(an analytics.Dispatcher) *Fetcher {
return &Fetcher{httpreq.New(), an}
return &Fetcher{retryhttp.DefaultClient, an}
}

func (f *Fetcher) Fetch(update *UpdateInstaller, targetDir string) error {
logging.Debug("Fetching update: %s", update.url)
b, _, err := f.httpreq.Get(update.url)
resp, err := f.retryhttp.Get(update.url)
if err != nil {
msg := fmt.Sprintf("Fetch %s failed", update.url)
f.analyticsEvent(update.AvailableUpdate.Version, msg)
return errs.Wrap(err, msg)
}

b, err := ioutil.ReadAll(resp.Body)
if err != nil {
msg := "Could not read response body"
f.analyticsEvent(update.AvailableUpdate.Version, msg)
return errs.Wrap(err, msg)
}

if err := verifySha(b, update.AvailableUpdate.Sha256); err != nil {
msg := "Could not verify sha256"
f.analyticsEvent(update.AvailableUpdate.Version, msg)
Expand Down
3 changes: 2 additions & 1 deletion test/integration/activate_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ version: %s
`, constants.BranchName, constants.Version))

ts.PrepareActiveStateYAML(content)
ts.PrepareCommitIdFile("59404293-e5a9-4fd0-8843-77cd4761b5b5")

// Pull to ensure we have an up to date config file
cp := ts.Spawn("pull")
Expand Down Expand Up @@ -453,7 +454,7 @@ func (suite *ActivateIntegrationTestSuite) TestActivate_NamespaceWins() {
suite.Require().NoError(err)

// Create the project file at the root of the temp dir
ts.PrepareProject("ActiveState-CLI/Python3", "")
ts.PrepareProject("ActiveState-CLI/Python3", "59404293-e5a9-4fd0-8843-77cd4761b5b5")

// Pull to ensure we have an up to date config file
cp := ts.Spawn("pull")
Expand Down
6 changes: 6 additions & 0 deletions test/integration/checkout_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ func (suite *CheckoutIntegrationTestSuite) TestJSON() {
cp := ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/small-python", "-o", "json"))
cp.ExpectExitCode(0)
AssertValidJSON(suite.T(), cp)

cp = ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Bogus-Project-That-Doesnt-Exist", "-o", "json"))
cp.Expect("does not exist") // error
cp.Expect(`"tips":["If this is a private project`) // tip
cp.ExpectNotExitCode(0)
AssertValidJSON(suite.T(), cp)
}

func (suite *CheckoutIntegrationTestSuite) TestCheckoutCaseInsensitive() {
Expand Down

0 comments on commit 0034f49

Please sign in to comment.