mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 15:12:02 +00:00
sg/msp: warn user if sg-msp lockfile differs from current version (#62134)
In https://github.com/sourcegraph/managed-services/pull/1288 I'm introducing granular, per-category version locks for https://github.com/sourcegraph/managed-services/issues/599. This change adds warnings that are shown to the user on version mismatches. This may cause some friction with users, but for now, let's just deal with this on a case-by-case basis - our primary goal right now is to build a process for https://github.com/sourcegraph/managed-services/issues/599 by introducing more granular version locks. Requires https://github.com/sourcegraph/sourcegraph/pull/62176 so that we can access the same version format as the one used in our lockfiles. Details on our locking strategy is here: https://sourcegraph.notion.site/Deploying-new-versions-of-MSP-1808e7e45bd54f419dd93af542d99238#58dabe4992754ca18ed39bc212ccbbba ## Test plan ``` sg msp generate -all ``` 
This commit is contained in:
parent
3b5fb78377
commit
0fb6806f3b
@ -7,6 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/exp/maps"
|
||||
@ -152,7 +153,44 @@ func syncEnvironmentWorkspaces(c *cli.Context, tfc *terraformcloud.Client, servi
|
||||
return std.Out.WriteMarkdown(summary.String())
|
||||
}
|
||||
|
||||
type toolingLockfileChecker struct {
|
||||
version string
|
||||
categories map[spec.EnvironmentCategory]*sync.Once
|
||||
}
|
||||
|
||||
// checkCategoryVersion performs warning checks for the given environment category's
|
||||
// tooling version.
|
||||
//
|
||||
// Requires UseManagedServicesRepo.
|
||||
func (c *toolingLockfileChecker) checkCategoryVersion(out *std.Output, category spec.EnvironmentCategory) {
|
||||
var categoryOnce *sync.Once
|
||||
if o, ok := c.categories[category]; ok {
|
||||
categoryOnce = o
|
||||
} else {
|
||||
categoryOnce = &sync.Once{}
|
||||
c.categories[category] = categoryOnce
|
||||
}
|
||||
|
||||
categoryOnce.Do(func() {
|
||||
lockedSgVersion, err := msprepo.ToolingLockfileVersion(category)
|
||||
if err != nil {
|
||||
out.WriteWarningf("Unable to determine locked 'sg' version for category %q: %s",
|
||||
category, err.Error())
|
||||
} else if lockedSgVersion != c.version {
|
||||
out.WriteWarningf(`Lockfile for category %q declares 'sg' version %q, you are using %q - generated outputs may differ from what is expected.
|
||||
If there is a diff in the generated output, try running the following:`,
|
||||
category, lockedSgVersion, c.version)
|
||||
_ = out.WriteCode("bash", fmt.Sprintf(
|
||||
"sg update -release %q &&\n SG_SKIP_AUTO_UPDATE=true sg msp generate -all -category %q",
|
||||
lockedSgVersion, string(category)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type generateTerraformOptions struct {
|
||||
// tooling is used to validate the current tooling version matches what
|
||||
// is expected, and warn the user if there is a mismatch.
|
||||
tooling *toolingLockfileChecker
|
||||
// targetEnv generates the specified env only, otherwise generates all
|
||||
targetEnv string
|
||||
// targetCategory generates the specified category only
|
||||
@ -188,6 +226,10 @@ func generateTerraform(service *spec.Spec, opts generateTerraformOptions) error
|
||||
continue
|
||||
}
|
||||
|
||||
// Check tooling version and emit warnings
|
||||
opts.tooling.checkCategoryVersion(std.Out, env.Category)
|
||||
|
||||
// Then, start our actual work
|
||||
pending := std.Out.Pending(output.StylePending.Linef(
|
||||
"[%s] Preparing Terraform for %q environment %q", serviceID, env.Category, env.ID))
|
||||
renderer := managedservicesplatform.Renderer{
|
||||
@ -262,7 +304,8 @@ func generateTerraform(service *spec.Spec, opts generateTerraformOptions) error
|
||||
}
|
||||
|
||||
pending.Complete(output.Styledf(output.StyleSuccess,
|
||||
"[%s] Infrastructure assets generated in %q!", serviceID, renderer.OutputDir))
|
||||
"[%s] Category %q environment %q infrastructure assets generated!",
|
||||
serviceID, env.Category, env.ID))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -2,9 +2,11 @@ package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
@ -13,6 +15,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/dev/managedservicesplatform/spec"
|
||||
"github.com/sourcegraph/sourcegraph/dev/sg/internal/std"
|
||||
"github.com/sourcegraph/sourcegraph/lib/cliutil/completions"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
// UseManagedServicesRepo is a cli.BeforeFunc that enforces that we are in the
|
||||
@ -94,19 +97,59 @@ func ServicesAndEnvironmentsCompletion(additionalArgs ...func(args cli.Args) (op
|
||||
return completions.CompletePositionalArgs(append(args, additionalArgs...)...)
|
||||
}
|
||||
|
||||
// ServiceYAMLPath returns the relative path to the service.yaml file for the
|
||||
// given service.
|
||||
//
|
||||
// Requires UseManagedServicesRepo to be relevant.
|
||||
func ServiceYAMLPath(serviceID string) string {
|
||||
return filepath.Join("services", serviceID, "service.yaml")
|
||||
}
|
||||
|
||||
// ServiceEnvironmentYAMLPath returns the relative path to the Terraform Stacks
|
||||
// directory for the given service environment's stack.
|
||||
//
|
||||
// Requires UseManagedServicesRepo to be relevant.
|
||||
func ServiceStackPath(serviceID, envID, stackID string) string {
|
||||
return filepath.Join("services", serviceID, "terraform", envID, "stacks", stackID)
|
||||
}
|
||||
|
||||
// ServiceStackTerraformPath returns the relative path to the Terraform CDKTF
|
||||
// configuration file for the given service environment's stack.
|
||||
//
|
||||
// Requires UseManagedServicesRepo to be relevant.
|
||||
func ServiceStackCDKTFPath(serviceID, envID, stackID string) string {
|
||||
return filepath.Join(ServiceStackPath(serviceID, envID, stackID), "cdk.tf.json")
|
||||
}
|
||||
|
||||
// ToolingLockfileVersion retrieves the contents of the sg-msp lockfile for the
|
||||
// given category (./sg-msp-$CATEGORY.lock).
|
||||
//
|
||||
// Requires UseManagedServicesRepo.
|
||||
func ToolingLockfileVersion(category spec.EnvironmentCategory) (string, error) {
|
||||
lockfile := fmt.Sprintf("sg-msp-%s.lock", category)
|
||||
if category == "" {
|
||||
lockfile = "sg-msp.lock" // fallback to the old format (no category)
|
||||
}
|
||||
|
||||
contents, err := os.ReadFile(lockfile)
|
||||
if err != nil {
|
||||
// Try to fall back to category-less-lockfile
|
||||
if v, fallbackErr := ToolingLockfileVersion(""); fallbackErr == nil {
|
||||
return v, nil
|
||||
}
|
||||
// Otherwise, return the error we got.
|
||||
return "", errors.Wrapf(err, "read %q", lockfile)
|
||||
}
|
||||
|
||||
version := strings.TrimSpace(string(contents))
|
||||
if len(version) == 0 {
|
||||
return "", errors.Newf("empty %q", lockfile)
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// GitRevision gets the revision of the managed-services repository.
|
||||
//
|
||||
// Requires UseManagedServicesRepo.
|
||||
func GitRevision(ctx context.Context) (string, error) {
|
||||
return run.Cmd(ctx, "git rev-parse HEAD").
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/exp/maps"
|
||||
@ -320,6 +321,11 @@ sg msp generate -all -category=test
|
||||
}
|
||||
}
|
||||
|
||||
toolingChecker := &toolingLockfileChecker{
|
||||
version: c.App.Version,
|
||||
categories: make(map[spec.EnvironmentCategory]*sync.Once),
|
||||
}
|
||||
|
||||
// Generate a specific service environment if '-all' is not provided
|
||||
if !generateAll {
|
||||
std.Out.WriteNoticef("Generating a specific service environment...")
|
||||
@ -328,6 +334,7 @@ sg msp generate -all -category=test
|
||||
return err
|
||||
}
|
||||
return generateTerraform(svc, generateTerraformOptions{
|
||||
tooling: toolingChecker,
|
||||
targetEnv: env.ID,
|
||||
stableGenerate: stableGenerate,
|
||||
})
|
||||
@ -341,6 +348,7 @@ sg msp generate -all -category=test
|
||||
return err
|
||||
}
|
||||
return generateTerraform(svc, generateTerraformOptions{
|
||||
tooling: toolingChecker,
|
||||
stableGenerate: stableGenerate,
|
||||
targetCategory: generateCategory,
|
||||
})
|
||||
@ -360,6 +368,7 @@ sg msp generate -all -category=test
|
||||
return err
|
||||
}
|
||||
if err := generateTerraform(s, generateTerraformOptions{
|
||||
tooling: toolingChecker,
|
||||
stableGenerate: stableGenerate,
|
||||
targetCategory: generateCategory,
|
||||
}); err != nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user