Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added state upgrade #3467

Merged
merged 16 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/state/internal/cmdtree/cmdtree.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ func New(prime *primer.Values, args ...string) *CmdTree {
newEvalCommand(prime),
newManifestCommmand(prime),
artifactsCmd,
newUpgradeCommand(prime),
)

return &CmdTree{
Expand Down
43 changes: 43 additions & 0 deletions cmd/state/internal/cmdtree/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cmdtree

import (
"github.com/ActiveState/cli/internal/captain"
"github.com/ActiveState/cli/internal/locale"
"github.com/ActiveState/cli/internal/primer"
"github.com/ActiveState/cli/internal/runners/upgrade"
)

func newUpgradeCommand(prime *primer.Values) *captain.Command {
runner := upgrade.New(prime)

params := upgrade.NewParams()

cmd := captain.NewCommand(
"upgrade",
locale.Tl("upgrade_cmd_title", "Upgrading Project"),
locale.Tl("upgrade_cmd_description", "Upgrade dependencies of a project"),
prime,
[]*captain.Flag{
{
Name: "ts",
Description: locale.T("flag_state_upgrade_ts_description"),
Value: &params.Timestamp,
},
{
Name: "expand",
Description: locale.T("flag_state_upgrade_expand_description"),
Value: &params.Expand,
},
},
[]*captain.Argument{},
func(_ *captain.Command, _ []string) error {
return runner.Run(params)
},
)

cmd.SetGroup(PackagesGroup)
cmd.SetSupportsStructuredOutput()
cmd.SetUnstable(true)

return cmd
}
8 changes: 7 additions & 1 deletion internal/colorize/colorize.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func init() {
defer profile.Measure("colorize:init", time.Now())
var err error
colorRx, err = regexp.Compile(
`\[(HEADING|NOTICE|SUCCESS|ERROR|WARNING|DISABLED|ACTIONABLE|CYAN|GREEN|RED|ORANGE|YELLOW|MAGENTA|/RESET)!?\]`,
`\[(HEADING|BOLD|NOTICE|SUCCESS|ERROR|WARNING|DISABLED|ACTIONABLE|CYAN|GREEN|RED|ORANGE|YELLOW|MAGENTA|/RESET)!?\]`,
)
if err != nil {
panic(fmt.Sprintf("Could not compile regex: %v", err))
Expand All @@ -27,6 +27,7 @@ func init() {

type ColorTheme interface {
Heading(writer io.Writer)
Bold(writer io.Writer)
Notice(writer io.Writer)
Success(writer io.Writer)
Error(writer io.Writer)
Expand All @@ -51,6 +52,11 @@ func (dct defaultColorTheme) Heading(writer io.Writer) {
c.SetStyle(colorstyle.Bold, false)
}

func (dct defaultColorTheme) Bold(writer io.Writer) {
c := colorstyle.New(writer)
c.SetStyle(colorstyle.Bold, false)
}

// Notice switches to bright foreground
func (dct defaultColorTheme) Notice(writer io.Writer) {
colorstyle.New(writer).SetStyle(colorstyle.Default, true)
Expand Down
9 changes: 9 additions & 0 deletions internal/locale/locale.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ func T(translationID string, args ...interface{}) string {
return translateFunction(translationID, args...)
}

// Ts aliases to T, but accepts a list of translationIDs to be translated
func Ts(translationIDs ...string) []string {
result := []string{}
for _, id := range translationIDs {
result = append(result, T(id))
}
return result
}

// Tr is like T but it accepts string params that will be used as numbered params, eg. V0, V1, V2 etc
func Tr(translationID string, values ...string) string {
return T(translationID, parseInput(values...))
Expand Down
32 changes: 32 additions & 0 deletions internal/locale/locales/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1549,3 +1549,35 @@ warn_additional_requirements:
[WARNING]WARNING:[/RESET] This project has additional build criteria that cannot be managed through the State Tool. Please edit your [ACTIONABLE]buildscript.as[/RESET] file manually to modify these:
migrate_project_error:
other: Could not migrate your project files. Please address any errors and try again. For full detail view your log file with '[ACTIONABLE]state export log -i 0[/RESET]'.
upgrade_solving:
other: • Searching for available upgrades for your requirements
upgrade_confirm:
other: Would you like to install these upgrades?
upgrade_no_changes:
other: No upgrades were found for your project. Note that requirements with fixed version numbers will never be upgraded.
upgrade_aborted:
other: Upgrade aborted
upgrade_success:
other: Upgrade completed
upgrade_field_same:
other: "[CYAN]{{.V0}}[/RESET]"
upgrade_field_change:
other: "[CYAN]{{.V0}}[/RESET] > [BOLD][ACTIONABLE]{{.V1}}[/RESET]"
name:
Comment on lines +1565 to +1566
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this not need a second [/RESET]?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the resets act on everything. It's basically telling the shell "go back to normal rendering".

other: Name
version:
other: Version
license:
other: License
vulnerabilities:
other: Vulnerabilities (CVEs)
dependency_row:
other: " [DISABLED]{{.V0}}[/RESET] [CYAN]{{.V1}}[/RESET] [DISABLED]transitive dependencies touched[/RESET]"
dependency_detail_row:
other: " [DISABLED]{{.V0}} {{.V1}}[/RESET] {{.V2}}"
namespace_row:
other: " [DISABLED]{{.V0}} namespace:[/RESET] [CYAN]{{.V1}}[/RESET]"
flag_state_upgrade_expand_description:
other: Show individual transitive dependency changes rather than a summary
flag_state_upgrade_ts_description:
other: Manually specify the timestamp to 'upgrade' to. Can be either 'now' or RFC3339 formatted timestamp.
26 changes: 21 additions & 5 deletions internal/output/presets.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,35 @@ func (h Emphasize) MarshalStructured(f Format) interface{} {
return Suppress
}

type preparedOutput struct {
plain interface{}
type plainOutput struct {
plain interface{}
}

type structuredOutput struct {
structured interface{}
}

func (o *preparedOutput) MarshalOutput(_ Format) interface{} {
type preparedOutput struct {
*plainOutput
*structuredOutput
}

func (o *plainOutput) MarshalOutput(_ Format) interface{} {
return o.plain
}

func (o *preparedOutput) MarshalStructured(_ Format) interface{} {
func (o *structuredOutput) MarshalStructured(_ Format) interface{} {
return o.structured
}

func Prepare(plain interface{}, structured interface{}) *preparedOutput {
return &preparedOutput{plain, structured}
return &preparedOutput{&plainOutput{plain}, &structuredOutput{structured}}
}

func Structured(structured interface{}) *structuredOutput {
return &structuredOutput{structured}
}

const TreeMid = "├─"
const TreeLink = "│"
const TreeEnd = "└─"
65 changes: 65 additions & 0 deletions internal/runbits/commits_runbit/time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package commits_runbit

import (
"time"

"github.com/ActiveState/cli/internal/captain"
"github.com/ActiveState/cli/internal/errs"
"github.com/ActiveState/cli/pkg/localcommit"
"github.com/ActiveState/cli/pkg/platform/authentication"
"github.com/ActiveState/cli/pkg/platform/model"
"github.com/ActiveState/cli/pkg/project"
)

// ExpandTime returns a timestamp based on the given "--ts" value.
// If the timestamp was already defined, we just return it.
// If "now" was given, returns "now" according to the platform.
// Otherwise, returns the specified timestamp or nil (which falls back on the default Platform
// timestamp for a given operation)
func ExpandTime(ts *captain.TimeValue, auth *authentication.Auth) (time.Time, error) {
if ts.Time != nil {
return *ts.Time, nil
}

if ts.Now() {
latest, err := model.FetchLatestRevisionTimeStamp(auth)
if err != nil {
return time.Time{}, errs.Wrap(err, "Unable to determine latest revision time")
}
return latest, nil
}

latest, err := model.FetchLatestTimeStamp(auth)
if err != nil {
return time.Time{}, errs.Wrap(err, "Unable to fetch latest Platform timestamp")
}

return latest, nil
}

// ExpandTimeForProject is the same as ExpandTime except that it ensures the returned time is either the same or
// later than that of the most recent commit.
func ExpandTimeForProject(ts *captain.TimeValue, auth *authentication.Auth, proj *project.Project) (time.Time, error) {
timestamp, err := ExpandTime(ts, auth)
if err != nil {
return time.Time{}, errs.Wrap(err, "Unable to expand time")
}

if proj != nil {
commitID, err := localcommit.Get(proj.Dir())
if err != nil {
return time.Time{}, errs.Wrap(err, "Unable to get commit ID")
}

atTime, err := model.FetchTimeStampForCommit(commitID, auth)
if err != nil {
return time.Time{}, errs.Wrap(err, "Unable to get commit time")
}

if atTime.After(timestamp) {
return *atTime, nil
}
}

return timestamp, nil
}
10 changes: 5 additions & 5 deletions internal/runbits/cves/cves.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ func (c *CveReport) Report(newBuildPlan *buildplan.BuildPlan, oldBuildPlan *buil
}

var ingredients []*request.Ingredient
for _, artifact := range changeset.Added {
for _, ing := range artifact.Ingredients {
for _, change := range changeset.Filter(buildplan.ArtifactAdded) {
for _, ing := range change.Artifact.Ingredients {
ingredients = append(ingredients, &request.Ingredient{
Namespace: ing.Namespace,
Name: ing.Name,
Expand All @@ -57,12 +57,12 @@ func (c *CveReport) Report(newBuildPlan *buildplan.BuildPlan, oldBuildPlan *buil
}
}

for _, change := range changeset.Updated {
for _, change := range changeset.Filter(buildplan.ArtifactUpdated) {
if !change.VersionsChanged() {
continue // For CVE reporting we only care about ingredient changes
}

for _, ing := range change.To.Ingredients {
for _, ing := range change.Artifact.Ingredients {
ingredients = append(ingredients, &request.Ingredient{
Namespace: ing.Namespace,
Name: ing.Name,
Expand Down Expand Up @@ -118,7 +118,7 @@ func (c *CveReport) shouldSkipReporting(changeset buildplan.ArtifactChangeset) b
return true
}

return len(changeset.Added) == 0 && len(changeset.Updated) == 0
return len(changeset.Filter(buildplan.ArtifactAdded, buildplan.ArtifactUpdated)) == 0
}

func (c *CveReport) shouldPromptForSecurity(vulnerabilities model.VulnerableIngredientsByLevels) bool {
Expand Down
18 changes: 10 additions & 8 deletions internal/runbits/dependencies/changesummary.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func OutputChangeSummary(out output.Outputer, newBuildPlan *buildplan.BuildPlan,
dependencies := buildplan.Ingredients{}
directDependencies := buildplan.Ingredients{}
changeset := newBuildPlan.DiffArtifacts(oldBuildPlan, false)
for _, a := range changeset.Added {
for _, change := range changeset.Filter(buildplan.ArtifactAdded) {
a := change.Artifact
if _, exists := requested[a.ArtifactID]; !exists {
continue
}
Expand All @@ -43,16 +44,17 @@ func OutputChangeSummary(out output.Outputer, newBuildPlan *buildplan.BuildPlan,
}

// Check for any direct dependencies added by a requested package update.
for _, u := range changeset.Updated {
if _, exists := requested[u.To.ArtifactID]; !exists {
for _, change := range changeset.Filter(buildplan.ArtifactUpdated) {
if _, exists := requested[change.Artifact.ArtifactID]; !exists {
continue
}
for _, dep := range u.To.RuntimeDependencies(false) {
for _, a := range changeset.Added {
for _, dep := range change.Artifact.RuntimeDependencies(false, nil) {
for _, subchange := range changeset.Filter(buildplan.ArtifactAdded) {
a := subchange.Artifact
if a.ArtifactID != dep.ArtifactID {
continue
}
v := fmt.Sprintf("%s@%s", u.To.Name(), u.To.Version()) // updated/requested package, not added package
v := fmt.Sprintf("%s@%s", change.Artifact.Name(), change.Artifact.Version()) // updated/requested package, not added package
addedString = append(addedLocale, v)
addedLocale = append(addedLocale, fmt.Sprintf("[ACTIONABLE]%s[/RESET]", v))

Expand Down Expand Up @@ -104,9 +106,9 @@ func OutputChangeSummary(out output.Outputer, newBuildPlan *buildplan.BuildPlan,
// depending on whether or not it has subdependencies, and whether or not showUpdatedPackages is
// `true`.
for i, ingredient := range directDependencies {
prefix := "├─"
prefix := output.TreeMid
if i == len(directDependencies)-1 {
prefix = "└─"
prefix = output.TreeEnd
}

// Retrieve runtime dependencies, and then filter out any dependencies that are common between all added ingredients.
Expand Down
4 changes: 2 additions & 2 deletions internal/runbits/dependencies/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ func OutputSummary(out output.Outputer, directDependencies buildplan.Artifacts)
out.Notice(locale.Tl("setting_up_dependencies", " Setting up the following dependencies:"))

for i, ingredient := range ingredients {
prefix := " ├─"
prefix := " " + output.TreeMid
if i == len(ingredients)-1 {
prefix = " └─"
prefix = " " + output.TreeEnd
}

subdependencies := ""
Expand Down
8 changes: 4 additions & 4 deletions internal/runners/artifacts/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ func (b *Artifacts) outputPlain(out *StructuredOutput, fullID bool) error {
switch {
case len(artifact.Errors) > 0:
b.out.Print(fmt.Sprintf(" • %s ([ERROR]%s[/RESET])", artifact.Name, locale.T("artifact_status_failed")))
b.out.Print(fmt.Sprintf(" ├─ %s: [ERROR]%s[/RESET]", locale.T("artifact_status_failed_message"), strings.Join(artifact.Errors, ": ")))
b.out.Print(fmt.Sprintf(" └─ %s: [ACTIONABLE]%s[/RESET]", locale.T("artifact_status_failed_log"), artifact.LogURL))
b.out.Print(fmt.Sprintf(" %s %s: [ERROR]%s[/RESET]", output.TreeMid, locale.T("artifact_status_failed_message"), strings.Join(artifact.Errors, ": ")))
b.out.Print(fmt.Sprintf(" %s %s: [ACTIONABLE]%s[/RESET]", output.TreeEnd, locale.T("artifact_status_failed_log"), artifact.LogURL))
continue
case artifact.status == types.ArtifactSkipped:
b.out.Print(fmt.Sprintf(" • %s ([NOTICE]%s[/RESET])", artifact.Name, locale.T("artifact_status_skipped")))
Expand All @@ -227,8 +227,8 @@ func (b *Artifacts) outputPlain(out *StructuredOutput, fullID bool) error {
switch {
case len(artifact.Errors) > 0:
b.out.Print(fmt.Sprintf(" • %s ([ERROR]%s[/RESET])", artifact.Name, locale.T("artifact_status_failed")))
b.out.Print(fmt.Sprintf(" ├─ %s: [ERROR]%s[/RESET]", locale.T("artifact_status_failed_message"), strings.Join(artifact.Errors, ": ")))
b.out.Print(fmt.Sprintf(" └─ %s: [ACTIONABLE]%s[/RESET]", locale.T("artifact_status_failed_log"), artifact.LogURL))
b.out.Print(fmt.Sprintf(" %s %s: [ERROR]%s[/RESET]", output.TreeMid, locale.T("artifact_status_failed_message"), strings.Join(artifact.Errors, ": ")))
b.out.Print(fmt.Sprintf(" %s %s: [ACTIONABLE]%s[/RESET]", output.TreeEnd, locale.T("artifact_status_failed_log"), artifact.LogURL))
continue
case artifact.status == types.ArtifactSkipped:
b.out.Print(fmt.Sprintf(" • %s ([NOTICE]%s[/RESET])", artifact.Name, locale.T("artifact_status_skipped")))
Expand Down
7 changes: 4 additions & 3 deletions internal/runners/branch/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"sort"
"strings"

"github.com/ActiveState/cli/internal/output"
"github.com/ActiveState/cli/pkg/platform/api/mono/mono_models"
"github.com/ActiveState/cli/pkg/platform/model"
)
Expand All @@ -17,9 +18,9 @@ type branchNode struct {
type tree map[branchNode]tree

const (
prefixLink string = "│"
prefixMid string = "├─"
prefixEnd string = "└─"
prefixLink string = output.TreeLink
prefixMid string = output.TreeMid
prefixEnd string = output.TreeEnd

branchFormatting string = "[NOTICE]%s[/RESET]"
localBranchFormatting string = "[ACTIONABLE]%s[/RESET] [DISABLED](Current)[/RESET]"
Expand Down
4 changes: 2 additions & 2 deletions internal/runners/cve/cve.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ func (rd *cveOutput) MarshalOutput(format output.Format) interface{} {
})

for i, d := range ap.Details {
bar := "├─"
bar := output.TreeMid
if i == len(ap.Details)-1 {
bar = "└─"
bar = output.TreeEnd
}
severity := d.Severity
if severity == "CRITICAL" {
Expand Down
2 changes: 1 addition & 1 deletion internal/runners/manifest/requirements.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (o requirements) Print(out output.Outputer) {
}

if req.Namespace != "" {
requirementOutput.Namespace = locale.Tl("manifest_namespace", " └─ [DISABLED]namespace:[/RESET] [CYAN]{{.V0}}[/RESET]", req.Namespace)
requirementOutput.Namespace = locale.Tr("namespace_row", output.TreeEnd, req.Namespace)
}

requirementsOutput = append(requirementsOutput, requirementOutput)
Expand Down
Loading
Loading