44 "encoding/json"
55 "fmt"
66 "net/http"
7+ "os"
8+ "strings"
79 "text/template"
810
911 "github.com/spf13/cobra"
@@ -45,6 +47,8 @@ func HandleOutput(cmd *cobra.Command, resp *http.Response) error {
4547 if err != nil {
4648 return fmt .Errorf ("failed to marshal to YAML: %w" , err )
4749 }
50+ case "github-action" :
51+ return handleGitHubActionOutput (result )
4852 default :
4953 output , err = json .MarshalIndent (result , "" , " " )
5054 if err != nil {
@@ -55,3 +59,116 @@ func HandleOutput(cmd *cobra.Command, resp *http.Response) error {
5559 fmt .Fprintln (cmd .OutOrStdout (), string (output ))
5660 return nil
5761}
62+
63+ func handleGitHubActionOutput (result map [string ]interface {}) error {
64+ writer , err := NewGitHubOutputWriter ()
65+ if err != nil {
66+ return fmt .Errorf ("failed to create GitHubOutputWriter: %w" , err )
67+ }
68+ defer writer .Close ()
69+
70+ output , err := json .Marshal (result )
71+ if err != nil {
72+ return fmt .Errorf ("failed to marshal to JSON: %w" , err )
73+ }
74+
75+ writer .Write ("json" , string (output ))
76+ var data map [string ]interface {}
77+ if err := json .Unmarshal (output , & data ); err != nil {
78+ return fmt .Errorf ("failed to unmarshal JSON: %w" , err )
79+ }
80+
81+ var flatten func (prefix string , v interface {}) error
82+ flatten = func (prefix string , v interface {}) error {
83+ switch val := v .(type ) {
84+ case map [string ]interface {}:
85+ for k , v := range val {
86+ newPrefix := strings .ReplaceAll (k , "/" , "_" )
87+ if prefix != "" {
88+ newPrefix = prefix + "_" + newPrefix
89+ }
90+ if err := flatten (newPrefix , v ); err != nil {
91+ return err
92+ }
93+ }
94+ case []interface {}:
95+ for i , v := range val {
96+ newPrefix := fmt .Sprintf ("%s_%d" , prefix , i )
97+ if err := flatten (newPrefix , v ); err != nil {
98+ return err
99+ }
100+ }
101+ default :
102+ if val == nil {
103+ return nil
104+ }
105+
106+ writer .Write (prefix , fmt .Sprintf ("%v" , val ))
107+ }
108+ return nil
109+ }
110+
111+ if err := flatten ("" , data ); err != nil {
112+ return fmt .Errorf ("failed to flatten output: %w" , err )
113+ }
114+
115+ return nil
116+ }
117+
118+ // GitHubOutputWriter is a helper for writing to the GITHUB_OUTPUT file.
119+ type GitHubOutputWriter struct {
120+ file * os.File
121+ }
122+
123+ // NewGitHubOutputWriter creates and initializes a new GitHubOutputWriter. It
124+ // opens the GITHUB_OUTPUT file for appending.
125+ func NewGitHubOutputWriter () (* GitHubOutputWriter , error ) {
126+ // Get the GITHUB_OUTPUT environment variable
127+ githubOutput := os .Getenv ("GITHUB_OUTPUT" )
128+ if githubOutput == "" {
129+ return nil , fmt .Errorf ("GITHUB_OUTPUT environment variable is not set" )
130+ }
131+
132+ // Open the file in append mode
133+ file , err := os .OpenFile (githubOutput , os .O_APPEND | os .O_WRONLY , 0644 )
134+ if err != nil {
135+ return nil , fmt .Errorf ("error opening GITHUB_OUTPUT file: %w" , err )
136+ }
137+
138+ return & GitHubOutputWriter {file : file }, nil
139+ }
140+
141+ // Write writes a key-value pair to the GITHUB_OUTPUT file.
142+ func (w * GitHubOutputWriter ) Write (key , value string ) error {
143+ if w .file == nil {
144+ return fmt .Errorf ("GitHubOutputWriter is not initialized" )
145+ }
146+
147+ // Format and write the output
148+ output := fmt .Sprintf ("%s=%s\n " , key , value )
149+ if _ , err := w .file .WriteString (output ); err != nil {
150+ return fmt .Errorf ("error writing to GITHUB_OUTPUT file: %w" , err )
151+ }
152+
153+ return nil
154+ }
155+
156+ // Close closes the GITHUB_OUTPUT file.
157+ func (w * GitHubOutputWriter ) Close () error {
158+ if w .file == nil {
159+ return nil
160+ }
161+ err := w .file .Close ()
162+ w .file = nil
163+ return err
164+ }
165+
166+ // GetEnv fetches the value of an environment variable or returns a default
167+ // value.
168+ func GetEnv (key string , defaultValue string ) string {
169+ value := os .Getenv (key )
170+ if value == "" {
171+ return defaultValue
172+ }
173+ return value
174+ }
0 commit comments