mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 14:51:44 +00:00
sg/msp: improve DX by enforcing repo structure (#56841)
Previously, the command expected the full YAML path, which is a bit annoying to write. Now, we just codify the repo structure of https://github.com/sourcegraph/managed-services and allow users to just use the service ID from anywhere in the repository. ## Test plan ```sh $ sg msp generate telemetry-gateway dev Terraform assets generated in "services/telemetry-gateway/terraform/dev"! $ cd services/telemetry-gateway/terraform/dev/stacks/project $ sg msp generate telemetry-gateway dev 💡 Using repo root /Users/robert@sourcegraph.com/Projects/sourcegraph/managed-services as working directory Terraform assets generated in "services/telemetry-gateway/terraform/dev"! ```
This commit is contained in:
parent
6fa37b2223
commit
ebb3b6ca4a
33
dev/sg/msp/repo/repo.go
Normal file
33
dev/sg/msp/repo/repo.go
Normal file
@ -0,0 +1,33 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/dev/sg/internal/std"
|
||||
)
|
||||
|
||||
// UseManagedServicesRepo is a cli.BeforeFunc that enforces that we are in the
|
||||
// sourcegraph/managed-services repository by setting the current working
|
||||
// directory.
|
||||
func UseManagedServicesRepo(c *cli.Context) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoRoot, err := repositoryRoot(cwd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if repoRoot != cwd {
|
||||
std.Out.WriteSuggestionf("Using repo root %s as working directory", repoRoot)
|
||||
return os.Chdir(repoRoot)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ServiceYAMLPath(serviceID string) string {
|
||||
return filepath.Join("services", serviceID, "service.yaml")
|
||||
}
|
||||
50
dev/sg/msp/repo/root.go
Normal file
50
dev/sg/msp/repo/root.go
Normal file
@ -0,0 +1,50 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
var repositoryRootValue string
|
||||
var repositoryRootError error
|
||||
|
||||
var ErrNotInsideManagedServices = errors.New("not running inside sourcegraph/managed-services")
|
||||
|
||||
// RepositoryRoot caches and returns the value of findRoot.
|
||||
func repositoryRoot(cwd string) (string, error) {
|
||||
once.Do(func() {
|
||||
if forcedRoot := os.Getenv("SG_MSP_FORCE_REPO_ROOT"); forcedRoot != "" {
|
||||
repositoryRootValue = forcedRoot
|
||||
} else {
|
||||
repositoryRootValue, repositoryRootError = findRoot(cwd)
|
||||
}
|
||||
})
|
||||
return repositoryRootValue, repositoryRootError
|
||||
}
|
||||
|
||||
// findRoot finds the root path of sourcegraph/managed-services from wd
|
||||
func findRoot(wd string) (string, error) {
|
||||
for {
|
||||
contents, err := os.ReadFile(filepath.Join(wd, ".repository"))
|
||||
if err == nil {
|
||||
for _, line := range strings.Split(string(contents), "\n") {
|
||||
if strings.HasPrefix(line, "sourcegraph/managed-services") {
|
||||
return wd, nil
|
||||
}
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if parent := filepath.Dir(wd); parent != wd {
|
||||
wd = parent
|
||||
continue
|
||||
}
|
||||
|
||||
return "", ErrNotInsideManagedServices
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/dev/managedservicesplatform/terraformcloud"
|
||||
"github.com/sourcegraph/sourcegraph/dev/sg/internal/secrets"
|
||||
"github.com/sourcegraph/sourcegraph/dev/sg/internal/std"
|
||||
msprepo "github.com/sourcegraph/sourcegraph/dev/sg/msp/repo"
|
||||
"github.com/sourcegraph/sourcegraph/dev/sg/msp/schema"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
"github.com/sourcegraph/sourcegraph/lib/output"
|
||||
@ -42,6 +43,7 @@ func init() {
|
||||
// Override no-op implementation with our real implementation.
|
||||
Command.Hidden = false
|
||||
Command.Action = nil
|
||||
// All 'sg msp ...' subcommands
|
||||
Command.Subcommands = []*cli.Command{
|
||||
{
|
||||
Name: "init",
|
||||
@ -55,6 +57,7 @@ func init() {
|
||||
Value: "services",
|
||||
},
|
||||
},
|
||||
Before: msprepo.UseManagedServicesRepo,
|
||||
Action: func(c *cli.Context) error {
|
||||
if c.Args().Len() != 1 {
|
||||
return errors.New("exactly 1 argument required: service ID")
|
||||
@ -125,8 +128,9 @@ func init() {
|
||||
},
|
||||
{
|
||||
Name: "generate",
|
||||
ArgsUsage: "<service spec file> <environment ID>",
|
||||
ArgsUsage: "<service ID> <environment ID>",
|
||||
Description: "Generate Terraform assets for a Managed Services Platform service spec.",
|
||||
Before: msprepo.UseManagedServicesRepo,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "output",
|
||||
@ -142,14 +146,12 @@ func init() {
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
if c.Args().Len() != 2 {
|
||||
return errors.New("exactly 2 arguments required: service spec file and environment ID")
|
||||
return errors.New("exactly 2 arguments required: service ID and environment ID")
|
||||
}
|
||||
|
||||
// Load specification
|
||||
serviceSpecPath, err := getYAMLPathArg(c, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serviceSpecPath := msprepo.ServiceYAMLPath(c.Args().First())
|
||||
|
||||
serviceSpecData, err := os.ReadFile(serviceSpecPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -205,11 +207,12 @@ func init() {
|
||||
Name: "terraform-cloud",
|
||||
Aliases: []string{"tfc"},
|
||||
Description: "Manage Terraform Cloud workspaces for a service",
|
||||
Before: msprepo.UseManagedServicesRepo,
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "sync",
|
||||
Description: "Create or update all required Terraform Cloud workspaces for a service",
|
||||
ArgsUsage: "<service spec file>",
|
||||
ArgsUsage: "<service ID>",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "workspace-run-mode",
|
||||
@ -223,10 +226,12 @@ func init() {
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
serviceSpecPath, err := getYAMLPathArg(c, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
serviceID := c.Args().First()
|
||||
if serviceID == "" {
|
||||
return errors.New("argument service is required")
|
||||
}
|
||||
serviceSpecPath := msprepo.ServiceYAMLPath(serviceID)
|
||||
|
||||
serviceSpecData, err := os.ReadFile(serviceSpecPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -355,11 +360,3 @@ func init() {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getYAMLPathArg(c *cli.Context, n int) (string, error) {
|
||||
v := c.Args().Get(n)
|
||||
if strings.HasSuffix(v, ".yaml") || strings.HasSuffix(v, ".yml") {
|
||||
return v, nil
|
||||
}
|
||||
return v, errors.Newf("expected argument %d %q to be a path to a YAML file", n, v)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user