feat(executor): create the artifacts and artifacts_list file commands
- commit
- 76ad031a05c22b803249c262a9db9512ad77bbc7
- author
- brice · · 2026-10-12 22:46 UTC
- parent
- 61fc6ee
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +23 -2
M internal/executor/filecmd.go +19 -1
| @@ -30,6 +30,11 @@ const ( | |||
| 30 | 30 | cmdStepSummary = "step_summary" | |
| 31 | 31 | cmdState = "state" | |
| 32 | 32 | cmdOutput = "output" | |
| 33 | + | // The two artifact files exist on GitHub-hosted runners (recordings: the | |
| 34 | + | // github context has artifacts and artifacts_list, the steps GITHUB_ARTIFACTS | |
| 35 | + | // and GITHUB_ARTIFACTS_LIST). ermite does not process them, see below. | |
| 36 | + | cmdArtifacts = "artifacts" | |
| 37 | + | cmdArtifactsList = "artifacts_list" | |
| 33 | 38 | ) | |
| 34 | 39 | ||
| 35 | 40 | // fileCommand describes one file command like the IFileCommandExtension of | |
| @@ -47,10 +52,21 @@ var fileCommands = []fileCommand{ | |||
| 47 | 52 | {cmdStepSummary, "step_summary_"}, // CreateStepSummaryCommand (:221) | |
| 48 | 53 | {cmdState, "save_state_"}, // SaveStateFileCommand (:295) | |
| 49 | 54 | {cmdOutput, "set_output_"}, // SetOutputFileCommand (:328) | |
| 55 | + | // CreateArtifactsFileCommand (CreateArtifactsFileCommand.cs:39) and | |
| 56 | + | // ArtifactsListFileCommand (ArtifactsListFileCommand.cs:37), registered in | |
| 57 | + | // ExtensionManager.cs:65-66. Both do nothing unless the feature flag | |
| 58 | + | // actions_runner_allow_artifacts_file or ACTIONS_RUNNER_ALLOW_ARTIFACTS_FILE | |
| 59 | + | // is on (CreateArtifactsFileCommand.cs:67-79); ermite has neither, so the | |
| 60 | + | // files are created empty (as the C# runner does when the feature is off) | |
| 61 | + | // and what a step writes to them is ignored. Artifact subjects are not | |
| 62 | + | // declared yet. | |
| 63 | + | {cmdArtifacts, "artifacts_"}, | |
| 64 | + | {cmdArtifactsList, "artifacts_list_"}, | |
| 50 | 65 | } | |
| 51 | 66 | ||
| 52 | 67 | // EnvVarName returns the environment variable that holds the file of a command: | |
| 53 | - | // GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH, GITHUB_STATE, GITHUB_STEP_SUMMARY | |
| 68 | + | // GITHUB_ARTIFACTS, GITHUB_ARTIFACTS_LIST, GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH, | |
| 69 | + | // GITHUB_STATE, GITHUB_STEP_SUMMARY | |
| 54 | 70 | // (GitHubContext.GetRuntimeEnvironmentVariables, GitHubContext.cs:52). | |
| 55 | 71 | func envVarName(contextName string) string { return "GITHUB_" + strings.ToUpper(contextName) } | |
| 56 | 72 | ||
| @@ -166,6 +182,8 @@ func (f *FileCommands) Process(sink Sink) { | |||
| 166 | 182 | err = processStepSummary(sink, f.root, p) | |
| 167 | 183 | case cmdState: | |
| 168 | 184 | err = processPairs(sink, f.root, p, sink.SaveState, func(k, v string) { sink.Debug(fmt.Sprintf("Save intra-action state %s = %s", k, v)) }) | |
| 185 | + | case cmdArtifacts, cmdArtifactsList: | |
| 186 | + | // Disabled feature: nothing to process (see fileCommands). | |
| 169 | 187 | case cmdOutput: | |
| 170 | 188 | err = processPairs(sink, f.root, p, sink.SetOutput, func(k, v string) { sink.Debug(fmt.Sprintf("Set output %s = %s", k, v)) }) | |
| 171 | 189 | } | |
| @@ -30,6 +30,11 @@ const ( | |||||
| 30 | cmdStepSummary = "step_summary" | 30 | cmdStepSummary = "step_summary" | ||
| 31 | cmdState = "state" | 31 | cmdState = "state" | ||
| 32 | cmdOutput = "output" | 32 | cmdOutput = "output" | ||
| 33 | + | // The two artifact files exist on GitHub-hosted runners (recordings: the | |||
| 34 | + | // github context has artifacts and artifacts_list, the steps GITHUB_ARTIFACTS | |||
| 35 | + | // and GITHUB_ARTIFACTS_LIST). ermite does not process them, see below. | |||
| 36 | + | cmdArtifacts = "artifacts" | |||
| 37 | + | cmdArtifactsList = "artifacts_list" | |||
| 33 | ) | 38 | ) | ||
| 34 | 39 | ||||
| 35 | // fileCommand describes one file command like the IFileCommandExtension of | 40 | // fileCommand describes one file command like the IFileCommandExtension of | ||
| @@ -47,10 +52,21 @@ var fileCommands = []fileCommand{ | |||||
| 47 | {cmdStepSummary, "step_summary_"}, // CreateStepSummaryCommand (:221) | 52 | {cmdStepSummary, "step_summary_"}, // CreateStepSummaryCommand (:221) | ||
| 48 | {cmdState, "save_state_"}, // SaveStateFileCommand (:295) | 53 | {cmdState, "save_state_"}, // SaveStateFileCommand (:295) | ||
| 49 | {cmdOutput, "set_output_"}, // SetOutputFileCommand (:328) | 54 | {cmdOutput, "set_output_"}, // SetOutputFileCommand (:328) | ||
| 55 | + | // CreateArtifactsFileCommand (CreateArtifactsFileCommand.cs:39) and | |||
| 56 | + | // ArtifactsListFileCommand (ArtifactsListFileCommand.cs:37), registered in | |||
| 57 | + | // ExtensionManager.cs:65-66. Both do nothing unless the feature flag | |||
| 58 | + | // actions_runner_allow_artifacts_file or ACTIONS_RUNNER_ALLOW_ARTIFACTS_FILE | |||
| 59 | + | // is on (CreateArtifactsFileCommand.cs:67-79); ermite has neither, so the | |||
| 60 | + | // files are created empty (as the C# runner does when the feature is off) | |||
| 61 | + | // and what a step writes to them is ignored. Artifact subjects are not | |||
| 62 | + | // declared yet. | |||
| 63 | + | {cmdArtifacts, "artifacts_"}, | |||
| 64 | + | {cmdArtifactsList, "artifacts_list_"}, | |||
| 50 | } | 65 | } | ||
| 51 | 66 | ||||
| 52 | // EnvVarName returns the environment variable that holds the file of a command: | 67 | // EnvVarName returns the environment variable that holds the file of a command: | ||
| 53 | - | // GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH, GITHUB_STATE, GITHUB_STEP_SUMMARY | 68 | + | // GITHUB_ARTIFACTS, GITHUB_ARTIFACTS_LIST, GITHUB_ENV, GITHUB_OUTPUT, GITHUB_PATH, |
| 69 | + | // GITHUB_STATE, GITHUB_STEP_SUMMARY | |||
| 54 | // (GitHubContext.GetRuntimeEnvironmentVariables, GitHubContext.cs:52). | 70 | // (GitHubContext.GetRuntimeEnvironmentVariables, GitHubContext.cs:52). | ||
| 55 | func envVarName(contextName string) string { return "GITHUB_" + strings.ToUpper(contextName) } | 71 | func envVarName(contextName string) string { return "GITHUB_" + strings.ToUpper(contextName) } | ||
| 56 | 72 | ||||
| @@ -166,6 +182,8 @@ func (f *FileCommands) Process(sink Sink) { | |||||
| 166 | err = processStepSummary(sink, f.root, p) | 182 | err = processStepSummary(sink, f.root, p) | ||
| 167 | case cmdState: | 183 | case cmdState: | ||
| 168 | err = processPairs(sink, f.root, p, sink.SaveState, func(k, v string) { sink.Debug(fmt.Sprintf("Save intra-action state %s = %s", k, v)) }) | 184 | err = processPairs(sink, f.root, p, sink.SaveState, func(k, v string) { sink.Debug(fmt.Sprintf("Save intra-action state %s = %s", k, v)) }) | ||
| 185 | + | case cmdArtifacts, cmdArtifactsList: | |||
| 186 | + | // Disabled feature: nothing to process (see fileCommands). | |||
| 169 | case cmdOutput: | 187 | case cmdOutput: | ||
| 170 | err = processPairs(sink, f.root, p, sink.SetOutput, func(k, v string) { sink.Debug(fmt.Sprintf("Set output %s = %s", k, v)) }) | 188 | err = processPairs(sink, f.root, p, sink.SetOutput, func(k, v string) { sink.Debug(fmt.Sprintf("Set output %s = %s", k, v)) }) | ||
| 171 | } | 189 | } | ||
M internal/executor/filecmd_test.go +4 -1
| @@ -104,7 +104,7 @@ func TestFileCommandsInit(t *testing.T) { | |||
| 104 | 104 | if err != nil { | |
| 105 | 105 | t.Fatal(err) | |
| 106 | 106 | } | |
| 107 | - | for _, name := range []string{"GITHUB_PATH", "GITHUB_ENV", "GITHUB_STEP_SUMMARY", "GITHUB_STATE", "GITHUB_OUTPUT"} { | |
| 107 | + | for _, name := range []string{"GITHUB_PATH", "GITHUB_ENV", "GITHUB_STEP_SUMMARY", "GITHUB_STATE", "GITHUB_OUTPUT", "GITHUB_ARTIFACTS", "GITHUB_ARTIFACTS_LIST"} { | |
| 108 | 108 | p := env[name] | |
| 109 | 109 | if p == "" || filepath.Dir(p) != dir { | |
| 110 | 110 | t.Fatalf("%s = %q", name, p) | |
| @@ -116,6 +116,9 @@ func TestFileCommandsInit(t *testing.T) { | |||
| 116 | 116 | if !strings.HasPrefix(filepath.Base(env["GITHUB_ENV"]), "set_env_") || !strings.HasPrefix(filepath.Base(env["GITHUB_PATH"]), "add_path_") { | |
| 117 | 117 | t.Fatalf("prefixes: %v", env) | |
| 118 | 118 | } | |
| 119 | + | if !strings.HasPrefix(filepath.Base(env["GITHUB_ARTIFACTS"]), "artifacts_") || !strings.HasPrefix(filepath.Base(env["GITHUB_ARTIFACTS_LIST"]), "artifacts_list_") { | |
| 120 | + | t.Fatalf("artifact prefixes: %v", env) | |
| 121 | + | } | |
| 119 | 122 | // A second Init deletes the previous files and uses new names. | |
| 120 | 123 | env2, _ := fc.Init() | |
| 121 | 124 | if env2["GITHUB_ENV"] == env["GITHUB_ENV"] { | |
| @@ -104,7 +104,7 @@ func TestFileCommandsInit(t *testing.T) { | |||||
| 104 | if err != nil { | 104 | if err != nil { | ||
| 105 | t.Fatal(err) | 105 | t.Fatal(err) | ||
| 106 | } | 106 | } | ||
| 107 | - | for _, name := range []string{"GITHUB_PATH", "GITHUB_ENV", "GITHUB_STEP_SUMMARY", "GITHUB_STATE", "GITHUB_OUTPUT"} { | 107 | + | for _, name := range []string{"GITHUB_PATH", "GITHUB_ENV", "GITHUB_STEP_SUMMARY", "GITHUB_STATE", "GITHUB_OUTPUT", "GITHUB_ARTIFACTS", "GITHUB_ARTIFACTS_LIST"} { |
| 108 | p := env[name] | 108 | p := env[name] | ||
| 109 | if p == "" || filepath.Dir(p) != dir { | 109 | if p == "" || filepath.Dir(p) != dir { | ||
| 110 | t.Fatalf("%s = %q", name, p) | 110 | t.Fatalf("%s = %q", name, p) | ||
| @@ -116,6 +116,9 @@ func TestFileCommandsInit(t *testing.T) { | |||||
| 116 | if !strings.HasPrefix(filepath.Base(env["GITHUB_ENV"]), "set_env_") || !strings.HasPrefix(filepath.Base(env["GITHUB_PATH"]), "add_path_") { | 116 | if !strings.HasPrefix(filepath.Base(env["GITHUB_ENV"]), "set_env_") || !strings.HasPrefix(filepath.Base(env["GITHUB_PATH"]), "add_path_") { | ||
| 117 | t.Fatalf("prefixes: %v", env) | 117 | t.Fatalf("prefixes: %v", env) | ||
| 118 | } | 118 | } | ||
| 119 | + | if !strings.HasPrefix(filepath.Base(env["GITHUB_ARTIFACTS"]), "artifacts_") || !strings.HasPrefix(filepath.Base(env["GITHUB_ARTIFACTS_LIST"]), "artifacts_list_") { | |||
| 120 | + | t.Fatalf("artifact prefixes: %v", env) | |||
| 121 | + | } | |||
| 119 | // A second Init deletes the previous files and uses new names. | 122 | // A second Init deletes the previous files and uses new names. | ||
| 120 | env2, _ := fc.Init() | 123 | env2, _ := fc.Init() | ||
| 121 | if env2["GITHUB_ENV"] == env["GITHUB_ENV"] { | 124 | if env2["GITHUB_ENV"] == env["GITHUB_ENV"] { | ||