diff --git a/.goreleaser.yaml b/.goreleaser.yaml index feb3c4a7c..c6921bbc0 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -139,6 +139,9 @@ archives: format_overrides: - goos: windows format: zip + builds_info: + group: root + owner: root files: - README.md - LICENSE.md diff --git a/internal/pipe/archive/archive.go b/internal/pipe/archive/archive.go index efea0c785..32c2dd5d0 100644 --- a/internal/pipe/archive/archive.go +++ b/internal/pipe/archive/archive.go @@ -206,6 +206,7 @@ func doCreate(ctx *context.Context, arch config.Archive, binaries []*artifact.Ar if err := a.Add(config.File{ Source: binary.Path, Destination: dst, + Info: arch.BuildsInfo, }); err != nil { return fmt.Errorf("failed to add: '%s' -> '%s': %w", binary.Path, dst, err) } diff --git a/internal/pipe/archive/archive_test.go b/internal/pipe/archive/archive_test.go index eaef21dcb..27c7b4dc9 100644 --- a/internal/pipe/archive/archive_test.go +++ b/internal/pipe/archive/archive_test.go @@ -82,8 +82,12 @@ func TestRunPipe(t *testing.T) { ProjectName: "foobar", Archives: []config.Archive{ { - ID: "myid", - Builds: []string{"default"}, + ID: "myid", + Builds: []string{"default"}, + BuildsInfo: config.FileInfo{ + Owner: "root", + Group: "root", + }, NameTemplate: defaultNameTemplate, StripParentBinaryFolder: dets.Strip, Files: []config.File{ @@ -233,6 +237,11 @@ func TestRunPipe(t *testing.T) { }, tarFiles(t, filepath.Join(dist, name)), ) + + header := tarInfo(t, filepath.Join(dist, name), expectBin) + require.Equal(t, "root", header.Uname) + require.Equal(t, "root", header.Gname) + } } if format == "zip" { @@ -363,6 +372,27 @@ func zipFiles(t *testing.T, path string) []string { return paths } +func tarInfo(t *testing.T, path, name string) *tar.Header { + t.Helper() + f, err := os.Open(path) + require.NoError(t, err) + defer f.Close() + gr, err := gzip.NewReader(f) + require.NoError(t, err) + defer gr.Close() + r := tar.NewReader(gr) + for { + next, err := r.Next() + if err == io.EOF { + break + } + if next.Name == name { + return next + } + } + return nil +} + func tarFiles(t *testing.T, path string) []string { t.Helper() f, err := os.Open(path) diff --git a/pkg/config/config.go b/pkg/config/config.go index fbb8fa103..c8b72acee 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -480,6 +480,7 @@ type UniversalBinary struct { type Archive struct { ID string `yaml:"id,omitempty" json:"id,omitempty"` Builds []string `yaml:"builds,omitempty" json:"builds,omitempty"` + BuildsInfo FileInfo `yaml:"builds_info,omitempty" json:"builds_info,omitempty"` NameTemplate string `yaml:"name_template,omitempty" json:"name_template,omitempty"` Replacements map[string]string `yaml:"replacements,omitempty" json:"replacements,omitempty"` // Deprecated: use templates instead Format string `yaml:"format,omitempty" json:"format,omitempty"` diff --git a/www/docs/customization/archive.md b/www/docs/customization/archive.md index 230d05be8..ec4422d2b 100644 --- a/www/docs/customization/archive.md +++ b/www/docs/customization/archive.md @@ -40,6 +40,19 @@ archives: # - `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}` name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + # Sets the given file info to all the binaries included from the `builds`. + # + # Default is to use the actual binary properties. + # + # Since: v1.14.0. + builds_info: + group: root + owner: root + mode: 0644 + # format is `time.RFC3339Nano` + mtime: 2008-01-02T15:04:05Z + + # Set this to true if you want all files in the archive to be in a single directory. # If set to true and you extract the archive 'goreleaser_Linux_arm64.tar.gz', # you'll get a folder 'goreleaser_Linux_arm64'. diff --git a/www/docs/static/schema.json b/www/docs/static/schema.json index 90f566d65..5a3a22d57 100644 --- a/www/docs/static/schema.json +++ b/www/docs/static/schema.json @@ -166,6 +166,9 @@ }, "type": "array" }, + "builds_info": { + "$ref": "#/$defs/FileInfo" + }, "name_template": { "type": "string" },