From 4499fbd2f13fa10b3eb678750b0803550be0625e Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Thu, 11 Jan 2024 14:03:41 -0600 Subject: [PATCH 01/19] rough draft of quick-start/flesh out USAGE.md --- DEVELOP.md | 13 +++++- README.md | 24 ++++++++--- USAGE.md | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 149 insertions(+), 10 deletions(-) diff --git a/DEVELOP.md b/DEVELOP.md index b6f1dfa5..0039d085 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -1,9 +1,14 @@ # Contributing to the RAPIDS devcontainers +## Features + From the official devcontainer [documentation on Features](https://containers.dev/implementors/features/): > Development container "Features" are self-contained, shareable units of installation code and development container configuration. -In short, a "feature" is a layer in a Dockerfile which encapsulates a reusable bit of logic executed when building a Docker image. +In short, a "feature" is a layer in a Dockerfile which encapsulates a reusable +bit of logic executed when building a Docker image. It is not a docker layer to +put on top of or copied into other layers. It is the script that creates a +layer. This repository defines features to install the following dev tools, compilers, and SDKs: @@ -21,3 +26,9 @@ This repository defines features to install the following dev tools, compilers, * [sccache](features/src/sccache/) * [devcontainer-utils](features/src/utils/) * [rapids-build-utils](features/src/rapids-build-utils/) + +These scripts assume that apt utilities are available, and thus only run on debian-based images. + +## Base images + +Base images are composed in [matrix.yml](./matrix.yml) using [YAML anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). These get built on Github Actions ([release.yml](./.github/workflows/release.yml) and [test.yml](.github/workflows/test.yml)) \ No newline at end of file diff --git a/README.md b/README.md index ef43c894..df48b81d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,25 @@ # RAPIDS [devcontainers](https://containers.dev/) -This repository contains features and workflows for building development containers to support local dev and CI for NVIDIA [RAPIDS](https://github.com/rapidsai), [CCCL](https://github.com/nvidia/cccl), and [Legate](https://github.com/nv-legate). +This repository contains features and workflows for building development +containers to support local dev and CI for NVIDIA +[RAPIDS](https://github.com/rapidsai), [CCCL](https://github.com/nvidia/cccl), +and [Legate](https://github.com/nv-legate). +[Devcontainers](https://containers.dev/) are an open standard for specifying the +creation and execution of Docker containers for developing a codebase. It's like +using a docker image to develop, but there's some extra configuration and +installation that can be done. It also provides some alternative ways of +composing functionality and configuration that can augment Docker's +capabilities. -We've chosen to use a monorepo, but it is similar in spirit to the official [devcontainers/features](https://github.com/devcontainers/features) and [devcontainers/images](https://github.com/devcontainers/images) repositories. +In addition to scripts that set up the devcontainer environment for things like GitHub auth, this repo +contains reusable scripts to install software in arbitrary containers, aiding in composition and code sharing. +A "feature" in VSCode terms refers to these installation scripts. The script for each feature runs when +creating the devcontainer. -### For details on using the RAPIDS devcontainers, see [`USAGE.md`](USAGE.md). +We've chosen to use a monorepo for the features here, but it is similar in spirit to the official [devcontainers/features](https://github.com/devcontainers/features) and [devcontainers/images](https://github.com/devcontainers/images) repositories. -### For details on contributing to this repository, see [`DEVELOP.md`](DEVELOP.md). +## For details on using the RAPIDS devcontainers, see [`USAGE.md`](USAGE.md). -### See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). +## For details on contributing to this repository, see [`DEVELOP.md`](DEVELOP.md). + +## See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). These tags are used as base images in devcontainers, and aren't really meant to be used directly. diff --git a/USAGE.md b/USAGE.md index bc202075..9ae71439 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,30 +1,144 @@ # Using the RAPIDS devcontainers -### See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). +- [Using the RAPIDS devcontainers](#using-the-rapids-devcontainers) + - [Quick start](#quick-start) + - [Using devcontainers in VS Code](#using-devcontainers-in-vs-code) + - [Using devcontainers from the terminal](#using-devcontainers-from-the-terminal) + - [Available tools in the devcontainer](#available-tools-in-the-devcontainer) + - [Generated build scripts](#generated-build-scripts) + - [rapids-build-utils](#rapids-build-utils) + - [Native build tools - CMake, python builds](#native-build-tools---cmake-python-builds) + - [Adding projects: manifest.yaml file](#adding-projects-manifestyaml-file) + - [Using the pre-built images](#using-the-pre-built-images) + - [Using in `devcontainer.json`](#using-in-devcontainerjson) + - [Custom devcontainers](#custom-devcontainers) + - [Build caching with `sccache`](#build-caching-with-sccache) + - [Build caching with private S3 buckets](#build-caching-with-private-s3-buckets) + - [Using GitHub OAuth to issue S3 credentials via Hashicorp Vault](#using-github-oauth-to-issue-s3-credentials-via-hashicorp-vault) + +## Quick start + +So, you have cloned a repo that you've heard has a devcontainer. You can see the file(s) for yourself by looking +in your repo's `.devcontainer` folder. You may find a `devcontainer.json` file, or you may find some number of folders, such as `cuda12.0-conda` and `cuda12.0-pip`. If you find folders, these each contain a `devcontainer.json` +file. These files specify how to create and run a container that leaves you with a good setup to do development. + +There are at least 2 ways to consume these devcontainer.json files. VS Code was +the original home of devcontainers prior to becoming an open specification, and +it remains a good way to use them. If you prefer not to use VS Code, the +[devcontainers-cli](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) +application will build the devcontainer and allow you to interact with it. + +### Using devcontainers in VS Code + +[The VS Code +docs](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container) +are the definitive source of information for this topic. + +Specifically for RAPIDS repos, we frequently have multiple folders for different +library configurations. Pay attention to which build environment you need when +launching your devcontainer. You can switch between them + +### Using devcontainers from the terminal + +The [devcontainer-cli](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) project +allows you to run and interact with devcontainers from the terminal. It uses NodeJS, so you need +to install that in order to run it. + +You need to specify the devcontainer.json file and workspace folder to use when starting the devcontainer: -* [Using the pre-built images](#using-the-pre-built-images) - * [Using in `devcontainer.json`](#using-in-devcontainerjson) -* [Build caching with sccache](#build-caching-with-sccache) +``` +devcontainer up --config .devcontainer/cuda12.0-pip/devcontainer.json --workspace-folder=. +``` + +## Available tools in the devcontainer + +### Generated build scripts + +Several scripts are generated for you based on the contents of manifest.yaml. By +default, manifest.yaml comes from [the RAPIDS/devcontainers +repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), +but you can use your own local manifest.yaml file. Refer to the "Adding +projects" section. + +The generated scripts are: +* /usr/bin/build-* +* /usr/bin/clean-* +* /usr/bin/clone-* +* /usr/bin/configure-* + +Here the * is a placeholder for the project name and the kind of +build. For example, a project with a python component in manifest.yaml +will have `build-ucxx-python`. + +These scripts may trigger side-effects. For example, build-* scripts are only +generated for projects that exist in the workspace. If you are working on UCXX, +which depends on RMM, the default workspace only mounts UCXX and generates +build-ucxx scripts. If you want RMM build scripts also, you can run `clone-rmm`, +which will clone RMM into your workspace and generate build scripts for it. + +### rapids-build-utils + +These are meta-build scripts. They assist with setting up the workspace and reloading things when important configuration +changes happen. You mostly won't need to worry about these, +but it's good to be aware of them. They come from the [rapidsai/devcontainers repo](https://github.com/rapidsai/devcontainers/tree/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/bin) + +### Native build tools - CMake, python builds + +The generated scripts mentioned above will take care of running +build tools for you. However, if you need to run the build tools +manually, you can `cd` into your source code folder, which is +mounted as a subfolder in `/home/coder`. +## Adding projects: manifest.yaml file + +The build script generation is controlled with a manifest.yaml file, which by default comes from [the rapidsai/devcontainers +repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml) + +If you would like to add your project, you can submit a PR to the rapidsai/devcontainers repo. Before you do that, though, you can +test it locally. Start by copying manifest.yaml from the rapidsai/devcontainers repo. You can put it anywhere, but let's say we put it in .devcontainer/manifest.yaml. + +Now open a devcontainer.json file that you want to work with. These +will likely live in a .devcontainer subfolder, such as cuda12.0-pip. In this file, add a top-level key with this: + +``` + "containerEnv": { + "PROJECT_MANIFEST_YML": "${localWorkspaceFolder}/.devcontainer/manifest.yaml" + }, +``` + +Rebuild or re-open your devcontainer, and you should now see updated +generated scripts. ## Using the pre-built images +The choice of using a pre-built image refers to the build/args/BASE entry in devcontainer.json. The pre-built +images are not meant to be used directly. The rapids-build-utils scripts are installed with a "feature," so +they won't be present if you directly run a pre-built image with Docker instead of with a devcontainer tool (VS Code or devcontainer-cli) + We publish a [matrix](matrix.yml) of pre-built images to DockerHub to accelerate initializing local devcontainers, GitHub Codespaces, and CI jobs. The features that comprise the image are noted in the image tags. If no version is defined for a tool or SDK, the image includes the latest available version at image build time. > **NOTE:** `git`, `git-lfs`, `github-cli`, `gitlab-cli`, `cmake`, `ninja`, `sccache`, and our devcontainer-utils [are included](image/.devcontainer/devcontainer.json#L12-L33) in each pre-built image. +See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). + ### Using in [`devcontainer.json`](https://containers.dev/implementors/json_reference/#image-specific) The pre-built images can be used as the `"image"`, or as the base of a Dockerfile in `"build"`, in `devcontainer.json`:
devcontainer.json using pre-built image
{
"image": "rapidsai/devcontainers:24.02-cpp-llvm16-cuda12.0-nvhpc23.5-ubuntu22.04",
"hostRequirements": { "gpu": true },
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
+### Custom devcontainers + You can also build a custom devcontainer by composing individual features:
devcontainer.json using individual features
{
"image": "ubuntu:22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.02": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
+You can also add libraries or programs on top of a pre-built image using this +same mechanism. These are not baked into the image, but cached as a docker +layer. + > **NOTE:** Feature updates published since your most recent image build will invalidate your docker image layer cache, meaning it can take the [devcontainers CLI](https://github.com/devcontainers/cli) longer to initialize containers composed from individual features. ## Build caching with `sccache` From a7fc05e0650a7c3b6dba10f16e974d3f32456786 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Thu, 11 Jan 2024 16:08:58 -0600 Subject: [PATCH 02/19] reference Brad's rapids-dev script --- USAGE.md | 106 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/USAGE.md b/USAGE.md index 9ae71439..339509d3 100644 --- a/USAGE.md +++ b/USAGE.md @@ -2,13 +2,14 @@ - [Using the RAPIDS devcontainers](#using-the-rapids-devcontainers) - [Quick start](#quick-start) + - [Detailed start](#detailed-start) - [Using devcontainers in VS Code](#using-devcontainers-in-vs-code) - [Using devcontainers from the terminal](#using-devcontainers-from-the-terminal) - - [Available tools in the devcontainer](#available-tools-in-the-devcontainer) - [Generated build scripts](#generated-build-scripts) - [rapids-build-utils](#rapids-build-utils) - [Native build tools - CMake, python builds](#native-build-tools---cmake-python-builds) - - [Adding projects: manifest.yaml file](#adding-projects-manifestyaml-file) + - [Exiting the devcontainer](#exiting-the-devcontainer) + - [Adding projects: `manifest.yaml` file](#adding-projects-manifestyaml-file) - [Using the pre-built images](#using-the-pre-built-images) - [Using in `devcontainer.json`](#using-in-devcontainerjson) - [Custom devcontainers](#custom-devcontainers) @@ -18,6 +19,32 @@ ## Quick start +If you really want to get started right away and ignore all the details of how +devcontainers work, the easiest way is to treat the devcontainer +like a docker container that you use interactively. Brad Dice wrote [a script +that wraps the devcontainer +CLI](https://gist.github.com/bdice/a92d224b3e3b1b387fc18b8095b3bdbd) to do this. + +To obtain this script: +``` +curl -LO https://gist.githubusercontent.com/bdice/a92d224b3e3b1b387fc18b8095b3bdbd/raw/28eb8edc856ae04d4cd83571fea5b894f714f01c/rapids-dev +chmod +x rapids-dev +./rapids-dev +``` + +This script expects you to have your current directory set to the +root of a repo that has a .devcontainer folder. You may want to move +this script to a folder that you place on PATH, such as `~/bin` + +Running that command will build the devcontainer and drop you at +an interactive prompt. You can immediately build your project +with one of the devcontainers scripts. Type `build-` and hit `` to see your options. + +Skip ahead to [Available tools in the devcontainer](#available-tools-in-the-devcontainer) to see more options +for interaction at this prompt. + +## Detailed start + So, you have cloned a repo that you've heard has a devcontainer. You can see the file(s) for yourself by looking in your repo's `.devcontainer` folder. You may find a `devcontainer.json` file, or you may find some number of folders, such as `cuda12.0-conda` and `cuda12.0-pip`. If you find folders, these each contain a `devcontainer.json` file. These files specify how to create and run a container that leaves you with a good setup to do development. @@ -44,37 +71,60 @@ The [devcontainer-cli](https://code.visualstudio.com/docs/devcontainers/devconta allows you to run and interact with devcontainers from the terminal. It uses NodeJS, so you need to install that in order to run it. -You need to specify the devcontainer.json file and workspace folder to use when starting the devcontainer: +There are wrappers to facilitate working with this CLI. Refer back to the +[Quick-start section](#quick-start). If you need more flexibility, you can call +the devcontainer CLI directly. + +You need to specify the `devcontainer.json` file and workspace folder to use when starting the devcontainer. Also note that you must manage the 3 steps of the lifecycle yourself: + +* bring up the devcontainer +* run your command (or run bash for interactive prompt) +* stop and remove the docker container ``` -devcontainer up --config .devcontainer/cuda12.0-pip/devcontainer.json --workspace-folder=. +CONTAINER_JSON=.devcontainer/cuda12.0-pip/devcontainer.json +devcontainer up --config ${CONTAINER_JSON} --workspace-folder=$(pwd) +devcontainer exec --config ${CONTAINER_JSON} --workspace-folder=$(pwd) bash ``` -## Available tools in the devcontainer +Stopping and removing the docker container is manual. The devcontainer CLI does +not currently facilitate this in any way. One possible workflow (copied from [aforementioned wrapper](https://gist.github.com/bdice/a92d224b3e3b1b387fc18b8095b3bdbd)): + +``` +CONTAINER_ID=$(docker ps --quiet \ + --filter label=devcontainer.local_folder=$(pwd) \ + --filter label=devcontainer.config_file=${CONTAINER_JSON}) +num_active_shells=$(docker exec "${container_id}" ps aux | grep -c "/bin/sh") +if [[ ${num_active_shells} -le 1 ]]; then + echo "All devcontainers are closed. Stopping and removing container ${container_id}." + docker stop "${container_id}" + docker rm "${container_id}" +fi +``` ### Generated build scripts Several scripts are generated for you based on the contents of manifest.yaml. By -default, manifest.yaml comes from [the RAPIDS/devcontainers +default, `manifest.yaml` comes from [the RAPIDS/devcontainers repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), -but you can use your own local manifest.yaml file. Refer to the "Adding +but you can use your own local `manifest.yaml` file. Refer to the "Adding projects" section. The generated scripts are: -* /usr/bin/build-* -* /usr/bin/clean-* -* /usr/bin/clone-* -* /usr/bin/configure-* +* `/usr/bin/build-*` +* `/usr/bin/clean-*` +* `/usr/bin/clone-*` +* `/usr/bin/configure-*` -Here the * is a placeholder for the project name and the kind of -build. For example, a project with a python component in manifest.yaml -will have `build-ucxx-python`. +Here the `*` is a placeholder for the project name and the kind of +build. For example, a project with a python component in `manifest.yaml` +will have `build-cudf-python`. -These scripts may trigger side-effects. For example, build-* scripts are only -generated for projects that exist in the workspace. If you are working on UCXX, -which depends on RMM, the default workspace only mounts UCXX and generates -build-ucxx scripts. If you want RMM build scripts also, you can run `clone-rmm`, -which will clone RMM into your workspace and generate build scripts for it. +These scripts may trigger side-effects. For example, `build-*` scripts are only +generated for projects that exist in the workspace. If you are working on `cudf`, +which depends on `rmm`, the default workspace only mounts `cudf` and generates +`build-cudf` scripts. If you want `rmm` build scripts also, you can run `clone-rmm`, +which will clone `rmm` into your workspace and generate build scripts for it. ### rapids-build-utils @@ -89,13 +139,18 @@ build tools for you. However, if you need to run the build tools manually, you can `cd` into your source code folder, which is mounted as a subfolder in `/home/coder`. -## Adding projects: manifest.yaml file +### Exiting the devcontainer + +If you are in VS Code and you need to return to your host machine (local or SSH), +you can run `Dev Containers: Reopen in SSH`. + +## Adding projects: `manifest.yaml` file -The build script generation is controlled with a manifest.yaml file, which by default comes from [the rapidsai/devcontainers +The build script generation is controlled with a `manifest.yaml` file, which by default comes from [the rapidsai/devcontainers repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml) If you would like to add your project, you can submit a PR to the rapidsai/devcontainers repo. Before you do that, though, you can -test it locally. Start by copying manifest.yaml from the rapidsai/devcontainers repo. You can put it anywhere, but let's say we put it in .devcontainer/manifest.yaml. +test it locally. Start by copying `manifest.yaml` from the rapidsai/devcontainers repo. You can put it anywhere, but let's say we put it in .devcontainer/manifest.yaml. Now open a devcontainer.json file that you want to work with. These will likely live in a .devcontainer subfolder, such as cuda12.0-pip. In this file, add a top-level key with this: @@ -111,11 +166,12 @@ generated scripts. ## Using the pre-built images -The choice of using a pre-built image refers to the build/args/BASE entry in devcontainer.json. The pre-built +The choice of using a pre-built image refers to the build/args/BASE entry in `devcontainer.json`. The pre-built images are not meant to be used directly. The rapids-build-utils scripts are installed with a "feature," so they won't be present if you directly run a pre-built image with Docker instead of with a devcontainer tool (VS Code or devcontainer-cli) -We publish a [matrix](matrix.yml) of pre-built images to DockerHub to accelerate initializing local devcontainers, GitHub Codespaces, and CI jobs. +We publish a [matrix](matrix.yml) of pre-built images to DockerHub to accelerate initializing local devcontainers, GitHub Codespaces, and CI jobs. These use the "feature" scripts to install their components, +so you can think of them as caching those steps. The features that comprise the image are noted in the image tags. If no version is defined for a tool or SDK, the image includes the latest available version at image build time. @@ -135,7 +191,7 @@ You can also build a custom devcontainer by composing individual features:
devcontainer.json using individual features
{
"image": "ubuntu:22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.02": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
-You can also add libraries or programs on top of a pre-built image using this +You can add libraries or programs on top of a pre-built image using this same mechanism. These are not baked into the image, but cached as a docker layer. From e7a5d5c3c6f9db7385a7bccfaf70a113e01f1024 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Thu, 11 Jan 2024 16:13:52 -0600 Subject: [PATCH 03/19] fix unfinished thought on switching devcontainers --- USAGE.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/USAGE.md b/USAGE.md index 339509d3..9f1df2ca 100644 --- a/USAGE.md +++ b/USAGE.md @@ -63,7 +63,10 @@ are the definitive source of information for this topic. Specifically for RAPIDS repos, we frequently have multiple folders for different library configurations. Pay attention to which build environment you need when -launching your devcontainer. You can switch between them +launching your devcontainer. You can switch between them by reopening your +native host (e.g. CMD+SHIFT+P -> "Reopen folder in SSH"), and then re-opening in +devcontainer (CMD+SHIFT+P -> "Reopen in container"), at which point you'll see a +prompt to choose a different `devcontainer.json`. ### Using devcontainers from the terminal From dc153c0eb980a488744a66b30319208b854961cc Mon Sep 17 00:00:00 2001 From: Mike Sarahan Date: Thu, 11 Jan 2024 16:14:47 -0600 Subject: [PATCH 04/19] Update USAGE.md Co-authored-by: Bradley Dice --- USAGE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/USAGE.md b/USAGE.md index 9f1df2ca..8e9c104e 100644 --- a/USAGE.md +++ b/USAGE.md @@ -107,7 +107,7 @@ fi ### Generated build scripts -Several scripts are generated for you based on the contents of manifest.yaml. By +Several scripts are generated for you based on the contents of `manifest.yaml`. By default, `manifest.yaml` comes from [the RAPIDS/devcontainers repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), but you can use your own local `manifest.yaml` file. Refer to the "Adding From c82f0f700bf6751a04b0552f7283599ae41ddc78 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Fri, 12 Jan 2024 08:45:14 -0600 Subject: [PATCH 05/19] system requirements and remote VS code usage --- USAGE.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/USAGE.md b/USAGE.md index 8e9c104e..90579e92 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,6 +1,7 @@ # Using the RAPIDS devcontainers - [Using the RAPIDS devcontainers](#using-the-rapids-devcontainers) + - [System requirements](#system-requirements) - [Quick start](#quick-start) - [Detailed start](#detailed-start) - [Using devcontainers in VS Code](#using-devcontainers-in-vs-code) @@ -17,6 +18,14 @@ - [Build caching with private S3 buckets](#build-caching-with-private-s3-buckets) - [Using GitHub OAuth to issue S3 credentials via Hashicorp Vault](#using-github-oauth-to-issue-s3-credentials-via-hashicorp-vault) +## System requirements + +Devcontainers can be used on Linux, Mac and Windows. They use Docker, so the +system requirements and limitations associated with Docker apply here also. On +Mac and Windows, where a Linux VM must run to support Docker, you may need to be +aware of memory limitations of that Linux VM. Otherwise, devcontainers do not add +system requirements beyond the needs of the individual projects we're building. + ## Quick start If you really want to get started right away and ignore all the details of how @@ -61,6 +70,13 @@ application will build the devcontainer and allow you to interact with it. docs](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container) are the definitive source of information for this topic. +You can use devcontainers in VS Code either locally (docker running on your +local machine) or with VS Code's remote-ssh or remote-tunnel connections. To use +the devcontainers on a remote machine, connect normally using SSH or tunnel, and +then follow the VS Code docs for using the dev containers. There is no special +way to connect directly to a devcontainer on a remote host. You must go via +SSH/tunnel first. + Specifically for RAPIDS repos, we frequently have multiple folders for different library configurations. Pay attention to which build environment you need when launching your devcontainer. You can switch between them by reopening your From ad07fbb7baaddf4b27a6c19f8edfaba0ecb61897 Mon Sep 17 00:00:00 2001 From: Mike Sarahan Date: Fri, 12 Jan 2024 12:15:56 -0600 Subject: [PATCH 06/19] Apply suggestions from code review Co-authored-by: Paul Taylor <178183+trxcllnt@users.noreply.github.com> --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index df48b81d..c536e5db 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,11 @@ installation that can be done. It also provides some alternative ways of composing functionality and configuration that can augment Docker's capabilities. -In addition to scripts that set up the devcontainer environment for things like GitHub auth, this repo -contains reusable scripts to install software in arbitrary containers, aiding in composition and code sharing. -A "feature" in VSCode terms refers to these installation scripts. The script for each feature runs when -creating the devcontainer. +In addition to scripts that set up the devcontainer environment for things like GitHub auth, this repo contains reusable scripts to install software in arbitrary containers, aiding in composition and code sharing. A "feature" in VSCode terms refers to these installation scripts. The script for each feature runs when creating the devcontainer. We've chosen to use a monorepo for the features here, but it is similar in spirit to the official [devcontainers/features](https://github.com/devcontainers/features) and [devcontainers/images](https://github.com/devcontainers/images) repositories. ## For details on using the RAPIDS devcontainers, see [`USAGE.md`](USAGE.md). ## For details on contributing to this repository, see [`DEVELOP.md`](DEVELOP.md). - ## See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). These tags are used as base images in devcontainers, and aren't really meant to be used directly. From bda365a5402e72122b5e41e9f7cca249ef77f3b2 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Tue, 16 Jan 2024 11:08:33 -0800 Subject: [PATCH 07/19] flesh out 3-doc readme, copy img from CCCL --- DEVELOP.md | 167 ++++++++++++++++-- README.md | 30 ++-- USAGE.md | 245 ++++++-------------------- USAGE_IN_PROJECT.md | 172 ++++++++++++++++++ docs-img/container_list.png | Bin 0 -> 159943 bytes docs-img/github_auth.png | Bin 0 -> 54609 bytes docs-img/open_in_container_manual.png | Bin 0 -> 58565 bytes docs-img/reopen_in_container.png | Bin 0 -> 27864 bytes launch-devcontainer.sh | 86 +++++++++ 9 files changed, 487 insertions(+), 213 deletions(-) create mode 100644 USAGE_IN_PROJECT.md create mode 100644 docs-img/container_list.png create mode 100644 docs-img/github_auth.png create mode 100644 docs-img/open_in_container_manual.png create mode 100644 docs-img/reopen_in_container.png create mode 100755 launch-devcontainer.sh diff --git a/DEVELOP.md b/DEVELOP.md index 0039d085..a0813080 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -1,16 +1,30 @@ # Contributing to the RAPIDS devcontainers +This document contains implementation details and design overviews for +[rapidsai/devcontainers](https://github.com/rapidsai/devcontainers) as a +centralized source of common scripts and patterns for providing devcontainers. + +For the user-level overview providing instructions on how to use the +devcontainer as a development environment, see +[USAGE_IN_PROJECT.md](USAGE_IN_PROJECT.md) + +For the project maintainer-level overview providing instructions on how to add +and change .devcontainer.json to suit your project, see [USAGE.md](USAGE.md) + +The code in this repository fits into a few main categories: +1. Features +1. GitHub Actions automations +1. Scripts +1. matrix.yml +1. Dockerfiles + ## Features From the official devcontainer [documentation on Features](https://containers.dev/implementors/features/): -> Development container "Features" are self-contained, shareable units of installation code and development container configuration. - -In short, a "feature" is a layer in a Dockerfile which encapsulates a reusable -bit of logic executed when building a Docker image. It is not a docker layer to -put on top of or copied into other layers. It is the script that creates a -layer. +> Development container "Features" are self-contained, shareable units of installation code and development container configuration. Each "feature" specified becomes a `RUN` statement in a temporary Dockerfile, +and as such each "feature" results in an image layer. -This repository defines features to install the following dev tools, compilers, and SDKs: +This repository defines `features` to install the following dev tools, compilers, and SDKs: * [CMake](features/src/cmake/) * [CUDA Toolkit](features/src/cuda/) @@ -27,8 +41,141 @@ This repository defines features to install the following dev tools, compilers, * [devcontainer-utils](features/src/utils/) * [rapids-build-utils](features/src/rapids-build-utils/) -These scripts assume that apt utilities are available, and thus only run on debian-based images. +These scripts assume that apt utilities are available, and thus generally only +run on debian-based images. + +### Utility features + +A few of the features install custom tools for the devcontainer ecosystem here, +rather than just installation scripts of external tools and libraries. A brief +overview of responsibilities for these features follows. + +#### Rapids-build-utils + +Most of the scripts here serve to prepare the devcontainer prior to use, but you may use them to update +the devcontainer after adding to your container's /opt/rapids-build-utils/manifest.yml file to add new projects. + +If you are wondering where a command or behavior in a devcontainer is coming +from, this is a good place to start. + +These scripts are installed by +[`install.sh`](./features/src/rapids-build-utils/install.sh), which creates +aliases for the .sh scripts. if you see `rapids-*` for a script or command name +in the devcontainer, look in +[`install.sh`](./features/src/rapids-build-utils/install.sh) to see how it is +mapped back to one of these scripts. + +* [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If you project is not in manifest.yaml, you will not get build scripts generated in your devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) +* [generate-scripts.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/generate-scripts.sh): generate `build-*`, `clone-*`, etc. scripts +* [make-pip-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-pip-env.sh) and [make-conda-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-conda-env.sh): +creating pip and conda python virtual environments +* [pull-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/pull-repositories.sh) and [push-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/push-repositories.sh) help you manage git operations on multiple repos that you may have cloned +* [update-content-command.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/update-content-command.sh): calls `rapids-generate-script` and `rapids-make-vscode-workspace`. Called by VS Code in the [`postAttachCommand`](https://containers.dev/implementors/json_reference/#lifecycle-scripts), which is a reliable hook when the project is reopened or its configuration is changed. + +There are more scripts here, dealing with CMake variable parsing and +pass-through, python package dependency installation, and more. + +#### devcontainers-utils + +These scripts handle mostly git-related configuration, setting up SSH deploy +keys, GitHub authorization, and the vault setup for S3. The commands here are +prefixed with `devcontainer-` during installation, so if you see that prefix, +look in here. + +## Github Actions automations + +Github Actions runs the build matrix of the many base images define in [matrix.yml](./matrix.yml). +These actions are broken up into many reusable pieces. The image build jobs start in +[release.yml](./.github/workflows/release.yml). + +```mermaid +flowchart TD + subgraph Legend + workflow + action(action) + script{{script}} + end + subgraph Image build Github Actions flowchart + release.yml --> release-features.yml[Publish features] + release-features.yml --> image-matrix(Determine image matrix) + image-matrix --> write-matrix{{Call feature-matrix/action.sh}} + write-matrix --> build-test-and-push-linux-image.yml + write-matrix --> build-test-and-push-windows-image.yml + build-test-and-push-linux-image.yml --> write-json(Write .devcontainer.json) + write-json --> write-script{{Call devcontainer-json/action.sh}} + build-test-and-push-windows-image.yml --> build-windows(Build windows image) + write-script --> build-linux-image(Build linux limage) + end +``` + +These are divided into 3 categories: +* Workflows are `.yml` files in `.github/workflows` +* Actions are folders in `.github/actions`. One folder per action. Actions must have a `action.yml` file, but may also have accompanying shell scripts. +* Scripts are the shell scripts that are in some of the actions. They are broken out in this diagram to help show where the functionality actually lives. + +## Base images (matrix.yml) + +Base images are composed from individual features in [matrix.yml](./matrix.yml) +using [YAML +anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). +These get built on Github Actions as described +[above](#github-actions-automations) The devcontainers repo does not contain +scripts to facilitate building one particular image. Some downstream repos, such +as CCCL, have such scripts for their reduced subspace of the matrix. CCCL's +example is their +[make_devcontainers.sh](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/make_devcontainers.sh) +script. + +## Dockerfiles + +Dockerfiles do not play much role in this scheme. They serve to [set a few global +variables and extend from the base image](./.devcontainer/rapids.Dockerfile). If you think you need to modify a +Dockerfile, make sure that your goal wouldn't be better achieved by adding or +changing a feature script instead. + +## Build caching with `sccache` + +The devcontainers configure CMake to use +[sccache](https://github.com/mozilla/sccache) as C, C++, CUDA, and Rust compiler +launchers. Refer to the [sccache +docs](https://github.com/mozilla/sccache/tree/main/docs) for configuring the +various storage back-ends. + +### Build caching with private S3 buckets + +You can use a private S3 bucket as the `sccache` storage back-end. + +If you're using a [GitHub action](https://github.com/aws-actions/configure-aws-credentials) to assume AWS roles in CI, or are comfortable distributing and managing S3 credentials, you can define the `SCCACHE_BUCKET`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY` variables in the container environment. + +### Using GitHub OAuth to issue S3 credentials via Hashicorp Vault + +The [`devcontainer-utils`](features/src/utils/) feature includes a `devcontainer-utils-vault-s3-init` script that uses GitHub OAuth and Hashicorp Vault to issue temporary S3 credentials to authorized users. + +> **NOTE:** This script runs in the devcontainer's [`postAttachCommand`](https://containers.dev/implementors/json_reference/#lifecycle-scripts), but it does nothing unless `SCCACHE_BUCKET` and `VAULT_HOST` are in the container environment. + +The `devcontainer-utils-vault-s3-init` script performs the following actions, exiting early if any step is unsuccessful: + +1. Log in via the [GitHub CLI](https://cli.github.com/) +2. Authenticate via [Vault's GitHub auth method](https://developer.hashicorp.com/vault/docs/auth/github#authentication) +3. Use Vault to [generate temporary AWS credentials](https://developer.hashicorp.com/vault/api-docs/secret/aws#generate-credentials) +4. Store results in `~/.aws` and install crontab to re-authenticate + +The above steps can be customized via the following environment variables: +``` +# The hostname of the Vault instance to use +VAULT_HOST="https://vault.ops.k8s.rapids.ai" + +# List of GitHub organizations for which Vault can generate credentials. +# The scripts assumes the Vault instance exposes an authentication endpoint +# for each org at `$VAULT_HOST/v1/auth/github-$org/login`. +# https://developer.hashicorp.com/vault/docs/auth/github#authentication +VAULT_GITHUB_ORGS="nvidia nv-morpheus nv-legate rapids" -## Base images +# The TTL for the generated AWS credentials +VAULT_S3_TTL=43200 -Base images are composed in [matrix.yml](./matrix.yml) using [YAML anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). These get built on Github Actions ([release.yml](./.github/workflows/release.yml) and [test.yml](.github/workflows/test.yml)) \ No newline at end of file +# The URI to the Vault API that generates AWS credentials +# The full URL expands to `$VAULT_HOST/$VAULT_S3_URI?ttl=$VAULT_S3_TTL` +# https://developer.hashicorp.com/vault/api-docs/secret/aws#generate-credentials +VAULT_S3_URI="v1/aws/creds/devs" +``` \ No newline at end of file diff --git a/README.md b/README.md index c536e5db..8cc0d1bb 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,23 @@ # RAPIDS [devcontainers](https://containers.dev/) -This repository contains features and workflows for building development -containers to support local dev and CI for NVIDIA -[RAPIDS](https://github.com/rapidsai), [CCCL](https://github.com/nvidia/cccl), -and [Legate](https://github.com/nv-legate). +This repository contains centralized features and workflows for building +development containers ([devcontainers](https://containers.dev/)) to support +local dev and CI for projects in NVIDIA [RAPIDS](https://github.com/rapidsai), +[CCCL](https://github.com/nvidia/cccl), and +[Legate](https://github.com/nv-legate). + [Devcontainers](https://containers.dev/) are an open standard for specifying the -creation and execution of Docker containers for developing a codebase. It's like -using a docker image to develop, but there's some extra configuration and -installation that can be done. It also provides some alternative ways of -composing functionality and configuration that can augment Docker's -capabilities. +creation and execution of Docker containers for developing a codebase. + +Downstream repositories that utilize devcontainers use both the `feature` +scripts that install software, as well as docker images that serve to cache sets +of installed software. These images serve as base images for the devcontainers +specified in the downstream repositories. -In addition to scripts that set up the devcontainer environment for things like GitHub auth, this repo contains reusable scripts to install software in arbitrary containers, aiding in composition and code sharing. A "feature" in VSCode terms refers to these installation scripts. The script for each feature runs when creating the devcontainer. +## Usage -We've chosen to use a monorepo for the features here, but it is similar in spirit to the official [devcontainers/features](https://github.com/devcontainers/features) and [devcontainers/images](https://github.com/devcontainers/images) repositories. +### [Using devcontainers to provide a build environment on a project](./USAGE_IN_PROJECT.md) -## For details on using the RAPIDS devcontainers, see [`USAGE.md`](USAGE.md). +### [Setting up and maintaining devcontainer configuration in other projects](./USAGE.md) -## For details on contributing to this repository, see [`DEVELOP.md`](DEVELOP.md). -## See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). These tags are used as base images in devcontainers, and aren't really meant to be used directly. +### [Developing the centralized `feature` scripts and base images in this repository](DEVELOP.md). diff --git a/USAGE.md b/USAGE.md index 90579e92..ec937e61 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,131 +1,38 @@ -# Using the RAPIDS devcontainers - -- [Using the RAPIDS devcontainers](#using-the-rapids-devcontainers) - - [System requirements](#system-requirements) - - [Quick start](#quick-start) - - [Detailed start](#detailed-start) - - [Using devcontainers in VS Code](#using-devcontainers-in-vs-code) - - [Using devcontainers from the terminal](#using-devcontainers-from-the-terminal) - - [Generated build scripts](#generated-build-scripts) - - [rapids-build-utils](#rapids-build-utils) - - [Native build tools - CMake, python builds](#native-build-tools---cmake-python-builds) - - [Exiting the devcontainer](#exiting-the-devcontainer) - - [Adding projects: `manifest.yaml` file](#adding-projects-manifestyaml-file) - - [Using the pre-built images](#using-the-pre-built-images) - - [Using in `devcontainer.json`](#using-in-devcontainerjson) - - [Custom devcontainers](#custom-devcontainers) - - [Build caching with `sccache`](#build-caching-with-sccache) - - [Build caching with private S3 buckets](#build-caching-with-private-s3-buckets) - - [Using GitHub OAuth to issue S3 credentials via Hashicorp Vault](#using-github-oauth-to-issue-s3-credentials-via-hashicorp-vault) - -## System requirements - -Devcontainers can be used on Linux, Mac and Windows. They use Docker, so the -system requirements and limitations associated with Docker apply here also. On -Mac and Windows, where a Linux VM must run to support Docker, you may need to be -aware of memory limitations of that Linux VM. Otherwise, devcontainers do not add -system requirements beyond the needs of the individual projects we're building. - -## Quick start - -If you really want to get started right away and ignore all the details of how -devcontainers work, the easiest way is to treat the devcontainer -like a docker container that you use interactively. Brad Dice wrote [a script -that wraps the devcontainer -CLI](https://gist.github.com/bdice/a92d224b3e3b1b387fc18b8095b3bdbd) to do this. - -To obtain this script: -``` -curl -LO https://gist.githubusercontent.com/bdice/a92d224b3e3b1b387fc18b8095b3bdbd/raw/28eb8edc856ae04d4cd83571fea5b894f714f01c/rapids-dev -chmod +x rapids-dev -./rapids-dev -``` - -This script expects you to have your current directory set to the -root of a repo that has a .devcontainer folder. You may want to move -this script to a folder that you place on PATH, such as `~/bin` - -Running that command will build the devcontainer and drop you at -an interactive prompt. You can immediately build your project -with one of the devcontainers scripts. Type `build-` and hit `` to see your options. - -Skip ahead to [Available tools in the devcontainer](#available-tools-in-the-devcontainer) to see more options -for interaction at this prompt. - -## Detailed start - -So, you have cloned a repo that you've heard has a devcontainer. You can see the file(s) for yourself by looking -in your repo's `.devcontainer` folder. You may find a `devcontainer.json` file, or you may find some number of folders, such as `cuda12.0-conda` and `cuda12.0-pip`. If you find folders, these each contain a `devcontainer.json` -file. These files specify how to create and run a container that leaves you with a good setup to do development. - -There are at least 2 ways to consume these devcontainer.json files. VS Code was -the original home of devcontainers prior to becoming an open specification, and -it remains a good way to use them. If you prefer not to use VS Code, the -[devcontainers-cli](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) -application will build the devcontainer and allow you to interact with it. +# Adding and adapting devcontainers to a project -### Using devcontainers in VS Code +This document describes how to add devcontainers to a project that does not yet +have them, and how you can customize the devcontainer to fit your project's +needs. -[The VS Code -docs](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container) -are the definitive source of information for this topic. +For how to use devcontainers to provide development environments, see +[USAGE_IN_PROJECT.md](./USAGE_IN_PROJECT.md) -You can use devcontainers in VS Code either locally (docker running on your -local machine) or with VS Code's remote-ssh or remote-tunnel connections. To use -the devcontainers on a remote machine, connect normally using SSH or tunnel, and -then follow the VS Code docs for using the dev containers. There is no special -way to connect directly to a devcontainer on a remote host. You must go via -SSH/tunnel first. +For how to change the centralized installation and configuration scripts that +are shared among projects, see [DEVELOP.md](./DEVELOP.md). -Specifically for RAPIDS repos, we frequently have multiple folders for different -library configurations. Pay attention to which build environment you need when -launching your devcontainer. You can switch between them by reopening your -native host (e.g. CMD+SHIFT+P -> "Reopen folder in SSH"), and then re-opening in -devcontainer (CMD+SHIFT+P -> "Reopen in container"), at which point you'll see a -prompt to choose a different `devcontainer.json`. +## Adding devcontainers to a project -### Using devcontainers from the terminal +Adding devcontainers to a project means adding one or more devcontainer.json +files. You may see scripts in other repos to automate managing multiple +configurations, but fundamentally all you need is at least the one JSON file. +You can bootstrap yourself by copying the folders from +[rapids/devcontainers](./.devcontainer) -The [devcontainer-cli](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) project -allows you to run and interact with devcontainers from the terminal. It uses NodeJS, so you need -to install that in order to run it. +Maintaining a matrix of configurations may be easier by following patterns +established by CCCL, or by managing most of the [matrix in the +rapidsai/devcontainers +repo](./matrix.yml) +itself, and then simplifying your actual local devcontainer.json files to be +primarily using a particular base image produced by [the matrix in +rapidsai/devcontainers](./matrix.yml). -There are wrappers to facilitate working with this CLI. Refer back to the -[Quick-start section](#quick-start). If you need more flexibility, you can call -the devcontainer CLI directly. - -You need to specify the `devcontainer.json` file and workspace folder to use when starting the devcontainer. Also note that you must manage the 3 steps of the lifecycle yourself: - -* bring up the devcontainer -* run your command (or run bash for interactive prompt) -* stop and remove the docker container - -``` -CONTAINER_JSON=.devcontainer/cuda12.0-pip/devcontainer.json -devcontainer up --config ${CONTAINER_JSON} --workspace-folder=$(pwd) -devcontainer exec --config ${CONTAINER_JSON} --workspace-folder=$(pwd) bash -``` - -Stopping and removing the docker container is manual. The devcontainer CLI does -not currently facilitate this in any way. One possible workflow (copied from [aforementioned wrapper](https://gist.github.com/bdice/a92d224b3e3b1b387fc18b8095b3bdbd)): - -``` -CONTAINER_ID=$(docker ps --quiet \ - --filter label=devcontainer.local_folder=$(pwd) \ - --filter label=devcontainer.config_file=${CONTAINER_JSON}) -num_active_shells=$(docker exec "${container_id}" ps aux | grep -c "/bin/sh") -if [[ ${num_active_shells} -le 1 ]]; then - echo "All devcontainers are closed. Stopping and removing container ${container_id}." - docker stop "${container_id}" - docker rm "${container_id}" -fi -``` +## Devcontainers helper scripts ### Generated build scripts Several scripts are generated for you based on the contents of `manifest.yaml`. By default, `manifest.yaml` comes from [the RAPIDS/devcontainers -repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), +repo](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), but you can use your own local `manifest.yaml` file. Refer to the "Adding projects" section. @@ -147,32 +54,27 @@ which will clone `rmm` into your workspace and generate build scripts for it. ### rapids-build-utils -These are meta-build scripts. They assist with setting up the workspace and reloading things when important configuration -changes happen. You mostly won't need to worry about these, -but it's good to be aware of them. They come from the [rapidsai/devcontainers repo](https://github.com/rapidsai/devcontainers/tree/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/bin) - -### Native build tools - CMake, python builds - -The generated scripts mentioned above will take care of running -build tools for you. However, if you need to run the build tools -manually, you can `cd` into your source code folder, which is -mounted as a subfolder in `/home/coder`. - -### Exiting the devcontainer +These are meta-build scripts. They assist with setting up the workspace and +reloading things when important configuration changes happen. You mostly won't +need to worry about these, but it's good to be aware of them. They come from the +[rapidsai/devcontainers +repo](./features/src/rapids-build-utils/opt/rapids-build-utils/bin). These are +described in more detail in [DEVELOP.md](./DEVELOP.md#rapids-build-utils). -If you are in VS Code and you need to return to your host machine (local or SSH), -you can run `Dev Containers: Reopen in SSH`. +### Generating scripts for other projects: `manifest.yaml` file -## Adding projects: `manifest.yaml` file +The build script generation is controlled with a `manifest.yaml` file, which by +default comes from [the rapidsai/devcontainers +repo](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml) -The build script generation is controlled with a `manifest.yaml` file, which by default comes from [the rapidsai/devcontainers -repo](https://github.com/rapidsai/devcontainers/blob/branch-24.02/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml) +If you would like to add your project, you can submit a PR to the +rapidsai/devcontainers repo. Before you do that, though, you can test it +locally. Start by copying `manifest.yaml` from the rapidsai/devcontainers repo. +You can put it anywhere, but let's say we put it in .devcontainer/manifest.yaml. -If you would like to add your project, you can submit a PR to the rapidsai/devcontainers repo. Before you do that, though, you can -test it locally. Start by copying `manifest.yaml` from the rapidsai/devcontainers repo. You can put it anywhere, but let's say we put it in .devcontainer/manifest.yaml. - -Now open a devcontainer.json file that you want to work with. These -will likely live in a .devcontainer subfolder, such as cuda12.0-pip. In this file, add a top-level key with this: +Now open a devcontainer.json file that you want to work with. These will likely +live in a .devcontainer subfolder, such as cuda12.0-pip. In this file, add a +top-level key with this: ``` "containerEnv": { @@ -185,14 +87,16 @@ generated scripts. ## Using the pre-built images -The choice of using a pre-built image refers to the build/args/BASE entry in `devcontainer.json`. The pre-built -images are not meant to be used directly. The rapids-build-utils scripts are installed with a "feature," so -they won't be present if you directly run a pre-built image with Docker instead of with a devcontainer tool (VS Code or devcontainer-cli) - -We publish a [matrix](matrix.yml) of pre-built images to DockerHub to accelerate initializing local devcontainers, GitHub Codespaces, and CI jobs. These use the "feature" scripts to install their components, -so you can think of them as caching those steps. +The choice of using a pre-built image refers to the `build/args/BASE` or `image` +entry in `devcontainer.json`. The pre-built images are not meant to be used +directly. We publish a [matrix](matrix.yml) of pre-built images to DockerHub to +accelerate initializing local devcontainers, GitHub Codespaces, and CI jobs. +These use the "feature" scripts to install their components, so you can think of +them as caching those steps. -The features that comprise the image are noted in the image tags. If no version is defined for a tool or SDK, the image includes the latest available version at image build time. +The features that comprise the image are noted in the image tags. If no version +is defined for a tool or SDK, the image includes the latest available version at +image build time. > **NOTE:** `git`, `git-lfs`, `github-cli`, `gitlab-cli`, `cmake`, `ninja`, `sccache`, and our devcontainer-utils [are included](image/.devcontainer/devcontainer.json#L12-L33) in each pre-built image. @@ -210,51 +114,14 @@ You can also build a custom devcontainer by composing individual features:
devcontainer.json using individual features
{
"image": "ubuntu:22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.02": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
-You can add libraries or programs on top of a pre-built image using this -same mechanism. These are not baked into the image, but cached as a docker -layer. - -> **NOTE:** Feature updates published since your most recent image build will invalidate your docker image layer cache, meaning it can take the [devcontainers CLI](https://github.com/devcontainers/cli) longer to initialize containers composed from individual features. - -## Build caching with `sccache` +Similarly, any base conatiner can be extended by adding additional features: -The devcontainers configure CMake to use [sccache](https://github.com/mozilla/sccache) as C, C++, CUDA, and Rust compiler launchers. Refer to the [sccache docs](https://github.com/mozilla/sccache/tree/main/docs) for configuring the various storage back-ends. +
devcontainer.json extending base image with additional features
{
"rapidsai/devcontainers:24.02-cpp-llvm16-cuda12.0-nvhpc23.5-ubuntu22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.02": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
-### Build caching with private S3 buckets +This example is contrived, because base images already all include common build tools such as CMake, ninja and sccache. -You can use a private S3 bucket as the `sccache` storage back-end. -If you're using a [GitHub action](https://github.com/aws-actions/configure-aws-credentials) to assume AWS roles in CI, or are comfortable distributing and managing S3 credentials, you can define the `SCCACHE_BUCKET`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY` variables in the container environment. - -### Using GitHub OAuth to issue S3 credentials via Hashicorp Vault - -The [`devcontainer-utils`](features/src/utils/) feature includes a `devcontainer-utils-vault-s3-init` script that uses GitHub OAuth and Hashicorp Vault to issue temporary S3 credentials to authorized users. - -> **NOTE:** This script runs in the devcontainer's [`postAttachCommand`](https://containers.dev/implementors/json_reference/#lifecycle-scripts), but it does nothing unless `SCCACHE_BUCKET` and `VAULT_HOST` are in the container environment. - -The `devcontainer-utils-vault-s3-init` script performs the following actions, exiting early if any step is unsuccessful: - -1. Log in via the [GitHub CLI](https://cli.github.com/) -2. Authenticate via [Vault's GitHub auth method](https://developer.hashicorp.com/vault/docs/auth/github#authentication) -3. Use Vault to [generate temporary AWS credentials](https://developer.hashicorp.com/vault/api-docs/secret/aws#generate-credentials) -4. Store results in `~/.aws` and install crontab to re-authenticate - -The above steps can be customized via the following environment variables: -``` -# The hostname of the Vault instance to use -VAULT_HOST="https://vault.ops.k8s.rapids.ai" - -# List of GitHub organizations for which Vault can generate credentials. -# The scripts assumes the Vault instance exposes an authentication endpoint -# for each org at `$VAULT_HOST/v1/auth/github-$org/login`. -# https://developer.hashicorp.com/vault/docs/auth/github#authentication -VAULT_GITHUB_ORGS="nvidia nv-morpheus nv-legate rapids" - -# The TTL for the generated AWS credentials -VAULT_S3_TTL=43200 - -# The URI to the Vault API that generates AWS credentials -# The full URL expands to `$VAULT_HOST/$VAULT_S3_URI?ttl=$VAULT_S3_TTL` -# https://developer.hashicorp.com/vault/api-docs/secret/aws#generate-credentials -VAULT_S3_URI="v1/aws/creds/devs" -``` +> **NOTE:** Feature updates published since your most recent image build will +invalidate your docker image layer cache, meaning it can take the [devcontainers +CLI](https://github.com/devcontainers/cli) longer to initialize containers +composed from individual features. diff --git a/USAGE_IN_PROJECT.md b/USAGE_IN_PROJECT.md new file mode 100644 index 00000000..3f6821b4 --- /dev/null +++ b/USAGE_IN_PROJECT.md @@ -0,0 +1,172 @@ +# Using devcontainers in projects to provide development environments + +This document describes usage of devcontainers as development environments. It +is intended as a general overview that any project employing devcontainers can +link to and avoid duplicating. + +For how to add devcontainers to a project, or how to change existing devcontainer +configuration, see [USAGE.md](./USAGE.md). + +For how to change the centralized installation and configuration scripts that +are shared among projects, see [DEVELOP.md](./DEVELOP.md). + +## System requirements + +Devcontainers can be used on Linux, Mac and Windows. They use Docker, so the +system requirements and limitations associated with Docker apply here also. On +Mac and Windows, where a Linux VM must run to support Docker, you may need to be +aware of memory limitations of that Linux VM. Otherwise, devcontainers do not add +system requirements beyond the needs of the individual projects we're building, but +they also don't emulate hardware. If your project needs an NVIDIA GPU, then you +need to run your devcontainer on a machine with an NVIDIA GPU. + +Devcontainers require Docker. To set that up: +* [Linux - docker engine](https://docs.docker.com/engine/install/) +* [Mac - docker desktop](https://docs.docker.com/desktop/install/mac-install/) +* [Windows](https://docs.docker.com/desktop/install/windows-install/) + +Docker Desktop has licensing requirements. NVIDIA employees may [request a +license](https://confluence.nvidia.com/pages/viewpage.action?spaceKey=SWDOCS&title=Requesting+a+Docker+Desktop+License). + +## Quickstart + +At this point, you have cloned a repo that you've heard has a devcontainer. You +can see the file(s) for yourself by looking in your repo's `.devcontainer` +folder. You may find a `devcontainer.json` file, or you may find some number of +folders, such as `cuda12.0-conda` and `cuda12.0-pip`. If you find folders, these +each contain a `devcontainer.json` file. These files specify how to create and +run a container that leaves you with a good setup to do development. + +### VS Code (Recommended) + +Working with devcontainers in VS Code requires an extension: [Remote - +Containers +extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). +When VS Code detects devcontainer.json files, it should prompt you to install +this extension with a pop-up in the lower-right of your VS Code window. If it +doesn't, you'll need to manually install the extension another way. + +**Steps** + +1. Open the cloned directory in VSCode + +1. Launch a Dev Container by clicking the pop-up prompt in the lower right of +the VS Code window that suggests to "Reopen in Container" + + ![Shows "Reopen in Container" prompt when opening the cccl directory in VScode.](./docs-img/reopen_in_container.png) + + - If the pop-up prompt doesn't come up, use the Command Palette to start a Dev Container. Press `[Ctrl|CMD]+Shift+P` to open the Command Palette. Type "Remote-Containers: Reopen in Container" and select it. + + ![Shows "Reopen in Container" in command pallete.](./docs-img/open_in_container_manual.png) + +1. Select an environment with the desired build tools from the list: + + ![Shows list of available container environments.](./docs-img/container_list.png) + + The available tools depend on your project. These can be configured when + generating the matrix of base images. See [the docs on adapting devcontainers](./USAGE.md#custom-devcontainers) + for more info. + +1. VSCode will initialize the selected Dev Container. This can take a few +minutes the first time, as it downloads the base docker image and runs any +specified feature installations. These steps are cached, so subsequent runs are +faster. + +1. Once initialized, the local project directory is mounted into the container +to ensure any changes are persistent. + +1. You project should now look like any other VS Code project, except that the +blue box in the lower left of the VS Code window should now read `Dev Container +@ `. You're done! Any terminal you open will have the build +environment activated appropriately. + +1. Check the contributing guide in your repo for further instructions. The +devcontainers adds build scripts that fit general usage. Type `build-` and hit +`TAB` to see options for your project. + +**Exiting the devcontainer** + +If you are in VS Code and you need to return to your host machine (local or SSH), +you can run `Dev Containers: Reopen in SSH`. + +### Docker (Manual Approach) + +Your project may have its own launch scripts that account for options in +libraries and/or tools. The steps here should work with any repo that uses +devcontainers, but the repo-specific scripts will probably work better. + +**Prerequisites** + +- [Devcontainer CLI ](https://github.com/devcontainers/cli) - needs NodeJS/npm + +**Steps** + +1. Download the [launch-devcontainer.sh script](./launch-devcontainer.sh) and + put it somewhere on PATH. If your project has its own launch script, use it + here instead. + +1. Set your current working directory to the root of your repo containing the +.devcontainer folder + +1. Run the launch-container.sh script. Called without arguments, you'll get a menu of containers to choose from: + +``` +$ ./launch-devcontainer.sh +Using devcontainers in /workspaces/devcontainers. +Select a container (or provide it as a positional argument): +1) cuda11.8-conda +2) cuda11.8-pip +3) cuda12.0-conda +4) cuda12.0-pip +5) main +#? +``` + +You can also provide devcontainer label (folder name) directly: + +``` +./launch-devcontainer.sh cuda12.0-conda +``` + +1. The devcontainer will be built, and you'll be dropped at a shell prompt +inside the container. You're done! + +1. Check the contributing guide in your repo for further instructions. The +devcontainers adds build scripts that fit general usage. Type `build-` and hit +`TAB` to see options for your project. + + +## (Optional) Native build tools - CMake, python builds + +The generated scripts mentioned above will take care of running +build tools for you. However, if you need to run the build tools +manually, you can `cd` into your source code folder, which is +mounted as a subfolder in `/home/coder`. + +## (Optional) Working with upstream projects + +Build scripts are generated only for the main project - the one you have +mounted. If you would like to work with other projects, you can run their +`clone-*` scripts. After they have been cloned, appropriate `build-*` scripts +will be generated. See [the project maintainer docs on this +topic](./USAGE.md#generating-scripts-for-other-projects-manifestyaml-file). + +## (Optional) Authenticate with GitHub for `sccache` + +After starting the container with any method, there will be a prompt to +authenticate with GitHub. This grants access to a +[`sccache`](https://github.com/mozilla/sccache) server shared with CI and +greatly accelerates local build times. This is currently limited to NVIDIA +employees belonging to the `NVIDIA` or `rapidsai` GitHub organizations. Assuming +the GitHub authentication here worked, this should work "out of the box" and +should not require any additional AWS credentials for any individual. + +Without authentication to the remote server, `sccache` will still accelerate local builds by using a filesystem cache. + +Follow the instructions in the prompt as below and enter the one-time code at https://github.com/login/device + + ![Shows authentication with GitHub to access sccache bucket.](./docs-img/github_auth.png) + +To manually trigger this authentication, execute the `devcontainer-utils-vault-s3-init` script within the container. + +For more information about the sccache configuration and authentication, see the documentation at [`rapidsai/devcontainers`](https://github.com/rapidsai/devcontainers/blob/branch-23.10/USAGE.md#build-caching-with-sccache). diff --git a/docs-img/container_list.png b/docs-img/container_list.png new file mode 100644 index 0000000000000000000000000000000000000000..09c4510f34de9b8ed44ca5c33c4b714ea07620b7 GIT binary patch literal 159943 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 EZ`ExK#Q*>R literal 0 HcmV?d00001 diff --git a/docs-img/github_auth.png b/docs-img/github_auth.png new file mode 100644 index 0000000000000000000000000000000000000000..3f52b3a2335790996bc98cb002a05fb9b36bf1dc GIT binary patch literal 54609 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 literal 0 HcmV?d00001 diff --git a/docs-img/open_in_container_manual.png b/docs-img/open_in_container_manual.png new file mode 100644 index 0000000000000000000000000000000000000000..e09435b83ced66073a9fa13e08108764dbf9a40d GIT binary patch literal 58565 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 k1k;)0F(G+4xaYIr??uGt;P(pT<`TTT zH0GD)hl48*dvm7?5B~q8FD5Sy2j@x#2loRC2X_nJ`mqfM=fD65xBCqajw>Dx?%ns~ z2D#7R0D_*Rs1V%a)7S6j+$iu4n!c`#BODy+)4?xraLC{+@Oq3nZ_nZ2ELg>b_!XV! z4i+7pF~#xWj%Tw>6`WLd4@KbT1W@8uzt_PaJ?TA=o@ag?≺Xd~M>uGMmV2Y}7Ez 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 literal 0 HcmV?d00001 diff --git a/launch-devcontainer.sh b/launch-devcontainer.sh new file mode 100755 index 00000000..72b65e27 --- /dev/null +++ b/launch-devcontainer.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# +# Launch devcontainers in a command line interface. +# +# This script can be run from inside of a git repo that defines devcontainers. +# The user is prompted to select one of the devcontainers, then the +# devcontainer is launched. The user can also provide a devcontainer name like +# "cuda12.0-conda" as an argument to this script. If invoked multiple times +# with the same devcontainer configuration, the CLI instances will reuse the +# same running container. After the last shell utilizing that devcontainer is +# closed, the container is torn down. +# +# This script requires the devcontainer CLI. + +set -euo pipefail + +create_menu() { + select option; do + if [ 1 -le "$REPLY" ] && [ "$REPLY" -le "$#" ]; then + echo "${option}" + break; + else + echo "Invalid choice: Select a number 1-$#" >&2 + fi + done +} + +choose_container() { + echo "Select a container (or provide it as a positional argument):" >&2 + containers=() + while IFS= read -r -d '' dir; do + containers+=("$(basename $dir)") + done < <(find ${devcontainers_root}/.devcontainer -mindepth 1 -maxdepth 1 -type d -print0 | sort -z --version-sort) + create_menu "${containers[@]}" +} + +find_container() { + docker ps --quiet \ + --filter label=devcontainer.local_folder=${devcontainers_root} \ + --filter label=devcontainer.config_file=${devcontainer_config} +} + +container_up() { + devcontainer up --config ${devcontainer_config} --workspace-folder ${devcontainers_root} +} + +container_exec() { + devcontainer exec --config ${devcontainer_config} --workspace-folder ${devcontainers_root} bash +} + +container_teardown() { + # If this is the last active shell, stop and remove the container + container_id="$(find_container)" + num_active_shells=$(docker exec "${container_id}" ps aux | grep -c "/bin/sh") + if [[ ${num_active_shells} -le 1 ]]; then + echo "All devcontainers are closed. Stopping and removing container ${container_id}." + docker stop "${container_id}" + docker rm "${container_id}" + fi +} + +main() { + if ! command -v devcontainer &> /dev/null; then + echo "devcontainer CLI must be installed." + echo "Try running 'npm install -g @devcontainers/cli'." + exit 1 + fi + + devcontainers_root=$(git rev-parse --show-toplevel 2>/dev/null || realpath devcontainers) + if [ -d ${devcontainers_root} ]; then + echo "Using devcontainers in ${devcontainers_root}." + else + echo "Devcontainers could not be found." + exit 1 + fi + container_name=${1:-$(choose_container)} + devcontainer_config="${devcontainers_root}/.devcontainer/${container_name}/devcontainer.json" + + if [ -z "$(find_container)" ]; then + container_up + fi + container_exec + container_teardown +} + +main \ No newline at end of file From 3048772a5b01bd1dd58f78dfcce17370a43c1a39 Mon Sep 17 00:00:00 2001 From: Mike Sarahan Date: Thu, 18 Jan 2024 09:27:17 -0600 Subject: [PATCH 08/19] Apply suggestions from code review Thanks for the clarifications, @harrism! Co-authored-by: Mark Harris <783069+harrism@users.noreply.github.com> --- DEVELOP.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DEVELOP.md b/DEVELOP.md index a0813080..b85c996c 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -50,22 +50,22 @@ A few of the features install custom tools for the devcontainer ecosystem here, rather than just installation scripts of external tools and libraries. A brief overview of responsibilities for these features follows. -#### Rapids-build-utils +#### `rapids-build-utils` -Most of the scripts here serve to prepare the devcontainer prior to use, but you may use them to update +Most of the `rapids-build-utils` scripts serve to prepare the devcontainer prior to use, but you may use them to update the devcontainer after adding to your container's /opt/rapids-build-utils/manifest.yml file to add new projects. If you are wondering where a command or behavior in a devcontainer is coming from, this is a good place to start. -These scripts are installed by +`rapids-build-utils` scripts are installed by [`install.sh`](./features/src/rapids-build-utils/install.sh), which creates aliases for the .sh scripts. if you see `rapids-*` for a script or command name in the devcontainer, look in [`install.sh`](./features/src/rapids-build-utils/install.sh) to see how it is mapped back to one of these scripts. -* [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If you project is not in manifest.yaml, you will not get build scripts generated in your devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) +* [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If your project is not in manifest.yaml, it will not get build scripts generated in the devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) * [generate-scripts.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/generate-scripts.sh): generate `build-*`, `clone-*`, etc. scripts * [make-pip-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-pip-env.sh) and [make-conda-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-conda-env.sh): creating pip and conda python virtual environments From 8383e68e169f6d06581df80befa0a5bbbec8f8cc Mon Sep 17 00:00:00 2001 From: Mike Sarahan Date: Thu, 18 Jan 2024 11:19:38 -0600 Subject: [PATCH 09/19] Update DEVELOP.md Co-authored-by: Mark Harris <783069+harrism@users.noreply.github.com> --- DEVELOP.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DEVELOP.md b/DEVELOP.md index b85c996c..1637843e 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -13,10 +13,10 @@ and change .devcontainer.json to suit your project, see [USAGE.md](USAGE.md) The code in this repository fits into a few main categories: 1. Features -1. GitHub Actions automations -1. Scripts -1. matrix.yml -1. Dockerfiles +2. GitHub Actions automations +3. Scripts +4. matrix.yml +5. Dockerfiles ## Features From aaaf1ec60657dc4f3cc58019c8c94bd3742014f1 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Thu, 18 Jan 2024 10:36:47 -0800 Subject: [PATCH 10/19] make language less ambiguous --- DEVELOP.md | 87 ++++++++++----- USAGE.md | 105 ++++++++++-------- USAGE_IN_PROJECT.md | 47 ++++---- .../launch-devcontainer.sh | 0 4 files changed, 144 insertions(+), 95 deletions(-) rename launch-devcontainer.sh => scripts/launch-devcontainer.sh (100%) diff --git a/DEVELOP.md b/DEVELOP.md index 1637843e..4fbc64c5 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -12,19 +12,28 @@ For the project maintainer-level overview providing instructions on how to add and change .devcontainer.json to suit your project, see [USAGE.md](USAGE.md) The code in this repository fits into a few main categories: +<<<<<<< HEAD 1. Features 2. GitHub Actions automations 3. Scripts 4. matrix.yml 5. Dockerfiles +======= +* Features +* GitHub Actions automations +* Scripts +* matrix.yml +* Dockerfiles +>>>>>>> 884030c (make language less ambiguous) ## Features From the official devcontainer [documentation on Features](https://containers.dev/implementors/features/): -> Development container "Features" are self-contained, shareable units of installation code and development container configuration. Each "feature" specified becomes a `RUN` statement in a temporary Dockerfile, -and as such each "feature" results in an image layer. +> Development container "Features" are self-contained, shareable units of installation code and development container configuration. -This repository defines `features` to install the following dev tools, compilers, and SDKs: +Each "feature" specified becomes a `RUN` statement in a temporary Dockerfile, +and as such each "feature" results in an image layer. This repository defines +`features` to install the following dev tools, compilers, and SDKs: * [CMake](features/src/cmake/) * [CUDA Toolkit](features/src/cuda/) @@ -41,17 +50,18 @@ This repository defines `features` to install the following dev tools, compilers * [devcontainer-utils](features/src/utils/) * [rapids-build-utils](features/src/rapids-build-utils/) -These scripts assume that apt utilities are available, and thus generally only +These feature scripts assume that apt utilities are available, and thus generally only run on debian-based images. ### Utility features -A few of the features install custom tools for the devcontainer ecosystem here, +A few of the features install custom tools for the devcontainer environment, rather than just installation scripts of external tools and libraries. A brief overview of responsibilities for these features follows. #### `rapids-build-utils` +<<<<<<< HEAD Most of the `rapids-build-utils` scripts serve to prepare the devcontainer prior to use, but you may use them to update the devcontainer after adding to your container's /opt/rapids-build-utils/manifest.yml file to add new projects. @@ -66,10 +76,35 @@ in the devcontainer, look in mapped back to one of these scripts. * [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If your project is not in manifest.yaml, it will not get build scripts generated in the devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) +======= +Most of the scripts in [`rapids-build-utils`](./features/src/rapids-build-utils) +serve to prepare the devcontainer prior to use, but you may use them to update +the devcontainer after adding to your container's +/opt/rapids-build-utils/manifest.yml file to add new projects. See [USAGE.md](./USAGE.md#generating-scripts-for-other-projects-manifestyaml-file) +for more information on customizing manifest.yml + +`rapids-build-utils` is a good place to start when investigating an unknown +command or behavior in a devcontainer. The scripts from this project are +installed by [`install.sh`](./features/src/rapids-build-utils/install.sh), which +creates aliases for the .sh scripts. if you see `rapids-*` for a script or +command name in the devcontainer, look in +[`install.sh`](./features/src/rapids-build-utils/install.sh) to see how it is +mapped back to one of these scripts. + +Some scripts in downstream projects, especially those called in `./ci/` folders, +call scripts from the +[gha-tools](https://github.com/rapidsai/gha-tools/tree/main/tools) repository, +which also start with a `rapids-` prefix. These scripts are not currently +compatible with devcontainer images. If you need to run these scripts, check the +images at [rapidsai/ci-imgs](https://github.com/rapidsai/ci-imgs) instead of the +devcontainers. + +* [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If a project is not in manifest.yaml, it will not get build scripts generated in the devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) +>>>>>>> 884030c (make language less ambiguous) * [generate-scripts.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/generate-scripts.sh): generate `build-*`, `clone-*`, etc. scripts * [make-pip-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-pip-env.sh) and [make-conda-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-conda-env.sh): creating pip and conda python virtual environments -* [pull-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/pull-repositories.sh) and [push-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/push-repositories.sh) help you manage git operations on multiple repos that you may have cloned +* [pull-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/pull-repositories.sh) and [push-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/push-repositories.sh) helps manage git operations on multiple repos that have been cloned * [update-content-command.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/update-content-command.sh): calls `rapids-generate-script` and `rapids-make-vscode-workspace`. Called by VS Code in the [`postAttachCommand`](https://containers.dev/implementors/json_reference/#lifecycle-scripts), which is a reliable hook when the project is reopened or its configuration is changed. There are more scripts here, dealing with CMake variable parsing and @@ -79,8 +114,7 @@ pass-through, python package dependency installation, and more. These scripts handle mostly git-related configuration, setting up SSH deploy keys, GitHub authorization, and the vault setup for S3. The commands here are -prefixed with `devcontainer-` during installation, so if you see that prefix, -look in here. +prefixed with `devcontainer-` during installation. ## Github Actions automations @@ -96,42 +130,39 @@ flowchart TD script{{script}} end subgraph Image build Github Actions flowchart - release.yml --> release-features.yml[Publish features] - release-features.yml --> image-matrix(Determine image matrix) - image-matrix --> write-matrix{{Call feature-matrix/action.sh}} + release.yml[release.yml workflow dispatch] --> release-features.yml["Publish features (release-features.yml)"] + release-features.yml --> image-matrix("Determine image matrix (image-matrix/action.yml)") + image-matrix --> write-matrix{{Write matrix by calling image-matrix/action.sh}} write-matrix --> build-test-and-push-linux-image.yml write-matrix --> build-test-and-push-windows-image.yml - build-test-and-push-linux-image.yml --> write-json(Write .devcontainer.json) - write-json --> write-script{{Call devcontainer-json/action.sh}} - build-test-and-push-windows-image.yml --> build-windows(Build windows image) - write-script --> build-linux-image(Build linux limage) + build-test-and-push-linux-image.yml --> write-json("Write .devcontainer.json (devcontainer-json/action.yml)") + write-json --> write-script{{Write devcontainer.json by calling devcontainer-json/action.sh}} + build-test-and-push-windows-image.yml --> build-windows("Build windows image (build-windows-image/action.yml)") + write-script --> build-linux-image("Build linux limage (build-linux-image/action.yml)") end ``` These are divided into 3 categories: * Workflows are `.yml` files in `.github/workflows` * Actions are folders in `.github/actions`. One folder per action. Actions must have a `action.yml` file, but may also have accompanying shell scripts. -* Scripts are the shell scripts that are in some of the actions. They are broken out in this diagram to help show where the functionality actually lives. +* Scripts are the shell scripts that are in some of the actions folders. They are broken out in this diagram to help show where the functionality actually lives. ## Base images (matrix.yml) Base images are composed from individual features in [matrix.yml](./matrix.yml) -using [YAML -anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). -These get built on Github Actions as described -[above](#github-actions-automations) The devcontainers repo does not contain -scripts to facilitate building one particular image. Some downstream repos, such -as CCCL, have such scripts for their reduced subspace of the matrix. CCCL's -example is their -[make_devcontainers.sh](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/make_devcontainers.sh) +using [YAML anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). +These get built on Github Actions as described [above](#github-actions-automations) +The devcontainers repo does not contain scripts to facilitate building one particular +image. Some downstream repos, such as CCCL, have such scripts for their reduced subspace +of the matrix. CCCL's example is their [make_devcontainers.sh](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/make_devcontainers.sh) script. ## Dockerfiles Dockerfiles do not play much role in this scheme. They serve to [set a few global -variables and extend from the base image](./.devcontainer/rapids.Dockerfile). If you think you need to modify a -Dockerfile, make sure that your goal wouldn't be better achieved by adding or -changing a feature script instead. +variables and extend from the base image](./.devcontainer/rapids.Dockerfile). +Dockerfile changes are usually better achieved by adding or changing a feature +script instead. ## Build caching with `sccache` @@ -143,7 +174,7 @@ various storage back-ends. ### Build caching with private S3 buckets -You can use a private S3 bucket as the `sccache` storage back-end. +A private S3 bucket can be used as the `sccache` storage back-end. If you're using a [GitHub action](https://github.com/aws-actions/configure-aws-credentials) to assume AWS roles in CI, or are comfortable distributing and managing S3 credentials, you can define the `SCCACHE_BUCKET`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY` variables in the container environment. diff --git a/USAGE.md b/USAGE.md index ec937e61..05a8caac 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,7 +1,7 @@ # Adding and adapting devcontainers to a project This document describes how to add devcontainers to a project that does not yet -have them, and how you can customize the devcontainer to fit your project's +have them and how to customize the devcontainer to fit a project's needs. For how to use devcontainers to provide development environments, see @@ -12,29 +12,21 @@ are shared among projects, see [DEVELOP.md](./DEVELOP.md). ## Adding devcontainers to a project -Adding devcontainers to a project means adding one or more devcontainer.json -files. You may see scripts in other repos to automate managing multiple -configurations, but fundamentally all you need is at least the one JSON file. -You can bootstrap yourself by copying the folders from -[rapids/devcontainers](./.devcontainer) - -Maintaining a matrix of configurations may be easier by following patterns -established by CCCL, or by managing most of the [matrix in the -rapidsai/devcontainers -repo](./matrix.yml) -itself, and then simplifying your actual local devcontainer.json files to be -primarily using a particular base image produced by [the matrix in -rapidsai/devcontainers](./matrix.yml). +Adding devcontainers to a project means adding one or more `devcontainer.json` +files. One devcontainer is equivalent to one `devcontainer.json` file. Projects +such as [CCCL](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/README.md) +have additional scripts that manage many configurations. New projects needing +only cuda and python can bootstrap themselves by copying the `cuda-*` folders +from [rapids/devcontainers](./.devcontainer). ## Devcontainers helper scripts ### Generated build scripts -Several scripts are generated for you based on the contents of `manifest.yaml`. By +Several scripts are generated based on the contents of `manifest.yaml`. By default, `manifest.yaml` comes from [the RAPIDS/devcontainers repo](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), -but you can use your own local `manifest.yaml` file. Refer to the "Adding -projects" section. +but [a local `manifest.yaml` file can be used instead](#generating-scripts-for-other-projects-manifestyaml-file). The generated scripts are: * `/usr/bin/build-*` @@ -47,43 +39,66 @@ build. For example, a project with a python component in `manifest.yaml` will have `build-cudf-python`. These scripts may trigger side-effects. For example, `build-*` scripts are only -generated for projects that exist in the workspace. If you are working on `cudf`, +generated for projects that exist in the workspace. When working on `cudf`, which depends on `rmm`, the default workspace only mounts `cudf` and generates -`build-cudf` scripts. If you want `rmm` build scripts also, you can run `clone-rmm`, -which will clone `rmm` into your workspace and generate build scripts for it. +`build-cudf` scripts. To obtain `rmm` build scripts also, run `clone-rmm`, +which will clone `rmm` into the workspace and generate build scripts for it. ### rapids-build-utils -These are meta-build scripts. They assist with setting up the workspace and -reloading things when important configuration changes happen. You mostly won't -need to worry about these, but it's good to be aware of them. They come from the -[rapidsai/devcontainers -repo](./features/src/rapids-build-utils/opt/rapids-build-utils/bin). These are -described in more detail in [DEVELOP.md](./DEVELOP.md#rapids-build-utils). +[`rapids-build-utils`](./features/src/rapids-build-utils/opt/rapids-build-utils/bin) +scripts are meta-build scripts. They assist with setting up the workspace and +reloading things when important configuration changes happen. +`rapids-build-utils` scripts are most often called indirectly by devcontainer +lifecycle hooks, but are also useful for forcing updates in the workspace. +`rapids-build-utils` scripts are described in more detail in +[DEVELOP.md](./DEVELOP.md#rapids-build-utils). ### Generating scripts for other projects: `manifest.yaml` file -The build script generation is controlled with a `manifest.yaml` file, which by -default comes from [the rapidsai/devcontainers -repo](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml) +Build script generation is controlled with a `manifest.yaml` file. This file +comes from [the rapidsai/devcontainers +repo](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml), +but can be [overridden with a local manifest.yaml file](#local-changes). New +projects and changes to dependencies can be submitted in a PR to the +[rapidsai/devcontainers](https://github.com/rapidsai/devcontainers) repo. + +> **NOTE** manifest.yaml's content is pinned in +`.devcontainer/*/devcontainer.json` indirectly via the pin on rapids-build-utils. +For changes in manifest.yaml to be reflected in the devcontainer, the manifest.yaml +changes need to be present in a release of `rapidsai/devcontainers`, and the pin +on `rapids-build-utils` must be updated in the project's devcontainer.json file(s). + +``` + "features": { + "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:24.2": {} + }, +``` + +In this `devcontainer.json` excerpt, the `24.2` value is the pin that would need +to be updated. + +#### Local changes -If you would like to add your project, you can submit a PR to the -rapidsai/devcontainers repo. Before you do that, though, you can test it -locally. Start by copying `manifest.yaml` from the rapidsai/devcontainers repo. -You can put it anywhere, but let's say we put it in .devcontainer/manifest.yaml. +To work around the delay in getting a change merged into the devcontainers repo +and have a new tag in place, a local manifest.yaml file can be used. Start by +copying `manifest.yaml` from the rapidsai/devcontainers repo. This file can +live anywhere, but this example has it in `.devcontainer/manifest.yaml`. -Now open a devcontainer.json file that you want to work with. These will likely -live in a .devcontainer subfolder, such as cuda12.0-pip. In this file, add a -top-level key with this: +In the desired devcontainer.json file, add a top-level key with this: ``` "containerEnv": { - "PROJECT_MANIFEST_YML": "${localWorkspaceFolder}/.devcontainer/manifest.yaml" + "PROJECT_MANIFEST_YML": "/home/coder/${localWorkspaceFolderBasename}/.devcontainer/manifest.yaml" }, ``` -Rebuild or re-open your devcontainer, and you should now see updated -generated scripts. +Rebuild or re-open the devcontainer, and the scripts (`build-*`, `clone-*`, +etc.) will be regenerated using the local `.devcontainer/manifest.yaml` instead +of the manifest.yaml that comes from the devcontainer.json-pinned +`rapids-build-utils` version. The `rapids-generate-scripts` command from +[rapids-build-utils](./features/src/rapids-build-utils/opt/rapids-build-utils/bin) +will also force a refresh of these scripts without rebuilding the devcontainer. ## Using the pre-built images @@ -91,14 +106,14 @@ The choice of using a pre-built image refers to the `build/args/BASE` or `image` entry in `devcontainer.json`. The pre-built images are not meant to be used directly. We publish a [matrix](matrix.yml) of pre-built images to DockerHub to accelerate initializing local devcontainers, GitHub Codespaces, and CI jobs. -These use the "feature" scripts to install their components, so you can think of -them as caching those steps. +These use the "feature" scripts to install their components, so these base +containers effectively cache running their feature scripts. The features that comprise the image are noted in the image tags. If no version is defined for a tool or SDK, the image includes the latest available version at image build time. -> **NOTE:** `git`, `git-lfs`, `github-cli`, `gitlab-cli`, `cmake`, `ninja`, `sccache`, and our devcontainer-utils [are included](image/.devcontainer/devcontainer.json#L12-L33) in each pre-built image. +> **NOTE:** `git`, `git-lfs`, `github-cli`, `gitlab-cli`, `cmake`, `ninja`, `sccache`, and [devcontainer-utils](./features/src/utils) [are included](image/.devcontainer/devcontainer.json#L12-L33) in each pre-built image. See the list of `rapidsai/devcontainers` tags [on DockerHub](https://hub.docker.com/r/rapidsai/devcontainers/tags). @@ -110,7 +125,7 @@ The pre-built images can be used as the `"image"`, or as the base of a Dockerfil ### Custom devcontainers -You can also build a custom devcontainer by composing individual features: +Custom devcontainers can be specified by composing individual features:
devcontainer.json using individual features
{
"image": "ubuntu:22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.02": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
@@ -121,7 +136,7 @@ Similarly, any base conatiner can be extended by adding additional features: This example is contrived, because base images already all include common build tools such as CMake, ninja and sccache. -> **NOTE:** Feature updates published since your most recent image build will -invalidate your docker image layer cache, meaning it can take the [devcontainers +> **NOTE:** Feature updates published since the most recent image build will +invalidate the docker image layer cache, meaning it can take the [devcontainers CLI](https://github.com/devcontainers/cli) longer to initialize containers composed from individual features. diff --git a/USAGE_IN_PROJECT.md b/USAGE_IN_PROJECT.md index 3f6821b4..4370dbd8 100644 --- a/USAGE_IN_PROJECT.md +++ b/USAGE_IN_PROJECT.md @@ -14,11 +14,13 @@ are shared among projects, see [DEVELOP.md](./DEVELOP.md). Devcontainers can be used on Linux, Mac and Windows. They use Docker, so the system requirements and limitations associated with Docker apply here also. On -Mac and Windows, where a Linux VM must run to support Docker, you may need to be -aware of memory limitations of that Linux VM. Otherwise, devcontainers do not add -system requirements beyond the needs of the individual projects we're building, but -they also don't emulate hardware. If your project needs an NVIDIA GPU, then you -need to run your devcontainer on a machine with an NVIDIA GPU. +Mac and Windows, where a Linux VM must run to support Docker, memory limitations +of that Linux VM may present problems. Otherwise, devcontainers do not add +system requirements beyond the needs of the individual projects being built. +Devcontainers also don't emulate hardware. If a project needs an NVIDIA GPU to +run, then the devcontainer needs to run on a machine with an NVIDIA GPU. +Building is different from running, though, and devcontainers can often be used +to build software that may need a GPU to run. Devcontainers require Docker. To set that up: * [Linux - docker engine](https://docs.docker.com/engine/install/) @@ -31,11 +33,12 @@ license](https://confluence.nvidia.com/pages/viewpage.action?spaceKey=SWDOCS&tit ## Quickstart At this point, you have cloned a repo that you've heard has a devcontainer. You -can see the file(s) for yourself by looking in your repo's `.devcontainer` -folder. You may find a `devcontainer.json` file, or you may find some number of -folders, such as `cuda12.0-conda` and `cuda12.0-pip`. If you find folders, these -each contain a `devcontainer.json` file. These files specify how to create and -run a container that leaves you with a good setup to do development. +can see the file(s) for yourself by inspecting the repo's `.devcontainer` +folder. The .devcontainer folder will have either a `devcontainer.json` file, or +some number of folders, such as `cuda12.0-conda` and `cuda12.0-pip`. Where +folders are present, each contain a `devcontainer.json` file. These files +specify how to create and run a container with a known-good development +environment. ### VS Code (Recommended) @@ -50,7 +53,7 @@ doesn't, you'll need to manually install the extension another way. 1. Open the cloned directory in VSCode -1. Launch a Dev Container by clicking the pop-up prompt in the lower right of +2. Launch a Dev Container by clicking the pop-up prompt in the lower right of the VS Code window that suggests to "Reopen in Container" ![Shows "Reopen in Container" prompt when opening the cccl directory in VScode.](./docs-img/reopen_in_container.png) @@ -59,7 +62,7 @@ the VS Code window that suggests to "Reopen in Container" ![Shows "Reopen in Container" in command pallete.](./docs-img/open_in_container_manual.png) -1. Select an environment with the desired build tools from the list: +3. Select an environment with the desired build tools from the list: ![Shows list of available container environments.](./docs-img/container_list.png) @@ -67,20 +70,20 @@ the VS Code window that suggests to "Reopen in Container" generating the matrix of base images. See [the docs on adapting devcontainers](./USAGE.md#custom-devcontainers) for more info. -1. VSCode will initialize the selected Dev Container. This can take a few +4. VSCode will initialize the selected Dev Container. This can take a few minutes the first time, as it downloads the base docker image and runs any specified feature installations. These steps are cached, so subsequent runs are faster. -1. Once initialized, the local project directory is mounted into the container +5. Once initialized, the local project directory is mounted into the container to ensure any changes are persistent. -1. You project should now look like any other VS Code project, except that the +6. You project should now look like any other VS Code project, except that the blue box in the lower left of the VS Code window should now read `Dev Container @ `. You're done! Any terminal you open will have the build environment activated appropriately. -1. Check the contributing guide in your repo for further instructions. The +7. Check the contributing guide in your repo for further instructions. The devcontainers adds build scripts that fit general usage. Type `build-` and hit `TAB` to see options for your project. @@ -101,14 +104,14 @@ devcontainers, but the repo-specific scripts will probably work better. **Steps** -1. Download the [launch-devcontainer.sh script](./launch-devcontainer.sh) and +1. Download the [launch-devcontainer.sh script](./scripts/launch-devcontainer.sh) and put it somewhere on PATH. If your project has its own launch script, use it here instead. -1. Set your current working directory to the root of your repo containing the +2. Set your current working directory to the root of your repo containing the .devcontainer folder -1. Run the launch-container.sh script. Called without arguments, you'll get a menu of containers to choose from: +3. Run the launch-container.sh script. Called without arguments, you'll get a menu of containers to choose from: ``` $ ./launch-devcontainer.sh @@ -128,12 +131,12 @@ You can also provide devcontainer label (folder name) directly: ./launch-devcontainer.sh cuda12.0-conda ``` -1. The devcontainer will be built, and you'll be dropped at a shell prompt +4. The devcontainer will be built, and you'll be dropped at a shell prompt inside the container. You're done! -1. Check the contributing guide in your repo for further instructions. The +5. Check the contributing guide in your repo for further instructions. The devcontainers adds build scripts that fit general usage. Type `build-` and hit -`TAB` to see options for your project. +`TAB` to see options for the project. ## (Optional) Native build tools - CMake, python builds diff --git a/launch-devcontainer.sh b/scripts/launch-devcontainer.sh similarity index 100% rename from launch-devcontainer.sh rename to scripts/launch-devcontainer.sh From 90966c2162c78ef4885c2ed0556e1ff028932bb7 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Fri, 19 Jan 2024 09:37:36 -0800 Subject: [PATCH 11/19] more language revision --- DEVELOP.md | 115 +++++++++++++++++--------------------------- USAGE_IN_PROJECT.md | 60 +++++++++++++---------- 2 files changed, 79 insertions(+), 96 deletions(-) diff --git a/DEVELOP.md b/DEVELOP.md index 4fbc64c5..61f57497 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -8,23 +8,16 @@ For the user-level overview providing instructions on how to use the devcontainer as a development environment, see [USAGE_IN_PROJECT.md](USAGE_IN_PROJECT.md) -For the project maintainer-level overview providing instructions on how to add +For a project maintainer-level overview providing instructions on how to add and change .devcontainer.json to suit your project, see [USAGE.md](USAGE.md) The code in this repository fits into a few main categories: -<<<<<<< HEAD -1. Features -2. GitHub Actions automations -3. Scripts -4. matrix.yml -5. Dockerfiles -======= + * Features * GitHub Actions automations * Scripts * matrix.yml * Dockerfiles ->>>>>>> 884030c (make language less ambiguous) ## Features @@ -32,8 +25,9 @@ From the official devcontainer [documentation on Features](https://containers.de > Development container "Features" are self-contained, shareable units of installation code and development container configuration. Each "feature" specified becomes a `RUN` statement in a temporary Dockerfile, -and as such each "feature" results in an image layer. This repository defines -`features` to install the following dev tools, compilers, and SDKs: +and as such each "feature" results in an image layer. The +[rapidsai/devcontainers repository](https://github.com/rapidsai/devcontainers) +defines `features` to install the following dev tools, compilers, and SDKs: * [CMake](features/src/cmake/) * [CUDA Toolkit](features/src/cuda/) @@ -50,8 +44,8 @@ and as such each "feature" results in an image layer. This repository defines * [devcontainer-utils](features/src/utils/) * [rapids-build-utils](features/src/rapids-build-utils/) -These feature scripts assume that apt utilities are available, and thus generally only -run on debian-based images. +Many of these feature scripts use apt utilities and thus only run on debian-based +images. ### Utility features @@ -61,64 +55,39 @@ overview of responsibilities for these features follows. #### `rapids-build-utils` -<<<<<<< HEAD -Most of the `rapids-build-utils` scripts serve to prepare the devcontainer prior to use, but you may use them to update -the devcontainer after adding to your container's /opt/rapids-build-utils/manifest.yml file to add new projects. - -If you are wondering where a command or behavior in a devcontainer is coming -from, this is a good place to start. - -`rapids-build-utils` scripts are installed by -[`install.sh`](./features/src/rapids-build-utils/install.sh), which creates -aliases for the .sh scripts. if you see `rapids-*` for a script or command name -in the devcontainer, look in -[`install.sh`](./features/src/rapids-build-utils/install.sh) to see how it is -mapped back to one of these scripts. - -* [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If your project is not in manifest.yaml, it will not get build scripts generated in the devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) -======= -Most of the scripts in [`rapids-build-utils`](./features/src/rapids-build-utils) -serve to prepare the devcontainer prior to use, but you may use them to update -the devcontainer after adding to your container's -/opt/rapids-build-utils/manifest.yml file to add new projects. See [USAGE.md](./USAGE.md#generating-scripts-for-other-projects-manifestyaml-file) -for more information on customizing manifest.yml - -`rapids-build-utils` is a good place to start when investigating an unknown -command or behavior in a devcontainer. The scripts from this project are -installed by [`install.sh`](./features/src/rapids-build-utils/install.sh), which -creates aliases for the .sh scripts. if you see `rapids-*` for a script or -command name in the devcontainer, look in -[`install.sh`](./features/src/rapids-build-utils/install.sh) to see how it is -mapped back to one of these scripts. - -Some scripts in downstream projects, especially those called in `./ci/` folders, -call scripts from the -[gha-tools](https://github.com/rapidsai/gha-tools/tree/main/tools) repository, -which also start with a `rapids-` prefix. These scripts are not currently -compatible with devcontainer images. If you need to run these scripts, check the -images at [rapidsai/ci-imgs](https://github.com/rapidsai/ci-imgs) instead of the +The `rapids-build-utils` feature is a good place to start when investigating an +unknown command or behavior in a devcontainer. Most of the scripts in the this +feature prepare the devcontainer prior to use. The scripts from this project are +installed by [`install.sh`](./features/src/rapids-build-utils/install.sh). `install.sh` +creates aliases that begin with a `rapids-` prefix for the .sh scripts in the +[`rapids-build-utils` bin +folder](features/src/rapids-build-utils/opt/rapids-build-utils/bin). + +The `rapids-build-utils` scripts can also be run manually to force an update the +devcontainer scripts after modifying a project's manifest.yml file to add new +projects or change dependencies. See +[USAGE.md](./USAGE.md#generating-scripts-for-other-projects-manifestyaml-file) +for more information on customizing manifest.yml. + +> **NOTE:** Some scripts in downstream projects, especially those in `ci/` +folders, call scripts that start with the `rapids-` prefix but are not provided +by the `rapids-build-utils` feature. These `rapids-` prefixed scripts come from +the [gha-tools](https://github.com/rapidsai/gha-tools/tree/main/tools) +repository, which is part of the older RAPIDS unified CI configuration and not +currently part of the devcontainer features. To run the scripts in a project's +`ci` folder, use the images at +[rapidsai/ci-imgs](https://github.com/rapidsai/ci-imgs) instead of the devcontainers. -* [manifest.yaml](./features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml): This enumerates where projects should be cloned from and how they depend on each other. It is used to generate build scripts. If a project is not in manifest.yaml, it will not get build scripts generated in the devcontainer. Refer to [docs on manifest.yaml](./USAGE.md#generated-build-scripts) ->>>>>>> 884030c (make language less ambiguous) -* [generate-scripts.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/generate-scripts.sh): generate `build-*`, `clone-*`, etc. scripts -* [make-pip-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-pip-env.sh) and [make-conda-env.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/make-conda-env.sh): -creating pip and conda python virtual environments -* [pull-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/pull-repositories.sh) and [push-repositories.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/push-repositories.sh) helps manage git operations on multiple repos that have been cloned -* [update-content-command.sh](./features/src/rapids-build-utils/opt/rapids-build-utils/bin/update-content-command.sh): calls `rapids-generate-script` and `rapids-make-vscode-workspace`. Called by VS Code in the [`postAttachCommand`](https://containers.dev/implementors/json_reference/#lifecycle-scripts), which is a reliable hook when the project is reopened or its configuration is changed. - -There are more scripts here, dealing with CMake variable parsing and -pass-through, python package dependency installation, and more. - #### devcontainers-utils -These scripts handle mostly git-related configuration, setting up SSH deploy +These scripts handle git-related configuration, setting up SSH deploy keys, GitHub authorization, and the vault setup for S3. The commands here are prefixed with `devcontainer-` during installation. ## Github Actions automations -Github Actions runs the build matrix of the many base images define in [matrix.yml](./matrix.yml). +Github Actions runs the build matrix of the many base images defined in [matrix.yml](./matrix.yml). These actions are broken up into many reusable pieces. The image build jobs start in [release.yml](./.github/workflows/release.yml). @@ -142,26 +111,30 @@ flowchart TD end ``` -These are divided into 3 categories: +These are divided into 3 categories in the diagram: * Workflows are `.yml` files in `.github/workflows` -* Actions are folders in `.github/actions`. One folder per action. Actions must have a `action.yml` file, but may also have accompanying shell scripts. -* Scripts are the shell scripts that are in some of the actions folders. They are broken out in this diagram to help show where the functionality actually lives. +* Actions are folders in `.github/actions`. One folder per action. Actions must have a `action.yml` file, but may +also have accompanying shell scripts. +* Scripts are the shell scripts that are in some of the actions folders. They are broken out in this diagram to help +show that functionality can be defined outside of action.yml files. ## Base images (matrix.yml) Base images are composed from individual features in [matrix.yml](./matrix.yml) -using [YAML anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). -These get built on Github Actions as described [above](#github-actions-automations) -The devcontainers repo does not contain scripts to facilitate building one particular -image. Some downstream repos, such as CCCL, have such scripts for their reduced subspace -of the matrix. CCCL's example is their [make_devcontainers.sh](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/make_devcontainers.sh) +using [YAML +anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). +These get built on Github Actions as described +[above](#github-actions-automations) The devcontainers repo does not contain +scripts to facilitate building one particular image. Some downstream repos have +such scripts for their reduced subspace of the matrix. An example is CCCL's +[make_devcontainers.sh](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/make_devcontainers.sh) script. ## Dockerfiles Dockerfiles do not play much role in this scheme. They serve to [set a few global variables and extend from the base image](./.devcontainer/rapids.Dockerfile). -Dockerfile changes are usually better achieved by adding or changing a feature +Changes made to a Dockerfile are usually better achieved by adding or changing a feature script instead. ## Build caching with `sccache` diff --git a/USAGE_IN_PROJECT.md b/USAGE_IN_PROJECT.md index 4370dbd8..37f066c8 100644 --- a/USAGE_IN_PROJECT.md +++ b/USAGE_IN_PROJECT.md @@ -1,11 +1,11 @@ # Using devcontainers in projects to provide development environments -This document describes usage of devcontainers as development environments. It -is intended as a general overview that any project employing devcontainers can -link to and avoid duplicating. +This document is aimed at developers who want to use devcontainers to set up +development environments for themselves. It is intended as a general overview +that any project employing devcontainers can link to and avoid duplicating. For how to add devcontainers to a project, or how to change existing devcontainer -configuration, see [USAGE.md](./USAGE.md). +configuration in a project, see [USAGE.md](./USAGE.md). For how to change the centralized installation and configuration scripts that are shared among projects, see [DEVELOP.md](./DEVELOP.md). @@ -15,7 +15,7 @@ are shared among projects, see [DEVELOP.md](./DEVELOP.md). Devcontainers can be used on Linux, Mac and Windows. They use Docker, so the system requirements and limitations associated with Docker apply here also. On Mac and Windows, where a Linux VM must run to support Docker, memory limitations -of that Linux VM may present problems. Otherwise, devcontainers do not add +of that VM may present problems. Otherwise, devcontainers do not add system requirements beyond the needs of the individual projects being built. Devcontainers also don't emulate hardware. If a project needs an NVIDIA GPU to run, then the devcontainer needs to run on a machine with an NVIDIA GPU. @@ -23,6 +23,7 @@ Building is different from running, though, and devcontainers can often be used to build software that may need a GPU to run. Devcontainers require Docker. To set that up: + * [Linux - docker engine](https://docs.docker.com/engine/install/) * [Mac - docker desktop](https://docs.docker.com/desktop/install/mac-install/) * [Windows](https://docs.docker.com/desktop/install/windows-install/) @@ -30,15 +31,20 @@ Devcontainers require Docker. To set that up: Docker Desktop has licensing requirements. NVIDIA employees may [request a license](https://confluence.nvidia.com/pages/viewpage.action?spaceKey=SWDOCS&title=Requesting+a+Docker+Desktop+License). +### Local vs. Remote Usage + +Devcontainers can be used similarly on local machines and on remote machines. +There are no special steps required, but menu options may differ slightly. + ## Quickstart -At this point, you have cloned a repo that you've heard has a devcontainer. You -can see the file(s) for yourself by inspecting the repo's `.devcontainer` -folder. The .devcontainer folder will have either a `devcontainer.json` file, or -some number of folders, such as `cuda12.0-conda` and `cuda12.0-pip`. Where -folders are present, each contain a `devcontainer.json` file. These files -specify how to create and run a container with a known-good development -environment. +At this point, you have cloned a repo that nominally has some devcontainer +configuration. Devcontainer configuration is stored in a `.devcontainer` folder +in the repository root. The .devcontainer folder will have either a +`devcontainer.json` file, or some number of folders, such as `cuda12.0-conda` +and `cuda12.0-pip`. Where folders are present, each will contain a +`devcontainer.json` file. These files specify how to create and run a container +with a known-good development environment. ### VS Code (Recommended) @@ -83,20 +89,22 @@ blue box in the lower left of the VS Code window should now read `Dev Container @ `. You're done! Any terminal you open will have the build environment activated appropriately. -7. Check the contributing guide in your repo for further instructions. The -devcontainers adds build scripts that fit general usage. Type `build-` and hit -`TAB` to see options for your project. +7. The devcontainers adds build scripts that fit general usage. Type `build-` and hit +`TAB` to see options for your project. Check the contributing guide in your repo +for further instructions. **Exiting the devcontainer** -If you are in VS Code and you need to return to your host machine (local or SSH), -you can run `Dev Containers: Reopen in SSH`. +If you are in a VS Code devcontainer on a remote (SSH) machine, you can run +`CTRL|CMD + SHIFT + P` and select `Dev Containers: Reopen in SSH` to return to +your host machine. ### Docker (Manual Approach) Your project may have its own launch scripts that account for options in libraries and/or tools. The steps here should work with any repo that uses -devcontainers, but the repo-specific scripts will probably work better. +devcontainers, but any repo-specific scripts and instructions will probably work +better. **Prerequisites** @@ -134,9 +142,9 @@ You can also provide devcontainer label (folder name) directly: 4. The devcontainer will be built, and you'll be dropped at a shell prompt inside the container. You're done! -5. Check the contributing guide in your repo for further instructions. The -devcontainers adds build scripts that fit general usage. Type `build-` and hit -`TAB` to see options for the project. +5. The devcontainers adds build scripts that fit general usage. Type `build-` +and hit `TAB` to see options for the project. Check the contributing guide in +your repo for further instructions. ## (Optional) Native build tools - CMake, python builds @@ -149,9 +157,11 @@ mounted as a subfolder in `/home/coder`. ## (Optional) Working with upstream projects Build scripts are generated only for the main project - the one you have -mounted. If you would like to work with other projects, you can run their -`clone-*` scripts. After they have been cloned, appropriate `build-*` scripts -will be generated. See [the project maintainer docs on this +mounted. Dependencies are automatically downloaded, but these dependencies are +not built locally by default. If you would like to develop other projects in +tandem, you can run their `clone-*` scripts. After they have been cloned, +appropriate `build-*` scripts will be generated. See [the project maintainer +docs on this topic](./USAGE.md#generating-scripts-for-other-projects-manifestyaml-file). ## (Optional) Authenticate with GitHub for `sccache` @@ -172,4 +182,4 @@ Follow the instructions in the prompt as below and enter the one-time code at ht To manually trigger this authentication, execute the `devcontainer-utils-vault-s3-init` script within the container. -For more information about the sccache configuration and authentication, see the documentation at [`rapidsai/devcontainers`](https://github.com/rapidsai/devcontainers/blob/branch-23.10/USAGE.md#build-caching-with-sccache). +For more information about the sccache configuration and authentication, see [the developer documentation](./DEVELOP.md#build-caching-with-sccache). From bd294308c7d1e10af3f3b0a44e9916ebce5f546e Mon Sep 17 00:00:00 2001 From: Paul Taylor <178183+trxcllnt@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:46:30 -0800 Subject: [PATCH 12/19] temporarily allow unbound variables while activating the conda env (#216) --- features/src/mambaforge/.bashrc | 12 ++++++++++-- features/src/mambaforge/devcontainer-feature.json | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/features/src/mambaforge/.bashrc b/features/src/mambaforge/.bashrc index 1d054380..7ef4b92b 100644 --- a/features/src/mambaforge/.bashrc +++ b/features/src/mambaforge/.bashrc @@ -5,8 +5,16 @@ for default_conda_env_name in ${DEFAULT_CONDA_ENV:-} ${CONDA_DEFAULT_ENV:-} base if grep -qF "(${default_conda_env_name})" <<< "${CONDA_PROMPT_MODIFIER:-}"; then break; fi - conda activate "$default_conda_env_name" 2>/dev/null && break || continue; -done; + # Temporarily allow unbound variables for conda activation. + oldstate="$(shopt -po; shopt -p)"; [[ -o errexit ]] && oldstate="${oldstate}; set -e"; set +u; + if conda activate "${default_conda_env_name}" 2>/dev/null; then + { set +vx; } 2>/dev/null; eval "${oldstate}"; unset oldstate; + break; + else + { set +vx; } 2>/dev/null; eval "${oldstate}"; unset oldstate; + continue; + fi +done if [ -n "${CONDA_EXE:-}" ]; then conda_bin_paths="$(dirname "$(dirname "${CONDA_EXE}")")/condabin"; diff --git a/features/src/mambaforge/devcontainer-feature.json b/features/src/mambaforge/devcontainer-feature.json index 4dcbaad1..d35147a0 100644 --- a/features/src/mambaforge/devcontainer-feature.json +++ b/features/src/mambaforge/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "Mambaforge", "id": "mambaforge", - "version": "24.2.1", + "version": "24.2.2", "description": "A feature to install mambaforge", "options": { "version": { From 635876f9e7b647ac14c0087d0603097813778926 Mon Sep 17 00:00:00 2001 From: Paul Taylor <178183+trxcllnt@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:39:18 -0800 Subject: [PATCH 13/19] Fix mambaforge shell history (backport #219) (#225) * Fix mambaforge shell history (#219) * disable history when restoring shell options * Update devcontainer-feature.json * login to dockerhub so we don't hit rate limits --- .github/workflows/build-and-test-feature.yml | 6 ++++++ .../workflows/build-test-and-push-linux-image.yml | 6 ++++++ .../workflows/build-test-and-push-windows-image.yml | 13 ++++++------- features/src/mambaforge/.bashrc | 6 +++--- features/src/mambaforge/devcontainer-feature.json | 2 +- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-and-test-feature.yml b/.github/workflows/build-and-test-feature.yml index fcca147d..e94ae089 100644 --- a/.github/workflows/build-and-test-feature.yml +++ b/.github/workflows/build-and-test-feature.yml @@ -25,6 +25,12 @@ jobs: with: persist-credentials: false + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.GPUCIBOT_DOCKERHUB_USER }} + password: ${{ secrets.GPUCIBOT_DOCKERHUB_TOKEN }} + - name: ${{ inputs.name }} uses: ./.github/actions/build-and-test-feature with: diff --git a/.github/workflows/build-test-and-push-linux-image.yml b/.github/workflows/build-test-and-push-linux-image.yml index ad4ae47d..2b267a00 100644 --- a/.github/workflows/build-test-and-push-linux-image.yml +++ b/.github/workflows/build-test-and-push-linux-image.yml @@ -51,6 +51,12 @@ jobs: features: "${{ inputs.features }}" container_env: "${{ inputs.container_env }}" + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.GPUCIBOT_DOCKERHUB_USER }} + password: ${{ secrets.GPUCIBOT_DOCKERHUB_TOKEN }} + - name: Build ${{ steps.json.outputs.tag }}-${{ matrix.arch }} uses: ./.github/actions/build-linux-image with: diff --git a/.github/workflows/build-test-and-push-windows-image.yml b/.github/workflows/build-test-and-push-windows-image.yml index 35eacdbe..69a9d4f5 100644 --- a/.github/workflows/build-test-and-push-windows-image.yml +++ b/.github/workflows/build-test-and-push-windows-image.yml @@ -59,6 +59,12 @@ jobs: tag=${version}-cuda${cuda}-cl${cl}-${{ inputs.os }}${{ matrix.edition }} EOF + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.GPUCIBOT_DOCKERHUB_USER }} + password: ${{ secrets.GPUCIBOT_DOCKERHUB_TOKEN }} + - name: Build ${{ steps.info.outputs.tag }} uses: ./.github/actions/build-windows-image with: @@ -79,13 +85,6 @@ jobs: version: "${{ steps.info.outputs.version }}" edition: "${{ matrix.edition }}" - - if: inputs.push == 'true' - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.GPUCIBOT_DOCKERHUB_USER }} - password: ${{ secrets.GPUCIBOT_DOCKERHUB_TOKEN }} - - if: inputs.push == 'true' name: Push ${{ steps.info.outputs.tag }} shell: powershell diff --git a/features/src/mambaforge/.bashrc b/features/src/mambaforge/.bashrc index 7ef4b92b..c6804046 100644 --- a/features/src/mambaforge/.bashrc +++ b/features/src/mambaforge/.bashrc @@ -6,12 +6,12 @@ for default_conda_env_name in ${DEFAULT_CONDA_ENV:-} ${CONDA_DEFAULT_ENV:-} base break; fi # Temporarily allow unbound variables for conda activation. - oldstate="$(shopt -po; shopt -p)"; [[ -o errexit ]] && oldstate="${oldstate}; set -e"; set +u; + oldstate="$(shopt -po | grep -E '(nounset|verbose|xtrace)')"; set +u; if conda activate "${default_conda_env_name}" 2>/dev/null; then - { set +vx; } 2>/dev/null; eval "${oldstate}"; unset oldstate; + { set +vxo history; } 2>/dev/null; eval "${oldstate}"; unset oldstate; break; else - { set +vx; } 2>/dev/null; eval "${oldstate}"; unset oldstate; + { set +vxo history; } 2>/dev/null; eval "${oldstate}"; unset oldstate; continue; fi done diff --git a/features/src/mambaforge/devcontainer-feature.json b/features/src/mambaforge/devcontainer-feature.json index d35147a0..4bcff969 100644 --- a/features/src/mambaforge/devcontainer-feature.json +++ b/features/src/mambaforge/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "Mambaforge", "id": "mambaforge", - "version": "24.2.2", + "version": "24.2.3", "description": "A feature to install mambaforge", "options": { "version": { From b900eba1da10943c2e7248a3803f58d9cb9d81b8 Mon Sep 17 00:00:00 2001 From: ptaylor Date: Wed, 7 Feb 2024 18:02:51 -0800 Subject: [PATCH 14/19] Revert "Merge branch 'branch-24.04' into branch-24.02" This reverts commit 03d3fd48bee1e49214f3f18bbb9641a85fd8fa15, reversing changes made to 635876f9e7b647ac14c0087d0603097813778926. --- .devcontainer/build-rapids.sh | 2 +- .../cuda11.8-conda/devcontainer.json | 2 +- .devcontainer/cuda11.8-pip/devcontainer.json | 2 +- .../cuda12.0-conda/devcontainer.json | 2 +- .devcontainer/cuda12.0-pip/devcontainer.json | 2 +- .github/actions/setup-runner-env/action.yml | 21 +--- USAGE.md | 4 +- .../src/cccl-dev/devcontainer-feature.json | 2 +- features/src/cmake/devcontainer-feature.json | 2 +- features/src/cuda/devcontainer-feature.json | 110 +++++++++--------- features/src/gcc/devcontainer-feature.json | 2 +- .../src/gitlab-cli/devcontainer-feature.json | 2 +- features/src/llvm/devcontainer-feature.json | 2 +- .../src/mambaforge/devcontainer-feature.json | 2 +- features/src/ninja/devcontainer-feature.json | 2 +- features/src/nvhpc/devcontainer-feature.json | 2 +- features/src/oneapi/devcontainer-feature.json | 2 +- .../devcontainer-feature.json | 2 +- .../opt/rapids-build-utils/manifest.yaml | 10 +- features/src/rust/devcontainer-feature.json | 2 +- .../src/sccache/devcontainer-feature.json | 2 +- features/src/ucx/devcontainer-feature.json | 2 +- features/src/utils/devcontainer-feature.json | 2 +- 23 files changed, 83 insertions(+), 100 deletions(-) diff --git a/.devcontainer/build-rapids.sh b/.devcontainer/build-rapids.sh index 48b0530a..1a76cb7f 100755 --- a/.devcontainer/build-rapids.sh +++ b/.devcontainer/build-rapids.sh @@ -47,7 +47,7 @@ build_rapids() { ( echo "building cuDF"; clean-cudf; - build-cudf -DBUILD_BENCHMARKS=ON --verbose + build-cudf -DBUILD_BENCHMARKS=ON -DNVBench_ENABLE_CUPTI=OFF --verbose sccache -s; ) 2>&1 | maybe_write_build_log cudf; diff --git a/.devcontainer/cuda11.8-conda/devcontainer.json b/.devcontainer/cuda11.8-conda/devcontainer.json index 7c2332c5..5aa82c5f 100644 --- a/.devcontainer/cuda11.8-conda/devcontainer.json +++ b/.devcontainer/cuda11.8-conda/devcontainer.json @@ -5,7 +5,7 @@ "args": { "CUDA": "11.8", "PYTHON_PACKAGE_MANAGER": "conda", - "BASE": "rapidsai/devcontainers:24.04-cpp-cuda11.8-mambaforge-ubuntu22.04" + "BASE": "rapidsai/devcontainers:24.02-cpp-cuda11.8-mambaforge-ubuntu22.04" } }, "hostRequirements": {"gpu": "optional"}, diff --git a/.devcontainer/cuda11.8-pip/devcontainer.json b/.devcontainer/cuda11.8-pip/devcontainer.json index ae4b06a3..94212b75 100644 --- a/.devcontainer/cuda11.8-pip/devcontainer.json +++ b/.devcontainer/cuda11.8-pip/devcontainer.json @@ -5,7 +5,7 @@ "args": { "CUDA": "11.8", "PYTHON_PACKAGE_MANAGER": "pip", - "BASE": "rapidsai/devcontainers:24.04-cpp-llvm16-cuda11.8-ubuntu22.04" + "BASE": "rapidsai/devcontainers:24.02-cpp-llvm16-cuda11.8-ubuntu22.04" } }, "hostRequirements": {"gpu": "optional"}, diff --git a/.devcontainer/cuda12.0-conda/devcontainer.json b/.devcontainer/cuda12.0-conda/devcontainer.json index 09cfc9ce..40c6b889 100644 --- a/.devcontainer/cuda12.0-conda/devcontainer.json +++ b/.devcontainer/cuda12.0-conda/devcontainer.json @@ -5,7 +5,7 @@ "args": { "CUDA": "12.0", "PYTHON_PACKAGE_MANAGER": "conda", - "BASE": "rapidsai/devcontainers:24.04-cpp-mambaforge-ubuntu22.04" + "BASE": "rapidsai/devcontainers:24.02-cpp-mambaforge-ubuntu22.04" } }, "hostRequirements": {"gpu": "optional"}, diff --git a/.devcontainer/cuda12.0-pip/devcontainer.json b/.devcontainer/cuda12.0-pip/devcontainer.json index 9dd89cb4..186498d1 100644 --- a/.devcontainer/cuda12.0-pip/devcontainer.json +++ b/.devcontainer/cuda12.0-pip/devcontainer.json @@ -5,7 +5,7 @@ "args": { "CUDA": "12.0", "PYTHON_PACKAGE_MANAGER": "pip", - "BASE": "rapidsai/devcontainers:24.04-cpp-llvm16-cuda12.0-ubuntu22.04" + "BASE": "rapidsai/devcontainers:24.02-cpp-llvm16-cuda12.0-ubuntu22.04" } }, "hostRequirements": {"gpu": "optional"}, diff --git a/.github/actions/setup-runner-env/action.yml b/.github/actions/setup-runner-env/action.yml index ae701557..b5248736 100644 --- a/.github/actions/setup-runner-env/action.yml +++ b/.github/actions/setup-runner-env/action.yml @@ -5,30 +5,27 @@ description: Setup self-hosted runner environment runs: using: composite steps: - - name: Dump env - shell: bash -eo pipefail {0} - run: echo "${{ toJSON(env) }}" - - if: env.RUNNER_ENVIRONMENT != 'self-hosted' + - if: env.RUNNER_ENVIRONMENT == 'github-hosted' name: Free up disk space uses: ./.github/actions/free-disk-space with: tool_cache: "${{ runner.tool_cache }}" - - if: env.RUNNER_ENVIRONMENT == 'self-hosted' + - if: env.RUNNER_ENVIRONMENT != 'github-hosted' name: Setup self-hosted runner environment shell: bash -eo pipefail {0} run: | echo "HOME=${{ runner.workspace }}" >> $GITHUB_ENV; echo "TMPDIR=${{ runner.temp }}" >> $GITHUB_ENV; - - if: env.RUNNER_ENVIRONMENT == 'self-hosted' + - if: env.RUNNER_ENVIRONMENT != 'github-hosted' name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '16' - - if: env.RUNNER_ENVIRONMENT != 'self-hosted' + - if: env.RUNNER_ENVIRONMENT == 'github-hosted' name: Set up QEMU uses: docker/setup-qemu-action@v2 @@ -36,15 +33,7 @@ runs: shell: bash run: docker context create builder - - if: env.RUNNER_ENVIRONMENT != 'self-hosted' - name: Setup docker buildx on github-hosted runners - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - endpoint: builder - - - if: env.RUNNER_ENVIRONMENT == 'self-hosted' - name: Setup docker buildx on self-hosted runners + - name: Setup docker buildx uses: docker/setup-buildx-action@v2 with: buildkitd-flags: --debug --config /etc/buildkit/buildkitd.toml diff --git a/USAGE.md b/USAGE.md index f1379831..bc202075 100644 --- a/USAGE.md +++ b/USAGE.md @@ -19,11 +19,11 @@ The features that comprise the image are noted in the image tags. If no version The pre-built images can be used as the `"image"`, or as the base of a Dockerfile in `"build"`, in `devcontainer.json`: -
devcontainer.json using pre-built image
{
"image": "rapidsai/devcontainers:24.04-cpp-llvm16-cuda12.0-nvhpc23.5-ubuntu22.04",
"hostRequirements": { "gpu": true },
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
+
devcontainer.json using pre-built image
{
"image": "rapidsai/devcontainers:24.02-cpp-llvm16-cuda12.0-nvhpc23.5-ubuntu22.04",
"hostRequirements": { "gpu": true },
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
You can also build a custom devcontainer by composing individual features: -
devcontainer.json using individual features
{
"image": "ubuntu:22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.04": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.04": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.04": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
+
devcontainer.json using individual features
{
"image": "ubuntu:22.04",
"features": {
"ghcr.io/rapidsai/devcontainers/features/cmake:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/ninja:24.02": {},
"ghcr.io/rapidsai/devcontainers/features/sccache:24.02": {
"version": "0.5.4"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/cmake",
"ghcr.io/rapidsai/devcontainers/features/ninja",
"ghcr.io/rapidsai/devcontainers/features/sccache"
],
"workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind"
}
> **NOTE:** Feature updates published since your most recent image build will invalidate your docker image layer cache, meaning it can take the [devcontainers CLI](https://github.com/devcontainers/cli) longer to initialize containers composed from individual features. diff --git a/features/src/cccl-dev/devcontainer-feature.json b/features/src/cccl-dev/devcontainer-feature.json index b75458b4..58df0dd8 100644 --- a/features/src/cccl-dev/devcontainer-feature.json +++ b/features/src/cccl-dev/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "NVIDIA CCCL development utilities", "id": "cccl-dev", - "version": "24.4.0", + "version": "24.2.2", "description": "A feature to install NVIDIA CCCL development utilities", "options": { "litVersion": { diff --git a/features/src/cmake/devcontainer-feature.json b/features/src/cmake/devcontainer-feature.json index d3159ddd..66943ae5 100644 --- a/features/src/cmake/devcontainer-feature.json +++ b/features/src/cmake/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "CMake", "id": "cmake", - "version": "24.4.0", + "version": "24.2.0", "description": "A feature to install CMake", "options": { "version": { diff --git a/features/src/cuda/devcontainer-feature.json b/features/src/cuda/devcontainer-feature.json index e4c4bead..fd686841 100644 --- a/features/src/cuda/devcontainer-feature.json +++ b/features/src/cuda/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "CUDA Toolkit", "id": "cuda", - "version": "24.4.0", + "version": "24.2.2", "description": "A feature to install the NVIDIA CUDA Toolkit", "options": { "version": { @@ -23,94 +23,94 @@ "description": "Version of the CUDA Toolkit to install." }, "installCompilers": { - "type": "boolean", - "default": true, - "description": "Install NVIDIA CUDA Compiler (nvcc)" + "type": "boolean", + "default": true, + "description": "Install NVIDIA CUDA Compiler (nvcc)" }, "installProfilers": { - "type": "boolean", - "default": true, - "description": "Install NVIDIA NSight Systems Profiler (nsys)" + "type": "boolean", + "default": true, + "description": "Install NVIDIA NSight Systems Profiler (nsys)" }, "installCTKLibraries": { - "type": "boolean", - "default": true, - "description": "Shortcut to install all CUDA Toolkit Libraries" + "type": "boolean", + "default": true, + "description": "Shortcut to install all CUDA Toolkit Libraries" }, "installDevPackages": { - "type": "boolean", - "default": true, - "description": "Whether to install the CUDA dev packages (static libraries + headers)" + "type": "boolean", + "default": true, + "description": "Whether to install the CUDA dev packages (static libraries + headers)" }, "installcuDNN": { - "type": "boolean", - "default": false, - "description": "Install CUDA Deep Neural Network Library (cuDNN)" + "type": "boolean", + "default": false, + "description": "Install CUDA Deep Neural Network Library (cuDNN)" }, "installcuTensor": { - "type": "boolean", - "default": false, - "description": "Install CUDA Tensor Linear Algebra Library (cuTensor)" + "type": "boolean", + "default": false, + "description": "Install CUDA Tensor Linear Algebra Library (cuTensor)" }, "installNCCL": { - "type": "boolean", - "default": true, - "description": "Install NVIDIA Collective Communications Library (NCCL)" + "type": "boolean", + "default": true, + "description": "Install NVIDIA Collective Communications Library (NCCL)" }, "installCUDARuntime": { - "type": "boolean", - "default": true, - "description": "Install CUDA Runtime Library (cudart)" + "type": "boolean", + "default": true, + "description": "Install CUDA Runtime Library (cudart)" }, "installNVRTC": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA Runtime Compilation Library (NVRTC)" + "type": "boolean", + "default": false, + "description": "Install NVIDIA Runtime Compilation Library (NVRTC)" }, "installOpenCL": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA CUDA OpenCL Library" + "type": "boolean", + "default": false, + "description": "Install NVIDIA CUDA OpenCL Library" }, "installcuBLAS": { - "type": "boolean", - "default": false, - "description": "Install CUDA Basic Linear Algebra Library (cuBLAS)" + "type": "boolean", + "default": false, + "description": "Install CUDA Basic Linear Algebra Library (cuBLAS)" }, "installcuSPARSE": { - "type": "boolean", - "default": false, - "description": "Install CUDA Basic Linear Algebra for Sparse Matrices Library (cuSPARSE)" + "type": "boolean", + "default": false, + "description": "Install CUDA Basic Linear Algebra for Sparse Matrices Library (cuSPARSE)" }, "installcuFFT": { - "type": "boolean", - "default": false, - "description": "Install CUDA Fast Fourier Transform Library (cuFFT)" + "type": "boolean", + "default": false, + "description": "Install CUDA Fast Fourier Transform Library (cuFFT)" }, "installcuFile": { - "type": "boolean", - "default": false, - "description": "Install CUDA GPUDirect Storage API Library (cuFile)" + "type": "boolean", + "default": false, + "description": "Install CUDA GPUDirect Storage API Library (cuFile)" }, "installcuRAND": { - "type": "boolean", - "default": false, - "description": "Install CUDA Random Number Generation Library (cuRAND)" + "type": "boolean", + "default": false, + "description": "Install CUDA Random Number Generation Library (cuRAND)" }, "installcuSOLVER": { - "type": "boolean", - "default": false, - "description": "Install CUDA Direct Linear Solvers Library (cuSOLVER)" + "type": "boolean", + "default": false, + "description": "Install CUDA Direct Linear Solvers Library (cuSOLVER)" }, "installNPP": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA Performance Primitives (NPP)" + "type": "boolean", + "default": false, + "description": "Install NVIDIA Performance Primitives (NPP)" }, "installnvJPEG": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA JPEG decoder, encoder, and transcoder library (nvJPEG)" + "type": "boolean", + "default": false, + "description": "Install NVIDIA JPEG decoder, encoder, and transcoder library (nvJPEG)" }, "pruneStaticLibs": { "type": "boolean", diff --git a/features/src/gcc/devcontainer-feature.json b/features/src/gcc/devcontainer-feature.json index 0aa1deb5..8b609468 100644 --- a/features/src/gcc/devcontainer-feature.json +++ b/features/src/gcc/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "GCC", "id": "gcc", - "version": "24.4.0", + "version": "24.2.1", "description": "A feature to install gcc", "options": { "version": { diff --git a/features/src/gitlab-cli/devcontainer-feature.json b/features/src/gitlab-cli/devcontainer-feature.json index 9562d59f..0642d4ec 100644 --- a/features/src/gitlab-cli/devcontainer-feature.json +++ b/features/src/gitlab-cli/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "gitlab-cli", - "version": "24.4.0", + "version": "24.2.0", "name": "GitLab CLI", "documentationURL": "https://github.com/rapidsai/devcontainers/features/tree/main/src/gitlab-cli", "description": "Installs the GitLab CLI. Auto-detects latest version and installs needed dependencies.", diff --git a/features/src/llvm/devcontainer-feature.json b/features/src/llvm/devcontainer-feature.json index 45fad8f4..62dd3b96 100644 --- a/features/src/llvm/devcontainer-feature.json +++ b/features/src/llvm/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "LLVM compilers and tools", "id": "llvm", - "version": "24.4.0", + "version": "24.2.3", "description": "A feature to install LLVM compilers and tools", "options": { "version": { diff --git a/features/src/mambaforge/devcontainer-feature.json b/features/src/mambaforge/devcontainer-feature.json index 77013cb0..4bcff969 100644 --- a/features/src/mambaforge/devcontainer-feature.json +++ b/features/src/mambaforge/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "Mambaforge", "id": "mambaforge", - "version": "24.4.2", + "version": "24.2.3", "description": "A feature to install mambaforge", "options": { "version": { diff --git a/features/src/ninja/devcontainer-feature.json b/features/src/ninja/devcontainer-feature.json index 0df8f2f0..a3b7ca1f 100644 --- a/features/src/ninja/devcontainer-feature.json +++ b/features/src/ninja/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "Ninja build", "id": "ninja", - "version": "24.4.0", + "version": "24.2.0", "description": "A feature to install ninja-build", "options": { "version": { diff --git a/features/src/nvhpc/devcontainer-feature.json b/features/src/nvhpc/devcontainer-feature.json index 7019155e..ec292fc2 100644 --- a/features/src/nvhpc/devcontainer-feature.json +++ b/features/src/nvhpc/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "NVHPC SDK", "id": "nvhpc", - "version": "24.4.0", + "version": "24.2.2", "description": "A feature to install the NVHPC SDK", "options": { "version": { diff --git a/features/src/oneapi/devcontainer-feature.json b/features/src/oneapi/devcontainer-feature.json index 8230fad3..3ee97e75 100644 --- a/features/src/oneapi/devcontainer-feature.json +++ b/features/src/oneapi/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "Intel oneapi toolchain", "id": "oneapi", - "version": "24.4.0", + "version": "24.2.0", "description": "A feature to install the Intel oneapi toolchain", "options": { "version": { diff --git a/features/src/rapids-build-utils/devcontainer-feature.json b/features/src/rapids-build-utils/devcontainer-feature.json index de316729..588dde87 100644 --- a/features/src/rapids-build-utils/devcontainer-feature.json +++ b/features/src/rapids-build-utils/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "NVIDIA RAPIDS devcontainer build utilities", "id": "rapids-build-utils", - "version": "24.4.0", + "version": "24.2.7", "description": "A feature to install the RAPIDS devcontainer build utilities", "containerEnv": { "BASH_ENV": "/etc/bash.bash_env" diff --git a/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml b/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml index 3d57e10f..0e2dc4e2 100755 --- a/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml +++ b/features/src/rapids-build-utils/opt/rapids-build-utils/manifest.yaml @@ -1,6 +1,6 @@ x-git-defaults: &git_defaults host: github - tag: branch-24.04 + tag: branch-24.02 upstream: rapidsai repos: @@ -24,7 +24,7 @@ repos: git: repo: ucxx <<: *git_defaults - tag: branch-0.37 + tag: branch-0.36 cpp: - name: ucxx sub_dir: "cpp" @@ -158,9 +158,6 @@ repos: - name: cugraph sub_dir: cpp depends: [rmm, raft, cugraph-ops] - - name: cugraph_etl - sub_dir: cpp/libcugraph_etl - depends: [cugraph, cudf] python: - name: pylibcugraph sub_dir: python/pylibcugraph @@ -174,9 +171,6 @@ repos: - name: cugraph-dgl sub_dir: python/cugraph-dgl depends: [cugraph] - - name: cugraph-equivariant - sub_dir: python/cugraph-equivariant - depends: [cugraph] - name: cugraph_pyg sub_dir: python/cugraph-pyg depends: [cugraph] diff --git a/features/src/rust/devcontainer-feature.json b/features/src/rust/devcontainer-feature.json index 80f27fca..03429f32 100644 --- a/features/src/rust/devcontainer-feature.json +++ b/features/src/rust/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "rust", - "version": "24.4.0", + "version": "24.2.0", "name": "Rust", "documentationURL": "https://github.com/rapidsai/devcontainers/features/tree/main/src/rust", "description": "Installs Rust, common Rust utilities, and their required dependencies", diff --git a/features/src/sccache/devcontainer-feature.json b/features/src/sccache/devcontainer-feature.json index cddd2ba8..71244954 100644 --- a/features/src/sccache/devcontainer-feature.json +++ b/features/src/sccache/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "sccache", "id": "sccache", - "version": "24.4.0", + "version": "24.2.1", "description": "A feature to install sccache", "options": { "version": { diff --git a/features/src/ucx/devcontainer-feature.json b/features/src/ucx/devcontainer-feature.json index 6915c84c..6f21df04 100644 --- a/features/src/ucx/devcontainer-feature.json +++ b/features/src/ucx/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "UCX", "id": "ucx", - "version": "24.4.0", + "version": "24.2.0", "description": "A feature to install UCX", "options": { "version": { diff --git a/features/src/utils/devcontainer-feature.json b/features/src/utils/devcontainer-feature.json index d319c04f..9096df9e 100644 --- a/features/src/utils/devcontainer-feature.json +++ b/features/src/utils/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "devcontainer-utils", "id": "utils", - "version": "24.4.4", + "version": "24.2.7", "description": "A feature to install RAPIDS devcontainer utility scripts", "containerEnv": { "BASH_ENV": "/etc/bash.bash_env" From 1b85460d13f29fc296d7a600e9c7bd0b3bf55f2e Mon Sep 17 00:00:00 2001 From: Paul Taylor <178183+trxcllnt@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:39:23 -0800 Subject: [PATCH 15/19] Backport `sccache v0.7.7` update to `branch-24.02` (#231) * Update to sccache v0.7.7 (#228) * Fix `devcontainer-utils-vault-s3-init` for `sccache@v0.7.7` (#229) --- .../actions/build-and-test-feature/action.yml | 4 -- .github/workflows/build-and-test-feature.yml | 2 - .../devcontainer-feature.json | 2 +- features/src/rapids-build-utils/install.sh | 11 +++-- .../src/sccache/devcontainer-feature.json | 4 +- features/src/utils/devcontainer-feature.json | 2 +- features/src/utils/install.sh | 11 +++-- .../bin/vault/s3/creds/persist.sh | 41 +++++++---------- .../bin/vault/s3/creds/propagate.sh | 2 +- .../devcontainer/bin/vault/s3/creds/test.sh | 46 +++++-------------- .../opt/devcontainer/bin/vault/s3/init.sh | 43 ++++++----------- features/test/utils/scenarios.json | 18 +++----- features/test/utils/ubuntu18.04.sh | 19 ++------ features/test/utils/ubuntu20.04.sh | 19 ++------ features/test/utils/ubuntu22.04.sh | 19 ++------ image/.devcontainer/devcontainer.json | 2 +- 16 files changed, 77 insertions(+), 168 deletions(-) diff --git a/.github/actions/build-and-test-feature/action.yml b/.github/actions/build-and-test-feature/action.yml index d844418c..4c02bcd8 100644 --- a/.github/actions/build-and-test-feature/action.yml +++ b/.github/actions/build-and-test-feature/action.yml @@ -8,8 +8,6 @@ inputs: vault_host: {type: string, defaut: '', required: false} rw_sccache_bucket: {type: string, defaut: '', required: false} rw_sccache_region: {type: string, defaut: '', required: false} - ro_sccache_bucket: {type: string, defaut: '', required: false} - ro_sccache_region: {type: string, defaut: '', required: false} runs: using: composite @@ -34,5 +32,3 @@ runs: vault_host: "${{ inputs.vault_host }}" rw_sccache_bucket: "${{ inputs.rw_sccache_bucket }}" rw_sccache_region: "${{ inputs.rw_sccache_region }}" - ro_sccache_bucket: "${{ inputs.ro_sccache_bucket }}" - ro_sccache_region: "${{ inputs.ro_sccache_region }}" diff --git a/.github/workflows/build-and-test-feature.yml b/.github/workflows/build-and-test-feature.yml index e94ae089..33868d1f 100644 --- a/.github/workflows/build-and-test-feature.yml +++ b/.github/workflows/build-and-test-feature.yml @@ -39,5 +39,3 @@ jobs: vault_host: "${{ secrets.GIST_REPO_READ_ORG_GITHUB_TOKEN && 'https://vault.ops.k8s.rapids.ai' || '' }}" rw_sccache_bucket: "${{ secrets.GIST_REPO_READ_ORG_GITHUB_TOKEN && 'rapids-sccache-devs' || '' }}" rw_sccache_region: "${{ vars.AWS_REGION }}" - ro_sccache_bucket: rapids-sccache-east - ro_sccache_region: "${{ vars.AWS_REGION }}" diff --git a/features/src/rapids-build-utils/devcontainer-feature.json b/features/src/rapids-build-utils/devcontainer-feature.json index 588dde87..6adf8ce4 100644 --- a/features/src/rapids-build-utils/devcontainer-feature.json +++ b/features/src/rapids-build-utils/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "NVIDIA RAPIDS devcontainer build utilities", "id": "rapids-build-utils", - "version": "24.2.7", + "version": "24.2.8", "description": "A feature to install the RAPIDS devcontainer build utilities", "containerEnv": { "BASH_ENV": "/etc/bash.bash_env" diff --git a/features/src/rapids-build-utils/install.sh b/features/src/rapids-build-utils/install.sh index 49b9fc0d..425c18fd 100644 --- a/features/src/rapids-build-utils/install.sh +++ b/features/src/rapids-build-utils/install.sh @@ -11,15 +11,16 @@ check_packages bc jq sudo wget gettext-base bash-completion ca-certificates; # Install yq if not installed if ! type yq >/dev/null 2>&1; then - YQ_VERSION=latest; - find_version_from_git_tags YQ_VERSION https://github.com/mikefarah/yq; - YQ_BINARY="yq"; YQ_BINARY+="_$(uname -s | tr '[:upper:]' '[:lower:]')"; YQ_BINARY+="_${TARGETARCH:-$(dpkg --print-architecture | awk -F'-' '{print $NF}')}"; - wget --no-hsts -q -O- "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${YQ_BINARY}.tar.gz" \ - | tar -C /usr/bin -zf - -x ./${YQ_BINARY} --transform="s/${YQ_BINARY}/yq/"; + YQ_VERSION=latest; + find_version_from_git_tags YQ_VERSION https://github.com/mikefarah/yq; + while ! wget --no-hsts -q -O- "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${YQ_BINARY}.tar.gz" | tar -C /usr/bin -zf - -x ./${YQ_BINARY} --transform="s/${YQ_BINARY}/yq/"; do + echo "(!) YQ version ${YQ_VERSION} failed to download. Attempting to fall back one version to retry..."; + find_prev_version_from_git_tags YQ_VERSION https://github.com/mikefarah/yq; + done fi # Install the rapids dependency file generator and conda-merge diff --git a/features/src/sccache/devcontainer-feature.json b/features/src/sccache/devcontainer-feature.json index 71244954..49146b5f 100644 --- a/features/src/sccache/devcontainer-feature.json +++ b/features/src/sccache/devcontainer-feature.json @@ -1,14 +1,14 @@ { "name": "sccache", "id": "sccache", - "version": "24.2.1", + "version": "24.2.2", "description": "A feature to install sccache", "options": { "version": { "type": "string", "proposals": [ "latest", - "0.7.4", + "0.7.7", "0.4.0", "0.3.1", "0.3.0", diff --git a/features/src/utils/devcontainer-feature.json b/features/src/utils/devcontainer-feature.json index 9096df9e..49a7fc6b 100644 --- a/features/src/utils/devcontainer-feature.json +++ b/features/src/utils/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "devcontainer-utils", "id": "utils", - "version": "24.2.7", + "version": "24.2.8", "description": "A feature to install RAPIDS devcontainer utility scripts", "containerEnv": { "BASH_ENV": "/etc/bash.bash_env" diff --git a/features/src/utils/install.sh b/features/src/utils/install.sh index 4681cd6a..53cbfcc9 100644 --- a/features/src/utils/install.sh +++ b/features/src/utils/install.sh @@ -32,15 +32,16 @@ fi # Install yq if not installed if ! type yq >/dev/null 2>&1; then - YQ_VERSION=latest; - find_version_from_git_tags YQ_VERSION https://github.com/mikefarah/yq; - YQ_BINARY="yq"; YQ_BINARY+="_$(uname -s | tr '[:upper:]' '[:lower:]')"; YQ_BINARY+="_${TARGETARCH:-$(dpkg --print-architecture | awk -F'-' '{print $NF}')}"; - wget --no-hsts -q -O- "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${YQ_BINARY}.tar.gz" \ - | tar -C /usr/bin -zf - -x ./${YQ_BINARY} --transform="s/${YQ_BINARY}/yq/"; + YQ_VERSION=latest; + find_version_from_git_tags YQ_VERSION https://github.com/mikefarah/yq; + while ! wget --no-hsts -q -O- "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${YQ_BINARY}.tar.gz" | tar -C /usr/bin -zf - -x ./${YQ_BINARY} --transform="s/${YQ_BINARY}/yq/"; do + echo "(!) YQ version ${YQ_VERSION} failed to download. Attempting to fall back one version to retry..."; + find_prev_version_from_git_tags YQ_VERSION https://github.com/mikefarah/yq; + done fi # Remove built-in anacron configs diff --git a/features/src/utils/opt/devcontainer/bin/vault/s3/creds/persist.sh b/features/src/utils/opt/devcontainer/bin/vault/s3/creds/persist.sh index bbd78d51..d9886982 100755 --- a/features/src/utils/opt/devcontainer/bin/vault/s3/creds/persist.sh +++ b/features/src/utils/opt/devcontainer/bin/vault/s3/creds/persist.sh @@ -38,7 +38,6 @@ store_s3_creds() { local region=; local no_bucket=; local no_region=; - local no_credentials=; local aws_access_key_id=; local aws_session_token=; local aws_secret_access_key=; @@ -50,7 +49,6 @@ store_s3_creds() { region | no_bucket | no_region | - no_credentials | aws_access_key_id | aws_session_token | aws_secret_access_key | @@ -64,7 +62,6 @@ store_s3_creds() { reset_envvar "AWS_ACCESS_KEY_ID"; reset_envvar "AWS_SESSION_TOKEN"; reset_envvar "AWS_SECRET_ACCESS_KEY"; - reset_envvar "SCCACHE_S3_NO_CREDENTIALS"; mkdir -p ~/.aws; rm -f ~/.aws/{config,credentials}; @@ -92,41 +89,37 @@ ________EOF fi if test -f ~/.aws/config; then - cat <<________EOF > ~/.aws/config + cat <<________EOF > ~/.aws/config2 && mv ~/.aws/config{2,} [default] $(cat ~/.aws/config) ________EOF fi - if ! grep -qE "^$" <<< "${no_credentials:-}"; then - export_envvar "SCCACHE_S3_NO_CREDENTIALS" "1"; - else - if ! grep -qE "^$" <<< "${aws_access_key_id:-}"; then - cat <<____________EOF >> ~/.aws/credentials + if ! grep -qE "^$" <<< "${aws_access_key_id:-}"; then + cat <<________EOF >> ~/.aws/credentials aws_access_key_id=${aws_access_key_id} -____________EOF - fi +________EOF + fi - if ! grep -qE "^$" <<< "${aws_session_token:-}"; then - cat <<____________EOF >> ~/.aws/credentials + if ! grep -qE "^$" <<< "${aws_session_token:-}"; then + cat <<________EOF >> ~/.aws/credentials aws_session_token=${aws_session_token} -____________EOF - fi +________EOF + fi - if ! grep -qE "^$" <<< "${aws_secret_access_key:-}"; then - cat <<____________EOF >> ~/.aws/credentials + if ! grep -qE "^$" <<< "${aws_secret_access_key:-}"; then + cat <<________EOF >> ~/.aws/credentials aws_secret_access_key=${aws_secret_access_key} -____________EOF - fi +________EOF + fi - if test -f ~/.aws/credentials; then - cat <<____________EOF > ~/.aws/credentials + if test -f ~/.aws/credentials; then + cat <<________EOF > ~/.aws/credentials2 && mv ~/.aws/credentials{2,} [default] $(cat ~/.aws/credentials) -____________EOF - chmod 0600 ~/.aws/credentials; - fi +________EOF + chmod 0600 ~/.aws/credentials; fi } diff --git a/features/src/utils/opt/devcontainer/bin/vault/s3/creds/propagate.sh b/features/src/utils/opt/devcontainer/bin/vault/s3/creds/propagate.sh index 941905dd..e0d00085 100755 --- a/features/src/utils/opt/devcontainer/bin/vault/s3/creds/propagate.sh +++ b/features/src/utils/opt/devcontainer/bin/vault/s3/creds/propagate.sh @@ -16,7 +16,7 @@ ensure_s3_creds_have_propagated() { while true; do - if SCCACHE_NO_DAEMON=1 sccache --show-stats >/dev/null 2>&1; then + if sccache --start-server >/dev/null 2>&1; then if [ "${num_restarts}" -gt "0" ]; then echo "Success!"; fi exit 0; fi diff --git a/features/src/utils/opt/devcontainer/bin/vault/s3/creds/test.sh b/features/src/utils/opt/devcontainer/bin/vault/s3/creds/test.sh index 85a1f46f..dc2fe7ad 100755 --- a/features/src/utils/opt/devcontainer/bin/vault/s3/creds/test.sh +++ b/features/src/utils/opt/devcontainer/bin/vault/s3/creds/test.sh @@ -17,47 +17,25 @@ test_aws_creds() { fi fi - local bucket="${SCCACHE_BUCKET:-"$(grep 'bucket=' ~/.aws/config 2>/dev/null | sed 's/bucket=//' || echo)"}"; + local bucket="${SCCACHE_BUCKET:-"$(sed -n 's/bucket=//p' ~/.aws/config 2>/dev/null)"}"; if [ -z "${bucket:-}" ]; then exit 1; fi - local region="${SCCACHE_REGION:-"${AWS_DEFAULT_REGION:-"$(grep 'region=' ~/.aws/config 2>/dev/null | sed 's/region=//' || echo)"}"}"; - local aws_access_key_id="${AWS_ACCESS_KEY_ID:-"$(grep 'aws_access_key_id=' ~/.aws/credentials 2>/dev/null | sed 's/aws_access_key_id=//' || echo)"}"; - local aws_session_token="${AWS_SESSION_TOKEN:-"$(grep 'aws_session_token=' ~/.aws/credentials 2>/dev/null | sed 's/aws_session_token=//' || echo)"}"; - local aws_secret_access_key="${AWS_SECRET_ACCESS_KEY:-"$(grep 'aws_secret_access_key=' ~/.aws/credentials 2>/dev/null | sed 's/aws_secret_access_key=//' || echo)"}"; + local region="${SCCACHE_REGION:-"${AWS_DEFAULT_REGION:-"$(sed -n 's/region=//p' ~/.aws/config 2>/dev/null)"}"}"; + local aws_access_key_id="${AWS_ACCESS_KEY_ID:-"$(sed -n 's/aws_access_key_id=//p' ~/.aws/credentials 2>/dev/null)"}"; + local aws_session_token="${AWS_SESSION_TOKEN:-"$(sed -n 's/aws_session_token=//p' ~/.aws/credentials 2>/dev/null)"}"; + local aws_secret_access_key="${AWS_SECRET_ACCESS_KEY:-"$(sed -n 's/aws_secret_access_key=//p' ~/.aws/credentials 2>/dev/null)"}"; if test -n "$(pgrep sccache || echo)"; then sccache --stop-server >/dev/null 2>&1 || true; fi - export SCCACHE_NO_DAEMON="1"; - export SCCACHE_BUCKET="${bucket:-}"; - export SCCACHE_REGION="${region:-}"; - export AWS_ACCESS_KEY_ID="${aws_access_key_id:-}"; - export AWS_SESSION_TOKEN="${aws_session_token:-}"; - export AWS_SECRET_ACCESS_KEY="${aws_secret_access_key:-}"; - - if ! sccache --show-stats 2>&1 | grep -qE 'Cache location \s+ s3'; then - - export SCCACHE_S3_NO_CREDENTIALS="1"; - - export AWS_ACCESS_KEY_ID=; - export AWS_SESSION_TOKEN=; - export AWS_SECRET_ACCESS_KEY=; - export -n AWS_ACCESS_KEY_ID; - export -n AWS_SESSION_TOKEN; - export -n AWS_SECRET_ACCESS_KEY; - unset AWS_ACCESS_KEY_ID; - unset AWS_SESSION_TOKEN; - unset AWS_SECRET_ACCESS_KEY; - - if sccache --show-stats 2>&1 | grep -qE 'Cache location \s+ s3'; then - exit 2; - fi - - exit 1; - fi - - exit 0; + SCCACHE_BUCKET="${bucket:-}" \ + SCCACHE_REGION="${region:-}" \ + AWS_ACCESS_KEY_ID="${aws_access_key_id:-}" \ + AWS_SESSION_TOKEN="${aws_session_token:-}" \ + AWS_SECRET_ACCESS_KEY="${aws_secret_access_key:-}" \ + sccache --start-server >/dev/null 2>&1; + sccache --show-stats | grep -qE 'Cache location \s+ s3'; } if test -n "${devcontainer_utils_debug:-}"; then diff --git a/features/src/utils/opt/devcontainer/bin/vault/s3/init.sh b/features/src/utils/opt/devcontainer/bin/vault/s3/init.sh index bcabe313..3592c2f2 100755 --- a/features/src/utils/opt/devcontainer/bin/vault/s3/init.sh +++ b/features/src/utils/opt/devcontainer/bin/vault/s3/init.sh @@ -9,9 +9,9 @@ ____EOF s3_bucket_auth() { cat <<____EOF - --aws_access_key_id='$(grep 'aws_access_key_id=' ~/.aws/credentials 2>/dev/null | sed 's/aws_access_key_id=//' || echo)' - --aws_session_token='$(grep 'aws_session_token=' ~/.aws/credentials 2>/dev/null | sed 's/aws_session_token=//' || echo)' - --aws_secret_access_key='$(grep 'aws_secret_access_key=' ~/.aws/credentials 2>/dev/null | sed 's/aws_secret_access_key=//' || echo)' + --aws_access_key_id='$(sed -n 's/aws_access_key_id=//p' ~/.aws/credentials 2>/dev/null)' + --aws_session_token='$(sed -n 's/aws_session_token=//p' ~/.aws/credentials 2>/dev/null)' + --aws_secret_access_key='$(sed -n 's/aws_secret_access_key=//p' ~/.aws/credentials 2>/dev/null)' ____EOF } @@ -25,7 +25,7 @@ init_vault_s3_creds() { && grep -qE "^$" <<< "${AWS_SECRET_ACCESS_KEY:-}" ; then if test -n "${VAULT_HOST:-}" ; then # Generate S3 creds if they don't exist (or are expired) - if devcontainer-utils-vault-s3-creds-test 2>&1 >/dev/null\ + if devcontainer-utils-vault-s3-creds-test \ || devcontainer-utils-vault-s3-creds-generate; then # Persist creds in ~/.aws dir devcontainer-utils-vault-s3-creds-persist <<< " @@ -37,34 +37,21 @@ init_vault_s3_creds() { else devcontainer-utils-vault-s3-creds-persist <<< "--no_bucket --no_region"; fi + elif devcontainer-utils-vault-s3-creds-test; then + # bucket is read + write with the current credentials + devcontainer-utils-vault-s3-creds-persist <<< " + $(s3_bucket_args) + $(s3_bucket_auth) + "; else - # If credentials have been mounted in, ensure they're used - case $(devcontainer-utils-vault-s3-creds-test; echo $?) in - # bucket is read + write with the current credentials - [0] ) - devcontainer-utils-vault-s3-creds-persist <<< " - $(s3_bucket_args) - $(s3_bucket_auth) - ";; - # bucket is read-only and should be accessed without credentials - [2] ) - devcontainer-utils-vault-s3-creds-persist <<< " - --no_credentials - $(s3_bucket_args) - ";; - # bucket is inaccessible - * ) - devcontainer-utils-vault-s3-creds-persist <<< "--no_bucket --no_region";; - esac + # bucket is inaccessible + devcontainer-utils-vault-s3-creds-persist <<< "--no_bucket --no_region"; fi - elif devcontainer-utils-vault-s3-creds-propagate; then - # Block until the new temporary AWS S3 credentials propagate - echo -n ""; + elif ! devcontainer-utils-vault-s3-creds-propagate; then + # bucket is inaccessible + devcontainer-utils-vault-s3-creds-persist <<< "--no_bucket --no_region"; fi fi - . /etc/profile.d/*-devcontainer-utils.sh; - # start the sccache server - sccache --start-server >/dev/null 2>&1 || true; fi } diff --git a/features/test/utils/scenarios.json b/features/test/utils/scenarios.json index e823e52c..4546ca7c 100644 --- a/features/test/utils/scenarios.json +++ b/features/test/utils/scenarios.json @@ -7,9 +7,7 @@ "vault_host": "${localEnv:vault_host}", "VAULT_S3_TTL": "${localEnv:VAULT_S3_TTL}", "rw_sccache_bucket": "${localEnv:rw_sccache_bucket}", - "rw_sccache_region": "${localEnv:rw_sccache_region}", - "ro_sccache_bucket": "${localEnv:ro_sccache_bucket}", - "ro_sccache_region": "${localEnv:ro_sccache_region}" + "rw_sccache_region": "${localEnv:rw_sccache_region}" }, "features": { "ghcr.io/devcontainers/features/common-utils:2": { @@ -29,7 +27,7 @@ "cmake": {}, "ninja": {}, "sccache": { - "version": "0.7.4" + "version": "0.7.7" }, "utils": {} }, @@ -53,9 +51,7 @@ "vault_host": "${localEnv:vault_host}", "VAULT_S3_TTL": "${localEnv:VAULT_S3_TTL}", "rw_sccache_bucket": "${localEnv:rw_sccache_bucket}", - "rw_sccache_region": "${localEnv:rw_sccache_region}", - "ro_sccache_bucket": "${localEnv:ro_sccache_bucket}", - "ro_sccache_region": "${localEnv:ro_sccache_region}" + "rw_sccache_region": "${localEnv:rw_sccache_region}" }, "features": { "ghcr.io/devcontainers/features/common-utils:2": { @@ -75,7 +71,7 @@ "cmake": {}, "ninja": {}, "sccache": { - "version": "0.7.4" + "version": "0.7.7" }, "utils": {} }, @@ -99,9 +95,7 @@ "vault_host": "${localEnv:vault_host}", "VAULT_S3_TTL": "${localEnv:VAULT_S3_TTL}", "rw_sccache_bucket": "${localEnv:rw_sccache_bucket}", - "rw_sccache_region": "${localEnv:rw_sccache_region}", - "ro_sccache_bucket": "${localEnv:ro_sccache_bucket}", - "ro_sccache_region": "${localEnv:ro_sccache_region}" + "rw_sccache_region": "${localEnv:rw_sccache_region}" }, "features": { "ghcr.io/devcontainers/features/common-utils:2": { @@ -121,7 +115,7 @@ "cmake": {}, "ninja": {}, "sccache": { - "version": "0.7.4" + "version": "0.7.7" }, "utils": {} }, diff --git a/features/test/utils/ubuntu18.04.sh b/features/test/utils/ubuntu18.04.sh index bb4f96c4..d83f684d 100644 --- a/features/test/utils/ubuntu18.04.sh +++ b/features/test/utils/ubuntu18.04.sh @@ -126,19 +126,6 @@ if test -n "${rw_sccache_bucket:-}"; then check "bad creds with SCCACHE_BUCKET and no VAULT_HOST uses local disk cache" bad_creds_with_sccache_bucket_and_no_vault_host_uses_local_disk_cache; fi -if test -n "${ro_sccache_bucket:-}"; then - - readonly_sccache_bucket_uses_s3_cache() { - reset_state; - SCCACHE_BUCKET="${ro_sccache_bucket}" \ - SCCACHE_REGION="${ro_sccache_region}" \ - devcontainer-utils-post-attach-command; - expect_s3_cache_is_used; - } - - check "Readonly SCCACHE_BUCKET uses S3 cache" readonly_sccache_bucket_uses_s3_cache; -fi - if test -n "${gh_token:-}" \ && test -n "${vault_host:-}" \ && test -n "${rw_sccache_bucket:-}"; then @@ -173,9 +160,9 @@ if test -n "${gh_token:-}" \ reset_state; export SCCACHE_BUCKET="${rw_sccache_bucket}"; export SCCACHE_REGION="${rw_sccache_region}"; - export AWS_ACCESS_KEY_ID="$(grep 'aws_access_key_id=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_access_key_id=//' || echo)"; - export AWS_SESSION_TOKEN="$(grep 'aws_session_token=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_session_token=//' || echo)"; - export AWS_SECRET_ACCESS_KEY="$(grep 'aws_secret_access_key=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_secret_access_key=//' || echo)"; + export AWS_ACCESS_KEY_ID="$(sed -n 's/aws_access_key_id=//p' /tmp/.aws/credentials 2>/dev/null)"; + export AWS_SESSION_TOKEN="$(sed -n 's/aws_session_token=//p' /tmp/.aws/credentials 2>/dev/null)"; + export AWS_SECRET_ACCESS_KEY="$(sed -n 's/aws_secret_access_key=//p' /tmp/.aws/credentials 2>/dev/null)"; devcontainer-utils-post-attach-command; expect_s3_cache_is_used; } diff --git a/features/test/utils/ubuntu20.04.sh b/features/test/utils/ubuntu20.04.sh index bb4f96c4..d83f684d 100644 --- a/features/test/utils/ubuntu20.04.sh +++ b/features/test/utils/ubuntu20.04.sh @@ -126,19 +126,6 @@ if test -n "${rw_sccache_bucket:-}"; then check "bad creds with SCCACHE_BUCKET and no VAULT_HOST uses local disk cache" bad_creds_with_sccache_bucket_and_no_vault_host_uses_local_disk_cache; fi -if test -n "${ro_sccache_bucket:-}"; then - - readonly_sccache_bucket_uses_s3_cache() { - reset_state; - SCCACHE_BUCKET="${ro_sccache_bucket}" \ - SCCACHE_REGION="${ro_sccache_region}" \ - devcontainer-utils-post-attach-command; - expect_s3_cache_is_used; - } - - check "Readonly SCCACHE_BUCKET uses S3 cache" readonly_sccache_bucket_uses_s3_cache; -fi - if test -n "${gh_token:-}" \ && test -n "${vault_host:-}" \ && test -n "${rw_sccache_bucket:-}"; then @@ -173,9 +160,9 @@ if test -n "${gh_token:-}" \ reset_state; export SCCACHE_BUCKET="${rw_sccache_bucket}"; export SCCACHE_REGION="${rw_sccache_region}"; - export AWS_ACCESS_KEY_ID="$(grep 'aws_access_key_id=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_access_key_id=//' || echo)"; - export AWS_SESSION_TOKEN="$(grep 'aws_session_token=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_session_token=//' || echo)"; - export AWS_SECRET_ACCESS_KEY="$(grep 'aws_secret_access_key=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_secret_access_key=//' || echo)"; + export AWS_ACCESS_KEY_ID="$(sed -n 's/aws_access_key_id=//p' /tmp/.aws/credentials 2>/dev/null)"; + export AWS_SESSION_TOKEN="$(sed -n 's/aws_session_token=//p' /tmp/.aws/credentials 2>/dev/null)"; + export AWS_SECRET_ACCESS_KEY="$(sed -n 's/aws_secret_access_key=//p' /tmp/.aws/credentials 2>/dev/null)"; devcontainer-utils-post-attach-command; expect_s3_cache_is_used; } diff --git a/features/test/utils/ubuntu22.04.sh b/features/test/utils/ubuntu22.04.sh index bb4f96c4..d83f684d 100644 --- a/features/test/utils/ubuntu22.04.sh +++ b/features/test/utils/ubuntu22.04.sh @@ -126,19 +126,6 @@ if test -n "${rw_sccache_bucket:-}"; then check "bad creds with SCCACHE_BUCKET and no VAULT_HOST uses local disk cache" bad_creds_with_sccache_bucket_and_no_vault_host_uses_local_disk_cache; fi -if test -n "${ro_sccache_bucket:-}"; then - - readonly_sccache_bucket_uses_s3_cache() { - reset_state; - SCCACHE_BUCKET="${ro_sccache_bucket}" \ - SCCACHE_REGION="${ro_sccache_region}" \ - devcontainer-utils-post-attach-command; - expect_s3_cache_is_used; - } - - check "Readonly SCCACHE_BUCKET uses S3 cache" readonly_sccache_bucket_uses_s3_cache; -fi - if test -n "${gh_token:-}" \ && test -n "${vault_host:-}" \ && test -n "${rw_sccache_bucket:-}"; then @@ -173,9 +160,9 @@ if test -n "${gh_token:-}" \ reset_state; export SCCACHE_BUCKET="${rw_sccache_bucket}"; export SCCACHE_REGION="${rw_sccache_region}"; - export AWS_ACCESS_KEY_ID="$(grep 'aws_access_key_id=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_access_key_id=//' || echo)"; - export AWS_SESSION_TOKEN="$(grep 'aws_session_token=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_session_token=//' || echo)"; - export AWS_SECRET_ACCESS_KEY="$(grep 'aws_secret_access_key=' /tmp/.aws/credentials 2>/dev/null | sed 's/aws_secret_access_key=//' || echo)"; + export AWS_ACCESS_KEY_ID="$(sed -n 's/aws_access_key_id=//p' /tmp/.aws/credentials 2>/dev/null)"; + export AWS_SESSION_TOKEN="$(sed -n 's/aws_session_token=//p' /tmp/.aws/credentials 2>/dev/null)"; + export AWS_SECRET_ACCESS_KEY="$(sed -n 's/aws_secret_access_key=//p' /tmp/.aws/credentials 2>/dev/null)"; devcontainer-utils-post-attach-command; expect_s3_cache_is_used; } diff --git a/image/.devcontainer/devcontainer.json b/image/.devcontainer/devcontainer.json index 920de53d..63a5217f 100644 --- a/image/.devcontainer/devcontainer.json +++ b/image/.devcontainer/devcontainer.json @@ -27,7 +27,7 @@ "./features/src/cmake": {}, "./features/src/ninja": {}, "./features/src/sccache": { - "version": "0.7.4" + "version": "0.7.7" }, "./features/src/utils": {} }, From de5bd9424f4865052a4421f68ffcbc95d8b196ac Mon Sep 17 00:00:00 2001 From: Mike Sarahan Date: Wed, 21 Feb 2024 08:29:24 -0600 Subject: [PATCH 16/19] Apply suggestions from code review Co-authored-by: Mark Harris <783069+harrism@users.noreply.github.com> --- USAGE_IN_PROJECT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/USAGE_IN_PROJECT.md b/USAGE_IN_PROJECT.md index 37f066c8..a4d31361 100644 --- a/USAGE_IN_PROJECT.md +++ b/USAGE_IN_PROJECT.md @@ -89,7 +89,7 @@ blue box in the lower left of the VS Code window should now read `Dev Container @ `. You're done! Any terminal you open will have the build environment activated appropriately. -7. The devcontainers adds build scripts that fit general usage. Type `build-` and hit +7. The devcontainers add build scripts that fit general usage. Type `build-` and hit `TAB` to see options for your project. Check the contributing guide in your repo for further instructions. @@ -142,7 +142,7 @@ You can also provide devcontainer label (folder name) directly: 4. The devcontainer will be built, and you'll be dropped at a shell prompt inside the container. You're done! -5. The devcontainers adds build scripts that fit general usage. Type `build-` +5. The devcontainers add build scripts that fit general usage. Type `build-` and hit `TAB` to see options for the project. Check the contributing guide in your repo for further instructions. From 239106edc333d6e962268b2a8b59001f3c4e0349 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Mon, 15 Apr 2024 09:22:16 -0700 Subject: [PATCH 17/19] Make PATH usage of launch script consistent --- USAGE_IN_PROJECT.md | 10 +++++----- .../launch-devcontainer.sh => bin/launch-devcontainer | 0 2 files changed, 5 insertions(+), 5 deletions(-) rename scripts/launch-devcontainer.sh => bin/launch-devcontainer (100%) diff --git a/USAGE_IN_PROJECT.md b/USAGE_IN_PROJECT.md index a4d31361..a228bf7c 100644 --- a/USAGE_IN_PROJECT.md +++ b/USAGE_IN_PROJECT.md @@ -112,17 +112,17 @@ better. **Steps** -1. Download the [launch-devcontainer.sh script](./scripts/launch-devcontainer.sh) and - put it somewhere on PATH. If your project has its own launch script, use it +1. Download the [launch-devcontainer script](./bin/launch-devcontainer) and + [put it somewhere on PATH](https://phoenixnap.com/kb/linux-add-to-path). If your project has its own launch script, use it here instead. 2. Set your current working directory to the root of your repo containing the .devcontainer folder -3. Run the launch-container.sh script. Called without arguments, you'll get a menu of containers to choose from: +3. Run the launch-devcontainer script. Called without arguments, you'll get a menu of containers to choose from: ``` -$ ./launch-devcontainer.sh +$ launch-devcontainer Using devcontainers in /workspaces/devcontainers. Select a container (or provide it as a positional argument): 1) cuda11.8-conda @@ -136,7 +136,7 @@ Select a container (or provide it as a positional argument): You can also provide devcontainer label (folder name) directly: ``` -./launch-devcontainer.sh cuda12.0-conda +launch-devcontainer cuda12.0-conda ``` 4. The devcontainer will be built, and you'll be dropped at a shell prompt diff --git a/scripts/launch-devcontainer.sh b/bin/launch-devcontainer similarity index 100% rename from scripts/launch-devcontainer.sh rename to bin/launch-devcontainer From 4e72a50c4e5438ccd7fffd32a0b29d7816945044 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Mon, 15 Apr 2024 09:32:51 -0700 Subject: [PATCH 18/19] refine wording of develop shell scripts --- DEVELOP.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/DEVELOP.md b/DEVELOP.md index 61f57497..49de1cd9 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -124,9 +124,10 @@ Base images are composed from individual features in [matrix.yml](./matrix.yml) using [YAML anchors](https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/). These get built on Github Actions as described -[above](#github-actions-automations) The devcontainers repo does not contain -scripts to facilitate building one particular image. Some downstream repos have -such scripts for their reduced subspace of the matrix. An example is CCCL's +[above](#github-actions-automations) The devcontainers repo has some generic +scripts for generating, building and launch devcontainers in the scripts folder. +Some downstream repos have related, but more specialized scripts to facilitate +working with their subspace of the configuration matrix. An example is CCCL's [make_devcontainers.sh](https://github.com/NVIDIA/cccl/blob/main/.devcontainer/make_devcontainers.sh) script. From 2f7a0c90761f042930e73745842d68028dbe8738 Mon Sep 17 00:00:00 2001 From: Michael Sarahan Date: Mon, 15 Apr 2024 12:26:47 -0700 Subject: [PATCH 19/19] minimize unnecessary diffs --- .devcontainer/build-rapids.sh | 2 +- features/src/cuda/devcontainer-feature.json | 108 ++++++++++---------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/.devcontainer/build-rapids.sh b/.devcontainer/build-rapids.sh index 1a76cb7f..48b0530a 100755 --- a/.devcontainer/build-rapids.sh +++ b/.devcontainer/build-rapids.sh @@ -47,7 +47,7 @@ build_rapids() { ( echo "building cuDF"; clean-cudf; - build-cudf -DBUILD_BENCHMARKS=ON -DNVBench_ENABLE_CUPTI=OFF --verbose + build-cudf -DBUILD_BENCHMARKS=ON --verbose sccache -s; ) 2>&1 | maybe_write_build_log cudf; diff --git a/features/src/cuda/devcontainer-feature.json b/features/src/cuda/devcontainer-feature.json index fbe363ff..4e43ee5c 100644 --- a/features/src/cuda/devcontainer-feature.json +++ b/features/src/cuda/devcontainer-feature.json @@ -25,94 +25,94 @@ "description": "Version of the CUDA Toolkit to install." }, "installCompilers": { - "type": "boolean", - "default": true, - "description": "Install NVIDIA CUDA Compiler (nvcc)" + "type": "boolean", + "default": true, + "description": "Install NVIDIA CUDA Compiler (nvcc)" }, "installProfilers": { - "type": "boolean", - "default": true, - "description": "Install NVIDIA NSight Systems Profiler (nsys)" + "type": "boolean", + "default": true, + "description": "Install NVIDIA NSight Systems Profiler (nsys)" }, "installCTKLibraries": { - "type": "boolean", - "default": true, - "description": "Shortcut to install all CUDA Toolkit Libraries" + "type": "boolean", + "default": true, + "description": "Shortcut to install all CUDA Toolkit Libraries" }, "installDevPackages": { - "type": "boolean", - "default": true, - "description": "Whether to install the CUDA dev packages (static libraries + headers)" + "type": "boolean", + "default": true, + "description": "Whether to install the CUDA dev packages (static libraries + headers)" }, "installcuDNN": { - "type": "boolean", - "default": false, - "description": "Install CUDA Deep Neural Network Library (cuDNN)" + "type": "boolean", + "default": false, + "description": "Install CUDA Deep Neural Network Library (cuDNN)" }, "installcuTensor": { - "type": "boolean", - "default": false, - "description": "Install CUDA Tensor Linear Algebra Library (cuTensor)" + "type": "boolean", + "default": false, + "description": "Install CUDA Tensor Linear Algebra Library (cuTensor)" }, "installNCCL": { - "type": "boolean", - "default": true, - "description": "Install NVIDIA Collective Communications Library (NCCL)" + "type": "boolean", + "default": true, + "description": "Install NVIDIA Collective Communications Library (NCCL)" }, "installCUDARuntime": { - "type": "boolean", - "default": true, - "description": "Install CUDA Runtime Library (cudart)" + "type": "boolean", + "default": true, + "description": "Install CUDA Runtime Library (cudart)" }, "installNVRTC": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA Runtime Compilation Library (NVRTC)" + "type": "boolean", + "default": false, + "description": "Install NVIDIA Runtime Compilation Library (NVRTC)" }, "installOpenCL": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA CUDA OpenCL Library" + "type": "boolean", + "default": false, + "description": "Install NVIDIA CUDA OpenCL Library" }, "installcuBLAS": { - "type": "boolean", - "default": false, - "description": "Install CUDA Basic Linear Algebra Library (cuBLAS)" + "type": "boolean", + "default": false, + "description": "Install CUDA Basic Linear Algebra Library (cuBLAS)" }, "installcuSPARSE": { - "type": "boolean", - "default": false, - "description": "Install CUDA Basic Linear Algebra for Sparse Matrices Library (cuSPARSE)" + "type": "boolean", + "default": false, + "description": "Install CUDA Basic Linear Algebra for Sparse Matrices Library (cuSPARSE)" }, "installcuFFT": { - "type": "boolean", - "default": false, - "description": "Install CUDA Fast Fourier Transform Library (cuFFT)" + "type": "boolean", + "default": false, + "description": "Install CUDA Fast Fourier Transform Library (cuFFT)" }, "installcuFile": { - "type": "boolean", - "default": false, - "description": "Install CUDA GPUDirect Storage API Library (cuFile)" + "type": "boolean", + "default": false, + "description": "Install CUDA GPUDirect Storage API Library (cuFile)" }, "installcuRAND": { - "type": "boolean", - "default": false, - "description": "Install CUDA Random Number Generation Library (cuRAND)" + "type": "boolean", + "default": false, + "description": "Install CUDA Random Number Generation Library (cuRAND)" }, "installcuSOLVER": { - "type": "boolean", - "default": false, - "description": "Install CUDA Direct Linear Solvers Library (cuSOLVER)" + "type": "boolean", + "default": false, + "description": "Install CUDA Direct Linear Solvers Library (cuSOLVER)" }, "installNPP": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA Performance Primitives (NPP)" + "type": "boolean", + "default": false, + "description": "Install NVIDIA Performance Primitives (NPP)" }, "installnvJPEG": { - "type": "boolean", - "default": false, - "description": "Install NVIDIA JPEG decoder, encoder, and transcoder library (nvJPEG)" + "type": "boolean", + "default": false, + "description": "Install NVIDIA JPEG decoder, encoder, and transcoder library (nvJPEG)" }, "pruneStaticLibs": { "type": "boolean",