Upgrade nfpm package in fleetctl (#48961)
Resolves #48954. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [X] QA'd all new/changed functionality manually Tested a package generated with new `fleetctl` on Fedora 43, Ubuntu 25.04, and Omarchy. ## fleetd/orbit/Fleet Desktop - [x] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [x] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [x] Verified that fleetd runs on macOS, Linux and Windows - [x] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary of changes * **Bug Fixes** * Improved Linux RPM packaging consistency, including more reliable output filename normalization and correct platform metadata. * Ensured RPM metadata extraction stays aligned with the updated packaging flow. * **Tests** * Added coverage for RPM filename normalization edge cases. * Updated a CPE rule validation test expectation to match the new error-string format. * **Chores** * Upgraded packaging tooling and refreshed Go dependencies. * **Security** * Removed a previously ignored CVE entry from vulnerability scan ignore settings. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
@@ -39,6 +40,23 @@ const postInstallSafeRestart = `
|
||||
fi
|
||||
`
|
||||
|
||||
// stripRPMRelease removes the "-1" release segment that nfpm (v2.21+) inserts
|
||||
// before the architecture in an RPM file name, turning
|
||||
// "fleet-osquery-1.57.0-1.x86_64.rpm" into "fleet-osquery-1.57.0.x86_64.rpm".
|
||||
//
|
||||
// Fleet never overrides the RPM release, so nfpm always uses its default of "1".
|
||||
// We strip exactly the "-1.<arch>.rpm" suffix rather than guessing the
|
||||
// version/release boundary from the file name; a name that doesn't carry that
|
||||
// suffix (e.g. "orbit-1.0.0.x86_64.rpm") is returned unchanged.
|
||||
func stripRPMRelease(filename, arch string) string {
|
||||
suffix := "-1." + arch + ".rpm"
|
||||
trimmed := strings.TrimSuffix(filename, suffix)
|
||||
if trimmed == filename {
|
||||
return filename
|
||||
}
|
||||
return trimmed + "." + arch + ".rpm"
|
||||
}
|
||||
|
||||
func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) {
|
||||
// Initialize directories
|
||||
tmpDir, err := initializeTempDir()
|
||||
@@ -185,7 +203,7 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) {
|
||||
contents := files.Contents{
|
||||
&files.Content{
|
||||
Source: filepath.Join(rootDir, "**"),
|
||||
Destination: "/",
|
||||
Destination: "",
|
||||
},
|
||||
// Symlink current into /opt/orbit/bin/orbit/orbit
|
||||
&files.Content{
|
||||
@@ -209,10 +227,10 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) {
|
||||
|
||||
// Add empty folders to be created.
|
||||
for _, emptyFolder := range []string{"/var/log/osquery", "/var/log/orbit"} {
|
||||
contents = append(contents, (&files.Content{
|
||||
contents = append(contents, &files.Content{
|
||||
Destination: emptyFolder,
|
||||
Type: "dir",
|
||||
}).WithFileInfoDefaults())
|
||||
})
|
||||
}
|
||||
|
||||
if varLibSymlink {
|
||||
@@ -228,10 +246,6 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) {
|
||||
})
|
||||
}
|
||||
|
||||
contents, err = files.ExpandContentGlobs(contents, false)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("glob contents: %w", err)
|
||||
}
|
||||
for _, c := range contents {
|
||||
log.Debug().Interface("file", c).Msg("added file")
|
||||
}
|
||||
@@ -256,6 +270,7 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) {
|
||||
info := &nfpm.Info{
|
||||
Name: "fleet-osquery",
|
||||
Version: opt.Version,
|
||||
Platform: "linux",
|
||||
Description: "Fleet osquery -- runtime and autoupdater",
|
||||
Arch: opt.Architecture,
|
||||
Maintainer: "Fleet Device Management",
|
||||
@@ -274,6 +289,17 @@ func buildNFPM(opt Options, pkger nfpm.Packager) (string, error) {
|
||||
},
|
||||
}
|
||||
filename := pkger.ConventionalFileName(info)
|
||||
if _, ok := pkger.(*rpm.RPM); ok {
|
||||
// nfpm v2.21+ started including the RPM "release" number in the
|
||||
// conventional file name (name-version-release.arch.rpm). Fleet has
|
||||
// always shipped RPMs named name-version.arch.rpm, so strip the
|
||||
// release segment to keep the output file name stable. The release is
|
||||
// still set to 1 inside the package metadata.
|
||||
//
|
||||
// ConventionalFileName above maps info.Arch to its RPM form
|
||||
// (e.g. amd64 -> x86_64), which is exactly what appears in the file name.
|
||||
filename = stripRPMRelease(filename, info.Arch)
|
||||
}
|
||||
if opt.CustomOutfile != "" {
|
||||
filename = opt.CustomOutfile
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package packaging
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestStripRPMRelease(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
in string
|
||||
arch string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "amd64 conventional name",
|
||||
in: "fleet-osquery-1.57.0-1.x86_64.rpm",
|
||||
arch: "x86_64",
|
||||
want: "fleet-osquery-1.57.0.x86_64.rpm",
|
||||
},
|
||||
{
|
||||
name: "arm64 conventional name",
|
||||
in: "fleet-osquery-1.57.0-1.aarch64.rpm",
|
||||
arch: "aarch64",
|
||||
want: "fleet-osquery-1.57.0.aarch64.rpm",
|
||||
},
|
||||
{
|
||||
name: "version with build metadata (dots preserved, only release stripped)",
|
||||
in: "fleet-osquery-1.57.0.20260708-1.x86_64.rpm",
|
||||
arch: "x86_64",
|
||||
want: "fleet-osquery-1.57.0.20260708.x86_64.rpm",
|
||||
},
|
||||
{
|
||||
name: "single-component name still strips release",
|
||||
in: "orbit-1.0.0-1.x86_64.rpm",
|
||||
arch: "x86_64",
|
||||
want: "orbit-1.0.0.x86_64.rpm",
|
||||
},
|
||||
// Edge cases: inputs that don't carry the expected "-1.<arch>.rpm"
|
||||
// suffix are returned unchanged rather than mangled. In particular, a
|
||||
// version whose last component happens to look like a release
|
||||
// ("orbit-1.0.0") must not be truncated.
|
||||
{
|
||||
name: "no release segment with version is unchanged",
|
||||
in: "orbit-1.0.0.x86_64.rpm",
|
||||
arch: "x86_64",
|
||||
want: "orbit-1.0.0.x86_64.rpm",
|
||||
},
|
||||
{
|
||||
name: "no release segment (no dash before arch) is unchanged",
|
||||
in: "foobar.x86_64.rpm",
|
||||
arch: "x86_64",
|
||||
want: "foobar.x86_64.rpm",
|
||||
},
|
||||
{
|
||||
name: "no arch segment (no dot before ext) is unchanged",
|
||||
in: "foobar.rpm",
|
||||
arch: "x86_64",
|
||||
want: "foobar.rpm",
|
||||
},
|
||||
{
|
||||
name: "arch mismatch is unchanged",
|
||||
in: "fleet-osquery-1.57.0-1.aarch64.rpm",
|
||||
arch: "x86_64",
|
||||
want: "fleet-osquery-1.57.0-1.aarch64.rpm",
|
||||
},
|
||||
{
|
||||
name: "empty arch is a no-op",
|
||||
in: "fleet-osquery-1.57.0-1.x86_64.rpm",
|
||||
arch: "",
|
||||
want: "fleet-osquery-1.57.0-1.x86_64.rpm",
|
||||
},
|
||||
{
|
||||
name: "empty filename is unchanged",
|
||||
in: "",
|
||||
arch: "x86_64",
|
||||
want: "",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.Equal(t, tc.want, stripRPMRelease(tc.in, tc.arch))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,5 @@ import "github.com/goreleaser/nfpm/v2/rpm"
|
||||
// BuildRPM builds a .rpm package
|
||||
// Note: this function is not safe for concurrent use
|
||||
func BuildRPM(opt Options) (string, error) {
|
||||
return buildNFPM(opt, rpm.Default)
|
||||
return buildNFPM(opt, rpm.DefaultRPM)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user