github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/packager/deprecated/common.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2021-Present The Jackal Authors
     3  
     4  // Package deprecated handles package deprecations and migrations
     5  package deprecated
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  
    11  	"slices"
    12  
    13  	"github.com/Masterminds/semver/v3"
    14  	"github.com/Racer159/jackal/src/config"
    15  	"github.com/Racer159/jackal/src/pkg/message"
    16  	"github.com/Racer159/jackal/src/types"
    17  	"github.com/pterm/pterm"
    18  )
    19  
    20  // BreakingChange represents a breaking change that happened on a specified Jackal version
    21  type BreakingChange struct {
    22  	version    *semver.Version
    23  	title      string
    24  	mitigation string
    25  }
    26  
    27  // List of migrations tracked in the jackal.yaml build data.
    28  const (
    29  	// This should be updated when a breaking change is introduced to the Jackal package structure.  See: https://github.com/Racer159/jackal/releases/tag/v0.27.0
    30  	LastNonBreakingVersion   = "v0.27.0"
    31  	ScriptsToActionsMigrated = "scripts-to-actions"
    32  	PluralizeSetVariable     = "pluralize-set-variable"
    33  )
    34  
    35  // List of breaking changes to warn the user of.
    36  var breakingChanges = []BreakingChange{
    37  	{
    38  		version:    semver.New(0, 26, 0, "", ""),
    39  		title:      "Jackal container images are now mutated based on tag instead of repository name.",
    40  		mitigation: "Reinitialize the cluster using v0.26.0 or later and redeploy existing packages to update the image references (you can view existing packages with 'jackal package list' and view cluster images with 'jackal tools registry catalog').",
    41  	},
    42  }
    43  
    44  // MigrateComponent runs all migrations on a component.
    45  // Build should be empty on package create, but include just in case someone copied a jackal.yaml from a jackal package.
    46  func MigrateComponent(build types.JackalBuildData, component types.JackalComponent) (migratedComponent types.JackalComponent, warnings []string) {
    47  	migratedComponent = component
    48  
    49  	// If the component has already been migrated, clear the deprecated scripts.
    50  	if slices.Contains(build.Migrations, ScriptsToActionsMigrated) {
    51  		migratedComponent.DeprecatedScripts = types.DeprecatedJackalComponentScripts{}
    52  	} else {
    53  		// Otherwise, run the migration.
    54  		var warning string
    55  		if migratedComponent, warning = migrateScriptsToActions(migratedComponent); warning != "" {
    56  			warnings = append(warnings, warning)
    57  		}
    58  	}
    59  
    60  	// If the component has already been migrated, clear the setVariable definitions.
    61  	if slices.Contains(build.Migrations, PluralizeSetVariable) {
    62  		migratedComponent = clearSetVariables(migratedComponent)
    63  	} else {
    64  		// Otherwise, run the migration.
    65  		var warning string
    66  		if migratedComponent, warning = migrateSetVariableToSetVariables(migratedComponent); warning != "" {
    67  			warnings = append(warnings, warning)
    68  		}
    69  	}
    70  
    71  	// Show a warning if the component contains a group as that has been deprecated and will be removed.
    72  	if component.DeprecatedGroup != "" {
    73  		warnings = append(warnings, fmt.Sprintf("Component %s is using group which has been deprecated and will be removed in v1.0.0.  Please migrate to another solution.", component.Name))
    74  	}
    75  
    76  	// Future migrations here.
    77  	return migratedComponent, warnings
    78  }
    79  
    80  // PrintBreakingChanges prints the breaking changes between the provided version and the current CLIVersion
    81  func PrintBreakingChanges(deployedJackalVersion string) {
    82  	deployedSemver, err := semver.NewVersion(deployedJackalVersion)
    83  	if err != nil {
    84  		message.Debugf("Unable to check for breaking changes between Jackal versions")
    85  		return
    86  	}
    87  
    88  	applicableBreakingChanges := []BreakingChange{}
    89  
    90  	// Calculate the applicable breaking changes
    91  	for _, breakingChange := range breakingChanges {
    92  		if deployedSemver.LessThan(breakingChange.version) {
    93  			applicableBreakingChanges = append(applicableBreakingChanges, breakingChange)
    94  		}
    95  	}
    96  
    97  	if len(applicableBreakingChanges) > 0 {
    98  		// Print header information
    99  		message.HorizontalRule()
   100  		message.Title("Potential Breaking Changes", "breaking changes that may cause issues with this package")
   101  
   102  		// Print information about the versions
   103  		format := pterm.FgYellow.Sprint("CLI version ") + "%s" + pterm.FgYellow.Sprint(" is being used to deploy to a cluster that was initialized with ") +
   104  			"%s" + pterm.FgYellow.Sprint(". Between these versions there are the following breaking changes to consider:")
   105  		cliVersion := pterm.Bold.Sprintf(config.CLIVersion)
   106  		deployedVersion := pterm.Bold.Sprintf(deployedJackalVersion)
   107  		message.Warnf(format, cliVersion, deployedVersion)
   108  
   109  		// Print each applicable breaking change
   110  		for idx, applicableBreakingChange := range applicableBreakingChanges {
   111  			titleFormat := pterm.Bold.Sprintf("\n %d. ", idx+1) + "%s"
   112  
   113  			pterm.Printfln(titleFormat, applicableBreakingChange.title)
   114  
   115  			mitigationText := message.Paragraphn(96, "%s", pterm.FgLightCyan.Sprint(applicableBreakingChange.mitigation))
   116  
   117  			pterm.Printfln("\n  - %s", pterm.Bold.Sprint("Mitigation:"))
   118  			pterm.Printfln("    %s", strings.ReplaceAll(mitigationText, "\n", "\n    "))
   119  		}
   120  
   121  		message.HorizontalRule()
   122  	}
   123  }