Skip to content

Commit

Permalink
batches: query max unlicensed changesets count (#929)
Browse files Browse the repository at this point in the history
replace hardcoded permitted unlicensed changesets count by querying maxUnlicensedChangesets
  • Loading branch information
adeola-ak authored Jan 29, 2023
1 parent c967c5e commit 715ed43
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 29 deletions.
4 changes: 2 additions & 2 deletions cmd/src/batch_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func executeBatchSpec(ctx context.Context, opts executeBatchSpecOpts) (err error
Client: opts.client,
})

ffs, err := svc.DetermineFeatureFlags(ctx)
lr, ffs, err := svc.DetermineLicenseAndFeatureFlags(ctx)
if err != nil {
return err
}
Expand Down Expand Up @@ -521,7 +521,7 @@ func executeBatchSpec(ctx context.Context, opts executeBatchSpecOpts) (err error
execUI.CreatingBatchSpec()
id, url, err := svc.CreateBatchSpec(ctx, namespace.ID, rawSpec, ids)
if err != nil {
return execUI.CreatingBatchSpecError(err)
return execUI.CreatingBatchSpecError(lr.MaxUnlicensedChangesets, err)
}
previewURL := cfg.Endpoint + url
execUI.CreatingBatchSpecSuccess(previewURL)
Expand Down
2 changes: 1 addition & 1 deletion cmd/src/batch_new.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Examples:
Client: cfg.apiClient(apiFlags, flagSet.Output()),
})

ffs, err := svc.DetermineFeatureFlags(ctx)
_, ffs, err := svc.DetermineLicenseAndFeatureFlags(ctx)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/src/batch_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Examples:
Client: cfg.apiClient(flags.api, flagSet.Output()),
})

ffs, err := svc.DetermineFeatureFlags(ctx)
_, ffs, err := svc.DetermineLicenseAndFeatureFlags(ctx)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/src/batch_repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Examples:
Client: client,
})

ffs, err := svc.DetermineFeatureFlags(ctx)
_, ffs, err := svc.DetermineLicenseAndFeatureFlags(ctx)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/src/batch_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Examples:
Client: cfg.apiClient(apiFlags, flagSet.Output()),
})

ffs, err := svc.DetermineFeatureFlags(ctx)
_, ffs, err := svc.DetermineLicenseAndFeatureFlags(ctx)
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions internal/batches/license.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package batches

