mirror of
https://github.com/goreleaser/nfpm.git
synced 2026-06-19 08:05:04 +00:00
feat: add Requires(Post) for RPMS (#1085)
* feat: add Requires(Post) for RPMS https://rpm-software-management.github.io/rpm/manual/spec.html section Dependencies * test: add acceptance test Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> Co-authored-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -202,6 +202,7 @@ func TestRPMSpecific(t *testing.T) {
|
||||
"release",
|
||||
"directories",
|
||||
"verify",
|
||||
"postrequires",
|
||||
}
|
||||
for _, name := range testNames {
|
||||
for _, arch := range formatArchs[format] {
|
||||
|
||||
@@ -220,6 +220,7 @@ func (c *Config) expandEnvVars() {
|
||||
c.Overrides[or].Recommends = c.expandEnvVarsStringSlice(c.Overrides[or].Recommends)
|
||||
c.Overrides[or].Provides = c.expandEnvVarsStringSlice(c.Overrides[or].Provides)
|
||||
c.Overrides[or].Suggests = c.expandEnvVarsStringSlice(c.Overrides[or].Suggests)
|
||||
c.Overrides[or].RPM.Requires.Post = c.expandEnvVarsStringSlice(c.Overrides[or].RPM.Requires.Post)
|
||||
c.Overrides[or].Contents = c.expandEnvVarsContents(c.Overrides[or].Contents)
|
||||
}
|
||||
c.Conflicts = c.expandEnvVarsStringSlice(c.Conflicts)
|
||||
@@ -228,6 +229,7 @@ func (c *Config) expandEnvVars() {
|
||||
c.Recommends = c.expandEnvVarsStringSlice(c.Recommends)
|
||||
c.Provides = c.expandEnvVarsStringSlice(c.Provides)
|
||||
c.Suggests = c.expandEnvVarsStringSlice(c.Suggests)
|
||||
c.RPM.Requires.Post = c.expandEnvVarsStringSlice(c.RPM.Requires.Post)
|
||||
c.Contents = c.expandEnvVarsContents(c.Contents)
|
||||
|
||||
// Basic metadata fields
|
||||
@@ -392,6 +394,7 @@ type RPM struct {
|
||||
Arch string `yaml:"arch,omitempty" json:"arch,omitempty" jsonschema:"title=architecture in rpm nomenclature"`
|
||||
BuildHost string `yaml:"buildhost,omitempty" json:"buildhost,omitempty" jsonschema:"title=host name of the build environment, default=os.Hostname()"`
|
||||
Scripts RPMScripts `yaml:"scripts,omitempty" json:"scripts,omitempty" jsonschema:"title=rpm-specific scripts"`
|
||||
Requires RPMRequires `yaml:"requires,omitempty" json:"requires,omitempty" jsonschema:"title=rpm-specific requires"`
|
||||
Group string `yaml:"group,omitempty" json:"group,omitempty" jsonschema:"title=package group,example=Unspecified"`
|
||||
Summary string `yaml:"summary,omitempty" json:"summary,omitempty" jsonschema:"title=package summary"`
|
||||
Compression string `yaml:"compression,omitempty" json:"compression,omitempty" jsonschema:"title=compression algorithm to be used,enum=gzip,enum=lzma,enum=xz,enum=zstd,default=gzip:-1"`
|
||||
@@ -407,6 +410,11 @@ type RPMScripts struct {
|
||||
Verify string `yaml:"verify,omitempty" json:"verify,omitempty" jsonschema:"title=verify script"`
|
||||
}
|
||||
|
||||
// RPMRequires represents qualified RPM Requires dependencies.
|
||||
type RPMRequires struct {
|
||||
Post []string `yaml:"post,omitempty" json:"post,omitempty" jsonschema:"title=post requires directive,example=nfpm"`
|
||||
}
|
||||
|
||||
type PackageSignature struct {
|
||||
// PGP secret key, can be ASCII-armored
|
||||
KeyFile string `yaml:"key_file,omitempty" json:"key_file,omitempty" jsonschema:"title=key file,example=key.gpg"`
|
||||
|
||||
+19
@@ -30,6 +30,9 @@ const (
|
||||
tagChangelogText = 1082
|
||||
// https://github.com/rpm-software-management/rpm/blob/master/include/rpm/rpmtag.h#L183
|
||||
tagSourcePackage = 1106
|
||||
// RPMSENSE_SCRIPT_POST marks a dependency as Requires(post).
|
||||
// https://github.com/rpm-software-management/rpm/blob/master/include/rpm/rpmds.h
|
||||
rpmSenseScriptPost = 1 << 10
|
||||
|
||||
// Symbolic link
|
||||
tagLink = 0o120000
|
||||
@@ -248,6 +251,9 @@ func buildRPMMeta(info *nfpm.Info) (*rpmpack.RPMMetaData, error) {
|
||||
if depends, err = toRelation(info.Depends); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = addPostRequires(&depends, info.RPM.Requires.Post); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if recommends, err = toRelation(info.Recommends); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -328,6 +334,19 @@ func toRelation(items []string) (rpmpack.Relations, error) {
|
||||
return relations, nil
|
||||
}
|
||||
|
||||
func addPostRequires(relations *rpmpack.Relations, items []string) error {
|
||||
for idx := range items {
|
||||
relation, err := rpmpack.NewRelation(items[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
relation.Sense |= rpmSenseScriptPost
|
||||
*relations = append(*relations, relation)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addScriptFiles(info *nfpm.Info, rpm *rpmpack.RPM) error {
|
||||
if info.RPM.Scripts.PreTrans != "" {
|
||||
data, err := os.ReadFile(info.RPM.Scripts.PreTrans)
|
||||
|
||||
@@ -22,6 +22,12 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
tagRequireFlags = 1048
|
||||
tagRequireName = 1049
|
||||
tagRequireVersion = 1050
|
||||
)
|
||||
|
||||
func exampleInfo() *nfpm.Info {
|
||||
return setDefaults(nfpm.WithDefaults(&nfpm.Info{
|
||||
Name: "foo",
|
||||
@@ -154,6 +160,50 @@ func TestRPM(t *testing.T) {
|
||||
require.Equal(t, "Foo does things", description)
|
||||
}
|
||||
|
||||
func TestRPMPostRequires(t *testing.T) {
|
||||
info := exampleInfo()
|
||||
info.RPM.Requires.Post = []string{"systemd", "coreutils >= 9.0"}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := DefaultRPM.Package(info, &buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
rpm, err := rpmutils.ReadRpm(&buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
namesRaw, err := rpm.Header.Get(tagRequireName)
|
||||
require.NoError(t, err)
|
||||
names, ok := namesRaw.([]string)
|
||||
require.True(t, ok)
|
||||
versionsRaw, err := rpm.Header.Get(tagRequireVersion)
|
||||
require.NoError(t, err)
|
||||
versions, ok := versionsRaw.([]string)
|
||||
require.True(t, ok)
|
||||
flagsRaw, err := rpm.Header.Get(tagRequireFlags)
|
||||
require.NoError(t, err)
|
||||
flags, ok := flagsRaw.([]uint32)
|
||||
require.True(t, ok)
|
||||
|
||||
requireRPMRequire(t, names, versions, flags, "systemd", "", rpmSenseScriptPost)
|
||||
requireRPMRequire(t, names, versions, flags, "coreutils", "9.0", rpmSenseScriptPost|4|8)
|
||||
}
|
||||
|
||||
func requireRPMRequire(
|
||||
t *testing.T,
|
||||
names, versions []string,
|
||||
flags []uint32,
|
||||
name, version string,
|
||||
flag uint32,
|
||||
) {
|
||||
t.Helper()
|
||||
for idx := range names {
|
||||
if names[idx] == name && versions[idx] == version && flags[idx] == flag {
|
||||
return
|
||||
}
|
||||
}
|
||||
require.Failf(t, "RPM require not found", "name=%s version=%s flag=%d", name, version, flag)
|
||||
}
|
||||
|
||||
func TestRPMRiscv64(t *testing.T) {
|
||||
f, err := os.CreateTemp(t.TempDir(), "test-riscv.rpm")
|
||||
require.NoError(t, err)
|
||||
|
||||
Vendored
+6
@@ -226,3 +226,9 @@ FROM min AS verify
|
||||
RUN rpm -V foo
|
||||
RUN rm /tmp/postinstall-proof
|
||||
RUN ! rpm -V foo
|
||||
|
||||
# ---- postrequires test ----
|
||||
FROM min AS postrequires
|
||||
RUN rpm -qp --qf '[%{REQUIRENAME} %{REQUIREFLAGS} %{REQUIREVERSION}\n]' /tmp/foo.rpm
|
||||
RUN rpm -qp --qf '[%{REQUIRENAME} %{REQUIREFLAGS} %{REQUIREVERSION}\n]' /tmp/foo.rpm | grep -E '^bash 1024 ?$'
|
||||
RUN rpm -qp --qf '[%{REQUIRENAME} %{REQUIREFLAGS} %{REQUIREVERSION}\n]' /tmp/foo.rpm | grep -E '^coreutils 1036 9\.0$'
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
name: "foo"
|
||||
arch: "${BUILD_ARCH}"
|
||||
platform: "linux"
|
||||
version: "v1.2.3"
|
||||
maintainer: "Foo Bar"
|
||||
release: "4"
|
||||
description: |
|
||||
Foo bar
|
||||
Multiple lines
|
||||
vendor: "foobar"
|
||||
homepage: "https://foobar.org"
|
||||
license: "MIT"
|
||||
contents:
|
||||
- src: ./testdata/fake
|
||||
dst: /usr/bin/fake
|
||||
rpm:
|
||||
requires:
|
||||
post:
|
||||
- bash
|
||||
- coreutils >= 9.0
|
||||
@@ -340,6 +340,12 @@ rpm:
|
||||
# The verify script runs when verifying packages using `rpm -V`.
|
||||
verify: ./scripts/verify.sh
|
||||
|
||||
# RPM specific qualified Requires dependencies.
|
||||
requires:
|
||||
# Adds `Requires(post): systemd`.
|
||||
post:
|
||||
- systemd
|
||||
|
||||
# The package group. This option is deprecated by most distros
|
||||
# but required by old distros like CentOS 5 / EL 5 and earlier.
|
||||
group: Unspecified
|
||||
|
||||
@@ -974,6 +974,10 @@
|
||||
"$ref": "#/$defs/RPMScripts",
|
||||
"title": "rpm-specific scripts"
|
||||
},
|
||||
"requires": {
|
||||
"$ref": "#/$defs/RPMRequires",
|
||||
"title": "rpm-specific requires"
|
||||
},
|
||||
"group": {
|
||||
"type": "string",
|
||||
"title": "package group",
|
||||
@@ -1015,6 +1019,22 @@
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"RPMRequires": {
|
||||
"properties": {
|
||||
"post": {
|
||||
"items": {
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"nfpm"
|
||||
]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "post requires directive"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"RPMScripts": {
|
||||
"properties": {
|
||||
"pretrans": {
|
||||
|
||||
Reference in New Issue
Block a user