-
Notifications
You must be signed in to change notification settings - Fork 877
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add generator tool to run in the sdk automation pipeline
- Loading branch information
1 parent
254d76a
commit c79bf60
Showing
17 changed files
with
971 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package autorest | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
) | ||
|
||
// Task describes a generation task | ||
type Task struct { | ||
// AbsReadmeMd absolute path of the readme.md file to generate | ||
AbsReadmeMd string | ||
} | ||
|
||
// Execute executes the autorest task, and then invoke the after scripts | ||
// the error returned will be TaskError | ||
func (t *Task) Execute(options Options) error { | ||
if err := t.executeAutorest(options.AutorestArguments); err != nil { | ||
return err | ||
} | ||
|
||
if err := t.executeAfterScript(options.AfterScripts); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (t *Task) executeAutorest(options []string) error { | ||
arguments := append(options, t.AbsReadmeMd) | ||
c := exec.Command("autorest", arguments...) | ||
log.Printf("Executing autorest with parameters: %+v", arguments) | ||
c.Stdout = os.Stdout | ||
c.Stderr = os.Stderr | ||
c.Start() | ||
if err := c.Wait(); err != nil { | ||
return &TaskError{ | ||
AbsReadmeMd: t.AbsReadmeMd, | ||
Script: "autorest", | ||
Message: err.Error(), | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (t *Task) executeAfterScript(afterScripts []string) error { | ||
for _, script := range afterScripts { | ||
log.Printf("Executing after scripts %s...", script) | ||
arguments := strings.Split(script, " ") | ||
c := exec.Command(arguments[0], arguments[1:]...) | ||
output, err := c.CombinedOutput() | ||
if err != nil { | ||
return &TaskError{ | ||
AbsReadmeMd: t.AbsReadmeMd, | ||
Script: script, | ||
Message: string(output), | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Options describes the options used in an autorest task | ||
type Options struct { | ||
// AutorestArguments are the optional flags for the autorest tool | ||
AutorestArguments []string | ||
// AfterScripts are the scripts that need to be run after the SDK is generated | ||
AfterScripts []string | ||
} | ||
|
||
// NewOptionsFrom returns a new options from a io.Reader | ||
func NewOptionsFrom(reader io.Reader) (*Options, error) { | ||
b, err := ioutil.ReadAll(reader) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var result Options | ||
if err := json.Unmarshal(b, &result); err != nil { | ||
return nil, err | ||
} | ||
return &result, nil | ||
} | ||
|
||
// String ... | ||
func (o Options) String() string { | ||
b, _ := json.MarshalIndent(o, "", " ") | ||
return string(b) | ||
} | ||
|
||
// TaskError the error returned during an autorest task | ||
type TaskError struct { | ||
// AbsReadmeMd relative path of the readme.md file to generate | ||
AbsReadmeMd string | ||
// Script the script running when the error is thrown | ||
Script string | ||
// Message the error message | ||
Message string | ||
} | ||
|
||
func (r *TaskError) Error() string { | ||
return fmt.Sprintf("autorest task failed for readme file '%s' during '%s': %s", r.AbsReadmeMd, r.Script, r.Message) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package autorest | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
type ChangedPackagesMap map[string][]string | ||
|
||
func (c *ChangedPackagesMap) addFileToPackage(pkg, file string) { | ||
pkg = strings.ReplaceAll(pkg, "\\", "/") | ||
if _, ok := (*c)[pkg]; !ok { | ||
(*c)[pkg] = []string{} | ||
} | ||
(*c)[pkg] = append((*c)[pkg], file) | ||
} | ||
|
||
func (c *ChangedPackagesMap) String() string { | ||
var r []string | ||
for k, v := range *c { | ||
r = append(r, fmt.Sprintf("%s: %+v", k, v)) | ||
} | ||
return strings.Join(r, "\n") | ||
} | ||
|
||
func (c *ChangedPackagesMap) GetChangedPackages() []string { | ||
var r []string | ||
for k := range *c { | ||
r = append(r, k) | ||
} | ||
return r | ||
} | ||
|
||
// GetChangedPackages get the go SDK packages map from the given changed file list. | ||
// the map returned has the package full path as key, and the changed files in the package as the value. | ||
// This function identify the package by checking if a directory has both a `version.go` file and a `client.go` file. | ||
func GetChangedPackages(changedFiles []string) (ChangedPackagesMap, error) { | ||
changedFiles, err := ExpandChangedDirectories(changedFiles) | ||
if err != nil { | ||
return nil, err | ||
} | ||
r := ChangedPackagesMap{} | ||
for _, file := range changedFiles { | ||
fi, err := os.Stat(file) | ||
if err != nil { | ||
return nil, err | ||
} | ||
path := file | ||
if !fi.IsDir() { | ||
path = filepath.Dir(file) | ||
} | ||
if IsValidPackage(path) { | ||
r.addFileToPackage(path, file) | ||
} | ||
} | ||
return r, nil | ||
} | ||
|
||
// ExpandChangedDirectories expands every directory listed in the array to all its file | ||
func ExpandChangedDirectories(changedFiles []string) ([]string, error) { | ||
var result []string | ||
for _, path := range changedFiles { | ||
fi, err := os.Stat(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if fi.IsDir() { | ||
siblings, err := getAllFiles(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
result = append(result, siblings...) | ||
} else { | ||
result = append(result, path) | ||
} | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func getAllFiles(root string) ([]string, error) { | ||
var siblings []string | ||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
if !info.IsDir() { | ||
siblings = append(siblings, strings.ReplaceAll(path, "\\", "/")) | ||
} | ||
return nil | ||
}) | ||
return siblings, err | ||
} | ||
|
||
const ( | ||
clientGo = "client.go" | ||
versionGo = "version.go" | ||
) | ||
|
||
func IsValidPackage(dir string) bool { | ||
client := filepath.Join(dir, clientGo) | ||
version := filepath.Join(dir, versionGo) | ||
// both the above files must exist to return true | ||
if _, err := os.Stat(client); os.IsNotExist(err) { | ||
return false | ||
} | ||
if _, err := os.Stat(version); os.IsNotExist(err) { | ||
return false | ||
} | ||
return true | ||
} |
Oops, something went wrong.