diff --git a/main.go b/main.go index c738e60..09e4516 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "os/signal" "strconv" "strings" "time" @@ -12,6 +13,90 @@ import ( "golang.org/x/oauth2" ) +func handleInterrupt(client *github.Client, ctx context.Context, apprv *approvalEnvironment) { + newState := "closed" + closeComment := "Workflow cancelled, closing issue." + fmt.Println(closeComment) + _, _, err := client.Issues.CreateComment(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueComment{ + Body: &closeComment, + }) + if err != nil { + fmt.Printf("error commenting on issue: %v\n", err) + return + } + _, _, err = client.Issues.Edit(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueRequest{State: &newState}) + if err != nil { + fmt.Printf("error closing issue: %v\n", err) + return + } +} + +func newCommentLoopChannel(ctx context.Context, apprv *approvalEnvironment, client *github.Client, approvers []string, minimumApprovals int) chan int { + channel := make(chan int) + go func() { + for { + comments, _, err := client.Issues.ListComments(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueListCommentsOptions{}) + if err != nil { + fmt.Printf("error getting comments: %v\n", err) + channel <- 1 + close(channel) + } + + approved, err := approvalFromComments(comments, approvers, minimumApprovals) + if err != nil { + fmt.Printf("error getting approval from comments: %v\n", err) + channel <- 1 + close(channel) + } + fmt.Printf("Workflow status: %s\n", approved) + switch approved { + case approvalStatusApproved: + newState := "closed" + closeComment := "All approvers have approved, continuing workflow and closing this issue." + _, _, err := client.Issues.CreateComment(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueComment{ + Body: &closeComment, + }) + if err != nil { + fmt.Printf("error commenting on issue: %v\n", err) + channel <- 1 + close(channel) + } + _, _, err = client.Issues.Edit(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueRequest{State: &newState}) + if err != nil { + fmt.Printf("error closing issue: %v\n", err) + channel <- 1 + close(channel) + } + channel <- 0 + fmt.Println("Workflow manual approval completed") + close(channel) + case approvalStatusDenied: + newState := "closed" + closeComment := "Request denied. Closing issue and failing workflow." + _, _, err := client.Issues.CreateComment(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueComment{ + Body: &closeComment, + }) + if err != nil { + fmt.Printf("error commenting on issue: %v\n", err) + channel <- 1 + close(channel) + } + _, _, err = client.Issues.Edit(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueRequest{State: &newState}) + if err != nil { + fmt.Printf("error closing issue: %v\n", err) + channel <- 1 + close(channel) + } + channel <- 1 + close(channel) + } + + time.Sleep(pollingInterval) + } + }() + return channel +} + func newGithubClient(ctx context.Context) *github.Client { token := os.Getenv(envVarToken) ts := oauth2.StaticTokenSource( @@ -64,57 +149,16 @@ func main() { os.Exit(1) } -commentLoop: - for { - comments, _, err := client.Issues.ListComments(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueListCommentsOptions{}) - if err != nil { - fmt.Printf("error getting comments: %v\n", err) - os.Exit(1) - } + killSignalChannel := make(chan os.Signal, 1) + signal.Notify(killSignalChannel, os.Interrupt) - approved, err := approvalFromComments(comments, approvers, minimumApprovals) - if err != nil { - fmt.Printf("error getting approval from comments: %v\n", err) - os.Exit(1) - } - fmt.Printf("Workflow status: %s\n", approved) - switch approved { - case approvalStatusApproved: - newState := "closed" - closeComment := "All approvers have approved, continuing workflow and closing this issue." - _, _, err := client.Issues.CreateComment(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueComment{ - Body: &closeComment, - }) - if err != nil { - fmt.Printf("error commenting on issue: %v\n", err) - os.Exit(1) - } - _, _, err = client.Issues.Edit(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueRequest{State: &newState}) - if err != nil { - fmt.Printf("error closing issue: %v\n", err) - os.Exit(1) - } - break commentLoop - case approvalStatusDenied: - newState := "closed" - closeComment := "Request denied. Closing issue and failing workflow." - _, _, err := client.Issues.CreateComment(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueComment{ - Body: &closeComment, - }) - if err != nil { - fmt.Printf("error commenting on issue: %v\n", err) - os.Exit(1) - } - _, _, err = client.Issues.Edit(ctx, apprv.repoOwner, apprv.repo, apprv.approvalIssueNumber, &github.IssueRequest{State: &newState}) - if err != nil { - fmt.Printf("error closing issue: %v\n", err) - os.Exit(1) - } - os.Exit(1) - } + commentLoopChannel := newCommentLoopChannel(ctx, apprv, client, approvers, minimumApprovals) - time.Sleep(pollingInterval) + select { + case exitCode := <-commentLoopChannel: + os.Exit(exitCode) + case _ = <-killSignalChannel: + handleInterrupt(client, ctx, apprv) + os.Exit(1) } - - fmt.Println("Workflow manual approval completed") }