agent-harness / tasks /patches /TASK_S2_R001_014_source.patch
cuber12's picture
Publish agent harness research code and paper artifacts
d61821a verified
Raw
History Blame Contribute Delete
3.37 kB
diff --git a/apps/gitlab-runner-helper/main.go b/apps/gitlab-runner-helper/main.go
index 206fcf20..e469fbb6 100644
--- a/apps/gitlab-runner-helper/main.go
+++ b/apps/gitlab-runner-helper/main.go
@@ -29,6 +29,9 @@ func main() {
}
}()
+ // Must run before cli.NewApp. See commands/steps.RecoverArgv.
+ steps.RecoverArgv()
+
app := cli.NewApp()
app.Name = filepath.Base(os.Args[0])
app.Usage = "a GitLab Runner Helper"
diff --git a/commands/steps/recovery.go b/commands/steps/recovery.go
new file mode 100644
index 00000000..0d0d2d04
--- /dev/null
+++ b/commands/steps/recovery.go
@@ -0,0 +1,49 @@
+package steps
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "os"
+)
+
+// RecoveryEnvVar carries argv (base64-encoded JSON) for the helper to
+// reconstruct when an image entrypoint drops CMD. Set by the executor on
+// the build container; read and unset by RecoverArgv.
+const RecoveryEnvVar = "_GITLAB_RUNNER_HELPER_NATIVE_STEPS_ARGV"
+
+// EncodeRecoveryArgv returns the RecoveryEnvVar payload for argv.
+func EncodeRecoveryArgv(argv []string) (string, error) {
+ raw, err := json.Marshal(argv)
+ if err != nil {
+ return "", fmt.Errorf("marshalling argv: %w", err)
+ }
+ return base64.StdEncoding.EncodeToString(raw), nil
+}
+
+// RecoverArgv reconstructs os.Args from RecoveryEnvVar when the helper was
+// invoked with no subcommand, the fingerprint of an `sh -c` entrypoint
+// dropping CMD[1:] as positional params that exec doesn't forward. Call
+// from main before any arg processing. No-op otherwise.
+func RecoverArgv() {
+ if len(os.Args) > 1 {
+ return
+ }
+ encoded := os.Getenv(RecoveryEnvVar)
+ if encoded == "" {
+ return
+ }
+ raw, err := base64.StdEncoding.DecodeString(encoded)
+ if err != nil {
+ return
+ }
+ var argv []string
+ if err := json.Unmarshal(raw, &argv); err != nil {
+ return
+ }
+ if len(argv) == 0 {
+ return
+ }
+ os.Args = append(os.Args, argv...)
+ _ = os.Unsetenv(RecoveryEnvVar)
+}
diff --git a/executors/docker/docker.go b/executors/docker/docker.go
index a3997d28..05b871f5 100644
--- a/executors/docker/docker.go
+++ b/executors/docker/docker.go
@@ -30,6 +30,7 @@ import (
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
+ "gitlab.com/gitlab-org/gitlab-runner/commands/steps"
"gitlab.com/gitlab-org/gitlab-runner/common"
"gitlab.com/gitlab-org/gitlab-runner/common/buildlogger"
"gitlab.com/gitlab-org/gitlab-runner/common/spec"
@@ -942,9 +943,16 @@ func (e *executor) createContainerConfig(
if e.Build.UseNativeSteps() {
config.Cmd = append([]string{bootstrappedBinary, "steps", "serve"}, config.Cmd...)
- // Environment variables interferes with steps. Given this situation, when
- // native steps are enabled, we no longer add the env vars to the container.
- config.Env = nil
+ // Recovery for `sh -c` entrypoints that drop CMD[1:] as positional
+ // params exec doesn't forward. See commands/steps.RecoveryEnvVar.
+ recoveryArgv, err := steps.EncodeRecoveryArgv(config.Cmd[1:])
+ if err != nil {
+ return nil, fmt.Errorf("encoding native-steps recovery argv: %w", err)
+ }
+
+ // Job env vars are delivered by step-runner; the recovery var is
+ // the only one we set here.
+ config.Env = []string{steps.RecoveryEnvVar + "=" + recoveryArgv}
}
// user config should only be set in build containers