-
Notifications
You must be signed in to change notification settings - Fork 128
Improve git config section validation #1940
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
base: main
Are you sure you want to change the base?
Changes from all commits
23169cd
fa3f4cd
e5a85e9
3b19d8f
bf0ef9e
d4f3060
0322733
48e6b92
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ package mutator | |
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "path/filepath" | ||
|
|
||
| "github.com/databricks/cli/bundle" | ||
|
|
@@ -33,28 +34,55 @@ func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagn | |
| b.WorktreeRoot = vfs.MustNew(info.WorktreeRoot) | ||
| } | ||
|
|
||
| b.Config.Bundle.Git.ActualBranch = info.CurrentBranch | ||
| if b.Config.Bundle.Git.Branch == "" { | ||
| // Only load branch if there's no user defined value | ||
| b.Config.Bundle.Git.Inferred = true | ||
| b.Config.Bundle.Git.Branch = info.CurrentBranch | ||
| } | ||
| config := &b.Config.Bundle.Git | ||
|
|
||
| // load commit hash if undefined | ||
| if b.Config.Bundle.Git.Commit == "" { | ||
| b.Config.Bundle.Git.Commit = info.LatestCommit | ||
| config.ActualBranch = info.CurrentBranch | ||
| if config.Branch == "" { | ||
| config.Inferred = true | ||
| } | ||
|
|
||
| // load origin url if undefined | ||
| if b.Config.Bundle.Git.OriginURL == "" { | ||
| b.Config.Bundle.Git.OriginURL = info.OriginURL | ||
| } | ||
| // The value from config takes precedence; however, we always warn if configValue and fetchedValue disagree. | ||
| // In case of branch and commit and absence of --force we raise severity to Error | ||
| diags = append(diags, checkMatch("Git branch", info.CurrentBranch, &config.Branch, b.Config.Bundle.Force)...) | ||
| diags = append(diags, checkMatch("Git commit", info.LatestCommit, &config.Commit, b.Config.Bundle.Force)...) | ||
| diags = append(diags, checkMatch("Git origin URL", info.OriginURL, &config.OriginURL, true)...) | ||
|
|
||
| relBundlePath, err := filepath.Rel(b.WorktreeRoot.Native(), b.BundleRoot.Native()) | ||
| if err != nil { | ||
| diags = append(diags, diag.FromErr(err)...) | ||
| } else { | ||
| b.Config.Bundle.Git.BundleRootPath = filepath.ToSlash(relBundlePath) | ||
| config.BundleRootPath = filepath.ToSlash(relBundlePath) | ||
| } | ||
|
|
||
| return diags | ||
| } | ||
|
|
||
| func checkMatch(field, fetchedValue string, configValue *string, allowedToMismatch bool) []diag.Diagnostic { | ||
| if fetchedValue == "" { | ||
| return nil | ||
| } | ||
|
|
||
| if *configValue == "" { | ||
| *configValue = fetchedValue | ||
| return nil | ||
| } | ||
|
|
||
| if *configValue != fetchedValue { | ||
| tmpl := "not on the right %s:\n expected according to configuration: %s\n actual: %s%s" | ||
| extra := "" | ||
| var severity diag.Severity | ||
| if allowedToMismatch { | ||
| severity = diag.Warning | ||
| } else { | ||
| severity = diag.Error | ||
| extra = "\nuse --force to override" | ||
| } | ||
|
|
||
| return []diag.Diagnostic{{ | ||
| Severity: severity, | ||
| Summary: fmt.Sprintf(tmpl, field, *configValue, fetchedValue, extra), | ||
| }} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This happens only if the configuration is explicitly set. Can you include the location information here? You can access it through This means the user can Cmd-click on it to jump to the problematic location. Separate: I see this matches the existing warning and that's fine, but this should really be broken out into a short single-line summary and longer multi-line "detail" field.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, this is a good change but I think it can be a follow up? This PR focuses on the logic but keeps the message exactly the same (it just shows up in more places where relevant). Follow up PR can add location info and split summary/detail without changing the logic.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd also prefer to have this addressed here. The PR adds additional logic for commit and url check anyway and thus the message is different, so having location info is useful. |
||
| } | ||
|
|
||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| package mutator | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/databricks/cli/libs/diag" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestCheckMatch(t *testing.T) { | ||
| type test struct { | ||
| Fetched string | ||
| ConfiguredBefore string | ||
| ConfiguredAfter string | ||
| } | ||
|
|
||
| tests := []test{ | ||
| { | ||
| Fetched: "main", | ||
| ConfiguredBefore: "main", | ||
| ConfiguredAfter: "main", | ||
| }, | ||
| { | ||
| Fetched: "main", | ||
| ConfiguredBefore: "", | ||
| ConfiguredAfter: "main", | ||
| }, | ||
| { | ||
| Fetched: "", | ||
| ConfiguredBefore: "main", | ||
| ConfiguredAfter: "main", | ||
| }, | ||
| } | ||
|
|
||
| for _, test := range tests { | ||
| name := "CheckMatch " + test.Fetched + " " + test.ConfiguredBefore + " " + test.ConfiguredAfter | ||
| t.Run(name, func(t *testing.T) { | ||
| configValue := test.ConfiguredBefore | ||
| diags := checkMatch("", test.Fetched, &configValue, false) | ||
| assert.Nil(t, diags) | ||
| assert.Equal(t, test.ConfiguredAfter, configValue) | ||
| }) | ||
| t.Run(name+" force", func(t *testing.T) { | ||
| configValue := test.ConfiguredBefore | ||
| diags := checkMatch("", test.Fetched, &configValue, true) | ||
| assert.Nil(t, diags) | ||
| assert.Equal(t, test.ConfiguredAfter, configValue) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestCheckWarning(t *testing.T) { | ||
| configValue := "main" | ||
| diags := checkMatch("Git branch", "feature", &configValue, true) | ||
| require.Len(t, diags, 1) | ||
| assert.Equal(t, diags[0].Severity, diag.Warning) | ||
| assert.Equal(t, diags[0].Summary, "not on the right Git branch:\n expected according to configuration: main\n actual: feature") | ||
| assert.Equal(t, "main", configValue) | ||
| } | ||
|
|
||
| func TestCheckError(t *testing.T) { | ||
| configValue := "main" | ||
| diags := checkMatch("Git branch", "feature", &configValue, false) | ||
| require.Len(t, diags, 1) | ||
| assert.Equal(t, diags[0].Severity, diag.Error) | ||
| assert.Equal(t, diags[0].Summary, "not on the right Git branch:\n expected according to configuration: main\n actual: feature\nuse --force to override") | ||
| assert.Equal(t, "main", configValue) | ||
| } |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be renamed because it has side effects of setting configValue, not simply doing the check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setIfEmptyAndComparemaybe? Which hints and maybe refactoring this into 2 separate functions but I'm fine with both