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

Warn if project.toml contains keys not supported by schema #2042

108 changes: 108 additions & 0 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2346,6 +2346,114 @@ include = [ "*.jar", "media/mountain.jpg", "/media/person.png", ]
})
})
})

when("unsupported keys for schema are present in project.toml", func() {
var tempAppDir string

it.Before(func() {
appPath := filepath.Join("testdata", "mock_app")

var err error
tempAppDir, err = os.MkdirTemp("", "unsupported-schema-keys-app")
assert.Nil(err)

h.RecursiveCopy(t, appPath, tempAppDir)
})

it.After(func() {
os.RemoveAll(tempAppDir)
})

it("reports unsupported keys with default schema", func() {
h.SkipIf(t, !pack.SupportsFeature(invoke.UnsupportedSchemaKeysWarning), "")

projectToml := `
[project]
version = "1.0.2"
source-url = "https://github.com/buildpacks/pack"

[unsupported-table]
unsupported-key = "some value"
`
err := os.WriteFile(filepath.Join(tempAppDir, "project.toml"), []byte(projectToml), 0755)
assert.Nil(err)

output := pack.RunSuccessfully(
"build", repoName,
"-p", tempAppDir,
)

assert.Contains(output, "No schema version declared in project.toml, defaulting to schema version 0.1")

assertOutput := assertions.NewOutputAssertionManager(t, output)
assertOutput.ReportsUnsupportedKeys("0.1")
assertOutput.ReportsSuccessfulImageBuild(repoName)

t.Log("app is runnable")
assertImage.RunsWithOutput(repoName, "Launch Dep Contents", "Cached Dep Contents")
})

it("reports unsupported keys with schema version 0.1", func() {
h.SkipIf(t, !pack.SupportsFeature(invoke.UnsupportedSchemaKeysWarning), "")

projectToml := `
[_]
schema-version = "0.1"

[project]
version = "1.0.2"
source-url = "https://github.com/buildpacks/pack"

[unsupported-table]
unsupported-key = "some value"
`
err := os.WriteFile(filepath.Join(tempAppDir, "project.toml"), []byte(projectToml), 0755)
assert.Nil(err)

output := pack.RunSuccessfully(
"build", repoName,
"-p", tempAppDir,
)

assert.NotContains(output, "No schema version declared in project.toml, defaulting to schema version 0.1")

assertOutput := assertions.NewOutputAssertionManager(t, output)
assertOutput.ReportsUnsupportedKeys("0.1")
assertOutput.ReportsSuccessfulImageBuild(repoName)

t.Log("app is runnable")
assertImage.RunsWithOutput(repoName, "Launch Dep Contents", "Cached Dep Contents")
})

it("reports unsupported keys with schema version 0.2", func() {
h.SkipIf(t, !pack.SupportsFeature(invoke.UnsupportedSchemaKeysWarning), "")

projectToml := `
[_]
schema-version = "0.2"
name = "project name"

[unsupported-table]
unsupported-key = "some value"
`
err := os.WriteFile(filepath.Join(tempAppDir, "project.toml"), []byte(projectToml), 0755)
assert.Nil(err)

output := pack.RunSuccessfully(
"build", repoName,
"-p", tempAppDir,
)

assert.NotContains(output, "No schema version declared in project.toml, defaulting to schema version 0.1")

assertOutput := assertions.NewOutputAssertionManager(t, output)
assertOutput.ReportsUnsupportedKeys("0.2")
assertOutput.ReportsSuccessfulImageBuild(repoName)

t.Log("app is runnable")
assertImage.RunsWithOutput(repoName, "Launch Dep Contents", "Cached Dep Contents")
})
})
})