type LicenseRestrictions struct {
MaxUnlicensedChangesets int
}
36 changes: 22 additions & 14 deletions internal/batches/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ func New(opts *Opts) *Service {
// The reason we ask for batchChanges here is to surface errors about trying to use batch
// changes in an unsupported environment sooner, since the version check is typically the
// first thing we do.
const sourcegraphVersionQuery = `query SourcegraphVersion {
const getInstanceInfo = `query InstanceInfo {
site {
productVersion
}
maxUnlicensedChangesets
batchChanges(first: 1) {
nodes {
id
Expand All @@ -55,32 +56,39 @@ const sourcegraphVersionQuery = `query SourcegraphVersion {
}
`

// getSourcegraphVersion queries the Sourcegraph GraphQL API to get the
// current version of the Sourcegraph instance.
func (svc *Service) getSourcegraphVersion(ctx context.Context) (string, error) {
// getSourcegraphVersionAndMaxChangesetsCount queries the Sourcegraph GraphQL API to get the
// current version and max unlicensed changesets count for the Sourcegraph instance.
func (svc *Service) getSourcegraphVersionAndMaxChangesetsCount(ctx context.Context) (string, int, error) {
var result struct {
Site struct {
MaxUnlicensedChangesets int
Site struct {
ProductVersion string
}
}

ok, err := svc.client.NewQuery(sourcegraphVersionQuery).Do(ctx, &result)
ok, err := svc.client.NewQuery(getInstanceInfo).Do(ctx, &result)
if err != nil || !ok {
return "", err
return "", 0, err
}

return result.Site.ProductVersion, err
return result.Site.ProductVersion, result.MaxUnlicensedChangesets, err
}

// DetermineFeatureFlags fetches the version of the configured Sourcegraph and
// returns the enabled features.
func (svc *Service) DetermineFeatureFlags(ctx context.Context) (*batches.FeatureFlags, error) {
version, err := svc.getSourcegraphVersion(ctx)
// DetermineLicenseAndFeatureFlags returns the enabled features and license restrictions
// configured for the Sourcegraph instance.
func (svc *Service) DetermineLicenseAndFeatureFlags(ctx context.Context) (*batches.LicenseRestrictions, *batches.FeatureFlags, error) {
version, mc, err := svc.getSourcegraphVersionAndMaxChangesetsCount(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to query Sourcegraph version to check for available features")
return nil, nil, errors.Wrap(err, "failed to query Sourcegraph version and license info for instance")
}

lr := &batches.LicenseRestrictions{
MaxUnlicensedChangesets: mc,
}

ffs := &batches.FeatureFlags{}
return ffs, ffs.SetFromVersion(version)
return lr, ffs, ffs.SetFromVersion(version)

}

const applyBatchChangeMutation = `
Expand Down
2 changes: 1 addition & 1 deletion internal/batches/ui/exec_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type ExecUI interface {

CreatingBatchSpec()
CreatingBatchSpecSuccess(previewURL string)
CreatingBatchSpecError(err error) error
CreatingBatchSpecError(maxUnlicensedCS int, err error) error

PreviewBatchSpec(previewURL string)

Expand Down
2 changes: 1 addition & 1 deletion internal/batches/ui/json_lines.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func (ui *JSONLines) CreatingBatchSpecSuccess(batchSpecURL string) {
})
}

func (ui *JSONLines) CreatingBatchSpecError(err error) error {
func (ui *JSONLines) CreatingBatchSpecError(_ int, err error) error {
logOperationFailure(batcheslib.LogEventOperationCreatingBatchSpec, &batcheslib.CreatingBatchSpecMetadata{})
return err
}
Expand Down
14 changes: 7 additions & 7 deletions internal/batches/ui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ func (ui *TUI) CreatingBatchSpecSuccess(previewURL string) {
batchCompletePending(ui.pending, "Creating batch spec on Sourcegraph")
}

func (ui *TUI) CreatingBatchSpecError(err error) error {
return prettyPrintBatchUnlicensedError(ui.Out, err)
func (ui *TUI) CreatingBatchSpecError(maxUnlicensedCS int, err error) error {
return prettyPrintBatchUnlicensedError(ui.Out, maxUnlicensedCS, err)
}

func (ui *TUI) DockerWatchDogWarning(err error) {
Expand Down Expand Up @@ -307,7 +307,7 @@ func (ui *TUI) RemoteSuccess(url string) {
// is, then a better message is output. Regardless, the return value of this
// function should be used to replace the original error passed in to ensure
// that the displayed output is sensible.
func prettyPrintBatchUnlicensedError(out *output.Output, err error) error {
func prettyPrintBatchUnlicensedError(out *output.Output, maxUnlicensedCS int, err error) error {
// Pull apart the error to see if it's a licensing error: if so, we should
// display a friendlier and more actionable message than the usual GraphQL
// error output.
Expand All @@ -321,19 +321,19 @@ func prettyPrintBatchUnlicensedError(out *output.Output, err error) error {
// verbose mode, but let the original error bubble up rather
// than this one.
out.Verbosef("Unexpected error parsing the GraphQL error: %v", cerr)
} else if code == "ErrBatchChangesUnlicensed" {
} else if code == "ErrBatchChangesUnlicensed" || code == "ErrBatchChangesOverLimit" {
// OK, let's print a better message, then return an
// exitCodeError to suppress the normal automatic error block.
// Note that we have hand wrapped the output at 80 (printable)
// characters: having automatic wrapping some day would be nice,
// but this should be sufficient for now.
block := out.Block(output.Line("🪙", output.StyleWarning, "Batch Changes is a paid feature of Sourcegraph. All users can create sample"))
block.WriteLine(output.Linef("", output.StyleWarning, "batch changes with up to 10 changesets without a license. Contact Sourcegraph"))
block.WriteLine(output.Linef("", output.StyleWarning, "batch changes with up to %v changesets without a license. Contact Sourcegraph", maxUnlicensedCS))
block.WriteLine(output.Linef("", output.StyleWarning, "sales at %shttps://about.sourcegraph.com/contact/sales/%s to obtain a trial", output.StyleSearchLink, output.StyleWarning))
block.WriteLine(output.Linef("", output.StyleWarning, "license."))
block.Write("")
block.WriteLine(output.Linef("", output.StyleWarning, "To proceed with this batch change, you will need to create 5 or fewer"))
block.WriteLine(output.Linef("", output.StyleWarning, "changesets. To do so, you could try adding %scount:5%s to your", output.StyleSearchAlertProposedQuery, output.StyleWarning))
block.WriteLine(output.Linef("", output.StyleWarning, "To proceed with this batch change, you will need to create %v or fewer", maxUnlicensedCS))
block.WriteLine(output.Linef("", output.StyleWarning, "changesets. To do so, you could try adding %scount:%v%s to your", output.StyleSearchAlertProposedQuery, maxUnlicensedCS, output.StyleWarning))
block.WriteLine(output.Linef("", output.StyleWarning, "%srepositoriesMatchingQuery%s search, or reduce the number of changesets in", output.StyleReset, output.StyleWarning))
block.WriteLine(output.Linef("", output.StyleWarning, "%simportChangesets%s.", output.StyleReset, output.StyleWarning))
block.Close()
Expand Down

0 comments on commit 715ed43

Please sign in to comment.