From 2bc65a1bbd6a32c601019346de83cb061957d700 Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Sun, 15 Feb 2026 11:09:49 -0500 Subject: [PATCH 1/7] Use correct job conclusion values for expression evluator --- core/github_evaluator.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/github_evaluator.go b/core/github_evaluator.go index bca8415..e108a47 100644 --- a/core/github_evaluator.go +++ b/core/github_evaluator.go @@ -193,11 +193,11 @@ func (e *Evaluator) callFunction(name string, args []any) (any, error) { case "always": return true, nil case "success": - return true, nil + return e.ctx.JobConclusion == "success", nil case "failure": - return false, nil + return e.ctx.JobConclusion == "failure", nil case "cancelled": - return false, nil + return e.ctx.JobConclusion == "cancelled", nil case "fromjson": if len(args) < 1 { From 88656f7d57505c61e23d04a96f10d199ac7e3ff1 Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Sun, 15 Feb 2026 11:10:00 -0500 Subject: [PATCH 2/7] Implement post-step exec for gh action nodes --- core/context.go | 6 ++ core/gh_post_steps.go | 197 +++++++++++++++++++++++++++++++++++++ core/graph.go | 16 ++- github/server/start.go | 2 +- nodes/gh-action@v1.go | 183 ++++++++++++++++++++++++++++++++-- nodes/gh-context-parser.go | 58 +---------- 6 files changed, 393 insertions(+), 69 deletions(-) create mode 100644 core/gh_post_steps.go diff --git a/core/context.go b/core/context.go index c86da1a..5a649a2 100644 --- a/core/context.go +++ b/core/context.go @@ -165,6 +165,9 @@ type ExecutionState struct { ExecutionOutputCache map[string]any `json:"executionOutputCache"` StepCache *StepCache `json:"stepCache"` + PostSteps *PostStepQueue `json:"-"` + JobConclusion string `json:"jobConclusion"` + DebugCallback DebugCallback `json:"-"` } @@ -238,6 +241,9 @@ func (c *ExecutionState) PushNewExecutionState(parentNode NodeBaseInterface) *Ex ExecutionOutputCache: make(map[string]any), StepCache: NewStepCache(c.StepCache), + PostSteps: c.PostSteps, + JobConclusion: c.JobConclusion, + Visited: visited, DebugCallback: c.DebugCallback, } diff --git a/core/gh_post_steps.go b/core/gh_post_steps.go new file mode 100644 index 0000000..7781091 --- /dev/null +++ b/core/gh_post_steps.go @@ -0,0 +1,197 @@ +package core + +import ( + "fmt" + "os" + "strings" + "sync" + + "github.com/actionforge/actrun-cli/utils" +) + +// PostStepRunner is implemented by node types that support post-step execution. +type PostStepRunner interface { + RunPost(c *ExecutionState, env map[string]string) error +} + +// PostStep holds the information needed to execute a post step. +type PostStep struct { + ActionName string + NodeID string + PostIf string + Runner PostStepRunner + StateFilePath string + EnvSnapshot map[string]string +} + +// PostStepQueue is a thread-safe queue for post steps. +type PostStepQueue struct { + mu sync.Mutex + steps []PostStep +} + +// NewPostStepQueue creates a new empty PostStepQueue. +func NewPostStepQueue() *PostStepQueue { + return &PostStepQueue{} +} + +// Register adds a post step to the queue. +func (q *PostStepQueue) Register(step PostStep) { + q.mu.Lock() + defer q.mu.Unlock() + q.steps = append(q.steps, step) +} + +// Len returns the number of registered post steps. +func (q *PostStepQueue) Len() int { + q.mu.Lock() + defer q.mu.Unlock() + return len(q.steps) +} + +// DrainLIFO returns all post steps in LIFO order and clears the queue. +func (q *PostStepQueue) DrainLIFO() []PostStep { + q.mu.Lock() + defer q.mu.Unlock() + + result := make([]PostStep, len(q.steps)) + for i, step := range q.steps { + result[len(q.steps)-1-i] = step + } + q.steps = nil + return result +} + +// executePostSteps runs post steps in order, logging errors but continuing. +func executePostSteps(c *ExecutionState, steps []PostStep) { + for _, step := range steps { + utils.LogOut.Infof("Running post step: %s (%s)\n", step.ActionName, step.NodeID) + + if !evaluatePostIf(c, step) { + utils.LogOut.Infof("Post step skipped (post-if condition not met): %s\n", step.ActionName) + continue + } + + env := step.EnvSnapshot + if step.StateFilePath != "" { + injectStateVars(env, step.StateFilePath) + } + + if err := step.Runner.RunPost(c, env); err != nil { + utils.LogErr.Errorf("Post step failed: %s: %v\n", step.ActionName, err) + } + } +} + +// evaluatePostIf evaluates the post-if condition for a post step. +// Returns true if the step should run. +func evaluatePostIf(c *ExecutionState, step PostStep) bool { + condition := step.PostIf + if condition == "" { + // Default: always() + return true + } + + // Wrap in ${{ }} if not already wrapped + if !strings.Contains(condition, "${{") { + condition = "${{ " + condition + " }}" + } + + evaluator := NewEvaluator(c) + result, err := evaluator.Evaluate(condition) + if err != nil { + utils.LogErr.Errorf("Failed to evaluate post-if condition '%s' for %s: %v\n", step.PostIf, step.ActionName, err) + return false + } + + return isTruthy(result) +} + +// injectStateVars reads the GITHUB_STATE file and injects STATE_* env vars. +func injectStateVars(env map[string]string, stateFilePath string) { + if stateFilePath == "" { + return + } + + stateVars, err := ParseKeyValueFile(stateFilePath) + if err != nil { + utils.LogErr.Errorf("Failed to read state file %s: %v\n", stateFilePath, err) + return + } + + for key, value := range stateVars { + env[fmt.Sprintf("STATE_%s", key)] = value + } +} + +// ParseKeyValueFile parses a GitHub Actions file command output file. +// Supports both NAME=VALUE and NAME<= 0 && (heredocIndex < 0 || equalsIndex < heredocIndex) { + parts := strings.SplitN(line, "=", 2) + if len(parts) != 2 || parts[0] == "" { + return nil, CreateErr(nil, nil, "invalid format '%s'. Name must not be empty", line) + } + key, value = parts[0], parts[1] + } else if heredocIndex >= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex) { + // Heredoc style: NAME<= len(lines) { + return nil, CreateErr(nil, nil, "invalid value. Matching delimiter not found '%s'", delimiter) + } + value = heredocValue.String() + } else { + return nil, CreateErr(nil, nil, "invalid format '%s'", line) + } + + results[key] = value + } + + return results, nil +} diff --git a/core/graph.go b/core/graph.go index c0ce7b3..363248f 100644 --- a/core/graph.go +++ b/core/graph.go @@ -270,6 +270,9 @@ func NewExecutionState( DataOutputCache: make(map[string]any), ExecutionOutputCache: make(map[string]any), StepCache: NewStepCache(nil), + + PostSteps: NewPostStepQueue(), + JobConclusion: "success", } } @@ -481,11 +484,11 @@ func RunGraph(ctx context.Context, graphName string, graphContent []byte, opts R } rs, srvErr := server.StartServer(server.Config{StorageDir: storageDir}) if srvErr != nil { - return CreateErr(nil, srvErr, "failed to start local GitHub Actions server") + return CreateErr(nil, srvErr, "failed to start GitHub Actions mock server") } defer rs.Stop() rs.InjectEnv(finalEnv) - utils.LogOut.Infof("local GitHub Actions server started at %s\n", rs.URL) + utils.LogOut.Infof("GitHub Actions mock server started at %s\n", rs.URL) } // Use the updated GITHUB_WORKSPACE as the working directory. @@ -554,7 +557,14 @@ func RunGraph(ctx context.Context, graphName string, graphContent []byte, opts R c.PushNodeVisit(entryNode, true) } - return entry.ExecuteEntry(c, nil, opts.Args) + mainErr := entry.ExecuteEntry(c, nil, opts.Args) + if mainErr != nil { + c.JobConclusion = "failure" + } + if c.PostSteps.Len() > 0 { + executePostSteps(c, c.PostSteps.DrainLIFO()) + } + return mainErr } func LoadGraph(graphYaml map[string]any, parent NodeBaseInterface, parentId string, validate bool, opts RunOpts) (ActionGraph, []error) { diff --git a/github/server/start.go b/github/server/start.go index a8cdef5..3d371b6 100644 --- a/github/server/start.go +++ b/github/server/start.go @@ -10,7 +10,7 @@ import ( "path/filepath" ) -// Config holds parameters for starting a local GitHub Actions server. +// Config holds parameters for starting a GitHub Actions mock server. type Config struct { StorageDir string // Directory for blob storage (created if missing) OIDCIssuer string // OIDC token issuer (defaults to GitHub's) diff --git a/nodes/gh-action@v1.go b/nodes/gh-action@v1.go index 888ff73..5c5789c 100644 --- a/nodes/gh-action@v1.go +++ b/nodes/gh-action@v1.go @@ -62,10 +62,12 @@ type GhActionNode struct { core.Outputs core.Executions - actionName string - actionType ActionType // docker or node - actionRuns ActionRuns - actionRunJsPath string + actionName string + actionType ActionType // docker or node + actionRuns ActionRuns + actionRunJsPath string + actionPostJsPath string + actionDir string Data DockerData } @@ -163,6 +165,18 @@ func (n *GhActionNode) ExecuteImpl(c *core.ExecutionState, inputId core.InputId, executionEnv := maps.Clone(currentEnvMap) + // Register post step if action defines one + if n.actionPostJsPath != "" || n.actionRuns.PostEntrypoint != "" { + c.PostSteps.Register(core.PostStep{ + ActionName: n.actionName, + NodeID: n.GetId(), + PostIf: n.actionRuns.PostIf, + Runner: &GhActionPostRunner{node: n}, + StateFilePath: currentEnvMap["GITHUB_STATE"], + EnvSnapshot: maps.Clone(currentEnvMap), + }) + } + var runErr error switch n.actionType { case Docker: @@ -367,6 +381,141 @@ func (n *GhActionNode) ExecuteDocker(c *core.ExecutionState, workingDirectory st return nil } +// GhActionPostRunner implements core.PostStepRunner for GitHub Actions. +type GhActionPostRunner struct { + node *GhActionNode +} + +func (r *GhActionPostRunner) RunPost(c *core.ExecutionState, env map[string]string) error { + workspace := env["GITHUB_WORKSPACE"] + if workspace == "" { + return core.CreateErr(c, nil, "GITHUB_WORKSPACE is not set for post step") + } + + switch r.node.actionType { + case Node: + return r.node.ExecuteNodePost(c, workspace, env) + case Docker: + return r.node.ExecuteDockerPost(c, workspace, env) + default: + return core.CreateErr(c, nil, "unsupported action type for post step: %v", r.node.actionType) + } +} + +// ExecuteNodePost runs the post step for Node-type actions. +func (n *GhActionNode) ExecuteNodePost(c *core.ExecutionState, workspace string, envs map[string]string) error { + nodeBin := "node" + runners, err := getRunnersDir() + if err == nil { + externalNodeBin, pathErr := utils.SafeJoinPath(runners, "externals", n.actionRuns.Using, "bin", "node") + if pathErr == nil { + _, err := os.Stat(externalNodeBin) + if err == nil { + nodeBin = externalNodeBin + } + } + } + + utils.LogOut.Infof("Use node binary (post): %s %s\n", nodeBin, n.actionPostJsPath) + + cmd := exec.Command(nodeBin, n.actionPostJsPath) + cmd.Dir = workspace + cmd.Stdout = utils.LogOut.Out + cmd.Stderr = utils.LogErr.Out + cmd.Stdin = nil + cmd.Env = func() []string { + env := make([]string, 0, len(envs)) + for k, v := range envs { + env = append(env, fmt.Sprintf("%s=%s", k, v)) + } + return env + }() + return cmd.Run() +} + +// ExecuteDockerPost runs the post step for Docker-type actions. +func (n *GhActionNode) ExecuteDockerPost(c *core.ExecutionState, workingDirectory string, env map[string]string) error { + sysRunnerTempDir := env["RUNNER_TEMP"] + if sysRunnerTempDir == "" { + return core.CreateErr(c, nil, "RUNNER_TEMP is not set for post step") + } + + sysGithubWorkspace := env["GITHUB_WORKSPACE"] + if sysGithubWorkspace == "" { + return core.CreateErr(c, nil, "GITHUB_WORKSPACE is not set for post step") + } + + // path translation for file commands + fileCmds := []string{"GITHUB_ENV", "GITHUB_PATH", "GITHUB_OUTPUT", "GITHUB_STATE", "GITHUB_STEP_SUMMARY"} + for _, envName := range fileCmds { + path := env[envName] + if path != "" { + env[envName] = filepath.Join(dockerGithubFileCommands, filepath.Base(path)) + } + } + + env["HOME"] = dockerGithubHome + + entrypoint := n.actionRuns.PostEntrypoint + if entrypoint == "" { + return core.CreateErr(c, nil, "post-entrypoint is not set for Docker post step") + } + + ci := core.ContainerInfo{ + ContainerImage: n.Data.Image, + ContainerDisplayName: fmt.Sprintf("actionforge_%s_post_%s", n.Data.DockerInstanceLabel, uuid.New()), + ContainerWorkDirectory: dockerGithubWorkspace, + ContainerEntryPointArgs: entrypoint, + ContainerEnvironmentVariables: env, + } + + // mount docker sock + if runtime.GOOS == "linux" || runtime.GOOS == "darwin" { + ci.MountVolumes = append(ci.MountVolumes, core.Volume{ + SourceVolumePath: "/var/run/docker.sock", + TargetVolumePath: "/var/run/docker.sock", + ReadOnly: false, + }) + } + + ci.MountVolumes = append(ci.MountVolumes, core.Volume{ + SourceVolumePath: sysGithubWorkspace, + TargetVolumePath: dockerGithubWorkspace, + ReadOnly: false, + }) + ci.MountVolumes = append(ci.MountVolumes, core.Volume{ + SourceVolumePath: filepath.Join(sysRunnerTempDir, "_github_workflow"), + TargetVolumePath: dockerGithubWorkflow, + ReadOnly: false, + }) + ci.MountVolumes = append(ci.MountVolumes, core.Volume{ + SourceVolumePath: filepath.Join(sysRunnerTempDir, "_github_home"), + TargetVolumePath: dockerGithubHome, + ReadOnly: false, + }) + ci.MountVolumes = append(ci.MountVolumes, core.Volume{ + SourceVolumePath: filepath.Join(sysRunnerTempDir, "_runner_file_commands"), + TargetVolumePath: dockerGithubFileCommands, + ReadOnly: false, + }) + + dockerClient, err := core.NewDockerClient() + if err != nil { + return core.CreateErr(c, err, "failed to create Docker client for post step") + } + defer dockerClient.Close() + + config := core.ContainerInfo2DockerRunConfig(ci) + exitCode, err := dockerClient.RunContainer(context.Background(), config) + if err != nil { + return err + } + if exitCode != 0 { + return core.CreateErr(c, nil, "docker post step failed with exit code %d", exitCode) + } + return nil +} + func init() { err := core.RegisterNodeFactory(ghActionNodeDefinition, func(ctx any, parent core.NodeBaseInterface, parentId string, nodeDef map[string]any, validate bool, opts core.RunOpts) (core.NodeBaseInterface, []error) { @@ -502,6 +651,7 @@ func init() { node := &GhActionNode{ actionName: action.Name, actionRuns: action.Runs, + actionDir: actionDir, } switch action.Runs.Using { @@ -576,6 +726,19 @@ func init() { node.actionRunJsPath = actionRunFile + // resolve post script if defined + if action.Runs.Post != "" { + postRunFile := filepath.Join(actionDir, action.Runs.Post) + postRunFile = filepath.Clean(postRunFile) + + _, err := os.Stat(postRunFile) + if errors.Is(err, os.ErrNotExist) { + return nil, []error{core.CreateErr(nil, nil, "action post file does not exist: %s", postRunFile)} + } + + node.actionPostJsPath = postRunFile + } + case "composite": // we should never see a composite here, since they should have already been expanded by the editor/gateway // into a group node. In the future we may add support by returning the group node here in case graph @@ -678,11 +841,13 @@ type ActionOutput struct { } type ActionRuns struct { - Image string `json:"image"` - Using string `json:"using"` - Main string `json:"main"` - Post string `json:"post"` - Args []string `json:"args"` + Image string `json:"image"` + Using string `json:"using"` + Main string `json:"main"` + Post string `json:"post"` + PostIf string `json:"post-if" yaml:"post-if"` + PostEntrypoint string `json:"post-entrypoint" yaml:"post-entrypoint"` + Args []string `json:"args"` } // getRunnersDir returns the directory of the latest runner version. diff --git a/nodes/gh-context-parser.go b/nodes/gh-context-parser.go index a7c25c5..79f8981 100644 --- a/nodes/gh-context-parser.go +++ b/nodes/gh-context-parser.go @@ -92,7 +92,7 @@ func (p *GhContextParser) Parse(c *core.ExecutionState, contextEnvironMap map[st if err != nil { return nil, nil, core.CreateErr(c, nil, "unable to read file set in GITHUB_ENV") } - ghEnvs, err := parseOutputFile(string(b)) + ghEnvs, err := core.ParseKeyValueString(string(b)) if err != nil { return nil, nil, err } @@ -119,7 +119,7 @@ func (p *GhContextParser) Parse(c *core.ExecutionState, contextEnvironMap map[st return nil, nil, core.CreateErr(c, err, "unable to read file set in GITHUB_OUTPUT") } - ghOutputs, err := parseOutputFile(string(b)) + ghOutputs, err := core.ParseKeyValueString(string(b)) if err != nil { return nil, nil, err } @@ -138,60 +138,6 @@ func (p *GhContextParser) Parse(c *core.ExecutionState, contextEnvironMap map[st return envs, outputs, nil } -func parseOutputFile(input string) (map[string]string, error) { - results := make(map[string]string) - lines := strings.Split(input, "\n") - - for i := 0; i < len(lines); i++ { - line := lines[i] - if line == "" { - continue - } - - var key, value string - equalsIndex := strings.Index(line, "=") - heredocIndex := strings.Index(line, "<<") - - // Normal style: NAME=VALUE - if equalsIndex >= 0 && (heredocIndex < 0 || equalsIndex < heredocIndex) { - parts := strings.SplitN(line, "=", 2) - if len(parts) != 2 || parts[0] == "" { - return nil, core.CreateErr(nil, nil, "invalid format '%s'. Name must not be empty", line) - } - key, value = parts[0], parts[1] - } else if heredocIndex >= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex) { - // Heredoc style: NAME<= len(lines) { - return nil, core.CreateErr(nil, nil, "invalid value. Matching delimiter not found '%s'", delimiter) - } - value = heredocValue.String() - } else { - return nil, core.CreateErr(nil, nil, "invalid format '%s'", line) - } - - results[key] = value - } - - return results, nil -} - // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files var contextEnvList = map[string]string{ "add_path": "GITHUB_PATH", From fdbc7117bcf85daf1064597575b3bb25d3d898ff Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Tue, 17 Feb 2026 20:34:37 -0500 Subject: [PATCH 3/7] Fix CodeQL warning --- core/gh_post_steps.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/gh_post_steps.go b/core/gh_post_steps.go index 7781091..109fd66 100644 --- a/core/gh_post_steps.go +++ b/core/gh_post_steps.go @@ -100,7 +100,7 @@ func evaluatePostIf(c *ExecutionState, step PostStep) bool { evaluator := NewEvaluator(c) result, err := evaluator.Evaluate(condition) if err != nil { - utils.LogErr.Errorf("Failed to evaluate post-if condition '%s' for %s: %v\n", step.PostIf, step.ActionName, err) + utils.LogErr.Errorf("Failed to evaluate post-if condition for %s: %v\n", step.ActionName, err) return false } From e1d25d68806d4abda0b6d39ac75c470b86b21bea Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Tue, 17 Feb 2026 20:39:29 -0500 Subject: [PATCH 4/7] Missing job conclusion --- core/github_evaluator_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/github_evaluator_test.go b/core/github_evaluator_test.go index 4614ef1..2c075a3 100644 --- a/core/github_evaluator_test.go +++ b/core/github_evaluator_test.go @@ -8,6 +8,7 @@ import ( func TestEvaluate_GitHubParity(t *testing.T) { ctx := ExecutionState{ + JobConclusion: "success", GhNeeds: map[string]any{ "setup": map[string]any{ "outputs": map[string]any{ From eb48bbb30ac804985c80f70320fedc9f3eff1146 Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Tue, 17 Feb 2026 22:23:51 -0500 Subject: [PATCH 5/7] Bump tests --- .github/workflows/graphs/test_env.act | 4 ++-- .github/workflows/graphs/test_input_output.act | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/graphs/test_env.act b/.github/workflows/graphs/test_env.act index c45e5d3..c2e04cd 100644 --- a/.github/workflows/graphs/test_env.act +++ b/.github/workflows/graphs/test_env.act @@ -7,7 +7,7 @@ nodes: y: 450 - id: gh-actionforge-test-action-node-main-lemon-penguin-yellow type: >- - github.com/actionforge/test-action-node@22db00979573158856d37b2a91c05deccde3b41b + github.com/actionforge/test-action-node@3ab9dc157c66635112bf0abf7b2f668e401c8dba position: x: 1020 y: 510 @@ -49,7 +49,7 @@ nodes: fi - id: gh-actionforge-test-action-node-main-blueberry-monkey-plum type: >- - github.com/actionforge/test-action-node@22db00979573158856d37b2a91c05deccde3b41b + github.com/actionforge/test-action-node@3ab9dc157c66635112bf0abf7b2f668e401c8dba position: x: 1020 y: 990 diff --git a/.github/workflows/graphs/test_input_output.act b/.github/workflows/graphs/test_input_output.act index e105168..a417e76 100644 --- a/.github/workflows/graphs/test_input_output.act +++ b/.github/workflows/graphs/test_input_output.act @@ -7,7 +7,7 @@ nodes: y: 1360 - id: gh-actionforge-test-action-node-main-lemon-penguin-yellow type: >- - github.com/actionforge/test-action-node@22db00979573158856d37b2a91c05deccde3b41b + github.com/actionforge/test-action-node@3ab9dc157c66635112bf0abf7b2f668e401c8dba position: x: 290 y: 1220 @@ -45,7 +45,7 @@ nodes: env[0]: '' - id: gh-actionforge-test-action-registry-main-cat-purple-watermelon type: >- - github.com/actionforge/test-action-registry@6075e108fe3a7edd08d11178b02d96f5eef3e835 + github.com/actionforge/test-action-registry@fd5c912c37d3e7bf2ab1d8f8662418032ed8f55e position: x: 1980 y: 710 @@ -84,7 +84,7 @@ nodes: fi - id: gh-actionforge-test-action-dockerfile-main-purple-pear-kangaroo type: >- - github.com/actionforge/test-action-dockerfile@c3bd2754b38ec3500b786a3cca9279322d6ee5dd + github.com/actionforge/test-action-dockerfile@b534d25852e5eb0612450225b2d169bd47ecabe8 position: x: 3880 y: 250 From 879272a603aadc12504e2195d48ff1202c286cdb Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Tue, 17 Feb 2026 22:58:31 -0500 Subject: [PATCH 6/7] Bump test-action-node --- .github/workflows/graphs/test_env.act | 4 ++-- .github/workflows/graphs/test_input_output.act | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/graphs/test_env.act b/.github/workflows/graphs/test_env.act index c2e04cd..05f61f3 100644 --- a/.github/workflows/graphs/test_env.act +++ b/.github/workflows/graphs/test_env.act @@ -7,7 +7,7 @@ nodes: y: 450 - id: gh-actionforge-test-action-node-main-lemon-penguin-yellow type: >- - github.com/actionforge/test-action-node@3ab9dc157c66635112bf0abf7b2f668e401c8dba + github.com/actionforge/test-action-node@26491c0042d95182826dacd3c64d8254c69dadcb position: x: 1020 y: 510 @@ -49,7 +49,7 @@ nodes: fi - id: gh-actionforge-test-action-node-main-blueberry-monkey-plum type: >- - github.com/actionforge/test-action-node@3ab9dc157c66635112bf0abf7b2f668e401c8dba + github.com/actionforge/test-action-node@26491c0042d95182826dacd3c64d8254c69dadcb position: x: 1020 y: 990 diff --git a/.github/workflows/graphs/test_input_output.act b/.github/workflows/graphs/test_input_output.act index a417e76..70bad37 100644 --- a/.github/workflows/graphs/test_input_output.act +++ b/.github/workflows/graphs/test_input_output.act @@ -7,7 +7,7 @@ nodes: y: 1360 - id: gh-actionforge-test-action-node-main-lemon-penguin-yellow type: >- - github.com/actionforge/test-action-node@3ab9dc157c66635112bf0abf7b2f668e401c8dba + github.com/actionforge/test-action-node@26491c0042d95182826dacd3c64d8254c69dadcb position: x: 290 y: 1220 From ba01f08f0077bb0eebd9aae1a8a76bfb002a6d99 Mon Sep 17 00:00:00 2001 From: Sebastian Rath Date: Tue, 17 Feb 2026 23:15:22 -0500 Subject: [PATCH 7/7] Fix CodeQL warning --- core/gh_post_steps.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/gh_post_steps.go b/core/gh_post_steps.go index 109fd66..8bd61ee 100644 --- a/core/gh_post_steps.go +++ b/core/gh_post_steps.go @@ -78,7 +78,7 @@ func executePostSteps(c *ExecutionState, steps []PostStep) { } if err := step.Runner.RunPost(c, env); err != nil { - utils.LogErr.Errorf("Post step failed: %s: %v\n", step.ActionName, err) + utils.LogErr.Errorf("Post step failed: %s\n", step.ActionName) } } } @@ -100,7 +100,7 @@ func evaluatePostIf(c *ExecutionState, step PostStep) bool { evaluator := NewEvaluator(c) result, err := evaluator.Evaluate(condition) if err != nil { - utils.LogErr.Errorf("Failed to evaluate post-if condition for %s: %v\n", step.ActionName, err) + utils.LogErr.Errorf("Failed to evaluate post-if condition for %s\n", step.ActionName) return false }