mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-03-22 06:45:03 +01:00
feat: contextdata overlay api and more gh/gt instance flags (#105)
* add TestGetGitHubContextOverlay
This commit is contained in:
@@ -76,6 +76,14 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action
|
||||
EventJSON: parent.EventJSON,
|
||||
nodeToolFullPath: parent.nodeToolFullPath,
|
||||
}
|
||||
if parent.ContextData != nil {
|
||||
compositerc.ContextData = map[string]interface{}{}
|
||||
for k, v := range parent.ContextData {
|
||||
if !strings.EqualFold("inputs", k) {
|
||||
compositerc.ContextData[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
compositerc.ExprEval = compositerc.NewExpressionEvaluator(ctx)
|
||||
|
||||
return compositerc
|
||||
|
||||
@@ -90,6 +90,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
|
||||
Needs: using,
|
||||
Inputs: inputs,
|
||||
HashFiles: getHashFilesFunction(ctx, rc),
|
||||
CtxData: rc.ContextData,
|
||||
}
|
||||
if rc.JobContainer != nil {
|
||||
ee.Runner = rc.JobContainer.GetRunnerContext(ctx)
|
||||
@@ -155,9 +156,11 @@ func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step,
|
||||
// but required to interpolate/evaluate the inputs in actions/composite
|
||||
Inputs: inputs,
|
||||
HashFiles: getHashFilesFunction(ctx, rc),
|
||||
CtxData: rc.ContextData,
|
||||
}
|
||||
if rc.JobContainer != nil {
|
||||
ee.Runner = rc.JobContainer.GetRunnerContext(ctx)
|
||||
ee.EnvCS = !rc.JobContainer.IsEnvironmentCaseInsensitive()
|
||||
}
|
||||
return expressionEvaluator{
|
||||
interpreter: exprparser.NewInterpeter(ee, exprparser.Config{
|
||||
|
||||
@@ -53,6 +53,7 @@ type RunContext struct {
|
||||
cleanUpJobContainer common.Executor
|
||||
caller *caller // job calling this RunContext (reusable workflows)
|
||||
Cancelled bool
|
||||
ContextData map[string]interface{}
|
||||
nodeToolFullPath string
|
||||
}
|
||||
|
||||
@@ -959,6 +960,8 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext
|
||||
ghc.Workspace = rc.JobContainer.ToContainerPath(rc.Config.Workdir)
|
||||
}
|
||||
|
||||
rc.mergeGitHubContextWithContextData(ghc)
|
||||
|
||||
if ghc.RunAttempt == "" {
|
||||
ghc.RunAttempt = "1"
|
||||
}
|
||||
@@ -994,7 +997,7 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext
|
||||
|
||||
ghc.SetBaseAndHeadRef()
|
||||
repoPath := rc.Config.Workdir
|
||||
ghc.SetRepositoryAndOwner(ctx, rc.Config.GitHubInstance, rc.Config.RemoteName, repoPath)
|
||||
ghc.SetRepositoryAndOwner(ctx, rc.Config.GetGitHubInstance(), rc.Config.RemoteName, repoPath)
|
||||
if ghc.Ref == "" {
|
||||
ghc.SetRef(ctx, rc.Config.DefaultBranch, repoPath)
|
||||
}
|
||||
@@ -1004,16 +1007,16 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext
|
||||
|
||||
ghc.SetRefTypeAndName()
|
||||
|
||||
// defaults
|
||||
ghc.ServerURL = "https://github.com"
|
||||
ghc.APIURL = "https://api.github.com"
|
||||
ghc.GraphQLURL = "https://api.github.com/graphql"
|
||||
// per GHES
|
||||
if rc.Config.GitHubInstance != "github.com" {
|
||||
ghc.ServerURL = fmt.Sprintf("https://%s", rc.Config.GitHubInstance)
|
||||
ghc.APIURL = fmt.Sprintf("https://%s/api/v3", rc.Config.GitHubInstance)
|
||||
ghc.GraphQLURL = fmt.Sprintf("https://%s/api/graphql", rc.Config.GitHubInstance)
|
||||
if ghc.ServerURL == "" {
|
||||
ghc.ServerURL = rc.Config.GetGitHubServerURL()
|
||||
}
|
||||
if ghc.APIURL == "" {
|
||||
ghc.APIURL = rc.Config.GetGitHubAPIServerURL()
|
||||
}
|
||||
if ghc.GraphQLURL == "" {
|
||||
ghc.GraphQLURL = rc.Config.GetGitHubGraphQlAPIServerURL()
|
||||
}
|
||||
|
||||
// allow to be overridden by user
|
||||
if rc.Config.Env["GITHUB_SERVER_URL"] != "" {
|
||||
ghc.ServerURL = rc.Config.Env["GITHUB_SERVER_URL"]
|
||||
@@ -1028,6 +1031,25 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext
|
||||
return ghc
|
||||
}
|
||||
|
||||
func (rc *RunContext) mergeGitHubContextWithContextData(ghc *model.GithubContext) {
|
||||
if rnout, ok := rc.ContextData["github"]; ok {
|
||||
nout, ok := rnout.(map[string]interface{})
|
||||
if ok {
|
||||
var out map[string]interface{}
|
||||
content, _ := json.Marshal(ghc)
|
||||
_ = json.Unmarshal(content, &out)
|
||||
for k, v := range nout {
|
||||
// gitea sends empty string github contextdata, which replaced github.workspace
|
||||
if v != nil && v != "" {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
content, _ = json.Marshal(out)
|
||||
_ = json.Unmarshal(content, &ghc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isLocalCheckout(ghc *model.GithubContext, step *model.Step) bool {
|
||||
if step.Type() == model.StepTypeInvalid {
|
||||
// This will be errored out by the executor later, we need this here to avoid a null panic though
|
||||
|
||||
@@ -393,6 +393,54 @@ func TestGetGitHubContext(t *testing.T) {
|
||||
assert.Equal(t, "job1", ghc.Job)
|
||||
}
|
||||
|
||||
func TestGetGitHubContextOverlay(t *testing.T) {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
assert.Nil(t, err)
|
||||
|
||||
rc := &RunContext{
|
||||
Config: &Config{
|
||||
EventName: "push",
|
||||
Workdir: cwd,
|
||||
},
|
||||
Run: &model.Run{
|
||||
Workflow: &model.Workflow{
|
||||
Name: "GitHubContextTest",
|
||||
},
|
||||
},
|
||||
Name: "GitHubContextTest",
|
||||
CurrentStep: "step",
|
||||
Matrix: map[string]interface{}{},
|
||||
Env: map[string]string{},
|
||||
ExtraPath: []string{},
|
||||
StepResults: map[string]*model.StepResult{},
|
||||
OutputMappings: map[MappableOutput]MappableOutput{},
|
||||
ContextData: map[string]interface{}{
|
||||
"github": map[string]interface{}{
|
||||
"actor": "me",
|
||||
"repository": "myowner/myrepo",
|
||||
"repository_owner": "myowner",
|
||||
},
|
||||
},
|
||||
}
|
||||
rc.Run.JobID = "job1"
|
||||
|
||||
ghc := rc.getGithubContext(context.Background())
|
||||
|
||||
log.Debugf("%v", ghc)
|
||||
|
||||
assert.Equal(t, "1", ghc.RunID)
|
||||
assert.Equal(t, "1", ghc.RunNumber)
|
||||
assert.Equal(t, "0", ghc.RetentionDays)
|
||||
assert.Equal(t, "me", ghc.Actor)
|
||||
assert.Equal(t, "myowner/myrepo", ghc.Repository)
|
||||
assert.Equal(t, "myowner", ghc.RepositoryOwner)
|
||||
assert.Equal(t, "/dev/null", ghc.RunnerPerflog)
|
||||
assert.Equal(t, rc.Config.Secrets["GITHUB_TOKEN"], ghc.Token)
|
||||
assert.Equal(t, "job1", ghc.Job)
|
||||
}
|
||||
|
||||
func TestGetGithubContextRef(t *testing.T) {
|
||||
table := []struct {
|
||||
event string
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"github.com/actions-oss/act-cli/pkg/common"
|
||||
@@ -48,6 +49,9 @@ type Config struct {
|
||||
ContainerOptions string // Options for the job container
|
||||
UseGitIgnore bool // controls if paths in .gitignore should not be copied into container, default true
|
||||
GitHubInstance string // GitHub instance to use, default "github.com"
|
||||
GitHubServerURL string // GitHub server url to use
|
||||
GitHubAPIServerURL string // GitHub api server url to use
|
||||
GitHubGraphQlAPIServerURL string // GitHub graphql server url to use
|
||||
ContainerCapAdd []string // list of kernel capabilities to add to the containers
|
||||
ContainerCapDrop []string // list of kernel capabilities to remove from the containers
|
||||
AutoRemove bool // controls if the container is automatically removed upon workflow completion
|
||||
@@ -64,6 +68,38 @@ type Config struct {
|
||||
HostEnvironmentDir string // Custom folder for host environment, parallel jobs must be 1
|
||||
}
|
||||
|
||||
func (runnerConfig *Config) GetGitHubServerURL() string {
|
||||
if len(runnerConfig.GitHubServerURL) > 0 {
|
||||
return runnerConfig.GitHubServerURL
|
||||
}
|
||||
return fmt.Sprintf("https://%s", runnerConfig.GitHubInstance)
|
||||
}
|
||||
func (runnerConfig *Config) GetGitHubAPIServerURL() string {
|
||||
if len(runnerConfig.GitHubAPIServerURL) > 0 {
|
||||
return runnerConfig.GitHubAPIServerURL
|
||||
}
|
||||
if runnerConfig.GitHubInstance == "github.com" {
|
||||
return "https://api.github.com"
|
||||
}
|
||||
return fmt.Sprintf("https://%s/api/v3", runnerConfig.GitHubInstance)
|
||||
}
|
||||
func (runnerConfig *Config) GetGitHubGraphQlAPIServerURL() string {
|
||||
if len(runnerConfig.GitHubGraphQlAPIServerURL) > 0 {
|
||||
return runnerConfig.GitHubGraphQlAPIServerURL
|
||||
}
|
||||
if runnerConfig.GitHubInstance == "github.com" {
|
||||
return "https://api.github.com/graphql"
|
||||
}
|
||||
return fmt.Sprintf("https://%s/api/graphql", runnerConfig.GitHubInstance)
|
||||
}
|
||||
func (runnerConfig *Config) GetGitHubInstance() string {
|
||||
if len(runnerConfig.GitHubServerURL) > 0 {
|
||||
regex := regexp.MustCompile("^https?://(.*)$")
|
||||
return regex.ReplaceAllString(runnerConfig.GitHubServerURL, "$1")
|
||||
}
|
||||
return runnerConfig.GitHubInstance
|
||||
}
|
||||
|
||||
type caller struct {
|
||||
runContext *RunContext
|
||||
}
|
||||
|
||||
@@ -55,7 +55,10 @@ func TestStepActionRemote(t *testing.T) {
|
||||
read bool
|
||||
run bool
|
||||
}
|
||||
runError error
|
||||
runError error
|
||||
gitHubServerURL string
|
||||
gitHubAPIServerURL string
|
||||
gitHubGraphQlAPIServerURL string
|
||||
}{
|
||||
{
|
||||
name: "run-successful",
|
||||
@@ -80,6 +83,32 @@ func TestStepActionRemote(t *testing.T) {
|
||||
run: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "run-successful",
|
||||
stepModel: &model.Step{
|
||||
ID: "step",
|
||||
Uses: "remote/action@v1",
|
||||
},
|
||||
result: &model.StepResult{
|
||||
Conclusion: model.StepStatusSuccess,
|
||||
Outcome: model.StepStatusSuccess,
|
||||
Outputs: map[string]string{},
|
||||
},
|
||||
mocks: struct {
|
||||
env bool
|
||||
cloned bool
|
||||
read bool
|
||||
run bool
|
||||
}{
|
||||
env: true,
|
||||
cloned: true,
|
||||
read: true,
|
||||
run: true,
|
||||
},
|
||||
gitHubServerURL: "http://localhost:3000",
|
||||
gitHubAPIServerURL: "http://localhost:3000/api/v1",
|
||||
gitHubGraphQlAPIServerURL: "http://localhost:3000/api/graphql",
|
||||
},
|
||||
{
|
||||
name: "run-skipped",
|
||||
stepModel: &model.Step{
|
||||
@@ -142,8 +171,11 @@ func TestStepActionRemote(t *testing.T) {
|
||||
sar := &stepActionRemote{
|
||||
RunContext: &RunContext{
|
||||
Config: &Config{
|
||||
GitHubInstance: "github.com",
|
||||
ActionCache: cacheMock,
|
||||
GitHubInstance: "github.com",
|
||||
ActionCache: cacheMock,
|
||||
GitHubServerURL: tt.gitHubServerURL,
|
||||
GitHubAPIServerURL: tt.gitHubAPIServerURL,
|
||||
GitHubGraphQlAPIServerURL: tt.gitHubGraphQlAPIServerURL,
|
||||
},
|
||||
Run: &model.Run{
|
||||
JobID: "1",
|
||||
@@ -162,7 +194,12 @@ func TestStepActionRemote(t *testing.T) {
|
||||
}
|
||||
sar.RunContext.ExprEval = sar.RunContext.NewExpressionEvaluator(ctx)
|
||||
|
||||
cacheMock.Mock.On("Fetch", ctx, mock.AnythingOfType("string"), "https://github.com/remote/action", "v1", "").Return("someval")
|
||||
serverURL := "https://github.com"
|
||||
if tt.gitHubServerURL != "" {
|
||||
serverURL = tt.gitHubServerURL
|
||||
}
|
||||
|
||||
cacheMock.Mock.On("Fetch", ctx, mock.AnythingOfType("string"), serverURL+"/remote/action", "v1", "").Return("someval")
|
||||
suffixMatcher := func(suffix string) interface{} {
|
||||
return mock.MatchedBy(func(actionDir string) bool {
|
||||
return strings.HasSuffix(actionDir, suffix)
|
||||
@@ -173,7 +210,9 @@ func TestStepActionRemote(t *testing.T) {
|
||||
sarm.Mock.On("readAction", sar.Step, "someval", "", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
||||
}
|
||||
if tt.mocks.run {
|
||||
sarm.On("runAction", sar, suffixMatcher("act/remote-action@v1"), newRemoteAction(sar.Step.Uses)).Return(func(_ context.Context) error { return tt.runError })
|
||||
remoteAction := newRemoteAction(sar.Step.Uses)
|
||||
remoteAction.URL = serverURL
|
||||
sarm.On("runAction", sar, suffixMatcher("act/remote-action@v1"), remoteAction).Return(func(_ context.Context) error { return tt.runError })
|
||||
|
||||
cm.On("Copy", "/var/run/act", mock.AnythingOfType("[]*container.FileEntry")).Return(func(_ context.Context) error {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user