Skip to content

Commit

Permalink
Add support for getting the GitHub context (#44)
Browse files Browse the repository at this point in the history
* github context

* switch to parse env via external dep

* fix missing env

* Add support for getting the GitHub context

Co-authored-by: Bernardo Vale <[email protected]>
  • Loading branch information
sethvargo and bernardoVale authored May 17, 2022
1 parent 09ae8f6 commit 0cd4e5e
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 0 deletions.
63 changes: 63 additions & 0 deletions actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"os"
"strings"
"time"

"github.com/sethvargo/go-envconfig"
)

var (
Expand Down Expand Up @@ -449,3 +451,64 @@ func (c *Action) Getenv(key string) string {
// GetenvFunc is an abstraction to make tests feasible for commands that
// interact with environment variables.
type GetenvFunc func(key string) string

// GitHubContext of current workflow.
//
// Replicated from https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts
type GitHubContext struct {
EventPath string `env:"GITHUB_EVENT_PATH"`
EventName string `env:"GITHUB_EVENT_NAME"`
SHA string `env:"GITHUB_SHA"`
Ref string `env:"GITHUB_REF"`
Workflow string `env:"GITHUB_WORKFLOW"`
Action string `env:"GITHUB_ACTION"`
Actor string `env:"GITHUB_ACTOR"`
Job string `env:"GITHUB_JOB"`
RunNumber int64 `env:"GITHUB_RUN_NUMBER"`
RunID int64 `env:"GITHUB_RUN_ID"`
APIURL string `env:"GITHUB_API_URL,default=https://api.github.com"`
ServerURL string `env:"GITHUB_SERVER_URL,default=https://github.com"`
GraphqlURL string `env:"GITHUB_GRAPHQL_URL,default=https://api.github.com/graphql"`

// Event is populated by parsing the file at EventPath, if it exists.
Event map[string]any
}

// Context returns the context of current action with the payload object
// that triggered the workflow
func (c *Action) Context() (*GitHubContext, error) {
ctx := context.Background()
lookuper := &wrappedLookuper{f: c.getenv}

var githubContext GitHubContext
if err := envconfig.ProcessWith(ctx, &githubContext, lookuper); err != nil {
return nil, fmt.Errorf("could not process github context variables: %w", err)
}

if githubContext.EventPath != "" {
eventData, err := os.ReadFile(githubContext.EventPath)
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("could not read event file: %w", err)
}
if eventData != nil {
if err := json.Unmarshal(eventData, &githubContext.Event); err != nil {
return nil, fmt.Errorf("failed to unmarshal event payload: %w", err)
}
}
}

return &githubContext, nil
}

// wrappedLookuper creates a lookuper that wraps a given getenv func.
type wrappedLookuper struct {
f GetenvFunc
}

// Lookup implements a custom lookuper.
func (w *wrappedLookuper) Lookup(key string) (string, bool) {
if v := w.f(key); v != "" {
return v, true
}
return "", false
}
4 changes: 4 additions & 0 deletions actions_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,7 @@ func WithFieldsMap(m map[string]string) *Action {
func GetIDToken(ctx context.Context, audience string) (string, error) {
return defaultAction.GetIDToken(ctx, audience)
}

func Context() (*GitHubContext, error) {
return defaultAction.Context()
}
109 changes: 109 additions & 0 deletions actions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"reflect"
"strings"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestNew(t *testing.T) {
Expand Down Expand Up @@ -591,6 +593,113 @@ func TestAction_GetIDToken(t *testing.T) {
}
}

func TestAction_Context(t *testing.T) {
t.Parallel()

f, err := os.CreateTemp("", "")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
os.Remove(f.Name())
})

if _, err := f.Write([]byte(`{"foo": "bar"}`)); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}

eventPayloadPath := f.Name()

cases := []struct {
name string
env map[string]string
exp *GitHubContext
}{
{
name: "empty",
env: nil,
exp: &GitHubContext{
// Defaults
APIURL: "https://api.github.com",
ServerURL: "https://github.com",
GraphqlURL: "https://api.github.com/graphql",
},
},
{
name: "no_payload",
env: map[string]string{
"GITHUB_EVENT_NAME": "event_name",
"GITHUB_SHA": "abcd1234",
"GITHUB_REF": "main",
"GITHUB_WORKFLOW": "test",
"GITHUB_ACTION": "foo/bar@v0",
"GITHUB_ACTOR": "sethvargo",
"GITHUB_JOB": "12",
"GITHUB_RUN_NUMBER": "34",
"GITHUB_RUN_ID": "56",
"GITHUB_API_URL": "https://foo.com",
"GITHUB_SERVER_URL": "https://bar.com",
"GITHUB_GRAPHQL_URL": "https://baz.com",
},
exp: &GitHubContext{
EventName: "event_name",
SHA: "abcd1234",
Ref: "main",
Workflow: "test",
Action: "foo/bar@v0",
Actor: "sethvargo",
Job: "12",
RunNumber: 34,
RunID: 56,
APIURL: "https://foo.com",
ServerURL: "https://bar.com",
GraphqlURL: "https://baz.com",
},
},
{
name: "payload",
env: map[string]string{
"GITHUB_EVENT_PATH": eventPayloadPath,
},
exp: &GitHubContext{
EventPath: eventPayloadPath,

// Defaults
APIURL: "https://api.github.com",
ServerURL: "https://github.com",
GraphqlURL: "https://api.github.com/graphql",

Event: map[string]any{
"foo": "bar",
},
},
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()

a := New(WithGetenv(func(k string) string {
return tc.env[k]
}))
got, err := a.Context()
if err != nil {
t.Fatal(err)
}

if diff := cmp.Diff(tc.exp, got); diff != "" {
t.Fatalf("mismatch (-want, +got):\n%s", diff)
}
})
}
}

// newFakeGetenvFunc returns a new GetenvFunc that is expected to be called with
// the provided key. It returns the provided value if the call matches the
// provided key. It reports an error on test t otherwise.
Expand Down
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@
module github.com/sethvargo/go-githubactions

go 1.18

require (
github.com/google/go-cmp v0.4.1
github.com/sethvargo/go-envconfig v0.6.0
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/sethvargo/go-envconfig v0.6.0 h1:GxxdoeiNpWgGiVEphNFNObgMYRN/ZvI2dN7rBwadyss=
github.com/sethvargo/go-envconfig v0.6.0/go.mod h1:00S1FAhRUuTNJazWBWcJGvEHOM+NO6DhoRMAOX7FY5o=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

0 comments on commit 0cd4e5e

Please sign in to comment.