|
7 | 7 | "bytes" |
8 | 8 | "context" |
9 | 9 | "fmt" |
| 10 | + "io/ioutil" |
10 | 11 | "os" |
11 | 12 | "path/filepath" |
12 | 13 | "sort" |
@@ -404,6 +405,10 @@ func (c *Client) DownloadAction(ctx context.Context, actionDigest, outputPath st |
404 | 405 | return err |
405 | 406 | } |
406 | 407 |
|
| 408 | + if err := c.writeExecScript(ctx, commandProto, filepath.Join(outputPath, "run_locally.sh")); err != nil { |
| 409 | + return err |
| 410 | + } |
| 411 | + |
407 | 412 | log.Infof("Fetching input tree from input root digest.. %v", actionProto.GetInputRootDigest()) |
408 | 413 | rootPath := filepath.Join(outputPath, "input") |
409 | 414 | os.RemoveAll(rootPath) |
@@ -439,6 +444,55 @@ func (c *Client) DownloadAction(ctx context.Context, actionDigest, outputPath st |
439 | 444 | return nil |
440 | 445 | } |
441 | 446 |
|
| 447 | +func (c *Client) writeExecScript(ctx context.Context, cmd *repb.Command, filename string) error { |
| 448 | + if cmd == nil { |
| 449 | + return fmt.Errorf("invalid comment (nil)") |
| 450 | + } |
| 451 | + |
| 452 | + var runActionScript bytes.Buffer |
| 453 | + runActionFilename := filepath.Join(filepath.Dir(filename), "run_command.sh") |
| 454 | + wd := cmd.WorkingDirectory |
| 455 | + execCmd := strings.Join(cmd.GetArguments(), " ") |
| 456 | + runActionScript.WriteString(fmt.Sprintf("#!/bin/bash\n\n")) |
| 457 | + runActionScript.WriteString(fmt.Sprintf("# This script is meant to be called by %v.\n", filename)) |
| 458 | + if wd != "" { |
| 459 | + runActionScript.WriteString(fmt.Sprintf("cd %v\n", wd)) |
| 460 | + } |
| 461 | + for _, od := range cmd.GetOutputDirectories() { |
| 462 | + runActionScript.WriteString(fmt.Sprintf("mkdir -p %v\n", od)) |
| 463 | + } |
| 464 | + for _, of := range cmd.GetOutputFiles() { |
| 465 | + runActionScript.WriteString(fmt.Sprintf("mkdir -p %v\n", filepath.Dir(of))) |
| 466 | + } |
| 467 | + for _, e := range cmd.GetEnvironmentVariables() { |
| 468 | + runActionScript.WriteString(fmt.Sprintf("export %v=%v\n", e.GetName(), e.GetValue())) |
| 469 | + } |
| 470 | + runActionScript.WriteString(fmt.Sprintf("%v\n", execCmd)) |
| 471 | + runActionScript.WriteString(fmt.Sprintf("bash\n")) |
| 472 | + if err := ioutil.WriteFile(runActionFilename, runActionScript.Bytes(), 0755); err != nil { |
| 473 | + return err |
| 474 | + } |
| 475 | + |
| 476 | + var container string |
| 477 | + for _, property := range cmd.Platform.GetProperties() { |
| 478 | + if property.Name == "container-image" { |
| 479 | + container = strings.TrimPrefix(property.Value, "docker://") |
| 480 | + } |
| 481 | + } |
| 482 | + if container == "" { |
| 483 | + return fmt.Errorf("container-image platform property missing from command proto: %v", cmd) |
| 484 | + } |
| 485 | + var execScript bytes.Buffer |
| 486 | + dockerCmd := fmt.Sprintf("docker run -i -t -w /b/f/w -v `pwd`/input:/b/f/w -v `pwd`/run_command.sh:/b/f/w/run_command.sh %v ./run_command.sh\n", container) |
| 487 | + execScript.WriteString(fmt.Sprintf("#!/bin/bash\n\n")) |
| 488 | + execScript.WriteString(fmt.Sprintf("# This script can be used to run the action locally on\n")) |
| 489 | + execScript.WriteString(fmt.Sprintf("# this machine.\n")) |
| 490 | + execScript.WriteString(fmt.Sprintf("echo \"WARNING: The results from executing the action through this script may differ from results from RBE.\"\n")) |
| 491 | + execScript.WriteString(fmt.Sprintf("set -x\n")) |
| 492 | + execScript.WriteString(dockerCmd) |
| 493 | + return ioutil.WriteFile(filename, execScript.Bytes(), 0755) |
| 494 | +} |
| 495 | + |
442 | 496 | func (c *Client) prepProtos(ctx context.Context, actionRoot string) (string, error) { |
443 | 497 | cmdTxt, err := os.ReadFile(filepath.Join(actionRoot, "cmd.textproto")) |
444 | 498 | if err != nil { |
|
0 commit comments