Skip to content

Commit

Permalink
fix: apply value as version option in devcontainer
Browse files Browse the repository at this point in the history
  • Loading branch information
kylecarbs committed Jul 26, 2023
1 parent 82204fd commit b5101f9
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 22 deletions.
22 changes: 9 additions & 13 deletions devcontainer/devcontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,41 +191,37 @@ func (s *Spec) compileFeatures(fs billy.Filesystem, scratchDir, remoteUser, dock
if err != nil {
return "", fmt.Errorf("parse feature ref %s: %w", featureRefRaw, err)
}
featureImage := featureRefParsed.Repository.Name()
featureTag := featureRefParsed.TagStr()

featureOpts := map[string]any{}
switch t := s.Features[featureRefRaw].(type) {
case string:
featureTag = t
// As a shorthand, the value of the `features`` property can be provided as a
// single string. This string is mapped to an option called version.
// https://containers.dev/implementors/features/#devcontainer-json-properties
featureOpts["version"] = t
case map[string]any:
featureOpts = t
}

featureRef := featureImage
if featureTag != "" {
featureRef += ":" + featureTag
}

// It's important for caching that this directory is static.
// If it changes on each run then the container will not be cached.
//
// devcontainers/cli has a very complex method of computing the feature
// name from the feature reference. We're just going to hash it for simplicity.
featureSha := md5.Sum([]byte(featureRef))
featureName := filepath.Base(featureImage)
featureSha := md5.Sum([]byte(featureRefRaw))
featureName := filepath.Base(featureRefParsed.Repository.Name())
featureDir := filepath.Join(featuresDir, fmt.Sprintf("%s-%x", featureName, featureSha[:4]))
err = fs.MkdirAll(featureDir, 0644)
if err != nil {
return "", err
}
spec, err := features.Extract(fs, featureDir, featureRef)
spec, err := features.Extract(fs, featureDir, featureRefRaw)
if err != nil {
return "", fmt.Errorf("extract feature %s: %w", featureRef, err)
return "", fmt.Errorf("extract feature %s: %w", featureRefRaw, err)
}
directive, err := spec.Compile(featureOpts)
if err != nil {
return "", fmt.Errorf("compile feature %s: %w", featureRef, err)
return "", fmt.Errorf("compile feature %s: %w", featureRefRaw, err)
}
featureDirectives = append(featureDirectives, directive)
}
Expand Down
21 changes: 12 additions & 9 deletions devcontainer/devcontainer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestParse(t *testing.T) {
func TestCompileWithFeatures(t *testing.T) {
t.Parallel()
registry := registrytest.New(t)
featureOne := registrytest.WriteContainer(t, registry, "coder/test:tomato", features.TarLayerMediaType, map[string]any{
featureOne := registrytest.WriteContainer(t, registry, "coder/one:tomato", features.TarLayerMediaType, map[string]any{
"install.sh": "hey",
"devcontainer-feature.json": features.Spec{
ID: "rust",
Expand All @@ -53,7 +53,7 @@ func TestCompileWithFeatures(t *testing.T) {
},
},
})
featureTwo := registrytest.WriteContainer(t, registry, "coder/test:potato", features.TarLayerMediaType, map[string]any{
featureTwo := registrytest.WriteContainer(t, registry, "coder/two:potato", features.TarLayerMediaType, map[string]any{
"install.sh": "hey",
"devcontainer-feature.json": features.Spec{
ID: "go",
Expand All @@ -63,10 +63,13 @@ func TestCompileWithFeatures(t *testing.T) {
ContainerEnv: map[string]string{
"POTATO": "example",
},
Options: map[string]features.Option{
"version": {
Type: "string",
},
},
},
})
// Update the tag to ensure it comes from the feature value!
featureTwoFake := strings.Join(append(strings.Split(featureTwo, ":")[:2], "faketag"), ":")

raw := `{
"build": {
Expand All @@ -77,7 +80,7 @@ func TestCompileWithFeatures(t *testing.T) {
"image": "codercom/code-server:latest",
"features": {
"` + featureOne + `": {},
"` + featureTwoFake + `": "potato"
"` + featureTwo + `": "potato"
}
}`
dc, err := devcontainer.Parse([]byte(raw))
Expand All @@ -95,12 +98,12 @@ func TestCompileWithFeatures(t *testing.T) {
require.Equal(t, `FROM codercom/code-server:latest
USER root
# Go potato - Example description!
ENV POTATO=example
RUN .envbuilder/features/test-`+featureTwoSha+`/install.sh
# Rust tomato - Example description!
ENV TOMATO=example
RUN .envbuilder/features/test-`+featureOneSha+`/install.sh
RUN .envbuilder/features/one-`+featureOneSha+`/install.sh
# Go potato - Example description!
ENV POTATO=example
RUN VERSION=potato .envbuilder/features/two-`+featureTwoSha+`/install.sh
USER 1000`, params.DockerfileContent)
}

Expand Down

0 comments on commit b5101f9

Please sign in to comment.