Skip to content

Commit

Permalink
Update set outputs to latest specs
Browse files Browse the repository at this point in the history
  • Loading branch information
tjamet committed Sep 14, 2023
1 parent 07e4214 commit bb4c78d
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 17 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,18 @@ jobs:
run: go mod download

- name: run tests
id: tests
if: ${{ matrix.os }} != "windows-latest"
env:
# unauthenticated calls have lower limits than authenticated ones
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: go test -v -race ${{ matrix.coverageArgs }} ./...

- name: run tests with inputs
if: ${{ matrix.os }} != "windows-latest"
env:
ACTIONS_OUTPUT_SET: "true"
# unauthenticated calls have lower limits than authenticated ones
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# my_output: "${{ steps.tests.outputs.my-output }}"
run: go test -v -race ${{ matrix.coverageArgs }} ./...
58 changes: 57 additions & 1 deletion core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,61 @@ package core

import (
"fmt"
"io"
"os"
"strings"
"sync"
)

const (
delimiter = "_GitHubActionsGoFileCommandDelimeter_"

// StatusFailed is returned by Status() in case this action has been marked as failed
StatusFailed = 1
// StatusSuccess is returned by Status() in case this action has not been marked as failed. By default an action is claimed as successful
StatusSuccess = 0

GitHubOutputFilePathEnvName = "GITHUB_OUTPUT"
GitHubStateFilePathEnvName = "GITHUB_STATE"
GitHubExportEnvFilePathEnvName = "GITHUB_ENV"
)

var (
status = StatusSuccess
statusAccess = &sync.Mutex{}
lookupEnv = os.LookupEnv
open = func(path string, flag int, perm os.FileMode) (File, error) {
fd, err := os.OpenFile(path, flag, perm)
if err != nil {
return nil, err
}
return fd, nil
}
)

type File interface {
io.Reader
io.Writer
io.Closer
}

func formatOutput(name, value string) string {
return fmt.Sprintf("%s<<%s%s%s%s%s", name, delimiter, EOF, value, EOF, delimiter, EOF)
}

// ExportVariable sets the environment varaible name (for this action and future actions)
func ExportVariable(name, value string) {
const delimiter = "_GitHubActionsFileCommandDelimeter_"
if path, ok := os.LookupEnv(GitHubExportEnvFilePathEnvName); ok {
f, err := open(path, os.O_RDWR|os.O_APPEND, 0)
if err != nil {
Warningf("failed to open environment export file %s: %v", path, err)
} else {
defer f.Close()
f.Write([]byte(formatOutput(name, value)))
}
} else {
Warningf("did not find environment export file from environment variable %s, falling back to the deprecated command implementation", GitHubExportEnvFilePathEnvName)
}
if err := issueFileCommand("ENV", fmt.Sprintf("%s<<%s%s%s%s%s", name, delimiter, EOF, value, delimiter, EOF)); err != nil {
IssueCommand("set-env", map[string]string{"name": name}, value)
}
Expand Down Expand Up @@ -65,6 +99,17 @@ func GetInputOrDefault(name, dflt string) string {

// SetOutput sets the value of an output for future actions
func SetOutput(name, value string) {
if path, ok := os.LookupEnv(GitHubOutputFilePathEnvName); ok {
f, err := open(path, os.O_RDWR|os.O_APPEND, 0)
if err != nil {
Warningf("failed to open output file %s: %v", path, err)
} else {
defer f.Close()
f.Write([]byte(formatOutput(name, value)))
}
} else {
Warningf("did not find output file from environment variable %s, falling back to the deprecated command implementation", GitHubOutputFilePathEnvName)
}
IssueCommand("set-output", map[string]string{"name": name}, value)
}

Expand Down Expand Up @@ -142,6 +187,17 @@ func Group(name string, f func()) func() {

// SaveState saves state for current action, the state can only be retrieved by this action's post job execution.
func SaveState(name, value string) {
if path, ok := os.LookupEnv(GitHubStateFilePathEnvName); ok {
f, err := open(path, os.O_RDWR|os.O_APPEND, 0)
if err != nil {
Warningf("failed to open state file %s: %v", path, err)
} else {
defer f.Close()
f.Write([]byte(formatOutput(name, value)))
}
} else {
Warningf("did not find state file from environment variable %s, falling back to the deprecated command implementation", GitHubStateFilePathEnvName)
}
IssueCommand("save-state", map[string]string{"name": name}, value)
}

Expand Down
12 changes: 12 additions & 0 deletions core/core_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package core

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestOutputTasks(t *testing.T) {
if _, ok := os.LookupEnv("ACTIONS_OUTPUT_SET"); ok {
assert.Equal(t, "my-state-value", GetState("my-state"))
assert.Equal(t, "my-output-value", os.Getenv("my_output"))
assert.Equal(t, "my-env-value", os.Getenv("my_env"))
}
SaveState("my-state", "my-state-value")
ExportVariable("my_env", "my-env-value")
SetOutput("my-output", "my-output-value")
}

func TestGetInput(t *testing.T) {
t.Run("when environment variable is not net", func(t *testing.T) {
lookupEnv = func(name string) (string, bool) {
Expand Down
39 changes: 23 additions & 16 deletions github/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"strings"

"github.com/actions-go/toolkit/core"
"github.com/google/go-github/v42/github"
)

Expand Down Expand Up @@ -79,15 +80,18 @@ type ActionRepo struct {

// ActionContext contains details on the workflow execution
type ActionContext struct {
Payload WebhookPayload
EventName string
SHA string
Ref string
Workflow string
Action string
Actor string
Issue ActionIssue
Repo ActionRepo
Payload WebhookPayload
EventName string
SHA string
Ref string
Workflow string
Action string
Actor string
Issue ActionIssue
Repo ActionRepo
OutputFilePath string
StateFilePath string
ExportEnvFilePath string
}

func noGitHubEvent(path string) {
Expand All @@ -109,13 +113,16 @@ func ParseActionEnv() ActionContext {
Repo: getIndex(r, 1),
}
ctx := ActionContext{
EventName: os.Getenv("GITHUB_EVENT_NAME"),
SHA: os.Getenv("GITHUB_SHA"),
Ref: os.Getenv("GITHUB_REF"),
Workflow: os.Getenv("GITHUB_WORKFLOW"),
Action: os.Getenv("GITHUB_ACTION"),
Actor: os.Getenv("GITHUB_ACTOR"),
Repo: repo,
EventName: os.Getenv("GITHUB_EVENT_NAME"),
SHA: os.Getenv("GITHUB_SHA"),
Ref: os.Getenv("GITHUB_REF"),
Workflow: os.Getenv("GITHUB_WORKFLOW"),
Action: os.Getenv("GITHUB_ACTION"),
Actor: os.Getenv("GITHUB_ACTOR"),
OutputFilePath: os.Getenv(core.GitHubOutputFilePathEnvName),
StateFilePath: os.Getenv(core.GitHubStateFilePathEnvName),
ExportEnvFilePath: os.Getenv(core.GitHubExportEnvFilePathEnvName),
Repo: repo,
Issue: ActionIssue{
Owner: repo.Owner,
Repo: repo.Repo,
Expand Down

0 comments on commit bb4c78d

Please sign in to comment.