mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-11 14:39:28 +02:00
feat: metadata mod_timestamp (#4188)
closes #4167 --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
parent
b9a08c4dc9
commit
609e7c5657
@ -17,6 +17,9 @@ gomod:
|
||||
|
||||
report_sizes: true
|
||||
|
||||
metadata:
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
|
||||
"github.com/caarlos0/log"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/gio"
|
||||
"github.com/goreleaser/goreleaser/internal/tmpl"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
)
|
||||
|
||||
@ -20,6 +22,11 @@ func (Pipe) Skip(_ *context.Context) bool { return false }
|
||||
|
||||
// Run the pipe.
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
if err := tmpl.New(ctx).ApplyAll(
|
||||
&ctx.Config.Metadata.ModTimestamp,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeArtifacts(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -57,7 +64,11 @@ func writeJSON(ctx *context.Context, j interface{}, name string) error {
|
||||
}
|
||||
path := filepath.Join(ctx.Config.Dist, name)
|
||||
log.Log.WithField("file", path).Info("writing")
|
||||
return os.WriteFile(path, bts, 0o644)
|
||||
if err := os.WriteFile(path, bts, 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gio.Chtimes(path, ctx.Config.Metadata.ModTimestamp)
|
||||
}
|
||||
|
||||
type metadata struct {
|
||||
|
@ -1,15 +1,19 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/golden"
|
||||
"github.com/goreleaser/goreleaser/internal/testctx"
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -22,42 +26,74 @@ func TestRunWithError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
ctx := testctx.NewWithCfg(
|
||||
config.Project{
|
||||
Dist: tmp,
|
||||
ProjectName: "name",
|
||||
},
|
||||
testctx.WithPreviousTag("v1.2.2"),
|
||||
testctx.WithCurrentTag("v1.2.3"),
|
||||
testctx.WithCommit("aef34a"),
|
||||
testctx.WithVersion("1.2.3"),
|
||||
testctx.WithDate(time.Date(2022, 0o1, 22, 10, 12, 13, 0, time.UTC)),
|
||||
testctx.WithFakeRuntime,
|
||||
)
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "foo",
|
||||
Path: "foo.txt",
|
||||
Type: artifact.Binary,
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Goarm: "7",
|
||||
Extra: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
})
|
||||
modTime := time.Now().AddDate(-1, 0, 0).Round(1 * time.Second).UTC()
|
||||
|
||||
getCtx := func(tmp string) *context.Context {
|
||||
ctx := testctx.NewWithCfg(
|
||||
config.Project{
|
||||
Dist: tmp,
|
||||
ProjectName: "name",
|
||||
Metadata: config.ProjectMetadata{
|
||||
ModTimestamp: "{{.Env.MOD_TS}}",
|
||||
},
|
||||
},
|
||||
testctx.WithPreviousTag("v1.2.2"),
|
||||
testctx.WithCurrentTag("v1.2.3"),
|
||||
testctx.WithCommit("aef34a"),
|
||||
testctx.WithVersion("1.2.3"),
|
||||
testctx.WithDate(time.Date(2022, 0o1, 22, 10, 12, 13, 0, time.UTC)),
|
||||
testctx.WithFakeRuntime,
|
||||
testctx.WithEnv(map[string]string{
|
||||
"MOD_TS": fmt.Sprintf("%d", modTime.Unix()),
|
||||
}),
|
||||
)
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "foo",
|
||||
Path: "foo.txt",
|
||||
Type: artifact.Binary,
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Goarm: "7",
|
||||
Extra: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
})
|
||||
return ctx
|
||||
}
|
||||
|
||||
require.NoError(t, Pipe{}.Run(ctx))
|
||||
t.Run("artifacts", func(t *testing.T) {
|
||||
requireEqualJSONFile(t, tmp, "artifacts.json")
|
||||
tmp := t.TempDir()
|
||||
ctx := getCtx(tmp)
|
||||
require.NoError(t, Pipe{}.Run(ctx))
|
||||
requireEqualJSONFile(t, tmp, "artifacts.json", modTime)
|
||||
})
|
||||
t.Run("metadata", func(t *testing.T) {
|
||||
requireEqualJSONFile(t, tmp, "metadata.json")
|
||||
tmp := t.TempDir()
|
||||
ctx := getCtx(tmp)
|
||||
require.NoError(t, Pipe{}.Run(ctx))
|
||||
requireEqualJSONFile(t, tmp, "metadata.json", modTime)
|
||||
})
|
||||
|
||||
t.Run("invalid mod metadata", func(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
ctx := getCtx(tmp)
|
||||
ctx.Config.Metadata.ModTimestamp = "not a number"
|
||||
require.ErrorIs(t, Pipe{}.Run(ctx), strconv.ErrSyntax)
|
||||
})
|
||||
|
||||
t.Run("invalid mod metadata tmpl", func(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
ctx := getCtx(tmp)
|
||||
ctx.Config.Metadata.ModTimestamp = "{{.Nope}}"
|
||||
testlib.RequireTemplateError(t, Pipe{}.Run(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
func requireEqualJSONFile(tb testing.TB, tmp, s string) {
|
||||
func requireEqualJSONFile(tb testing.TB, tmp, s string, modTime time.Time) {
|
||||
tb.Helper()
|
||||
path := filepath.Join(tmp, s)
|
||||
golden.RequireEqualJSON(tb, golden.RequireReadFile(tb, path))
|
||||
stat, err := os.Stat(path)
|
||||
require.NoError(tb, err)
|
||||
require.Equal(tb, modTime.Unix(), stat.ModTime().Unix())
|
||||
}
|
||||
|
@ -17,9 +17,7 @@ func TestString(t *testing.T) {
|
||||
|
||||
func TestSkip(t *testing.T) {
|
||||
t.Run("skip", func(t *testing.T) {
|
||||
require.True(t, Pipe{}.Skip(testctx.NewWithCfg(config.Project{
|
||||
ReportSizes: false,
|
||||
})))
|
||||
require.True(t, Pipe{}.Skip(testctx.New()))
|
||||
})
|
||||
t.Run("dont skip", func(t *testing.T) {
|
||||
require.False(t, Pipe{}.Skip(testctx.NewWithCfg(config.Project{
|
||||
|
@ -1101,6 +1101,7 @@ type Project struct {
|
||||
Chocolateys []Chocolatey `yaml:"chocolateys,omitempty" json:"chocolateys,omitempty"`
|
||||
Git Git `yaml:"git,omitempty" json:"git,omitempty"`
|
||||
ReportSizes bool `yaml:"report_sizes,omitempty" json:"report_sizes,omitempty"`
|
||||
Metadata ProjectMetadata `yaml:"metadata,omitempty" json:"metadata,omitempty"`
|
||||
|
||||
UniversalBinaries []UniversalBinary `yaml:"universal_binaries,omitempty" json:"universal_binaries,omitempty"`
|
||||
UPXs []UPX `yaml:"upx,omitempty" json:"upx,omitempty"`
|
||||
@ -1120,6 +1121,10 @@ type Project struct {
|
||||
GiteaURLs GiteaURLs `yaml:"gitea_urls,omitempty" json:"gitea_urls,omitempty"`
|
||||
}
|
||||
|
||||
type ProjectMetadata struct {
|
||||
ModTimestamp string `yaml:"mod_timestamp,omitempty" json:"mod_timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type GoMod struct {
|
||||
Proxy bool `yaml:"proxy,omitempty" json:"proxy,omitempty"`
|
||||
Env []string `yaml:"env,omitempty" json:"env,omitempty"`
|
||||
|
18
www/docs/customization/metadata.md
Normal file
18
www/docs/customization/metadata.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Metadata
|
||||
|
||||
> Since v1.20
|
||||
|
||||
GoReleaser creates some metadata files in the `dist` folder before it finishes
|
||||
running.
|
||||
|
||||
These are the options available:
|
||||
|
||||
```yaml
|
||||
# .goreleaser.yaml
|
||||
#
|
||||
metadata:
|
||||
# Set the modified timestamp on the metadata files.
|
||||
#
|
||||
# Templates: allowed.
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
```
|
@ -120,6 +120,7 @@ nav:
|
||||
- customization/ko.md
|
||||
- customization/sbom.md
|
||||
- customization/reportsizes.md
|
||||
- customization/metadata.md
|
||||
- Signing:
|
||||
- Checksums and artifacts: customization/sign.md
|
||||
- Docker Images and Manifests: customization/docker_sign.md
|
||||
|
Loading…
x
Reference in New Issue
Block a user