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:
Lucas Manuel Rodriguez
2026-07-09 15:29:48 -03:00
committed by GitHub
parent 5cefa9d5bb
commit 21c024313a
11 changed files with 221 additions and 104 deletions
+33 -7
View File
@@ -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
}
+85
View File
@@ -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))
})
}
}
+1 -1
View File
@@ -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)
}