Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Feature dependsOn options customization #467

Open
rubensa opened this issue May 21, 2024 · 2 comments
Open

Proposal: Feature dependsOn options customization #467

rubensa opened this issue May 21, 2024 · 2 comments

Comments

@rubensa
Copy link

rubensa commented May 21, 2024

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.
{
  "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.
{
  "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).

{
  "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.

{
  "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:
{
  "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.

@rubensa rubensa changed the title Feature dependsOn options customization Proposal: Feature dependsOn options customization May 21, 2024
@joshspicer
Copy link
Member

Thank you for the detailed outline of your thoughts! I totally agree that there's room for improvement here.

Approach (1) seems to be a really good solution/compromise here, as it unblocks "passing down" options to dependencies while still tightly coupling the child Feature to its parent. Users are able to choose if a child's option(s) are customizable OR if they should be "frozen" with this given Feature release. Of course, with each Feature release that dependency's options could be updated.

My fear with approach (2) is that it could make it easier for a user to accidentally select incompatible child/parent Features without realizing the implication (ie: A user may not realize that a dependency exists and overrides it)

@rubensa
Copy link
Author

rubensa commented Jun 5, 2024

Yes, the only thing here is that, in case of (1), to give flexibility, the amount of options to be redefined (to be passed -throw) might be huge (depending on the combination of both extension options).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants