From 0c25629af794c020d89a9b3ea1e558d4fcfb9722 Mon Sep 17 00:00:00 2001 From: Erik G Date: Thu, 20 Aug 2020 06:00:17 +0200 Subject: [PATCH] feat: Introduce version_metadata for all packagers and deprecate deb.metadata. (#215) --- .../testdata/apk.env-var-version.dockerfile | 2 +- .../testdata/deb.env-var-version.dockerfile | 2 +- .../testdata/rpm.env-var-version.dockerfile | 2 +- apk/apk.go | 22 ++++++- deb/deb.go | 7 ++- deb/deb_test.go | 59 +++++++++++++++---- nfpm.go | 55 +++++++++++------ rpm/rpm.go | 12 +++- rpm/rpm_test.go | 29 +++++++-- www/docs/configuration.md | 16 ++--- 10 files changed, 155 insertions(+), 51 deletions(-) diff --git a/acceptance/testdata/apk.env-var-version.dockerfile b/acceptance/testdata/apk.env-var-version.dockerfile index 6f05a9ef..6ee0f36f 100644 --- a/acceptance/testdata/apk.env-var-version.dockerfile +++ b/acceptance/testdata/apk.env-var-version.dockerfile @@ -2,7 +2,7 @@ FROM alpine ARG package COPY ${package} /tmp/foo.apk RUN apk add --allow-untrusted /tmp/foo.apk -ENV EXPECTVER="foo-1.0.0~0.1.b1 description:" +ENV EXPECTVER="foo-1.0.0~0.1.b1+git.abcdefgh description:" RUN apk info foo | grep "foo-" | grep " description:" > found RUN export FOUND_VER="$(cat found)" && \ echo "Expected: '${EXPECTVER}' :: Found: '${FOUND_VER}'" && \ diff --git a/acceptance/testdata/deb.env-var-version.dockerfile b/acceptance/testdata/deb.env-var-version.dockerfile index 43c850ab..117f28ca 100644 --- a/acceptance/testdata/deb.env-var-version.dockerfile +++ b/acceptance/testdata/deb.env-var-version.dockerfile @@ -1,7 +1,7 @@ FROM ubuntu ARG package COPY ${package} /tmp/foo.deb -ENV EXPECTVER=" Version: 1.0.0~0.1.b1" +ENV EXPECTVER=" Version: 1.0.0~0.1.b1+git.abcdefgh" RUN dpkg --info /tmp/foo.deb | grep "Version" > found RUN export FOUND_VER="$(cat found)" && \ echo "Expected: '${EXPECTVER}' :: Found: '${FOUND_VER}'" && \ diff --git a/acceptance/testdata/rpm.env-var-version.dockerfile b/acceptance/testdata/rpm.env-var-version.dockerfile index 2922d1fe..165587da 100644 --- a/acceptance/testdata/rpm.env-var-version.dockerfile +++ b/acceptance/testdata/rpm.env-var-version.dockerfile @@ -1,7 +1,7 @@ FROM fedora ARG package COPY ${package} /tmp/foo.rpm -ENV EXPECTVER="Version : 1.0.0~0.1.b1" \ +ENV EXPECTVER="Version : 1.0.0~0.1.b1+git.abcdefgh" \ EXPECTREL="Release : 1" RUN rpm -qpi /tmp/foo.rpm | sed -e 's/ \+/ /g' | grep "Version" > found.ver RUN rpm -qpi /tmp/foo.rpm | sed -e 's/ \+/ /g' | grep "Release" > found.rel diff --git a/apk/apk.go b/apk/apk.go index 9f40df2d..a0f1aa51 100644 --- a/apk/apk.go +++ b/apk/apk.go @@ -77,7 +77,25 @@ type Apk struct{} func (a *Apk) ConventionalFileName(info *nfpm.Info) string { // TODO: verify this - return fmt.Sprintf("%s_%s_%s.apk", info.Name, info.Version, info.Arch) + arch, ok := archToAlpine[info.Arch] + if !ok { + arch = info.Arch + } + + version := info.Version + if info.Release != "" { + version += "-" + info.Release + } + + if info.Prerelease != "" { + version += "~" + info.Prerelease + } + + if info.VersionMetadata != "" { + version += "+" + info.VersionMetadata + } + + return fmt.Sprintf("%s_%s_%s.apk", info.Name, version, arch) } // Package writes a new apk package to the given writer using the given info. @@ -453,7 +471,7 @@ pkgname = {{.Info.Name}} pkgver = {{ if .Info.Epoch}}{{ .Info.Epoch }}:{{ end }}{{.Info.Version}} {{- if .Info.Release}}-{{ .Info.Release }}{{- end }} {{- if .Info.Prerelease}}~{{ .Info.Prerelease }}{{- end }} - {{- if .Info.Deb.VersionMetadata}}+{{ .Info.Deb.VersionMetadata }}{{- end }} + {{- if .Info.VersionMetadata}}+{{ .Info.VersionMetadata }}{{- end }} arch = {{.Info.Arch}} size = {{.InstalledSize}} pkgdesc = {{multiline .Info.Description}} diff --git a/deb/deb.go b/deb/deb.go index 77661daf..b77bd3fc 100644 --- a/deb/deb.go +++ b/deb/deb.go @@ -61,10 +61,15 @@ func (*Deb) ConventionalFileName(info *nfpm.Info) string { if info.Release != "" { version += "-" + info.Release } + if info.Prerelease != "" { version += "~" + info.Prerelease } + if info.VersionMetadata != "" { + version += "+" + info.VersionMetadata + } + // package_version_architecture.package-type return fmt.Sprintf("%s_%s_%s.deb", info.Name, version, arch) } @@ -502,7 +507,7 @@ Package: {{.Info.Name}} Version: {{ if .Info.Epoch}}{{ .Info.Epoch }}:{{ end }}{{.Info.Version}} {{- if .Info.Release}}-{{ .Info.Release }}{{- end }} {{- if .Info.Prerelease}}~{{ .Info.Prerelease }}{{- end }} - {{- if .Info.Deb.VersionMetadata}}+{{ .Info.Deb.VersionMetadata }}{{- end }} + {{- if .Info.VersionMetadata}}+{{ .Info.VersionMetadata }}{{- end }} Section: {{.Info.Section}} Priority: {{.Info.Priority}} Architecture: {{.Info.Arch}} diff --git a/deb/deb_test.go b/deb/deb_test.go index fa6d40a0..e791ba1f 100644 --- a/deb/deb_test.go +++ b/deb/deb_test.go @@ -121,28 +121,61 @@ func TestDebVersionWithRelease(t *testing.T) { } func TestDebVersionWithPrerelease(t *testing.T) { + var buf bytes.Buffer + info := exampleInfo() info.Version = "1.0.0" //nolint:golint,goconst info.Prerelease = "1" - var buf bytes.Buffer - var err = writeControl(&buf, controlData{info, 0}) + err := writeControl(&buf, controlData{info, 0}) require.NoError(t, err) - var v = extractDebVersion(&buf) + v := extractDebVersion(&buf) assert.Equal(t, "1.0.0~1", v) } func TestDebVersionWithReleaseAndPrerelease(t *testing.T) { + var buf bytes.Buffer + info := exampleInfo() info.Version = "1.0.0" //nolint:golint,goconst info.Release = "2" - info.Prerelease = "rc1" - var buf bytes.Buffer - var err = writeControl(&buf, controlData{info, 0}) + info.Prerelease = "rc1" //nolint:golint,goconst + err := writeControl(&buf, controlData{info, 0}) require.NoError(t, err) - var v = extractDebVersion(&buf) + v := extractDebVersion(&buf) assert.Equal(t, "1.0.0-2~rc1", v) } +func TestDebVersionWithVersionMetadata(t *testing.T) { + var buf bytes.Buffer + + info := exampleInfo() + info.Version = "1.0.0+meta" //nolint:golint,goconst + info.VersionMetadata = "" + err := writeControl(&buf, controlData{info, 0}) + require.NoError(t, err) + v := extractDebVersion(&buf) + assert.Equal(t, "1.0.0+meta", v) + + buf.Reset() + + info.Version = "1.0.0" //nolint:golint,goconst + info.VersionMetadata = "meta" + err = writeControl(&buf, controlData{info, 0}) + require.NoError(t, err) + v = extractDebVersion(&buf) + assert.Equal(t, "1.0.0+meta", v) + + buf.Reset() + + info.Version = "1.0.0+foo" //nolint:golint,goconst + info.Prerelease = "alpha" + info.VersionMetadata = "meta" + err = writeControl(&buf, controlData{nfpm.WithDefaults(info), 0}) + require.NoError(t, err) + v = extractDebVersion(&buf) + assert.Equal(t, "1.0.0~alpha+meta", v) +} + func TestControl(t *testing.T) { var w bytes.Buffer assert.NoError(t, writeControl(&w, controlData{ @@ -399,21 +432,25 @@ func TestDEBConventionalFileName(t *testing.T) { Release string Prerelease string Expected string + Metadata string }{ - {Version: "1.2.3", Release: "", Prerelease: "", + {Version: "1.2.3", Release: "", Prerelease: "", Metadata: "", Expected: fmt.Sprintf("%s_1.2.3_%s.deb", info.Name, info.Arch)}, - {Version: "1.2.3", Release: "4", Prerelease: "", + {Version: "1.2.3", Release: "4", Prerelease: "", Metadata: "", Expected: fmt.Sprintf("%s_1.2.3-4_%s.deb", info.Name, info.Arch)}, - {Version: "1.2.3", Release: "4", Prerelease: "5", + {Version: "1.2.3", Release: "4", Prerelease: "5", Metadata: "", Expected: fmt.Sprintf("%s_1.2.3-4~5_%s.deb", info.Name, info.Arch)}, - {Version: "1.2.3", Release: "", Prerelease: "5", + {Version: "1.2.3", Release: "", Prerelease: "5", Metadata: "", Expected: fmt.Sprintf("%s_1.2.3~5_%s.deb", info.Name, info.Arch)}, + {Version: "1.2.3", Release: "1", Prerelease: "5", Metadata: "git", + Expected: fmt.Sprintf("%s_1.2.3-1~5+git_%s.deb", info.Name, info.Arch)}, } for _, testCase := range testCases { info.Version = testCase.Version info.Release = testCase.Release info.Prerelease = testCase.Prerelease + info.VersionMetadata = testCase.Metadata assert.Equal(t, testCase.Expected, Default.ConventionalFileName(info)) } diff --git a/nfpm.go b/nfpm.go index 3b2a9640..53ff5a41 100644 --- a/nfpm.go +++ b/nfpm.go @@ -116,24 +116,25 @@ func (c *Config) Validate() error { // Info contains information about a single package. type Info struct { - Overridables `yaml:",inline"` - Name string `yaml:"name,omitempty"` - Arch string `yaml:"arch,omitempty"` - Platform string `yaml:"platform,omitempty"` - Epoch string `yaml:"epoch,omitempty"` - Version string `yaml:"version,omitempty"` - Release string `yaml:"release,omitempty"` - Prerelease string `yaml:"prerelease,omitempty"` - Section string `yaml:"section,omitempty"` - Priority string `yaml:"priority,omitempty"` - Maintainer string `yaml:"maintainer,omitempty"` - Description string `yaml:"description,omitempty"` - Vendor string `yaml:"vendor,omitempty"` - Homepage string `yaml:"homepage,omitempty"` - License string `yaml:"license,omitempty"` - Bindir string `yaml:"bindir,omitempty"` // Deprecated: this does nothing. TODO: remove. - Changelog string `yaml:"changelog,omitempty"` - Target string `yaml:"-"` + Overridables `yaml:",inline"` + Name string `yaml:"name,omitempty"` + Arch string `yaml:"arch,omitempty"` + Platform string `yaml:"platform,omitempty"` + Epoch string `yaml:"epoch,omitempty"` + Version string `yaml:"version,omitempty"` + Release string `yaml:"release,omitempty"` + Prerelease string `yaml:"prerelease,omitempty"` + VersionMetadata string `yaml:"version_metadata,omitempty"` + Section string `yaml:"section,omitempty"` + Priority string `yaml:"priority,omitempty"` + Maintainer string `yaml:"maintainer,omitempty"` + Description string `yaml:"description,omitempty"` + Vendor string `yaml:"vendor,omitempty"` + Homepage string `yaml:"homepage,omitempty"` + License string `yaml:"license,omitempty"` + Bindir string `yaml:"bindir,omitempty"` // Deprecated: this does nothing. TODO: remove. + Changelog string `yaml:"changelog,omitempty"` + Target string `yaml:"-"` } // Overridables contain the field which are overridable in a package. @@ -165,7 +166,7 @@ type RPM struct { type Deb struct { Scripts DebScripts `yaml:"scripts,omitempty"` Triggers DebTriggers `yaml:"triggers,omitempty"` - VersionMetadata string `yaml:"metadata,omitempty"` + VersionMetadata string `yaml:"metadata,omitempty"` // Deprecated: Moved to Info } // DebTriggers contains triggers only available for deb packages. @@ -213,6 +214,18 @@ func Validate(info *Info) error { if info.Version == "" { return ErrFieldEmpty{"version"} } + + // deprecation warnings + if info.Deb.VersionMetadata != "" { + fmt.Fprintln(os.Stderr, + "Warning: deb.metadata is deprecated and will be removed in a future version "+ + "(moved to version_metadata)") + } + + if info.Bindir != "" { + fmt.Fprintln(os.Stderr, "Warning: bindir is deprecated and will be removed in a future version") + } + return nil } @@ -232,6 +245,10 @@ func WithDefaults(info *Info) *Info { if info.Prerelease == "" { info.Prerelease = v.Prerelease() } + + if info.VersionMetadata == "" { + info.VersionMetadata = v.Metadata() + } } return info diff --git a/rpm/rpm.go b/rpm/rpm.go index 4852a260..eaa1deab 100644 --- a/rpm/rpm.go +++ b/rpm/rpm.go @@ -228,11 +228,17 @@ func buildRPMMeta(info *nfpm.Info) (*rpmpack.RPMMetaData, error) { } func formatVersion(info *nfpm.Info) string { - if info.Prerelease == "" { - return info.Version + version := info.Version + + if info.Prerelease != "" { + version += "~" + info.Prerelease + } + + if info.VersionMetadata != "" { + version += "+" + info.VersionMetadata } - return info.Version + "~" + info.Prerelease + return version } func defaultTo(in, def string) string { diff --git a/rpm/rpm_test.go b/rpm/rpm_test.go index 6c673b4c..c6b1bf80 100644 --- a/rpm/rpm_test.go +++ b/rpm/rpm_test.go @@ -249,6 +249,23 @@ func TestRPMVersionWithReleaseAndPrerelease(t *testing.T) { assert.Equal(t, "0.2", meta.Release) } +func TestRPMVersionWithVersionMetadata(t *testing.T) { + // https://fedoraproject.org/wiki/Package_Versioning_Examples#Complex_versioning_examples + info := exampleInfo() + + info.Version = "1.0.0+meta" + info.VersionMetadata = "" + meta, err := buildRPMMeta(nfpm.WithDefaults(info)) + require.NoError(t, err) + assert.Equal(t, "1.0.0+meta", meta.Version) + + info.Version = "1.0.0" + info.VersionMetadata = "meta" + meta, err = buildRPMMeta(nfpm.WithDefaults(info)) + require.NoError(t, err) + assert.Equal(t, "1.0.0+meta", meta.Version) +} + func TestWithInvalidEpoch(t *testing.T) { f, err := ioutil.TempFile("", "test.rpm") defer func() { @@ -378,21 +395,25 @@ func TestRPMConventionalFileName(t *testing.T) { Release string Prerelease string Expected string + Metadata string }{ - {Version: "1.2.3", Release: "", Prerelease: "", + {Version: "1.2.3", Release: "", Prerelease: "", Metadata: "", Expected: fmt.Sprintf("%s-1.2.3.%s.rpm", info.Name, info.Arch)}, - {Version: "1.2.3", Release: "4", Prerelease: "", + {Version: "1.2.3", Release: "4", Prerelease: "", Metadata: "", Expected: fmt.Sprintf("%s-1.2.3-4.%s.rpm", info.Name, info.Arch)}, - {Version: "1.2.3", Release: "4", Prerelease: "5", + {Version: "1.2.3", Release: "4", Prerelease: "5", Metadata: "", Expected: fmt.Sprintf("%s-1.2.3~5-4.%s.rpm", info.Name, info.Arch)}, - {Version: "1.2.3", Release: "", Prerelease: "5", + {Version: "1.2.3", Release: "", Prerelease: "5", Metadata: "", Expected: fmt.Sprintf("%s-1.2.3~5.%s.rpm", info.Name, info.Arch)}, + {Version: "1.2.3", Release: "1", Prerelease: "5", Metadata: "git", + Expected: fmt.Sprintf("%s-1.2.3~5+git-1.%s.rpm", info.Name, info.Arch)}, } for _, testCase := range testCases { info.Version = testCase.Version info.Release = testCase.Release info.Prerelease = testCase.Prerelease + info.VersionMetadata = testCase.Metadata assert.Equal(t, testCase.Expected, Default.ConventionalFileName(info)) } diff --git a/www/docs/configuration.md b/www/docs/configuration.md index e0b2d2a4..a402c015 100644 --- a/www/docs/configuration.md +++ b/www/docs/configuration.md @@ -22,14 +22,18 @@ version: v1.2.3 # Default is extracted from `version` if it is semver compatible. epoch: 2 -# Version Release. -# Default is extracted from `version` if it is semver compatible. -release: 1 - # Version Prerelease. # Default is extracted from `version` if it is semver compatible. prerelease: beta1 +# Version Metadata (previously deb.metadata). +# Default is extracted from `version` if it is semver compatible. +# Setting metadata might interfere with version comparisons depending on the packager. +version_metadata: git + +# Version Release. +release: 1 + # Section. section: default @@ -141,10 +145,6 @@ rpm: # Custon configuration applied only to the Deb packager. deb: - # Custom version metadata. - # Setting metadata might interfere with version comparisons. - metadata: xyz2 - # Custom deb rules script. scripts: rules: foo.sh