batches: Mount paths into a container
Created by: Piszmog
Closes #31790.
Add the ability to mount a path on the local machine into a container during a step
.
A path
can point to a file (./foo.sh
or /bar/foo.sh
) or a directory (./bar
or /foo/bar/
). The path
can be an absolute path or a relative path (for example ./foo.sh
). Regardless if the path is absolute or relative, the path must be within the same directory as the batch spec that is being ran (the batch spec directory is considered the "working directory").
Validation/handling of the mount
field in a step
is handled in the src-cli
versus batcheslib
in sourcegraph/sourcegraph
. The reason for this was the avoid having conditional logic to figure out if parseBatchSpec
is being called on a local machine vs behind an API. This also contains the file system logic within the context of src-cli
which is dealing with the file system.
This PR also includes some general fixes I saw while in the code (for example, package and variable naming collision).
Test plan
Go Unit Tests and manual testing.
Examples
Below are examples of mounting a path that contains a script (python or Go binary in this case) that is ran in the run
field of a step
.
Python
Example of running a python script that is mounted into the container and ran in a step
.
Batch Spec
name: python-script-test
description: Use a python script
on:
- repositoriesMatchingQuery: file:README.md
steps:
- run: python /tmp/updater.py
container: python:latest
mount:
- path: ./updater.py
mountpoint: /tmp/updater.py
changesetTemplate:
title: Hello from Python
body: Updated using a Python Script
branch: python-script-test
commit:
message: Append Hello World to all README.md files
Script
#!/usr/bin/env python3
import os.path
def main():
exists = os.path.exists('README.md')
if exists:
with open('README.md', 'a') as f:
f.write('\nHello from python')
if __name__ == "__main__":
main()
Changesets
Binary
Example of running a binary (written in Go) that is mounted into the container and ran in a step
.
Batch Spec
name: binary-test
description: Use a binary
on:
- repositoriesMatchingQuery: file:README.md
steps:
- run: /tmp/updater
container: alpine:latest
mount:
- path: ./updater # the linux binary
mountpoint: /tmp/updater
changesetTemplate:
title: Hello from a binary
body: Updated using a binary
branch: binary-test
commit:
message: Append Hello World to all README.md files
Binary
Binary was built from Go
package main
import "os"
func main() {
fileInfo, err := os.Stat("README.md")
if err != nil {
panic(err)
}
if fileInfo.IsDir() {
panic("file is a directory")
}
f, err := os.OpenFile("README.md", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer f.Close()
if _, err = f.WriteString("\nhello from go"); err != nil {
panic(err)
}
}
Built with the following command,
env GOOS=linux GOGOARCH=amd64 go build -ldflags="-s -w"
Changesets
Directory
The above examples have the path
pointing to a specific file. Directories can also be mounted in the container. This example reuses the above Python Example but mounts a directory that contains the script.
Batch Spec
name: python-script-test
description: Use a python script
on:
- repositoriesMatchingQuery: file:README.md
steps:
- run: python /tmp/scripts/updater.py
container: python:latest
mount:
- path: ./scripts
mountpoint: /tmp/scripts
changesetTemplate:
title: Hello from Python
body: Updated using a Python Script
branch: python-script-test
commit:
message: Append Hello World to all README.md files