Skip to content

Commit

Permalink
Merge pull request #81 from pipedrive/update-status-with-remote
Browse files Browse the repository at this point in the history
Update status with remote
  • Loading branch information
nathanleiby authored May 15, 2021
2 parents 1507658 + 14c6c65 commit b3a7e54
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 29 deletions.
25 changes: 25 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceRoot}",
"buildFlags": "-ldflags=-X=main.version=0.0.28",
"env": {
"GITHUB_API_TOKEN":"x"
},
"cwd": "x",
"args": [
"sync"
],
"port": 8080,
"host": "127.0.0.1"
}
]
}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# changelog

2021-05-14 - v0.0.29

- Adds - Command `mp sync` to sync local status with remote status [#81](https://github.com/Clever/microplane/pull/81)
- Changes - Command `mp status` has flag `--sync` to sync local status with remote status [#81](https://github.com/Clever/microplane/pull/81)

2021-03-22 - v0.0.28

- Adds MVP support for Github enterprise (testing pending). [#74](https://github.com/Clever/microplane/pull/74)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.28
0.0.29
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ func init() {
pushCmd.Flags().StringSliceVarP(&pushFlagLabels, "labels", "l", nil, "labels to attach to PR")

rootCmd.AddCommand(statusCmd)
statusCmd.Flags().BoolP("sync", "s", false, "Sync workflow status with repo origin")

rootCmd.AddCommand(syncCmd)

rootCmd.AddCommand(initCmd)

Expand Down
51 changes: 23 additions & 28 deletions cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/Clever/microplane/clone"
"github.com/Clever/microplane/initialize"
"github.com/Clever/microplane/lib"
"github.com/Clever/microplane/merge"
"github.com/Clever/microplane/plan"
"github.com/Clever/microplane/push"
Expand All @@ -33,30 +34,22 @@ var statusCmd = &cobra.Command{
log.Fatalf("error loading init.json: %s\n", err.Error())
}

singleRepo, err := cmd.Flags().GetString("repo")
if err == nil && singleRepo != "" {
valid := false
validRepoNames := []string{}
for _, r := range initOutput.Repos {
if r.Name == singleRepo {
valid = true
break
}
validRepoNames = append(validRepoNames, r.Name)
}
if !valid {
log.Fatalf("%s not a targeted repo name (valid target repos are: %s)", singleRepo, strings.Join(validRepoNames, ", "))
}
isSingleRepo = true
repos, err := whichRepos(cmd)
if err != nil {
log.Fatal(err)
}

repos := []string{}
for _, r := range initOutput.Repos {
if singleRepo != "" && r.Name != singleRepo {
continue
sync, err := cmd.Flags().GetBool("sync")
if err != nil {
log.Fatal(err)
}
if sync {
err = parallelize(repos, syncOneRepo)
if err != nil {
// TODO: dig into errors and display them with more detail
log.Fatal(err)
}
repos = append(repos, r.Name)
}

printStatus(repos)
},
}
Expand All @@ -76,7 +69,7 @@ func joinWithTab(s ...string) string {
return strings.Join(s, "\t")
}

func printStatus(repos []string) {
func printStatus(repos []lib.Repo) {
out := tabWriterWithDefaults()
fmt.Fprintln(out, joinWithTab("REPO", "STATUS", "DETAILS"))
for _, r := range repos {
Expand All @@ -86,19 +79,20 @@ func printStatus(repos []string) {
if len(d3) > 150 {
d3 = d3[:150] + "..."
}
fmt.Fprintln(out, joinWithTab(r, status, d3))
fmt.Fprintln(out, joinWithTab(r.Name, status, d3))
}
out.Flush()
}

func getRepoStatus(repo string) (status, details string) {
func getRepoStatus(repo lib.Repo) (status, details string) {
repoName := repo.Name
status = "initialized"
details = ""
var cloneOutput struct {
clone.Output
Error string
}
if !(loadJSON(outputPath(repo, "clone"), &cloneOutput) == nil && cloneOutput.Success) {
if !(loadJSON(outputPath(repoName, "clone"), &cloneOutput) == nil && cloneOutput.Success) {
if cloneOutput.Error != "" {
details = color.RedString("(clone error) ") + cloneOutput.Error
}
Expand All @@ -110,7 +104,7 @@ func getRepoStatus(repo string) (status, details string) {
plan.Output
Error string
}
if !(loadJSON(outputPath(repo, "plan"), &planOutput) == nil && planOutput.Success) {
if !(loadJSON(outputPath(repoName, "plan"), &planOutput) == nil && planOutput.Success) {
if planOutput.Error != "" {
details = color.RedString("(plan error) ") + planOutput.Error
}
Expand All @@ -129,7 +123,7 @@ func getRepoStatus(repo string) (status, details string) {
push.Output
Error string
}
if !(loadJSON(outputPath(repo, "push"), &pushOutput) == nil && pushOutput.Success) {
if !(loadJSON(outputPath(repoName, "push"), &pushOutput) == nil && pushOutput.Success) {
if pushOutput.Error != "" {
details = color.RedString("(push error) ") + pushOutput.Error
}
Expand All @@ -142,7 +136,8 @@ func getRepoStatus(repo string) (status, details string) {
merge.Output
Error string
}
if !(loadJSON(outputPath(repo, "merge"), &mergeOutput) == nil && mergeOutput.Success) {
// check PR was merged
if !(loadJSON(outputPath(repoName, "merge"), &mergeOutput) == nil && mergeOutput.Success) {
if mergeOutput.Error != "" {
details = color.RedString("(merge error) ") + mergeOutput.Error
}
Expand Down
114 changes: 114 additions & 0 deletions cmd/sync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package cmd

import (
"context"
"log"
"os"
"path/filepath"

"github.com/Clever/microplane/initialize"
"github.com/Clever/microplane/lib"
"github.com/Clever/microplane/merge"
"github.com/Clever/microplane/push"
"github.com/Clever/microplane/sync"
"github.com/spf13/cobra"
)

var syncCmd = &cobra.Command{
Use: "sync",
Short: "Sync workflow status with remote repo",
Run: func(cmd *cobra.Command, args []string) {
// find files and folders to explain the status of each repo
initPath := outputPath("", "init")

if _, err := os.Stat(initPath); os.IsNotExist(err) {
log.Fatalf("must run init first: %s\n", err.Error())
}

var initOutput initialize.Output
if err := loadJSON(initPath, &initOutput); err != nil {
log.Fatalf("error loading init.json: %s\n", err.Error())
}

repos, err := whichRepos(cmd)
if err != nil {
log.Fatal(err)
}

err = parallelize(repos, syncOneRepo)
if err != nil {
// TODO: dig into errors and display them with more detail
log.Fatal(err)
}
},
}

func syncOneRepo(r lib.Repo, ctx context.Context) error {
log.Printf("syncing: %s/%s", r.Owner, r.Name)
repoName := r.Name

var pushOutput struct {
push.Output
Error string
}

if !(loadJSON(outputPath(repoName, "push"), &pushOutput) == nil && pushOutput.Success) {
return nil
}
output, err := syncPush(r, ctx, pushOutput.Output)
if err != nil {
return err
}

var mergeOutput struct {
merge.Output
Error string
}

if loadJSON(outputPath(repoName, "merge"), &mergeOutput) == nil && mergeOutput.Success {
return nil
}

if err := syncMerge(r, ctx, output); err != nil {
return err
}

log.Printf("synced: %s/%s", r.Owner, r.Name)
return nil
}

func syncPush(r lib.Repo, ctx context.Context, pushOutput push.Output) (sync.Output, error) {

var output sync.Output
var err error
if r.IsGitlab() {
output, err = sync.GitlabSyncPush(ctx, r, pushOutput, repoLimiter)
} else if r.IsGithub() {
output, err = sync.GithubSyncPush(ctx, r, pushOutput, repoLimiter)
}
if err != nil {
return sync.Output{}, err
}
pushOutput.CommitSHA = output.CommitSHA
pushOutput.PullRequestCombinedStatus = output.PullRequestCombinedStatus

writeJSON(pushOutput, outputPath(r.Name, "push"))
return output, nil
}
func syncMerge(r lib.Repo, ctx context.Context, output sync.Output) error {
if !output.Merged {
return nil
}

mergeOutputPath := outputPath(r.Name, "merge")
mergeWorkDir := filepath.Dir(mergeOutputPath)
if err := os.MkdirAll(mergeWorkDir, 0755); err != nil {
return err
}

writeJSON(merge.Output{
Success: true,
MergeCommitSHA: output.MergeCommitSHA,
}, mergeOutputPath)
return nil
}
43 changes: 43 additions & 0 deletions sync/syncGithub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package sync

import (
"context"
"time"

"github.com/Clever/microplane/lib"
"github.com/Clever/microplane/push"
)

type Output struct {
CommitSHA string
PullRequestCombinedStatus string
MergeCommitSHA string
Merged bool
}

func GithubSyncPush(ctx context.Context, r lib.Repo, po push.Output, repoLimiter *time.Ticker) (Output, error) {
// Create Github Client
p := lib.NewProviderFromConfig(r.ProviderConfig)
client, err := p.GithubClient(ctx)
if err != nil {
return Output{}, err
}

pr, _, err := client.PullRequests.Get(ctx, r.Owner, r.Name, po.PullRequestNumber)
if err != nil {
return Output{}, err
}

<-repoLimiter.C
cs, _, err := client.Repositories.GetCombinedStatus(ctx, r.Owner, r.Name, *pr.Head.SHA, nil)
if err != nil {
return Output{}, err
}

return Output{
CommitSHA: *pr.Head.SHA,
PullRequestCombinedStatus: *cs.State,
MergeCommitSHA: *pr.MergeCommitSHA,
Merged: *pr.Merged,
}, nil
}
36 changes: 36 additions & 0 deletions sync/syncGitlab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package sync

import (
"context"
"fmt"
"time"

"github.com/Clever/microplane/lib"
"github.com/Clever/microplane/push"
"github.com/xanzy/go-gitlab"
)

func GitlabSyncPush(ctx context.Context, r lib.Repo, po push.Output, repoLimiter *time.Ticker) (Output, error) {
// Create client
p := lib.NewProviderFromConfig(r.ProviderConfig)
client, err := p.GitlabClient()
if err != nil {
return Output{}, err
}
pid := fmt.Sprintf("%s/%s", r.Owner, r.Name)
mr, _, err := client.MergeRequests.GetMergeRequest(pid, po.PullRequestNumber, nil)
if err != nil {
return Output{}, err
}
pipelineStatus, err := push.GetPipelineStatus(client, r.Owner, r.Name, &gitlab.ListProjectPipelinesOptions{SHA: &mr.SHA})
if err != nil {
return Output{}, err
}

return Output{
CommitSHA: mr.SHA,
PullRequestCombinedStatus: pipelineStatus,
MergeCommitSHA: mr.MergeCommitSHA,
Merged: mr.MergeStatus == "merged",
}, nil
}

0 comments on commit b3a7e54

Please sign in to comment.