From f64c4dcdb3305012c5e6faafd10eafd3ab53e25b Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 26 Apr 2024 17:30:02 +0000 Subject: [PATCH 1/4] Apply review comments --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- options.go | 12 ++++++++++++ scripts/docsgen/main.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 scripts/docsgen/main.go diff --git a/README.md b/README.md index d33f20a6..a7606e61 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ A sample script to pre-fetch a number of images can be viewed [here](./examples/ The `SETUP_SCRIPT` environment variable dynamically configures the user and init command (PID 1) after the container build process. -> **Note** > `TARGET_USER` is passed to the setup script to specify who will execute `INIT_COMMAND` (e.g., `code`). +> [!NOTE] > `TARGET_USER` is passed to the setup script to specify who will execute `INIT_COMMAND` (e.g., `code`). Write the following to `$ENVBUILDER_ENV` to shape the container's init process: @@ -250,3 +250,40 @@ On MacOS or Windows systems, we recommend either using a VM or the provided `.de - `develop`: runs `envbuilder:latest` against a sample Git repository. - `test`: run tests. - `test-registry`: stands up a local registry for caching images used in tests. + + + +## Environment Variables + +| Environment variable | Default | Description | +| - | - | - | +| SETUP_SCRIPT | | SetupScript is the script to run before the init script. It runs as the root user regardless of the user specified in the devcontainer.json file. SetupScript is ran as the root user prior to the init script. It is used to configure envbuilder dynamically during the runtime. e.g. specifying whether to start systemd or tiny init for PID 1. | +| INIT_SCRIPT | sleep infinity | InitScript is the script to run to initialize the workspace. | +| INIT_COMMAND | /bin/sh | InitCommand is the command to run to initialize the workspace. | +| INIT_ARGS | | InitArgs are the arguments to pass to the init command. They are split according to /bin/sh rules with https://github.com/kballard/go-shellquote. | +| CACHE_REPO | | CacheRepo is the name of the container registry to push the cache image to. If this is empty, the cache will not be pushed. | +| BASE_IMAGE_CACHE_DIR | | BaseImageCacheDir is the path to a directory where the base image can be found. This should be a read-only directory solely mounted for the purpose of caching the base image. | +| LAYER_CACHE_DIR | | LayerCacheDir is the path to a directory where built layers will be stored. This spawns an in-memory registry to serve the layers from. | +| DEVCONTAINER_DIR | | DevcontainerDir is a path to the folder containing the devcontainer.json file that will be used to build the workspace and can either be an absolute path or a path relative to the workspace folder. If not provided, defaults to `.devcontainer`. | +| DEVCONTAINER_JSON_PATH | | DevcontainerJSONPath is a path to a devcontainer.json file that is either an absolute path or a path relative to DevcontainerDir. This can be used in cases where one wants to substitute an edited devcontainer.json file for the one that exists in the repo. | +| DOCKERFILE_PATH | | DockerfilePath is a relative path to the Dockerfile that will be used to build the workspace. This is an alternative to using a devcontainer that some might find simpler. | +| BUILD_CONTEXT_PATH | | BuildContextPath can be specified when a DockerfilePath is specified outside the base WorkspaceFolder. This path MUST be relative to the WorkspaceFolder path into which the repo is cloned. | +| CACHE_TTL_DAYS | | CacheTTLDays is the number of days to use cached layers before expiring them. Defaults to 7 days. | +| DOCKER_CONFIG_BASE64 | | DockerConfigBase64 is a base64 encoded Docker config file that will be used to pull images from private container registries. | +| FALLBACK_IMAGE | | FallbackImage specifies an alternative image to use when neither an image is declared in the devcontainer.json file nor a Dockerfile is present. If there's a build failure (from a faulty Dockerfile) or a misconfiguration, this image will be the substitute. Set ExitOnBuildFailure to true to halt the container if the build faces an issue. | +| EXIT_ON_BUILD_FAILURE | | ExitOnBuildFailure terminates the container upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error. | +| FORCE_SAFE | | ForceSafe ignores any filesystem safety checks. This could cause serious harm to your system! This is used in cases where bypass is needed to unblock customers. | +| INSECURE | | Insecure bypasses TLS verification when cloning and pulling from container registries. | +| IGNORE_PATHS | /var/run | IgnorePaths is a comma separated list of paths to ignore when building the workspace. | +| SKIP_REBUILD | | SkipRebuild skips building if the MagicFile exists. This is used to skip building when a container is restarting. e.g. docker stop -> docker start This value can always be set to true - even if the container is being started for the first time. | +| GIT_URL | | GitURL is the URL of the Git repository to clone. This is optional. | +| GIT_CLONE_DEPTH | | GitCloneDepth is the depth to use when cloning the Git repository. | +| GIT_CLONE_SINGLE_BRANCH | | GitCloneSingleBranch clones only a single branch of the Git repository. | +| GIT_USERNAME | | GitUsername is the username to use for Git authentication. This is optional. | +| GIT_PASSWORD | | GitPassword is the password to use for Git authentication. This is optional. | +| GIT_HTTP_PROXY_URL | | GitHTTPProxyURL is the url for the http proxy. This is optional. | +| WORKSPACE_FOLDER | | WorkspaceFolder is the path to the workspace folder that will be built. This is optional. | +| SSL_CERT_BASE64 | | SSLCertBase64 is the content of an SSL cert file. This is useful for self-signed certificates. | +| EXPORT_ENV_FILE | | ExportEnvFile is an optional file path to a .env file where envbuilder will dump environment variables from devcontainer.json and the built container image. | +| POST_START_SCRIPT_PATH | | PostStartScriptPath is the path to a script that will be created by envbuilder based on the postStartCommand in devcontainer.json, if any is specified (otherwise the script is not created). If this is set, the specified InitCommand should check for the presence of this script and execute it after successful startup. | + diff --git a/options.go b/options.go index 9066d64b..072e1384 100644 --- a/options.go +++ b/options.go @@ -272,3 +272,15 @@ func (o *Options) CLI() serpent.OptionSet { }, } } + +func (o *Options) Markdown() string { + cliOptions := o.CLI() + mkd := "| Environment variable | Default | Description |\n" + + "| - | - | - |\n" + + for _, opt := range cliOptions { + mkd += "| " + opt.Env + " | " + opt.Default + " | " + opt.Description + " |\n" + } + + return mkd +} diff --git a/scripts/docsgen/main.go b/scripts/docsgen/main.go new file mode 100644 index 00000000..fa51c242 --- /dev/null +++ b/scripts/docsgen/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "os" + "strings" + + "github.com/coder/envbuilder" +) + +const ( + startSection = "" + endSection = "" +) + +func main() { + readmePath := "README.md" + readmeFile, err := os.ReadFile(readmePath) + if err != nil { + panic("error reading " + readmePath + " file") + } + readmeContent := string(readmeFile) + startIndex := strings.Index(readmeContent, startSection) + endIndex := strings.Index(readmeContent, endSection) + if startIndex == -1 || endIndex == -1 { + panic("start or end section comments not found in the file.") + } + + var options envbuilder.Options + mkd := "\n## Environment Variables\n\n" + options.Markdown() + modifiedContent := readmeContent[:startIndex+len(startSection)] + mkd + readmeContent[endIndex:] + + err = os.WriteFile(readmePath, []byte(modifiedContent), 0644) + if err != nil { + panic(err) + } + + fmt.Println("README updated successfully with the latest flags!") +} From 907e4ccdf1c48437eafd5b68f5e575fa94da6451 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 26 Apr 2024 17:37:23 +0000 Subject: [PATCH 2/4] Fix notes on README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a7606e61..59922eba 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,8 @@ A sample script to pre-fetch a number of images can be viewed [here](./examples/ The `SETUP_SCRIPT` environment variable dynamically configures the user and init command (PID 1) after the container build process. -> [!NOTE] > `TARGET_USER` is passed to the setup script to specify who will execute `INIT_COMMAND` (e.g., `code`). +> [!NOTE] +> `TARGET_USER` is passed to the setup script to specify who will execute `INIT_COMMAND` (e.g., `code`). Write the following to `$ENVBUILDER_ENV` to shape the container's init process: From b19c223fed8a036ee45b8f03479fbfae5353451b Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 26 Apr 2024 20:12:53 +0000 Subject: [PATCH 3/4] Setup CI for docs --- .github/workflows/ci.yaml | 30 +++++++++++++++++++++++++++++- Makefile | 3 +++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1407f3c8..a9055aa1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,10 +42,38 @@ jobs: path: ${{ steps.go-cache-paths.outputs.GOCACHE }} key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.**', '**.go') }} - # Install Go! - uses: actions/setup-go@v3 with: go-version: "~1.21" - name: Test run: make test + docs: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Echo Go Cache Paths + id: go-cache-paths + run: | + echo "GOCACHE=$(go env GOCACHE)" >> ${{ runner.os == 'Windows' && '$env:' || '$' }}GITHUB_OUTPUT + echo "GOMODCACHE=$(go env GOMODCACHE)" >> ${{ runner.os == 'Windows' && '$env:' || '$' }}GITHUB_OUTPUT + + - name: Go Build Cache + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.GOCACHE }} + key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.**', '**.go') }} + + - uses: actions/setup-go@v3 + with: + go-version: "~1.21" + + - name: Generate docs + run: make docs + + - name: Check for unstaged files + run: git diff --exit-code diff --git a/Makefile b/Makefile index 7d6102ce..d607f956 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ develop: build: scripts/envbuilder-$(GOARCH) ./scripts/build.sh +docs: options.go + go run ./scripts/docsgen/main.go + .PHONY: test test: test-registry test-images go test -count=1 ./... From e292feb462fd06c9cc3940d248f8b1483f57582a Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Mon, 29 Apr 2024 13:36:10 +0000 Subject: [PATCH 4/4] Change env var and default formatting --- README.md | 58 +++++++++++++++++++++++++++--------------------------- options.go | 9 +++++++-- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 59922eba..05a9b523 100644 --- a/README.md +++ b/README.md @@ -258,33 +258,33 @@ On MacOS or Windows systems, we recommend either using a VM or the provided `.de | Environment variable | Default | Description | | - | - | - | -| SETUP_SCRIPT | | SetupScript is the script to run before the init script. It runs as the root user regardless of the user specified in the devcontainer.json file. SetupScript is ran as the root user prior to the init script. It is used to configure envbuilder dynamically during the runtime. e.g. specifying whether to start systemd or tiny init for PID 1. | -| INIT_SCRIPT | sleep infinity | InitScript is the script to run to initialize the workspace. | -| INIT_COMMAND | /bin/sh | InitCommand is the command to run to initialize the workspace. | -| INIT_ARGS | | InitArgs are the arguments to pass to the init command. They are split according to /bin/sh rules with https://github.com/kballard/go-shellquote. | -| CACHE_REPO | | CacheRepo is the name of the container registry to push the cache image to. If this is empty, the cache will not be pushed. | -| BASE_IMAGE_CACHE_DIR | | BaseImageCacheDir is the path to a directory where the base image can be found. This should be a read-only directory solely mounted for the purpose of caching the base image. | -| LAYER_CACHE_DIR | | LayerCacheDir is the path to a directory where built layers will be stored. This spawns an in-memory registry to serve the layers from. | -| DEVCONTAINER_DIR | | DevcontainerDir is a path to the folder containing the devcontainer.json file that will be used to build the workspace and can either be an absolute path or a path relative to the workspace folder. If not provided, defaults to `.devcontainer`. | -| DEVCONTAINER_JSON_PATH | | DevcontainerJSONPath is a path to a devcontainer.json file that is either an absolute path or a path relative to DevcontainerDir. This can be used in cases where one wants to substitute an edited devcontainer.json file for the one that exists in the repo. | -| DOCKERFILE_PATH | | DockerfilePath is a relative path to the Dockerfile that will be used to build the workspace. This is an alternative to using a devcontainer that some might find simpler. | -| BUILD_CONTEXT_PATH | | BuildContextPath can be specified when a DockerfilePath is specified outside the base WorkspaceFolder. This path MUST be relative to the WorkspaceFolder path into which the repo is cloned. | -| CACHE_TTL_DAYS | | CacheTTLDays is the number of days to use cached layers before expiring them. Defaults to 7 days. | -| DOCKER_CONFIG_BASE64 | | DockerConfigBase64 is a base64 encoded Docker config file that will be used to pull images from private container registries. | -| FALLBACK_IMAGE | | FallbackImage specifies an alternative image to use when neither an image is declared in the devcontainer.json file nor a Dockerfile is present. If there's a build failure (from a faulty Dockerfile) or a misconfiguration, this image will be the substitute. Set ExitOnBuildFailure to true to halt the container if the build faces an issue. | -| EXIT_ON_BUILD_FAILURE | | ExitOnBuildFailure terminates the container upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error. | -| FORCE_SAFE | | ForceSafe ignores any filesystem safety checks. This could cause serious harm to your system! This is used in cases where bypass is needed to unblock customers. | -| INSECURE | | Insecure bypasses TLS verification when cloning and pulling from container registries. | -| IGNORE_PATHS | /var/run | IgnorePaths is a comma separated list of paths to ignore when building the workspace. | -| SKIP_REBUILD | | SkipRebuild skips building if the MagicFile exists. This is used to skip building when a container is restarting. e.g. docker stop -> docker start This value can always be set to true - even if the container is being started for the first time. | -| GIT_URL | | GitURL is the URL of the Git repository to clone. This is optional. | -| GIT_CLONE_DEPTH | | GitCloneDepth is the depth to use when cloning the Git repository. | -| GIT_CLONE_SINGLE_BRANCH | | GitCloneSingleBranch clones only a single branch of the Git repository. | -| GIT_USERNAME | | GitUsername is the username to use for Git authentication. This is optional. | -| GIT_PASSWORD | | GitPassword is the password to use for Git authentication. This is optional. | -| GIT_HTTP_PROXY_URL | | GitHTTPProxyURL is the url for the http proxy. This is optional. | -| WORKSPACE_FOLDER | | WorkspaceFolder is the path to the workspace folder that will be built. This is optional. | -| SSL_CERT_BASE64 | | SSLCertBase64 is the content of an SSL cert file. This is useful for self-signed certificates. | -| EXPORT_ENV_FILE | | ExportEnvFile is an optional file path to a .env file where envbuilder will dump environment variables from devcontainer.json and the built container image. | -| POST_START_SCRIPT_PATH | | PostStartScriptPath is the path to a script that will be created by envbuilder based on the postStartCommand in devcontainer.json, if any is specified (otherwise the script is not created). If this is set, the specified InitCommand should check for the presence of this script and execute it after successful startup. | +| `SETUP_SCRIPT` | | The script to run before the init script. It runs as the root user regardless of the user specified in the devcontainer.json file. SetupScript is ran as the root user prior to the init script. It is used to configure envbuilder dynamically during the runtime. e.g. specifying whether to start systemd or tiny init for PID 1. | +| `INIT_SCRIPT` | `sleep infinity` | The script to run to initialize the workspace. | +| `INIT_COMMAND` | `/bin/sh` | The command to run to initialize the workspace. | +| `INIT_ARGS` | | The arguments to pass to the init command. They are split according to /bin/sh rules with https://github.com/kballard/go-shellquote. | +| `CACHE_REPO` | | The name of the container registry to push the cache image to. If this is empty, the cache will not be pushed. | +| `BASE_IMAGE_CACHE_DIR` | | The path to a directory where the base image can be found. This should be a read-only directory solely mounted for the purpose of caching the base image. | +| `LAYER_CACHE_DIR` | | The path to a directory where built layers will be stored. This spawns an in-memory registry to serve the layers from. | +| `DEVCONTAINER_DIR` | | The path to the folder containing the devcontainer.json file that will be used to build the workspace and can either be an absolute path or a path relative to the workspace folder. If not provided, defaults to `.devcontainer`. | +| `DEVCONTAINER_JSON_PATH` | | The path to a devcontainer.json file that is either an absolute path or a path relative to DevcontainerDir. This can be used in cases where one wants to substitute an edited devcontainer.json file for the one that exists in the repo. | +| `DOCKERFILE_PATH` | | The relative path to the Dockerfile that will be used to build the workspace. This is an alternative to using a devcontainer that some might find simpler. | +| `BUILD_CONTEXT_PATH` | | Can be specified when a DockerfilePath is specified outside the base WorkspaceFolder. This path MUST be relative to the WorkspaceFolder path into which the repo is cloned. | +| `CACHE_TTL_DAYS` | | The number of days to use cached layers before expiring them. Defaults to 7 days. | +| `DOCKER_CONFIG_BASE64` | | The base64 encoded Docker config file that will be used to pull images from private container registries. | +| `FALLBACK_IMAGE` | | Specifies an alternative image to use when neither an image is declared in the devcontainer.json file nor a Dockerfile is present. If there's a build failure (from a faulty Dockerfile) or a misconfiguration, this image will be the substitute. Set ExitOnBuildFailure to true to halt the container if the build faces an issue. | +| `EXIT_ON_BUILD_FAILURE` | | Terminates the container upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error. | +| `FORCE_SAFE` | | Ignores any filesystem safety checks. This could cause serious harm to your system! This is used in cases where bypass is needed to unblock customers. | +| `INSECURE` | | Bypass TLS verification when cloning and pulling from container registries. | +| `IGNORE_PATHS` | `/var/run` | The comma separated list of paths to ignore when building the workspace. | +| `SKIP_REBUILD` | | Skip building if the MagicFile exists. This is used to skip building when a container is restarting. e.g. docker stop -> docker start This value can always be set to true - even if the container is being started for the first time. | +| `GIT_URL` | | The URL of the Git repository to clone. This is optional. | +| `GIT_CLONE_DEPTH` | | The depth to use when cloning the Git repository. | +| `GIT_CLONE_SINGLE_BRANCH` | | Clone only a single branch of the Git repository. | +| `GIT_USERNAME` | | The username to use for Git authentication. This is optional. | +| `GIT_PASSWORD` | | The password to use for Git authentication. This is optional. | +| `GIT_HTTP_PROXY_URL` | | The URL for the HTTP proxy. This is optional. | +| `WORKSPACE_FOLDER` | | The path to the workspace folder that will be built. This is optional. | +| `SSL_CERT_BASE64` | | The content of an SSL cert file. This is useful for self-signed certificates. | +| `EXPORT_ENV_FILE` | | Optional file path to a .env file where envbuilder will dump environment variables from devcontainer.json and the built container image. | +| `POST_START_SCRIPT_PATH` | | The path to a script that will be created by envbuilder based on the postStartCommand in devcontainer.json, if any is specified (otherwise the script is not created). If this is set, the specified InitCommand should check for the presence of this script and execute it after successful startup. | diff --git a/options.go b/options.go index 072e1384..792f4e1a 100644 --- a/options.go +++ b/options.go @@ -53,7 +53,7 @@ func (o *Options) CLI() serpent.OptionSet { Value: serpent.StringOf(&o.SetupScript), Description: "The script to run before the init script. It runs as " + "the root user regardless of the user specified in the devcontainer.json " + - "file.\n\nSetupScript is ran as the root user prior to the init script. " + + "file. SetupScript is ran as the root user prior to the init script. " + "It is used to configure envbuilder dynamically during the runtime. e.g. " + "specifying whether to start systemd or tiny init for PID 1.", }, @@ -279,7 +279,12 @@ func (o *Options) Markdown() string { "| - | - | - |\n" for _, opt := range cliOptions { - mkd += "| " + opt.Env + " | " + opt.Default + " | " + opt.Description + " |\n" + d := opt.Default + if d != "" { + + d = "`" + d + "`" + } + mkd += "| `" + opt.Env + "` | " + d + " | " + opt.Description + " |\n" } return mkd