Skip to content

Commit e67820f

Browse files
committed
fix: write to GITHUB_OUTPUT file
1 parent f43021b commit e67820f

3 files changed

Lines changed: 53 additions & 31 deletions

File tree

.github/workflows/main.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ jobs:
2828
images: ${{ env.DOCKER_IMAGE }}
2929
tags: latest
3030

31-
3231
- name: Build and push
3332
uses: docker/build-push-action@v2
3433
with:
@@ -39,3 +38,14 @@ jobs:
3938
${{ steps.meta.outputs.tags }}
4039
${{ env.DOCKER_IMAGE }}:${{ github.sha }}
4140
labels: ${{ steps.meta.outputs.labels }}
41+
42+
- name: Test action
43+
uses: ./ # Uses an action in the root directory
44+
id: render
45+
with:
46+
template: ./testdata/template.txt
47+
vars: |
48+
name: world
49+
50+
- name: Get `result` output
51+
run: echo "${{ steps.render.outputs.result }}"

main.go

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"io/ioutil"
88
"os"
99
"reflect"
10-
"strings"
1110
"text/template"
1211

1312
"github.com/caarlos0/env/v6"
@@ -56,18 +55,10 @@ func run() error {
5655
return fmt.Errorf("failed to render template: %v", err)
5756
}
5857

59-
githubOutput := fmt.Sprintf("%s=%s", "result", escape(output))
60-
if os.Getenv("GITHUB_OUTPUT") != "" {
61-
githubOutput = fmt.Sprintln(os.Getenv("GITHUB_OUTPUT")) + githubOutput
62-
}
63-
64-
err = os.Setenv("GITHUB_OUTPUT", githubOutput)
65-
if err != nil {
66-
return fmt.Errorf("failed to set GITHUB_OUTPUT: %v", err)
58+
if err = writeOutput(output); err != nil {
59+
return err
6760
}
6861

69-
fmt.Printf("::debug::%s", os.Getenv("GITHUB_OUTPUT"))
70-
7162
if len(c.ResultPath) != 0 {
7263
err := ioutil.WriteFile(c.ResultPath, []byte(output), 0644)
7364
if err != nil {
@@ -126,16 +117,36 @@ func renderTemplate(templateFilePath string, vars vars) (string, error) {
126117
return result.String(), nil
127118
}
128119

129-
func escape(str string) string {
130-
/*
131-
set-output truncates multiline strings.
132-
% and \n and \r can be escaped, the runner will unescape in reverse:
133-
https://github.community/t/set-output-truncates-multiline-strings/16852
134-
*/
135-
136-
return strings.NewReplacer(
137-
"%", "%25",
138-
"\n", "%0A",
139-
"\r", "%0D",
140-
).Replace(str)
120+
func writeOutput(output string) error {
121+
githubOutput := formatOutput("result", output)
122+
if githubOutput == "" {
123+
return nil
124+
}
125+
126+
path := os.Getenv("GITHUB_OUTPUT")
127+
128+
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644)
129+
if err != nil {
130+
return fmt.Errorf("failed to open result file %q: %v", path, err)
131+
}
132+
defer f.Close()
133+
134+
if _, err = f.WriteString(githubOutput); err != nil {
135+
return fmt.Errorf("failed to write result to file %q: %v", path, err)
136+
}
137+
138+
return nil
139+
}
140+
141+
func formatOutput(name, value string) string {
142+
if value == "" {
143+
return ""
144+
}
145+
146+
// if value contains new line, use multiline format
147+
if bytes.ContainsRune([]byte(value), '\n') {
148+
return fmt.Sprintf("%s<<OUTPUT\n%s\nOUTPUT", name, value)
149+
}
150+
151+
return fmt.Sprintf("%s=%s", name, value)
141152
}

main_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,23 @@ import (
77
"testing"
88
)
99

10-
func TestEscape(t *testing.T) {
10+
func TestFormatOutput(t *testing.T) {
1111
tests := []struct {
1212
in string
1313
expected string
1414
}{
1515
{"", ""},
16-
{"text", "text"},
17-
{"%", "%25"},
18-
{"\n", "%0A"},
19-
{"\r", "%0D"},
16+
{"text", "result=text"},
17+
{"%", "result=%"},
18+
{"some\ntext", "result<<OUTPUT\nsome\ntext\nOUTPUT"},
19+
{"\n", "result<<OUTPUT\n\n\nOUTPUT"},
20+
{"\r", "result=\r"},
2021
}
2122

2223
for _, tt := range tests {
23-
actual := escape(tt.in)
24+
actual := formatOutput("result", tt.in)
2425
if actual != tt.expected {
25-
t.Errorf("escape(%q) was incorrect, got: %q, want: %q.", tt.in, actual, tt.expected)
26+
t.Errorf("formatOutput(%q) was incorrect, got: %q, want: %q.", tt.in, actual, tt.expected)
2627
}
2728
}
2829
}

0 commit comments

Comments
 (0)