Feature: Save output (#132)

This commit is contained in:
Mateus Caruccio 2025-03-07 06:46:54 +00:00 committed by GitHub
parent 8248019266
commit c10ec77612
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 119 additions and 14 deletions

View file

@ -41,6 +41,13 @@ inputs:
description: Whether or not to fail the workflow if the approval is denied
required: false
default: 'true'
outputs:
issue-number:
description: The number of the issue created
issue-url:
description: The URL of the issue created
approval-status:
description: The status of the approval ("approved" or "denied")
runs:
using: docker
image: docker://ghcr.io/trstringer/manual-approval:1.9.1

View file

@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"os"
"regexp"
"strings"
@ -112,6 +113,44 @@ func (a *approvalEnvironment) createApprovalIssue(ctx context.Context) error {
return nil
}
func (a *approvalEnvironment) SetActionOutputs(outputs map[string]string) (bool, error) {
outputFile := os.Getenv("GITHUB_OUTPUT")
if outputFile == "" {
return false, nil
}
f, err := os.OpenFile(outputFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return false, err
}
defer f.Close()
var pairs []string
for key, value := range outputs {
pairs = append(pairs, fmt.Sprintf("%s=%s", key, value))
}
// Add a newline before writing the new outputs if the file is not empty. This prevents
// two outputs from being written on the same line.
fileInfo, err := f.Stat()
if err != nil {
return false, err
}
if fileInfo.Size() > 0 {
if _, err := f.WriteString("\n"); err != nil {
return false, err
}
}
if _, err := f.WriteString(strings.Join(pairs, "\n")); err != nil {
return false, err
}
return true, nil
}
func approvalFromComments(comments []*github.IssueComment, approvers []string, minimumApprovals int) (approvalStatus, error) {
remainingApprovers := make([]string, len(approvers))
copy(remainingApprovers, approvers)

View file

@ -1,6 +1,8 @@
package main
import (
"errors"
"os"
"testing"
"github.com/google/go-github/v43/github"
@ -427,3 +429,60 @@ func TestDeniedCommentBody(t *testing.T) {
})
}
}
func TestSaveOutput(t *testing.T) {
testCases := []struct {
name string
approvalIssueNumber int
env_github_output string
isSuccess bool
}{
{
name: "save_output_with_env",
approvalIssueNumber: 123,
env_github_output: "./output.txt",
isSuccess: true,
},
{
name: "fail_save_output_without_env",
approvalIssueNumber: 123,
env_github_output: "",
isSuccess: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
os.Setenv("GITHUB_OUTPUT", testCase.env_github_output)
a := approvalEnvironment{
client: nil,
repoFullName: "",
repo: "",
repoOwner: "",
runID: -1,
approvalIssueNumber: testCase.approvalIssueNumber,
issueTitle: "",
issueBody: "",
issueApprovers: nil,
minimumApprovals: 0,
}
os.Remove(testCase.env_github_output)
actual, err := a.SetActionOutputs(nil)
if err != nil {
t.Fatalf("error creating output file: %v: %v", testCase.env_github_output, err)
}
if actual != testCase.isSuccess {
t.Fatalf("expected %v but got %v", testCase.isSuccess, actual)
}
if actual == true {
if _, err := os.Stat(testCase.env_github_output); errors.Is(err, os.ErrNotExist) {
t.Fatalf("expected create output file %v but it was not", testCase.env_github_output)
}
}
})
}
}

28
main.go
View file

@ -13,19 +13,6 @@ import (
"golang.org/x/oauth2"
)
func setActionOutput(name, value string) error {
f, err := os.OpenFile(os.Getenv("GITHUB_OUTPUT"), os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer f.Close()
if _, err = f.WriteString(fmt.Sprintf("%s=%s\n", name, value)); err != nil {
return err
}
return nil
}
func handleInterrupt(ctx context.Context, client *github.Client, apprv *approvalEnvironment) {
newState := "closed"
closeComment := "Workflow cancelled, closing issue."
@ -235,6 +222,16 @@ func main() {
os.Exit(1)
}
outputs := map[string]string {
"issue-number": fmt.Sprintf("%d", apprv.approvalIssueNumber),
"issue-url": apprv.approvalIssue.GetHTMLURL(),
}
_, err = apprv.SetActionOutputs(outputs)
if err != nil {
fmt.Printf("error saving output: %v", err)
os.Exit(1)
}
killSignalChannel := make(chan os.Signal, 1)
signal.Notify(killSignalChannel, os.Interrupt)
@ -252,7 +249,10 @@ func main() {
} else {
approvalStatus = "approved"
}
if err := setActionOutput("approval_status", approvalStatus); err != nil {
outputs := map[string]string {
"approval-status": approvalStatus,
}
if _, err := apprv.SetActionOutputs(outputs); err != nil {
fmt.Printf("error setting action output: %v\n", err)
exitCode = 1
}