Introduce MVP Dev Containers support (#44442)

Partially addresses #11473 

MVP of dev containers with the following capabilities:

- If in a project with `.devcontainer/devcontainer.json`, a pop-up
notification will ask if you want to open the project in a dev
container. This can be dismissed:
<img width="1478" height="1191" alt="Screenshot 2025-12-08 at 3 15
23 PM"
src="https://github.com/user-attachments/assets/ec2e20d6-28ec-4495-8f23-4c1d48a9ce78"
/>
- Similarly, if a `devcontainer.json` file is in the project, you can
open a devcontainer (or go the devcontainer.json file for further
editing) via the `open remote` modal:


https://github.com/user-attachments/assets/61f2fdaa-2808-4efc-994c-7b444a92c0b1

*Limitations*

This is a first release, and comes with some limitations:
- Zed extensions are not managed in `devcontainer.json` yet. They will
need to be installed either on host or in the container. Host +
Container sync their extensions, so there is not currently a concept of
what is installed in the container vs what is installed on host: they
come from the same list of manifests
- This implementation uses the [devcontainer
CLI](https://github.com/devcontainers/cli) for its control plane. Hence,
it does not yet support the `forwardPorts` directive. A single port can
be opened with `appPort`. See reference in docs
[here](https://github.com/devcontainers/cli/tree/main/example-usage#how-the-tool-examples-work)
- Editing devcontainer.json does not automatically cause the dev
container to be rebuilt. So if you add features, change images, etc, you
will need to `docker kill` the existing dev container before proceeding.
- Currently takes a hard dependency on `docker` being available in the
user's `PATH`.


Release Notes:

- Added ability to Open a project in a DevContainer, provided a
`.devcontainer/devcontainer.json` is present

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
This commit is contained in:
KyleBarton
2025-12-10 12:10:43 -08:00
committed by GitHub
co-authored by Danilo Leal Danilo Leal
parent a61bf33fb0
commit 3a84ec38ac
22 changed files with 1991 additions and 85 deletions
+11 -5
View File
@@ -206,14 +206,14 @@ impl NodeRuntime {
pub async fn run_npm_subcommand(
&self,
directory: &Path,
directory: Option<&Path>,
subcommand: &str,
args: &[&str],
) -> Result<Output> {
let http = self.0.lock().await.http.clone();
self.instance()
.await
.run_npm_subcommand(Some(directory), http.proxy(), subcommand, args)
.run_npm_subcommand(directory, http.proxy(), subcommand, args)
.await
}
@@ -283,7 +283,7 @@ impl NodeRuntime {
]);
// This is also wrong because the directory is wrong.
self.run_npm_subcommand(directory, "install", &arguments)
self.run_npm_subcommand(Some(directory), "install", &arguments)
.await?;
Ok(())
}
@@ -559,7 +559,10 @@ impl NodeRuntimeTrait for ManagedNodeRuntime {
command.env("PATH", env_path);
command.env(NODE_CA_CERTS_ENV_VAR, node_ca_certs);
command.arg(npm_file).arg(subcommand);
command.args(["--cache".into(), self.installation_path.join("cache")]);
command.arg(format!(
"--cache={}",
self.installation_path.join("cache").display()
));
command.args([
"--userconfig".into(),
self.installation_path.join("blank_user_npmrc"),
@@ -703,7 +706,10 @@ impl NodeRuntimeTrait for SystemNodeRuntime {
.env("PATH", path)
.env(NODE_CA_CERTS_ENV_VAR, node_ca_certs)
.arg(subcommand)
.args(["--cache".into(), self.scratch_dir.join("cache")])
.arg(format!(
"--cache={}",
self.scratch_dir.join("cache").display()
))
.args(args);
configure_npm_command(&mut command, directory, proxy);
let output = command.output().await?;