You've already forked goreleaser
							
							
				mirror of
				https://github.com/goreleaser/goreleaser.git
				synced 2025-10-30 23:58:09 +02:00 
			
		
		
		
	Merge pull request #528 from goreleaser/simplified-config
Simplified config
This commit is contained in:
		
							
								
								
									
										121
									
								
								config/config.go
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								config/config.go
									
									
									
									
									
								
							| @@ -3,11 +3,9 @@ | ||||
| package config | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/apex/log" | ||||
| 	yaml "gopkg.in/yaml.v2" | ||||
| @@ -24,9 +22,6 @@ type GitHubURLs struct { | ||||
| type Repo struct { | ||||
| 	Owner string `yaml:",omitempty"` | ||||
| 	Name  string `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // String of the repo, e.g. owner/name | ||||
| @@ -52,9 +47,6 @@ type Homebrew struct { | ||||
| 	Homepage         string       `yaml:",omitempty"` | ||||
| 	SkipUpload       bool         `yaml:"skip_upload,omitempty"` | ||||
| 	DownloadStrategy string       `yaml:"download_strategy,omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // CommitAuthor is the author of a Git commit | ||||
| @@ -67,17 +59,11 @@ type CommitAuthor struct { | ||||
| type Hooks struct { | ||||
| 	Pre  string `yaml:",omitempty"` | ||||
| 	Post string `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // IgnoredBuild represents a build ignored by the user | ||||
| type IgnoredBuild struct { | ||||
| 	Goos, Goarch, Goarm string | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Build contains the build configuration section | ||||
| @@ -92,18 +78,12 @@ type Build struct { | ||||
| 	Binary  string         `yaml:",omitempty"` | ||||
| 	Hooks   Hooks          `yaml:",omitempty"` | ||||
| 	Env     []string       `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // FormatOverride is used to specify a custom format for a specific GOOS. | ||||
| type FormatOverride struct { | ||||
| 	Goos   string `yaml:",omitempty"` | ||||
| 	Format string `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Archive config used for the archive | ||||
| @@ -115,9 +95,6 @@ type Archive struct { | ||||
| 	FormatOverrides []FormatOverride `yaml:"format_overrides,omitempty"` | ||||
| 	WrapInDirectory bool             `yaml:"wrap_in_directory,omitempty"` | ||||
| 	Files           []string         `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Release config used for the GitHub release | ||||
| @@ -126,8 +103,6 @@ type Release struct { | ||||
| 	Draft        bool   `yaml:",omitempty"` | ||||
| 	Prerelease   bool   `yaml:",omitempty"` | ||||
| 	NameTemplate string `yaml:"name_template,omitempty"` | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // FPM config | ||||
| @@ -145,9 +120,6 @@ type FPM struct { | ||||
| 	License      string            `yaml:",omitempty"` | ||||
| 	Bindir       string            `yaml:",omitempty"` | ||||
| 	Files        map[string]string `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Sign config | ||||
| @@ -175,25 +147,16 @@ type Snapcraft struct { | ||||
| 	Grade       string                          `yaml:",omitempty"` | ||||
| 	Confinement string                          `yaml:",omitempty"` | ||||
| 	Apps        map[string]SnapcraftAppMetadata `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Snapshot config | ||||
| type Snapshot struct { | ||||
| 	NameTemplate string `yaml:"name_template,omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Checksum config | ||||
| type Checksum struct { | ||||
| 	NameTemplate string `yaml:"name_template,omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Docker image config | ||||
| @@ -208,9 +171,6 @@ type Docker struct { | ||||
| 	OldTagTemplate string   `yaml:"tag_template,omitempty"` | ||||
| 	TagTemplates   []string `yaml:"tag_templates,omitempty"` | ||||
| 	Files          []string `yaml:"extra_files,omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Artifactory server configuration | ||||
| @@ -219,26 +179,17 @@ type Artifactory struct { | ||||
| 	Name     string `yaml:",omitempty"` | ||||
| 	Username string `yaml:",omitempty"` | ||||
| 	Mode     string `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Filters config | ||||
| type Filters struct { | ||||
| 	Exclude []string `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Changelog Config | ||||
| type Changelog struct { | ||||
| 	Filters Filters `yaml:",omitempty"` | ||||
| 	Sort    string  `yaml:",omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Project includes all project configuration | ||||
| @@ -263,9 +214,6 @@ type Project struct { | ||||
|  | ||||
| 	// should be set if using github enterprise | ||||
| 	GitHubURLs GitHubURLs `yaml:"github_urls,omitempty"` | ||||
|  | ||||
| 	// Capture all undefined fields and should be empty after loading | ||||
| 	XXX map[string]interface{} `yaml:",inline"` | ||||
| } | ||||
|  | ||||
| // Load config file | ||||
| @@ -284,72 +232,7 @@ func LoadReader(fd io.Reader) (config Project, err error) { | ||||
| 	if err != nil { | ||||
| 		return config, err | ||||
| 	} | ||||
| 	if err := yaml.Unmarshal(data, &config); err != nil { | ||||
| 		return config, err | ||||
| 	} | ||||
| 	err = yaml.UnmarshalStrict(data, &config) | ||||
| 	log.WithField("config", config).Debug("loaded config file") | ||||
| 	return config, checkOverflows(config) | ||||
| } | ||||
|  | ||||
| // TODO: check if we can use UnmarshalStrict instead of the manual checkOverflow | ||||
| func checkOverflows(config Project) error { | ||||
| 	var overflow = &overflowChecker{} | ||||
| 	overflow.check(config.XXX, "") | ||||
| 	overflow.check(config.Archive.XXX, "archive") | ||||
| 	for i, ov := range config.Archive.FormatOverrides { | ||||
| 		overflow.check(ov.XXX, fmt.Sprintf("archive.format_overrides[%d]", i)) | ||||
| 	} | ||||
| 	overflow.check(config.Brew.XXX, "brew") | ||||
| 	overflow.check(config.Brew.GitHub.XXX, "brew.github") | ||||
| 	for i, build := range config.Builds { | ||||
| 		overflow.check(build.XXX, fmt.Sprintf("builds[%d]", i)) | ||||
| 		overflow.check(build.Hooks.XXX, fmt.Sprintf("builds[%d].hooks", i)) | ||||
| 		for j, ignored := range build.Ignore { | ||||
| 			overflow.check(ignored.XXX, fmt.Sprintf("builds[%d].ignored_builds[%d]", i, j)) | ||||
| 		} | ||||
| 	} | ||||
| 	overflow.check(config.FPM.XXX, "fpm") | ||||
| 	overflow.check(config.Snapcraft.XXX, "snapcraft") | ||||
| 	overflow.check(config.Release.XXX, "release") | ||||
| 	overflow.check(config.Release.GitHub.XXX, "release.github") | ||||
| 	overflow.check(config.SingleBuild.XXX, "build") | ||||
| 	overflow.check(config.SingleBuild.Hooks.XXX, "builds.hooks") | ||||
| 	for i, ignored := range config.SingleBuild.Ignore { | ||||
| 		overflow.check(ignored.XXX, fmt.Sprintf("builds.ignored_builds[%d]", i)) | ||||
| 	} | ||||
| 	overflow.check(config.Snapshot.XXX, "snapshot") | ||||
| 	overflow.check(config.Checksum.XXX, "checksum") | ||||
| 	for i, docker := range config.Dockers { | ||||
| 		overflow.check(docker.XXX, fmt.Sprintf("docker[%d]", i)) | ||||
| 	} | ||||
| 	for i, artifactory := range config.Artifactories { | ||||
| 		overflow.check(artifactory.XXX, fmt.Sprintf("artifactory[%d]", i)) | ||||
| 	} | ||||
| 	overflow.check(config.Changelog.XXX, "changelog") | ||||
| 	overflow.check(config.Changelog.Filters.XXX, "changelog.filters") | ||||
| 	return overflow.err() | ||||
| } | ||||
|  | ||||
| type overflowChecker struct { | ||||
| 	fields []string | ||||
| } | ||||
|  | ||||
| func (o *overflowChecker) check(m map[string]interface{}, ctx string) { | ||||
| 	for k := range m { | ||||
| 		var key = fmt.Sprintf("%s.%s", ctx, k) | ||||
| 		if ctx == "" { | ||||
| 			key = k | ||||
| 		} | ||||
| 		o.fields = append(o.fields, key) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (o *overflowChecker) err() error { | ||||
| 	if len(o.fields) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return fmt.Errorf( | ||||
| 		"unknown fields in the config file: %s", | ||||
| 		strings.Join(o.fields, ", "), | ||||
| 	) | ||||
| 	return config, err | ||||
| } | ||||
|   | ||||
| @@ -59,10 +59,15 @@ func TestFileNotFound(t *testing.T) { | ||||
|  | ||||
| func TestInvalidFields(t *testing.T) { | ||||
| 	_, err := Load("testdata/invalid_config.yml") | ||||
| 	assert.EqualError(t, err, "unknown fields in the config file: invalid_root, archive.invalid_archive, archive.format_overrides[0].invalid_archive_fmtoverrides, brew.invalid_brew, brew.github.invalid_brew_github, builds[0].invalid_builds, builds[0].hooks.invalid_builds_hooks, builds[0].ignored_builds[0].invalid_builds_ignore, fpm.invalid_fpm, release.invalid_release, release.github.invalid_release_github, build.invalid_build, builds.hooks.invalid_build_hook, builds.ignored_builds[0].invalid_build_ignore, snapshot.invalid_snapshot, docker[0].invalid_docker, artifactory[0].invalid_artifactory, changelog.invalid_changelog, changelog.filters.invalid_filters") | ||||
| 	assert.EqualError(t, err, "yaml: unmarshal errors:\n  line 2: field invalid_yaml not found in struct config.Build") | ||||
| } | ||||
|  | ||||
| func TestInvalidYaml(t *testing.T) { | ||||
| 	_, err := Load("testdata/invalid.yml") | ||||
| 	assert.EqualError(t, err, "yaml: line 1: did not find expected node content") | ||||
| } | ||||
|  | ||||
| func TestConfigWithAnchors(t *testing.T) { | ||||
| 	_, err := Load("testdata/anchor.yaml") | ||||
| 	assert.NoError(t, err) | ||||
| } | ||||
|   | ||||
							
								
								
									
										3
									
								
								config/testdata/anchor.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								config/testdata/anchor.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| project_name: &anchor_name This string will appear as the value of two keys. | ||||
| build: | ||||
|   binary: *anchor_name | ||||
							
								
								
									
										38
									
								
								config/testdata/invalid_config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								config/testdata/invalid_config.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,37 +1,3 @@ | ||||
| invalid_root: 1 | ||||
| build: | ||||
|   invalid_build: 1 | ||||
|   hooks: | ||||
|     invalid_build_hook: 1 | ||||
|   ignore: | ||||
|   - invalid_build_ignore: 1 | ||||
| builds: | ||||
| - invalid_builds: 1 | ||||
|   hooks: | ||||
|     invalid_builds_hooks: 1 | ||||
|   ignore: | ||||
|   - invalid_builds_ignore: 1 | ||||
| archive: | ||||
|   invalid_archive: 1 | ||||
|   format_overrides: | ||||
|   - invalid_archive_fmtoverrides: 1 | ||||
| release: | ||||
|   invalid_release: 1 | ||||
|   github: | ||||
|     invalid_release_github: 1 | ||||
| brew: | ||||
|   invalid_brew: 1 | ||||
|   github: | ||||
|     invalid_brew_github: 1 | ||||
| fpm: | ||||
|   invalid_fpm: 1 | ||||
| snapshot: | ||||
|   invalid_snapshot: 1 | ||||
| dockers: | ||||
|   - invalid_docker: 1 | ||||
| artifactories: | ||||
|   - invalid_artifactory: 1 | ||||
| changelog: | ||||
|   invalid_changelog: 1 | ||||
|   filters: | ||||
|     invalid_filters: 1 | ||||
|   invalid_yaml: 1 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user