## Description
<!-- **Please link some issue here describing what you are trying to achieve.**
In case there is no issue present for your PR, please consider creating one.
At least please give us some description what you are trying to achieve and why your change is needed. -->
relates to #1234
## Checklist
- [ ] Issue was linked above
- [ ] Code format was applied: `make fmt`
- [ ] Examples were added / adjusted (see `examples/` directory)
- [x] Docs are up-to-date: `make generate-docs` (will be checked by CI)
- [ ] Unit tests got implemented or updated
- [ ] Acceptance tests got implemented or updated (see e.g. [here](f5f99d1709/stackit/internal/services/dns/dns_acc_test.go))
- [x] Unit tests are passing: `make test` (will be checked by CI)
- [x] No linter issues: `make lint` (will be checked by CI)
Reviewed-on: #10
Co-authored-by: Marcel S. Henselin <marcel.henselin@stackit.cloud>
Co-committed-by: Marcel S. Henselin <marcel.henselin@stackit.cloud>
737 lines
18 KiB
Go
737 lines
18 KiB
Go
package build
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"log/slog"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/ldez/go-git-cmd-wrapper/v2/clone"
|
|
"github.com/ldez/go-git-cmd-wrapper/v2/git"
|
|
)
|
|
|
|
const (
|
|
OAS_REPO_NAME = "stackit-api-specifications"
|
|
OAS_REPO = "https://github.com/stackitcloud/stackit-api-specifications.git"
|
|
GEN_REPO_NAME = "stackit-sdk-generator"
|
|
GEN_REPO = "https://github.com/stackitcloud/stackit-sdk-generator.git"
|
|
)
|
|
|
|
type version struct {
|
|
verString string
|
|
major int
|
|
minor int
|
|
}
|
|
|
|
func Build() error {
|
|
slog.Info("Starting Builder")
|
|
root, err := getRoot()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if root == nil || *root == "" {
|
|
return fmt.Errorf("unable to determine root directory from git")
|
|
}
|
|
slog.Info("Using root directory", "dir", *root)
|
|
|
|
slog.Info("Cleaning up old generator directory")
|
|
err = os.RemoveAll(path.Join(*root, GEN_REPO_NAME))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Cleaning up old packages directory")
|
|
err = os.RemoveAll(path.Join(*root, "pkg_gen"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Creating generator dir", "dir", fmt.Sprintf("%s/%s", *root, GEN_REPO_NAME))
|
|
genDir, err := createGeneratorDir(*root, GEN_REPO, GEN_REPO_NAME)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Creating oas dir", "dir", fmt.Sprintf("%s/%s", *root, OAS_REPO_NAME))
|
|
repoDir, err := createRepoDir(genDir, OAS_REPO, OAS_REPO_NAME)
|
|
if err != nil {
|
|
return fmt.Errorf("%s", err.Error())
|
|
}
|
|
|
|
slog.Info("Retrieving versions from subdirs")
|
|
// TODO - major
|
|
verMap, err := getVersions(repoDir)
|
|
if err != nil {
|
|
return fmt.Errorf("%s", err.Error())
|
|
}
|
|
|
|
slog.Info("Reducing to only latest or highest")
|
|
res, err := getOnlyLatest(verMap)
|
|
if err != nil {
|
|
return fmt.Errorf("%s", err.Error())
|
|
}
|
|
|
|
slog.Info("Creating OAS dir")
|
|
err = os.MkdirAll(path.Join(genDir, "oas"), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Copying OAS files")
|
|
for service, item := range res {
|
|
baseService := strings.TrimSuffix(service, "alpha")
|
|
baseService = strings.TrimSuffix(baseService, "beta")
|
|
itemVersion := fmt.Sprintf("v%d%s", item.major, item.verString)
|
|
if item.minor != 0 {
|
|
itemVersion = itemVersion + "" + strconv.Itoa(item.minor)
|
|
}
|
|
srcFile := path.Join(
|
|
repoDir,
|
|
"services",
|
|
baseService,
|
|
itemVersion,
|
|
fmt.Sprintf("%s.json", baseService),
|
|
)
|
|
dstFile := path.Join(genDir, "oas", fmt.Sprintf("%s.json", service))
|
|
_, err = copyFile(srcFile, dstFile)
|
|
if err != nil {
|
|
return fmt.Errorf("%s", err.Error())
|
|
}
|
|
}
|
|
|
|
slog.Info("Cleaning up", "dir", repoDir)
|
|
err = os.RemoveAll(filepath.Dir(repoDir))
|
|
if err != nil {
|
|
return fmt.Errorf("%s", err.Error())
|
|
}
|
|
|
|
slog.Info("Changing dir", "dir", genDir)
|
|
err = os.Chdir(genDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Calling make", "command", "generate-go-sdk")
|
|
cmd := exec.Command("make", "generate-go-sdk")
|
|
var stdOut, stdErr bytes.Buffer
|
|
cmd.Stdout = &stdOut
|
|
cmd.Stderr = &stdErr
|
|
|
|
if err = cmd.Start(); err != nil {
|
|
slog.Error("cmd.Start", "error", err)
|
|
return err
|
|
}
|
|
|
|
if err = cmd.Wait(); err != nil {
|
|
var exitErr *exec.ExitError
|
|
if errors.As(err, &exitErr) {
|
|
slog.Error("cmd.Wait", "code", exitErr.ExitCode(), "error", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return fmt.Errorf("%s", stdErr.String())
|
|
}
|
|
if err != nil {
|
|
slog.Error("cmd.Wait", "err", err)
|
|
return err
|
|
}
|
|
}
|
|
|
|
slog.Info("Cleaning up go.mod and go.sum files")
|
|
cleanDir := path.Join(genDir, "sdk-repo-updated", "services")
|
|
dirEntries, err := os.ReadDir(cleanDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, entry := range dirEntries {
|
|
if entry.IsDir() {
|
|
err = deleteFiles(
|
|
path.Join(cleanDir, entry.Name(), "go.mod"),
|
|
path.Join(cleanDir, entry.Name(), "go.sum"),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
slog.Info("Changing dir", "dir", *root)
|
|
err = os.Chdir(*root)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Rearranging package directories")
|
|
err = os.MkdirAll(path.Join(*root, "pkg_gen"), 0755) // noqa:gosec
|
|
if err != nil {
|
|
return err
|
|
}
|
|
srcDir := path.Join(genDir, "sdk-repo-updated", "services")
|
|
items, err := os.ReadDir(srcDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, item := range items {
|
|
if item.IsDir() {
|
|
slog.Info(" -> package", "name", item.Name())
|
|
tgtDir := path.Join(*root, "pkg_gen", item.Name())
|
|
// no backup needed as we generate new
|
|
//bakName := fmt.Sprintf("%s.%s", item.Name(), time.Now().Format("20060102-150405"))
|
|
//if _, err = os.Stat(tgtDir); !os.IsNotExist(err) {
|
|
// err = os.Rename(
|
|
// tgtDir,
|
|
// path.Join(*root, "pkg", bakName),
|
|
// )
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//}
|
|
err = os.Rename(path.Join(srcDir, item.Name()), tgtDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// wait is placed outside now
|
|
//if _, err = os.Stat(path.Join(*root, "pkg", bakName, "wait")); !os.IsNotExist(err) {
|
|
// slog.Info(" Copying wait subfolder")
|
|
// err = os.Rename(path.Join(*root, "pkg", bakName, "wait"), path.Join(tgtDir, "wait"))
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//}
|
|
}
|
|
}
|
|
|
|
slog.Info("Checking needed commands available")
|
|
err = checkCommands([]string{"tfplugingen-framework", "tfplugingen-openapi"})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Generating service boilerplate")
|
|
err = generateServiceFiles(*root, path.Join(*root, GEN_REPO_NAME))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Copying all service files")
|
|
err = CopyDirectory(
|
|
path.Join(*root, "generated", "internal", "services"),
|
|
path.Join(*root, "stackit", "internal", "services"),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = createBoilerplate(*root, path.Join(*root, "stackit", "internal", "services"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Info("Finally removing temporary files and directories")
|
|
//err = os.RemoveAll(path.Join(*root, "generated"))
|
|
//if err != nil {
|
|
// slog.Error("RemoveAll", "dir", path.Join(*root, "generated"), "err", err)
|
|
// return err
|
|
//}
|
|
|
|
err = os.RemoveAll(path.Join(*root, GEN_REPO_NAME))
|
|
if err != nil {
|
|
slog.Error("RemoveAll", "dir", path.Join(*root, GEN_REPO_NAME), "err", err)
|
|
return err
|
|
}
|
|
|
|
slog.Info("Done")
|
|
return nil
|
|
}
|
|
|
|
type templateData struct {
|
|
PackageName string
|
|
NameCamel string
|
|
NamePascal string
|
|
NameSnake string
|
|
}
|
|
|
|
func fileExists(path string) bool {
|
|
_, err := os.Stat(path)
|
|
if os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return true
|
|
}
|
|
|
|
func createBoilerplate(rootFolder, folder string) error {
|
|
services, err := os.ReadDir(folder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, svc := range services {
|
|
if !svc.IsDir() {
|
|
continue
|
|
}
|
|
resources, err := os.ReadDir(path.Join(folder, svc.Name()))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var handleDS bool
|
|
var handleRes bool
|
|
var foundDS bool
|
|
var foundRes bool
|
|
|
|
for _, res := range resources {
|
|
if !res.IsDir() {
|
|
continue
|
|
}
|
|
|
|
resourceName := res.Name()
|
|
|
|
dsFile := path.Join(folder, svc.Name(), res.Name(), "datasources_gen", fmt.Sprintf("%s_data_source_gen.go", res.Name()))
|
|
handleDS = fileExists(dsFile)
|
|
|
|
resFile := path.Join(folder, svc.Name(), res.Name(), "resources_gen", fmt.Sprintf("%s_resource_gen.go", res.Name()))
|
|
handleRes = fileExists(resFile)
|
|
|
|
dsGoFile := path.Join(folder, svc.Name(), res.Name(), "datasource.go")
|
|
foundDS = fileExists(dsGoFile)
|
|
|
|
resGoFile := path.Join(folder, svc.Name(), res.Name(), "resource.go")
|
|
foundRes = fileExists(resGoFile)
|
|
|
|
if handleDS && !foundDS {
|
|
slog.Info("Creating missing datasource.go", "service", svc.Name(), "resource", resourceName)
|
|
if !ValidateSnakeCase(resourceName) {
|
|
return errors.New("resource name is invalid")
|
|
}
|
|
|
|
tplName := "data_source_scaffold.gotmpl"
|
|
err = writeTemplateToFile(
|
|
tplName,
|
|
path.Join(rootFolder, "tools", "templates", tplName),
|
|
path.Join(folder, svc.Name(), res.Name(), "datasource.go"),
|
|
&templateData{
|
|
PackageName: svc.Name(),
|
|
NameCamel: ToCamelCase(resourceName),
|
|
NamePascal: ToPascalCase(resourceName),
|
|
NameSnake: resourceName,
|
|
},
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
if handleRes && !foundRes {
|
|
slog.Info("Creating missing resource.go", "service", svc.Name(), "resource", resourceName)
|
|
if !ValidateSnakeCase(resourceName) {
|
|
return errors.New("resource name is invalid")
|
|
}
|
|
|
|
tplName := "resource_scaffold.gotmpl"
|
|
err = writeTemplateToFile(
|
|
tplName,
|
|
path.Join(rootFolder, "tools", "templates", tplName),
|
|
path.Join(folder, svc.Name(), res.Name(), "resource.go"),
|
|
&templateData{
|
|
PackageName: svc.Name(),
|
|
NameCamel: ToCamelCase(resourceName),
|
|
NamePascal: ToPascalCase(resourceName),
|
|
NameSnake: resourceName,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ucfirst(s string) string {
|
|
if len(s) == 0 {
|
|
return ""
|
|
}
|
|
return strings.ToUpper(s[:1]) + s[1:]
|
|
}
|
|
|
|
func writeTemplateToFile(tplName, tplFile, outFile string, data *templateData) error {
|
|
fn := template.FuncMap{
|
|
"ucfirst": ucfirst,
|
|
}
|
|
|
|
tmpl, err := template.New(tplName).Funcs(fn).ParseFiles(tplFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var f *os.File
|
|
f, err = os.Create(outFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = tmpl.Execute(f, *data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = f.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func generateServiceFiles(rootDir, generatorDir string) error {
|
|
// slog.Info("Generating specs folder")
|
|
err := os.MkdirAll(path.Join(rootDir, "generated", "specs"), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
specs, err := os.ReadDir(path.Join(rootDir, "service_specs"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, spec := range specs {
|
|
if spec.IsDir() {
|
|
continue
|
|
}
|
|
// slog.Info("Checking spec", "name", spec.Name())
|
|
r := regexp.MustCompile(`^([a-z-]+)_(.*)_config.yml$`)
|
|
matches := r.FindAllStringSubmatch(spec.Name(), -1)
|
|
if matches != nil {
|
|
fileName := matches[0][0]
|
|
service := matches[0][1]
|
|
resource := matches[0][2]
|
|
slog.Info(
|
|
"Found service spec",
|
|
"name",
|
|
spec.Name(),
|
|
"service",
|
|
service,
|
|
"resource",
|
|
resource,
|
|
)
|
|
|
|
for _, part := range []string{"alpha", "beta"} {
|
|
oasFile := path.Join(generatorDir, "oas", fmt.Sprintf("%s%s.json", service, part))
|
|
if _, err = os.Stat(oasFile); !os.IsNotExist(err) {
|
|
slog.Info("found matching oas", "service", service, "version", part)
|
|
scName := fmt.Sprintf("%s%s", service, part)
|
|
scName = strings.ReplaceAll(scName, "-", "")
|
|
err = os.MkdirAll(path.Join(rootDir, "generated", "internal", "services", scName, resource), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// slog.Info("Generating openapi spec json")
|
|
specFile := path.Join(rootDir, "generated", "specs", fmt.Sprintf("%s_%s_spec.json", scName, resource))
|
|
|
|
var stdOut, stdErr bytes.Buffer
|
|
|
|
// noqa:gosec
|
|
cmd := exec.Command(
|
|
"tfplugingen-openapi",
|
|
"generate",
|
|
"--config",
|
|
path.Join(rootDir, "service_specs", fileName),
|
|
"--output",
|
|
specFile,
|
|
oasFile,
|
|
)
|
|
cmd.Stdout = &stdOut
|
|
cmd.Stderr = &stdErr
|
|
|
|
if err = cmd.Start(); err != nil {
|
|
slog.Error("tfplugingen-openapi generate", "error", err)
|
|
return err
|
|
}
|
|
|
|
if err = cmd.Wait(); err != nil {
|
|
var exitErr *exec.ExitError
|
|
if errors.As(err, &exitErr) {
|
|
slog.Error("tfplugingen-openapi generate", "code", exitErr.ExitCode(), "error", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return fmt.Errorf("%s", stdErr.String())
|
|
}
|
|
if err != nil {
|
|
slog.Error("tfplugingen-openapi generate", "err", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return err
|
|
}
|
|
}
|
|
|
|
// slog.Info("Creating terraform service resource files folder")
|
|
tgtFolder := path.Join(rootDir, "generated", "internal", "services", scName, resource, "resources_gen")
|
|
err = os.MkdirAll(tgtFolder, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// slog.Info("Generating terraform service resource files")
|
|
|
|
// noqa:gosec
|
|
cmd2 := exec.Command(
|
|
"tfplugingen-framework",
|
|
"generate",
|
|
"resources",
|
|
"--input",
|
|
specFile,
|
|
"--output",
|
|
tgtFolder,
|
|
"--package",
|
|
scName,
|
|
)
|
|
|
|
cmd2.Stdout = &stdOut
|
|
cmd2.Stderr = &stdErr
|
|
if err = cmd2.Start(); err != nil {
|
|
slog.Error("tfplugingen-framework generate resources", "error", err)
|
|
return err
|
|
}
|
|
|
|
if err = cmd2.Wait(); err != nil {
|
|
var exitErr *exec.ExitError
|
|
if errors.As(err, &exitErr) {
|
|
slog.Error("tfplugingen-framework generate resources", "code", exitErr.ExitCode(), "error", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return fmt.Errorf("%s", stdErr.String())
|
|
}
|
|
if err != nil {
|
|
slog.Error("tfplugingen-framework generate resources", "err", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return err
|
|
}
|
|
}
|
|
|
|
// slog.Info("Creating terraform service datasource files folder")
|
|
tgtFolder = path.Join(rootDir, "generated", "internal", "services", scName, resource, "datasources_gen")
|
|
err = os.MkdirAll(tgtFolder, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// slog.Info("Generating terraform service resource files")
|
|
|
|
// noqa:gosec
|
|
cmd3 := exec.Command(
|
|
"tfplugingen-framework",
|
|
"generate",
|
|
"data-sources",
|
|
"--input",
|
|
specFile,
|
|
"--output",
|
|
tgtFolder,
|
|
"--package",
|
|
scName,
|
|
)
|
|
var stdOut3, stdErr3 bytes.Buffer
|
|
cmd3.Stdout = &stdOut3
|
|
cmd3.Stderr = &stdErr3
|
|
|
|
if err = cmd3.Start(); err != nil {
|
|
slog.Error("tfplugingen-framework generate data-sources", "error", err)
|
|
return err
|
|
}
|
|
|
|
if err = cmd3.Wait(); err != nil {
|
|
var exitErr *exec.ExitError
|
|
if errors.As(err, &exitErr) {
|
|
slog.Error("tfplugingen-framework generate data-sources", "code", exitErr.ExitCode(), "error", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return fmt.Errorf("%s", stdErr.String())
|
|
}
|
|
if err != nil {
|
|
slog.Error("tfplugingen-framework generate data-sources", "err", err, "stdout", stdOut.String(), "stderr", stdErr.String())
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func checkCommands(commands []string) error {
|
|
for _, commandName := range commands {
|
|
if !commandExists(commandName) {
|
|
return fmt.Errorf("missing command %s", commandName)
|
|
}
|
|
slog.Info("found", "command", commandName)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func commandExists(cmd string) bool {
|
|
_, err := exec.LookPath(cmd)
|
|
return err == nil
|
|
}
|
|
|
|
func deleteFiles(fNames ...string) error {
|
|
for _, fName := range fNames {
|
|
if _, err := os.Stat(fName); !os.IsNotExist(err) {
|
|
err = os.Remove(fName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func copyFile(src, dst string) (int64, error) {
|
|
sourceFileStat, err := os.Stat(src)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if !sourceFileStat.Mode().IsRegular() {
|
|
return 0, fmt.Errorf("%s is not a regular file", src)
|
|
}
|
|
|
|
source, err := os.Open(src)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer source.Close()
|
|
|
|
destination, err := os.Create(dst)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer destination.Close()
|
|
nBytes, err := io.Copy(destination, source)
|
|
return nBytes, err
|
|
}
|
|
|
|
func getOnlyLatest(m map[string]version) (map[string]version, error) {
|
|
tmpMap := make(map[string]version)
|
|
for k, v := range m {
|
|
item, ok := tmpMap[k]
|
|
if !ok {
|
|
tmpMap[k] = v
|
|
} else {
|
|
if item.major == v.major && item.minor < v.minor {
|
|
tmpMap[k] = v
|
|
}
|
|
}
|
|
}
|
|
return tmpMap, nil
|
|
}
|
|
|
|
func getVersions(dir string) (map[string]version, error) {
|
|
res := make(map[string]version)
|
|
children, err := os.ReadDir(path.Join(dir, "services"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, entry := range children {
|
|
if entry.IsDir() {
|
|
versions, err := os.ReadDir(path.Join(dir, "services", entry.Name()))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
m, err2 := extractVersions(entry.Name(), versions)
|
|
if err2 != nil {
|
|
return m, err2
|
|
}
|
|
for k, v := range m {
|
|
res[k] = v
|
|
}
|
|
}
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
func extractVersions(service string, versionDirs []os.DirEntry) (map[string]version, error) {
|
|
res := make(map[string]version)
|
|
for _, vDir := range versionDirs {
|
|
if vDir.IsDir() {
|
|
r := regexp.MustCompile(`v([0-9]+)([a-z]+)([0-9]*)`)
|
|
matches := r.FindAllStringSubmatch(vDir.Name(), -1)
|
|
if matches == nil {
|
|
continue
|
|
}
|
|
svc, ver, err := handleVersion(service, matches[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if svc != nil && ver != nil {
|
|
res[*svc] = *ver
|
|
}
|
|
}
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
func handleVersion(service string, match []string) (*string, *version, error) {
|
|
if match == nil {
|
|
fmt.Println("no matches")
|
|
return nil, nil, nil
|
|
}
|
|
verString := match[2]
|
|
if verString != "alpha" && verString != "beta" {
|
|
return nil, nil, errors.New("unsupported version")
|
|
}
|
|
majVer, err := strconv.Atoi(match[1])
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if match[3] == "" {
|
|
match[3] = "0"
|
|
}
|
|
minVer, err := strconv.Atoi(match[3])
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
resStr := fmt.Sprintf("%s%s", service, verString)
|
|
return &resStr, &version{verString: verString, major: majVer, minor: minVer}, nil
|
|
}
|
|
|
|
func createRepoDir(root, repoUrl, repoName string) (string, error) {
|
|
oasTmpDir, err := os.MkdirTemp(root, "oas-tmp")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
targetDir := path.Join(oasTmpDir, repoName)
|
|
_, err = git.Clone(
|
|
clone.Repository(repoUrl),
|
|
clone.Directory(targetDir),
|
|
)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return targetDir, nil
|
|
}
|
|
|
|
func createGeneratorDir(root, repoUrl, repoName string) (string, error) {
|
|
targetDir := path.Join(root, repoName)
|
|
_, err := git.Clone(
|
|
clone.Repository(repoUrl),
|
|
clone.Directory(targetDir),
|
|
)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return targetDir, nil
|
|
}
|
|
|
|
func getRoot() (*string, error) {
|
|
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
|
|
out, err := cmd.Output()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lines := strings.Split(string(out), "\n")
|
|
return &lines[0], nil
|
|
}
|