Skip to content

Commit

Permalink
Use go-git for common git operations instead of calling the git
Browse files Browse the repository at this point in the history
command using `os/exec`

This patch updates all the helper functions to use `go-git` library
instead of having to call `os/exec.Command`/`os/exec.CombinedOutput` in
order to clone repository, fetch tags... These changes brings more
dependencies to our `go.mod` but in exchange it simplifies the way we
interact with git repositories and improves errors handling and
readability.

Future changes will also benefit from this patch, especially
conversation webhook generator that will need to checkout multiple
version tags.
  • Loading branch information
a-hilaly committed Jun 29, 2021
1 parent 6911f92 commit 14b3d13
Show file tree
Hide file tree
Showing 10 changed files with 672 additions and 43 deletions.
451 changes: 451 additions & 0 deletions ATTRIBUTION.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cmd/ack-generate/command/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func generateAPIs(cmd *cobra.Command, args []string) error {
if optOutputPath == "" {
optOutputPath = filepath.Join(optServicesDir, svcAlias)
}
if err := ensureSDKRepo(optCacheDir); err != nil {
if err := ensureSDKRepo(optCacheDir, optRefreshCache); err != nil {
return err
}
sdkHelper := model.NewSDKHelper(sdkDir)
Expand Down
104 changes: 66 additions & 38 deletions cmd/ack-generate/command/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
package command

import (
"context"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"

"golang.org/x/mod/modfile"

"github.com/aws-controllers-k8s/code-generator/pkg/util"
)

const (
Expand Down Expand Up @@ -64,67 +66,93 @@ func isDirWriteable(fp string) bool {
// ensureSDKRepo ensures that we have a git clone'd copy of the aws-sdk-go
// repository, which we use model JSON files from. Upon successful return of
// this function, the sdkDir global variable will be set to the directory where
// the aws-sdk-go is found
func ensureSDKRepo(cacheDir string) error {
// the aws-sdk-go is found. It will also optionally fetch all the remote tags
// and checkout the given tag.
func ensureSDKRepo(
cacheDir string,
// A boolean instructing ensureSDKRepo whether to fetch the remote tags from
// the upstream repository
fetchTags bool,
) error {
var err error
srcPath := filepath.Join(cacheDir, "src")
if err = os.MkdirAll(srcPath, os.ModePerm); err != nil {
return err
}
// clone the aws-sdk-go repository locally so we can query for API
// information in the models/apis/ directories
sdkDir, err = cloneSDKRepo(srcPath)
return err
}

// cloneSDKRepo git clone's the aws-sdk-go source repo into the cache and
// returns the filepath to the clone'd repo. If the aws-sdk-go repository
// already exists in the cache, it will checkout the current sdk-go version
// mentionned in 'go.mod' file.
func cloneSDKRepo(srcPath string) (string, error) {
sdkVersion, err := getSDKVersion()
if err != nil {
return "", err
// Clone repository if it doen't exist
sdkDir = filepath.Join(srcPath, "aws-sdk-go")
if _, err := os.Stat(sdkDir); os.IsNotExist(err) {
err = util.CloneRepository(context.Background(), sdkDir, sdkRepoURL)
if err != nil {
return fmt.Errorf("canot clone repository: %v", err)
}
}
clonePath := filepath.Join(srcPath, "aws-sdk-go")
if optRefreshCache {
if _, err := os.Stat(filepath.Join(clonePath, ".git")); !os.IsNotExist(err) {
cmd := exec.Command("git", "-C", clonePath, "fetch", "--all", "--tags")
if err = cmd.Run(); err != nil {
return "", err
}
cmd = exec.Command("git", "-C", clonePath, "checkout", "tags/"+sdkVersion)
return clonePath, cmd.Run()

// Fetch all tags
if fetchTags {
err = util.FetchRepositoryTags(context.Background(), sdkDir)
if err != nil {
return fmt.Errorf("cannot fetch tags: %v", err)
}
}
if _, err := os.Stat(clonePath); os.IsNotExist(err) {
cmd := exec.Command("git", "clone", "-b", sdkVersion, sdkRepoURL, clonePath)
return clonePath, cmd.Run()

// get sdkVersion and correct it (adds missing 'v')
sdkVersion, err := getSDKVersion("")
if err != nil {
return err
}
sdkVersion = correctSemanticVersion(sdkVersion)

// Now checkout the local repository.
repo, err := util.LoadRepository(sdkDir)
if err != nil {
return fmt.Errorf("cannot read local repository: %v", err)
}

err = util.CheckoutRepositoryTag(repo, sdkVersion)
if err != nil {
return fmt.Errorf("cannot checkout tag: %v", err)
}
return clonePath, nil

return err
}

// correctSemanticVersion takes a semver string and tries to append the 'v'
// prefix if it's missing.
func correctSemanticVersion(s string) string {
if strings.HasPrefix(s, "v") {
return s
}
return fmt.Sprintf("v%s", s)
}

// getSDKVersion returns the github.com/aws/aws-sdk-go version to use. It
// first tries to get return version from the --aws-sdk-go-version flag, then
// look for the service controller and local go.mod files.
func getSDKVersion() (string, error) {
// first tries to get the version from the --aws-sdk-go-version flag, then
// from the ack-generate-metadata.yaml and finally look for the service
// go.mod controller.
func getSDKVersion(
//TODO(a-hilaly) Parse ack-generate-metadata.yaml and pass the aws-sdk-go
// version here.
lastGenerationVersion string,
) (string, error) {
// First try to get the version from --aws-sdk-go-version flag
if optAWSSDKGoVersion != "" {
return optAWSSDKGoVersion, nil
}

// then, try to use last generation version (from ack-generate-metadata.yaml)
if lastGenerationVersion != "" {
return lastGenerationVersion, nil
}

// then, try to parse the service controller go.mod file
sdkVersion, err := getSDKVersionFromGoMod(filepath.Join(optOutputPath, "go.mod"))
if err == nil {
return sdkVersion, nil
}

// then try to parse a local go.mod
sdkVersion, err = getSDKVersionFromGoMod("go.mod")
if err != nil {
return "", err
}
return sdkVersion, nil
return "", err
}

// getSDKVersionFromGoMod parses a given go.mod file and returns
Expand Down
2 changes: 1 addition & 1 deletion cmd/ack-generate/command/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func generateController(cmd *cobra.Command, args []string) error {
optOutputPath = filepath.Join(optServicesDir, svcAlias)
}

if err := ensureSDKRepo(optCacheDir); err != nil {
if err := ensureSDKRepo(optCacheDir, optRefreshCache); err != nil {
return err
}
sdkHelper := ackmodel.NewSDKHelper(sdkDir)
Expand Down
2 changes: 1 addition & 1 deletion cmd/ack-generate/command/crossplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func generateCrossplane(_ *cobra.Command, args []string) error {
if len(args) != 1 {
return fmt.Errorf("please specify the service alias for the AWS service API to generate")
}
if err := ensureSDKRepo(optCacheDir); err != nil {
if err := ensureSDKRepo(optCacheDir, optRefreshCache); err != nil {
return err
}
svcAlias := strings.ToLower(args[0])
Expand Down
2 changes: 1 addition & 1 deletion cmd/ack-generate/command/olm.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func generateOLMAssets(cmd *cobra.Command, args []string) error {
version := args[1]

// get the generator inputs
if err := ensureSDKRepo(optCacheDir); err != nil {
if err := ensureSDKRepo(optCacheDir, optRefreshCache); err != nil {
return err
}
sdkHelper := ackmodel.NewSDKHelper(sdkDir)
Expand Down
2 changes: 1 addition & 1 deletion cmd/ack-generate/command/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func generateRelease(cmd *cobra.Command, args []string) error {
// version supplied hasn't been used (as a Git tag) before...
releaseVersion := strings.ToLower(args[1])

if err := ensureSDKRepo(optCacheDir); err != nil {
if err := ensureSDKRepo(optCacheDir, optRefreshCache); err != nil {
return err
}
sdkHelper := ackmodel.NewSDKHelper(sdkDir)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ require (
github.com/spf13/cobra v1.1.1
github.com/stretchr/testify v1.7.0
golang.org/x/mod v0.4.1
gopkg.in/src-d/go-git.v4 v4.13.1
k8s.io/apimachinery v0.20.1
)
Loading

0 comments on commit 14b3d13

Please sign in to comment.