when("build --buildpack <flattened buildpack>", func() {
Expand Down
6 changes: 6 additions & 0 deletions acceptance/assertions/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,9 @@ func (o OutputAssertionManager) ReportsInvalidBuilderToml() {

o.assert.Contains(o.output, "invalid builder toml")
}

func (o OutputAssertionManager) ReportsUnsupportedKeys(schemaVersion string) {
o.testObject.Helper()

o.assert.ContainsF(o.output, "Warning: The following keys declared in project.toml are not supported in schema version %s:\n- unsupported-table\n- unsupported-table.unsupported-key\nThe above keys will be ignored. If this is not intentional, maybe try updating your schema version.\n", schemaVersion)
}
4 changes: 4 additions & 0 deletions acceptance/invoke/pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ const (
BuildpackFlatten
MetaBuildpackFolder
PlatformRetries
UnsupportedSchemaKeysWarning
FlattenBuilderCreationV2
)

Expand Down Expand Up @@ -267,6 +268,9 @@ var featureTests = map[Feature]func(i *PackInvoker) bool{
PlatformRetries: func(i *PackInvoker) bool {
return i.atLeast("v0.32.1")
},
UnsupportedSchemaKeysWarning: func(i *PackInvoker) bool {
return i.atLeast("v0.33.0")
},
FlattenBuilderCreationV2: func(i *PackInvoker) bool {
return i.atLeast("v0.33.1")
},
Expand Down
28 changes: 26 additions & 2 deletions pkg/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
colincasey marked this conversation as resolved.
Show resolved Hide resolved

"github.com/BurntSushi/toml"
"github.com/pkg/errors"
Expand All @@ -21,7 +22,7 @@ type VersionDescriptor struct {
Project Project `toml:"_"`
}

var parsers = map[string]func(string) (types.Descriptor, error){
var parsers = map[string]func(string) (types.Descriptor, toml.MetaData, error){
"0.1": v01.NewDescriptor,
"0.2": v02.NewDescriptor,
}
Expand All @@ -45,21 +46,44 @@ func ReadProjectDescriptor(pathToFile string) (types.Descriptor, error) {

version := versionDescriptor.Project.Version
if version == "" {
fmt.Println("No schema version declared in project.toml, defaulting to schema version 0.1")
colincasey marked this conversation as resolved.
Show resolved Hide resolved
version = "0.1"
}

if _, ok := parsers[version]; !ok {
return types.Descriptor{}, fmt.Errorf("unknown project descriptor schema version %s", version)
}

descriptor, err := parsers[version](string(projectTomlContents))
descriptor, tomlMetaData, err := parsers[version](string(projectTomlContents))
if err != nil {
return types.Descriptor{}, err
}

warnIfTomlContainsKeysNotSupportedBySchema(version, tomlMetaData)

return descriptor, validate(descriptor)
}

func warnIfTomlContainsKeysNotSupportedBySchema(schemaVersion string, tomlMetaData toml.MetaData) {
unsupportedKeys := []string{}

// filter out any keys from [_]
for _, undecodedKey := range tomlMetaData.Undecoded() {
keyName := undecodedKey.String()
if keyName != "_" && !strings.HasPrefix(keyName, "_.schema-version") {
unsupportedKeys = append(unsupportedKeys, keyName)
}
}

if len(unsupportedKeys) != 0 {
fmt.Printf("Warning: The following keys declared in project.toml are not supported in schema version %s:\n", schemaVersion)
for _, unsupportedKey := range unsupportedKeys {
fmt.Printf("- %s\n", unsupportedKey)
}
fmt.Printf("The above keys will be ignored. If this is not intentional, maybe try updating your schema version.\n")
}
}

func validate(p types.Descriptor) error {
if p.Build.Exclude != nil && p.Build.Include != nil {
return errors.New("project.toml: cannot have both include and exclude defined")
Expand Down
38 changes: 38 additions & 0 deletions pkg/project/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,44 @@ name = "licenses should have either a type or uri defined"
t.Fatal("Expected error for having neither type or uri defined for licenses")
}
})

it("should allow for unsupported keys to be declared with schema v0.1", func() {
projectToml := `
[_]
schema-version = "0.1"

[unsupported-table]
unsupported-key = "some value"
`
tmpProjectToml, err := createTmpProjectTomlFile(projectToml)
if err != nil {
t.Fatal(err)
}

_, err = ReadProjectDescriptor(tmpProjectToml.Name())
if err != nil {
t.Fatal("Expected unsupported keys in schema v0.1 to not throw an error")
}
})

it("should allow for unsupported keys to be declared with schema v0.2", func() {
projectToml := `
[_]
schema-version = "0.2"

[unsupported-table]
unsupported-key = "some value"
`
tmpProjectToml, err := createTmpProjectTomlFile(projectToml)
if err != nil {
t.Fatal(err)
}

_, err = ReadProjectDescriptor(tmpProjectToml.Name())
if err != nil {
t.Fatal("Expected unsupported keys in schema v0.2 to not throw an error")
}
})
})
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/project/v01/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ type Descriptor struct {
Metadata map[string]interface{} `toml:"metadata"`
}

func NewDescriptor(projectTomlContents string) (types.Descriptor, error) {
func NewDescriptor(projectTomlContents string) (types.Descriptor, toml.MetaData, error) {
versionedDescriptor := &Descriptor{}

_, err := toml.Decode(projectTomlContents, versionedDescriptor)
tomlMetaData, err := toml.Decode(projectTomlContents, versionedDescriptor)
if err != nil {
return types.Descriptor{}, err
return types.Descriptor{}, tomlMetaData, err
}

return types.Descriptor{
Project: versionedDescriptor.Project,
Build: versionedDescriptor.Build,
Metadata: versionedDescriptor.Metadata,
SchemaVersion: api.MustParse("0.1"),
}, nil
}, tomlMetaData, nil
}
8 changes: 4 additions & 4 deletions pkg/project/v02/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ type Descriptor struct {
IO IO `toml:"io"`
}

func NewDescriptor(projectTomlContents string) (types.Descriptor, error) {
func NewDescriptor(projectTomlContents string) (types.Descriptor, toml.MetaData, error) {
versionedDescriptor := &Descriptor{}
_, err := toml.Decode(projectTomlContents, &versionedDescriptor)
tomlMetaData, err := toml.Decode(projectTomlContents, &versionedDescriptor)
if err != nil {
return types.Descriptor{}, err
return types.Descriptor{}, tomlMetaData, err
}

// backward compatibility for incorrect key
Expand All @@ -72,5 +72,5 @@ func NewDescriptor(projectTomlContents string) (types.Descriptor, error) {
},
Metadata: versionedDescriptor.Project.Metadata,
SchemaVersion: api.MustParse("0.2"),
}, nil
}, tomlMetaData, nil
}
Loading