spec icon indicating copy to clipboard operation
spec copied to clipboard

[Features] Supported Architectures/OS

Open joshspicer opened this issue 3 years ago • 13 comments

This proposal is an enhancement idea to the current dev container features proposal.


@edgonmsft @chrmarti @joshspicer @craiglpeters One other thought. I think at one point we'd discussed the idea that a feature could declare the operating systems and architectures it supports. Given the number of hiccups we've seen with arm64 installs with existing features and PRs like https://github.com/microsoft/vscode-dev-containers/pull/1513 (for Gentoo) driving things into different base OS distros, I think it may be a good idea to include this in the spec from the beginning.

We could have normalized architecture values and then support for /etc/os-release detection based on ID or ID_LIKE for distribution. We can also detect the version in a similar way. Most of the features have some code in them to detect and block based on these values. Moving it into the core spec just makes things easier for feature authors and we can provide UX hints if a feature isn't expected to work given the current environment.

e.g., something like this might work

"architectures": [ "x86_64", "arm64"],
"os": "linux",
"version": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine": true
}

...where "true" means any version.

Originally posted by @Chuxel in https://github.com/devcontainers/spec/issues/48#issuecomment-1170035230

joshspicer avatar Jun 29 '22 15:06 joshspicer

Makes sense. "version" could be "distro"? And "os": "linux" can be omitted (at least for now).

chrmarti avatar Jun 30 '22 07:06 chrmarti

Yeah that's reasonable - to make it clear this is OS stuff, we could do osVersion just to make it clear that's what the version is for. Agree that right now "linux" is implied, so probably no point in adding it until we need to.

"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine": true
}

If no osVersion is specified, it's assumed that it works for everything.

Chuxel avatar Jun 30 '22 16:06 Chuxel

This may be an uncommon case, but one of the Features I maintain runs on various architectures in Debian, but only on amd64 in Ubuntu. I know it is difficult to balance simplicity and fineness, but if such cases could be covered (or at least the Feature could be executed ignoring warnings), it would be better.

eitsupi avatar Jan 04 '23 02:01 eitsupi

"alpine": true is a little counterintuitive. Why not just alpine?

"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine"
}

BusHero avatar Jan 04 '23 06:01 BusHero

"alpine": true is a little counterintuitive. Why not just alpine?

"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine"
}

Unfortunately that wouldn't be valid json.

This may be an uncommon case, but one of the Features I maintain runs on various architectures in Debian, but only on amd64 in Ubuntu. I know it is difficult to balance simplicity and fineness, but if such cases could be covered (or at least the Feature could be executed ignoring warnings), it would be better.

This is a good point. There could be an OS and version specific override for architectures since that would be a bit of an exception case. But I've definitely seen situations where a 3p Linux package feed only contains x86 for certain distros.

"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": { "architectures": ["x86_64"] },
   "alpine": true
}

or if it was only a specific version:

"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": [ "22.04", { "version": "20.04", "architectures": ["x86_64"] } ],
   "alpine": true
}

We also need to decide if we're aligning on codenames for versions or version numbers. For x86, we'd also need to decide between "amd64" which you see pretty frequently or x86_64. Or I guess we could support both.

Chuxel avatar Jan 05 '23 15:01 Chuxel

"alpine": true is a little counterintuitive. Why not just alpine?

"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine"
}

Indeed, this is not a valid JSON.

What about making osVersion an array rather than an object? In that case, it can accept both objects and strings:

"architectures": ["x86_64", "arm64"],
"osVersion": [
   {
      "name": "debian",
      "versions": ["10", "11"]
   },
   {
      "name": "ubuntu",
      "versions": ["20.04", "18.04"]
   },
   "alpine"
]

BusHero avatar Jan 05 '23 17:01 BusHero

Hmmm. That would be more verbose for the more common case of only a subset of versions working.

Chuxel avatar Jan 05 '23 21:01 Chuxel

I'm not sure why you would make the alpine section any different to the debian or ubuntu. Its a stretch to imply alpine: true means every possible version of alpine is supported. For consistency, why not have the version array for alpine too, and it imply the set of OS versions that the component developer has tested or supports. Any JSON validation then doesn't have to have exception rules to differentiate between a string array and a boolean.

{
"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine": ["3.16", "3.17.1"]
}

Using a generalized convention labels may help avoid over-specification: "3" (all 3.x.x minor and incremental versions), "3.16" (all 3.16.x incremental versions), "3.16.3" (a specifically identified version).

aschillingpayne avatar Jan 12 '23 18:01 aschillingpayne

I'm not sure why you would make the alpine section any different to the debian or ubuntu. Its a stretch to imply alpine: true means every possible version of alpine is supported. For consistency, why not have the version array for alpine too, and it imply the set of OS versions that the component developer has tested or supports. Any JSON validation then doesn't have to have exception rules to differentiate between a string array and a boolean.

{
"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine": ["3.16", "3.17.1"]
}

Using a generalized convention labels may help avoid over-specification: "3" (all 3.x.x minor and incremental versions), "3.16" (all 3.16.x incremental versions), "3.16.3" (a specifically identified version).

It's not specific to alpine. An alternative would be "debian": [ "*" ] - it means the feature owner is not putting a specific version restriction in place.

Chuxel avatar Jan 12 '23 18:01 Chuxel

I'm not sure why you would make the alpine section any different to the debian or ubuntu. Its a stretch to imply alpine: true means every possible version of alpine is supported. For consistency, why not have the version array for alpine too, and it imply the set of OS versions that the component developer has tested or supports. Any JSON validation then doesn't have to have exception rules to differentiate between a string array and a boolean.

{
"architectures": [ "x86_64", "arm64"],
"osVersion": {
   "debian": ["10", "11"],
   "ubuntu": ["20.04", "18.04"],
   "alpine": ["3.16", "3.17.1"]
}

Using a generalized convention labels may help avoid over-specification: "3" (all 3.x.x minor and incremental versions), "3.16" (all 3.16.x incremental versions), "3.16.3" (a specifically identified version).

It's not specific to alpine. An alternative would be "debian": [ "*" ] - it means the feature owner is not putting a specific version restriction in place.

Agreed, a wildcard version identifier also occured to me, and it makes sense that it apply to any osVersion, as well as the architectures.

aschillingpayne avatar Jan 12 '23 18:01 aschillingpayne

Can we also let a feature declare the shells they support? Some features only support bash, so when I set configureZshAsDefaultShell in common-utils it generates some unexpected errors.

joshuanianji avatar Jan 04 '24 20:01 joshuanianji

At image build time we can check against /etc/os-release to decide if a feature can be installed. Other cases we might want to consider:

  • When the user picks a template in the UI, we want to list the available features. This might need the corresponding information in the devcontainer-template.json, so we don't have to pull the image just to look at /etc/os-release.
  • When the devcontainer.json is open in the editor, we might want to show warnings on features that don't support the base image's arch / OS. Not sure if that can be done without pulling the image first.

chrmarti avatar Jan 26 '24 13:01 chrmarti

Using a generalized convention labels may help avoid over-specification: "3" (all 3.x.x minor and incremental versions), "3.16" (all 3.16.x incremental versions), "3.16.3" (a specifically identified version).

It's not specific to alpine. An alternative would be "debian": [ "*" ] - it means the feature owner is not putting a specific version restriction in place.

I know this issue is kind of old but I think this feature deserves some love :-) Why not use semver version ranges like npm does?

phorcys420 avatar Jul 05 '24 07:07 phorcys420