devcontainers / devcontainers/spec

Proposal: Feature dependsOn options customization

Open
#467 3 comments 3 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
5.7k
Forks
496
PR merge metrics
No merged PRs in 30d

Description

As for now, you can define that a feature `dependsOn` another feature but you are "forced" to specify all `options` that should be used in the "parent" feature.
On the other hand, you can specify that the new feature should be installed after other feature, by specifying `installsAfter` but the other feature is not installed if the user does not specify it in _devcontainer.json_.

The problem is that you can't allow the user to specify the options for the "parent" feature and, at the same time, "force" that feature to be installed before the dependent feature (with the user specified configuration, if he specified it).

For example:

- I can have a **nvm** feature that installs **Node Version Manager**. This feature might have the `version` option where the user can specify the version of **nvm** to install.
```json
{
"id": "nvm",
"version": "0.0.1",
"name": "nvm",
"description": "Installs nvm (Node Version Manager).",
"options": {
"version": {
"type": "string",
"proposals": [
"latest",
"0.39"
],
"default": "latest",
"description": "Version of NVM to install."
}
}
}
```
- Then, you might have a **node-nvm** feature that install **Node.js** using **nvm**. This feature also has a `version` option where the user can specify the version of **Node.js** to install.
```json
{
"id": "node-nvm",
"version": "0.0.1",
"name": "Node.js (via nvm)",
"description": "Installs Node.js using nvm (Node Version Manager).",
"options": {
"version": {
"type": "string",
"proposals": [
"node",
"18",
"16",
"14"
],
"default": "node",
"description": "Select or enter a Node.js version to install"
}
}
}
```
The problem here is that, if **node-nvm** `dependsOn` **nvm**, the developer is "forced" to specify the **nvm** version that should be installed -if not specified, the default one is used- (and the user is not allowed to change it).
```json
{
"id": "node-nvm",
"version": "0.0.1",
"name": "Node.js (via nvm)",
"description": "Installs Node.js using nvm (Node Version Manager).",
"options": {
"version": {
"type": "string",
"proposals": [
"node",
"18",
"16",
"14"
],
"default": "node",
"description": "Select or enter a Node.js version to install"
}
},
"dependsOn": {
"./local-features/nvm": {}
}
}
```
If the user also specifies a **nvm** feature in _devcontainer.json_, two versions are installed (or probably only the first one installed, if the feature checks if the command is installed before trying to install it again, but the user can't be sure if the version installed is the one specified by him or the one "hard-coded" in the **node-nvm**'s _devcontainer-feature.json_).

You could also use `installAfter` so the user can configure **nvm** to specify the version he wants to install, but the problem here is that, if the user do not specify the **nvm** feature, it is not "automatically" installed.
```json
{
"id": "node-nvm",
"version": "0.0.1",
"name": "Node.js (via nvm)",
"description": "Installs Node.js using nvm (Node Version Manager).",
"options": {
"version": {
"type": "string",
"proposals": [
"node",
"18",
"16",
"14"
],
"default": "node",
"description": "Select or enter a Node.js version to install"
}
},
"installsAfter": [
"./local-features/nvm"
]
}
```

There might be two approaches here to solve the problem:

- Allow a pass-throw of options, so the **node-nvm** extension could have options to configure the "underlying" **nvm** extension and pass them on. Something like:
```json
{
"id": "node-nvm",
"version": "0.0.1",
"name": "Node.js (via nvm)",
"description": "Installs Node.js using nvm (Node Version Manager).",
"options": {
"version": {
"type": "string",
"proposals": [
"node",
"18",
"16",
"14"
],
"default": "node",
"description": "Select or enter a Node.js version to install"
},
"nvmVersion": {
"type": "string",
"proposals": [
"latest",
"0.39"
],
"default": "latest",
"description": "Version of NVM to install."
}
},
"dependsOn": {
"./local-features/nvm": {
"version": "${options.nvmVersion}"
}
}
}
```
- In `dependsOn`, allow to specify that a feature depends on other feature but, if the user already defines the feature, use the user defined feature options instead of the ones (or default ones) defined in the `dependsOn`.

To me, the second one allows for more flexibility. The user is allowed to specify how to install **nvm** so the **node-nvm** uses that config but, if the user does not explicitly specify a **nvm** configuration the one specified in **node-nvm** `dependsOn` configuration should be used.

A third approach might be the combination of both. Allow the options "pass-throw" but only apply that config if the user did not already configured the "parent" feature.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.