-
Notifications
You must be signed in to change notification settings - Fork 309
[proposal] Composite Features #208
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
Conversation
|----------|------|-------------| | ||
| `id` | `string` | The ID of the Feature. This follows the same semantics of the `id` property in the `devcontainer-feature.json` file. | | ||
| `version` | `string` | The version of the Feature. This follows the same semantics of the `version` property in the `devcontainer-feature.json` file. | | ||
| `features` | `array` | An array of objects (in installation order) that define the Feature(s) that compose this Feature. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the correct installation order depend on each of the install script's requirements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd want to peek at each Feature's installsAfter
, i think. That was the primary reason that I didn't want to (for now) enable nesting composite Features. This spec does NOT let you nest one composite feature in another, making this process easier to resolve (we can "flatten" the installation from composite Features into one install order.
This is something to discuss and finalize in the spec, but we could have installation follow installsAfter
order with precedence within a composite Feature first, and then some algorithm for ordering composite Features based on that? Perhaps the other way around?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are already thinking about composite features depending on each other: Wouldn't it be simpler to avoid the additional artifact type of a "composite feature" and instead allow features to have hard dependencies in addition to the soft dependencies supported with "installAfter"? We already compute the dependency graph including cycle detection for "installAfter". (Other package management systems also seem to have only one package type that can carry code/binaries and dependencies. Do we have an example that keeps these apart?)
We could add "dependencies" to the feature metadata as an object like "features" in the devcontainer.json, so installation order is decided by the same dependency graph algorithm. A dependency would implicitly go into the "installAfter" list of the feature depending on it.
| `version` | `string` | The version of the Feature. This follows the same semantics of the `version` property in the `devcontainer-feature.json` file. | | ||
| `features` | `array` | An array of objects (in installation order) that define the Feature(s) that compose this Feature. | | ||
| `features.id` | `string` | The ID of the Feature that this Feature depends on. | | ||
| `features.version` | `string` | The version of the Feature that this Feature depends on. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if a different version is configured in the devcontainer.json?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this brings us back to similar discussion over at #44.
Maybe it would be helpful to define behavior for installing a Feature more than once. I think a goal of Features should be that they are idempotent - perhaps this would be a good time to also define some "Feature best practices" to guide authors toward the behavior we want Features to exhibit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. We already have that when you use a base image with a feature installed and you then install that feature again in a second devcontainer.json.
If the version and options objects are equal, we can optimize by running the feature only once.
Maybe a detail: The install order algorithm currently uses the feature ids to sort features that do not require a specific install order to arrive at a stable install order. With the same feature being allowed multiple times in the same install pass, we will need to include also the feature version and options object in this sorting to ensure a stable install order.
| `features` | `array` | An array of objects (in installation order) that define the Feature(s) that compose this Feature. | | ||
| `features.id` | `string` | The ID of the Feature that this Feature depends on. | | ||
| `features.version` | `string` | The version of the Feature that this Feature depends on. | | ||
| `features.detect` | `string` | A command that will be executed in a shell to determine if the Feature should be installed. If the command returns a non-zero exit code, the Feature will be installed. If the command returns a zero exit code, the remaining install steps will be skipped. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does "remaining install steps will be skipped" mean, the remaining features listed in the array will be skipped?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will clarify this - I meant that each Feature will have a detect
that will cause the further installation and merging of dev container config for that Feature. Remaining Features in the array will still be executed (and their detect phase run, too).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the examples we want to cover with this? Would this run after all previous features have detected & installed, immediately before this feature's install script would run?
| `features.id` | `string` | The ID of the Feature that this Feature depends on. | | ||
| `features.version` | `string` | The version of the Feature that this Feature depends on. | | ||
| `features.detect` | `string` | A command that will be executed in a shell to determine if the Feature should be installed. If the command returns a non-zero exit code, the Feature will be installed. If the command returns a zero exit code, the remaining install steps will be skipped. | | ||
| `features.options` | `object` | An object of key/value pairs that will be passed to the Feature's `install.sh` script. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are these merged when the same feature is installed by the devcontainer.json?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to #208 (comment)
} | ||
``` | ||
|
||
An optional `finalize.sh` script can be included, and will be fired after all Features have been installed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have good examples for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be omitted in the first pass if we find it to be unnecessary or without justification yet. I'll leave for discussion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that we are discussing various options. We should aim for as much simplicity as we can while still covering the important cases we have. It will be easier to later add to a simple design than a complex one.
Updating that featmake bash script has been deprecated in favor of a python cli program (which still going to be deprecated in the future in favor of this proposal)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very thorough and clear, thanks for putting this together! Left a couple minor comments and questions.
Co-authored-by: Brigit Murtaugh <[email protected]>
…ible dependency models.
📢 Open Questions |
closing in favor of #234 |
ref: #109
A proposal for a Composite Dev Container Feature.