Skip to content

Commit

Permalink
feat: add inital support for source RPMs
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Jan 17, 2024
1 parent d15dab3 commit 80fd5c8
Show file tree
Hide file tree
Showing 8 changed files with 416 additions and 0 deletions.
8 changes: 8 additions & 0 deletions internal/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ const (
CArchive
// CShared is a C shared library, generated via a CGo build with buildmode=c-shared.
CShared
// SourceRPM is a source RPM.
SourceRPM
// RPMSpec is an RPM .spec file.
RPMSpec
)

func (t Type) String() string {
Expand Down Expand Up @@ -137,6 +141,10 @@ func (t Type) String() string {
return "Winget Manifest"
case Nixpkg:
return "Nixpkg"
case SourceRPM:
return "Source RPM"
case RPMSpec:
return "RPM Spec"

Check warning on line 147 in internal/artifact/artifact.go

View check run for this annotation

Codecov / codecov/patch

internal/artifact/artifact.go#L144-L147

Added lines #L144 - L147 were not covered by tests
default:
return "unknown"
}
Expand Down
65 changes: 65 additions & 0 deletions internal/pipe/srpm/spec.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Generated by goreleaser
%bcond_without check

%global goipath {{ .ImportPath }}
%global commit {{ .FullCommit }}

%%gometa -f

%global common_description %{expand:
{{ .Description }}}

{{ if .LicenseFileName }}
%global golicenses {{ .LicenseFileName }}
{{ end }}
{{ if .Docs }}
%global godocs {{ range .Docs }} {{ . }}{{ end }}
{{ end }}

Name: %{goname}
Version: {{ .Version }}
Release: %autorelease -p
Summary: {{ .Summary }}

License: {{ .License }}
URL: {{ .URL }}
Source: {{ .Source }}

%description %{common_description}

%gopkg

%prep
%goprep

%generate_buildrequires
%go_generate_buildrequires

%build
{{ range $binary, $importPath := .Bins }}
%gobuild -o %{gobuilddir}/bin/{{ $binary }} {{ $importPath }}
{{ end }}

%install
%gopkginstall
install -m 0755 -vd %{buildroot}%{_bindir}
install -m 0755 -vp %{gobuilddir}/bin/* %{buildroot}%{_bindir}/

%if %{with check}
%check
%gocheck
%endif

%files
{{ range .Docs }}
%doc {{ . }}
{{ end }}
{{ if .LicenseFileName }}
%license {{ .LicenseFileName }}
{{ end }}
%{_bindir}/*

%gopkgfiles

%changelog
%autochangelog
229 changes: 229 additions & 0 deletions internal/pipe/srpm/srpm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// Package srpm implements the Pipe interface building source RPMs.
package srpm

import (
_ "embed"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/caarlos0/log"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/skips"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/goreleaser/nfpm/v2"
"github.com/goreleaser/nfpm/v2/files"

_ "github.com/goreleaser/nfpm/v2/rpm" // blank import to register the format
)

var (
defaultFileNameTemplate = "{{ .PackageName }}-{{ .Version }}.src.rpm"
defaultSpecFileNameTemplate = "{{ .PackageName }}.spec"
)

//go:embed spec.tmpl
var defaultSpecTemplate string

// Pipe for source RPMs.
type Pipe struct{}

func (Pipe) String() string { return "source RPMs" }
func (Pipe) Skip(ctx *context.Context) bool {
return skips.Any(ctx, skips.SRPM) || !ctx.Config.SRPM.Enabled
}

// Default sets the pipe defaults.
func (Pipe) Default(ctx *context.Context) error {
srpm := &ctx.Config.SRPM
if srpm.ID == "" {
srpm.ID = "default"
}
if srpm.PackageName == "" {
srpm.PackageName = ctx.Config.ProjectName
}
if srpm.FileNameTemplate == "" {
srpm.FileNameTemplate = defaultFileNameTemplate
}
if srpm.SpecFileNameTemplate == "" {
srpm.SpecFileNameTemplate = defaultSpecFileNameTemplate
}
if srpm.SpecTemplate == "" {
srpm.SpecTemplate = defaultSpecTemplate
}
if srpm.Bins == nil {
srpm.Bins = map[string]string{
ctx.Config.ProjectName: "%{goipath}",
}
}
return nil
}

// Run the pipe.
func (Pipe) Run(ctx *context.Context) error {
sourceArchives := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableSourceArchive)).List()
if len(sourceArchives) == 0 {
return fmt.Errorf("no source archives found")

Check warning on line 68 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L68

Added line #L68 was not covered by tests
} else if len(sourceArchives) > 1 {
return fmt.Errorf("multiple source archives found")
}

Check warning on line 71 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L70-L71

Added lines #L70 - L71 were not covered by tests

srpm := ctx.Config.SRPM
sourceArchive := sourceArchives[0]

t := tmpl.New(ctx).
WithExtraFields(tmpl.Fields{
"Summary": srpm.Summary,
"Group": srpm.Group,
"PackageName": srpm.PackageName,
"Epoch": srpm.Epoch,
"Section": srpm.Section,
"Maintainer": srpm.Maintainer,
"Vendor": srpm.Vendor,
"Packager": srpm.Packager,
"ImportPath": srpm.ImportPath,
"License": srpm.License,
"LicenseFileName": srpm.LicenseFileName,
"URL": srpm.URL,
"Description": srpm.Description,
"Source": sourceArchive.Name,
"Bins": srpm.Bins,
"Docs": srpm.Docs,
})

// Generate the spec file.
specFileName, err := t.Apply(srpm.SpecFileNameTemplate)
if err != nil {
return err
}

Check warning on line 100 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L99-L100

Added lines #L99 - L100 were not covered by tests
specContents, err := t.Apply(srpm.SpecTemplate)
if err != nil {
return err
}

Check warning on line 104 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L103-L104

Added lines #L103 - L104 were not covered by tests
specPath := filepath.Join(ctx.Config.Dist, specFileName)
if err := os.WriteFile(specPath, []byte(specContents), 0o666); err != nil {
return err
}

Check warning on line 108 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L107-L108

Added lines #L107 - L108 were not covered by tests
specFileArtifact := &artifact.Artifact{
Type: artifact.RPMSpec,
Name: specFileName,
Path: specPath,
}

// Default file info.
owner := "mockbuild"
group := "mock"
mtime := ctx.Git.CommitDate

contents := files.Contents{}

// Add the source archive.
contents = append(contents, &files.Content{
Source: sourceArchive.Path,
Destination: sourceArchive.Name,
// FIXME Type:
Packager: srpm.Packager,
FileInfo: &files.ContentFileInfo{
Owner: owner,
Group: group,
Mode: 0o664, // Source archives are group-writeable by default.
MTime: mtime,
// FIXME Size:
},
})

// Add extra contents.
contents = append(contents, srpm.Contents...)

// Add the spec file.
contents = append(contents, &files.Content{
Source: specFileArtifact.Path,
Destination: specFileArtifact.Name,
// FIXME Type:
Packager: srpm.Packager,
FileInfo: &files.ContentFileInfo{
Owner: owner,
Group: group,
Mode: 0o660, // Spec files are private by default.
MTime: mtime,
Size: int64(len(specContents)),
},
})

keyFile, err := t.Apply(srpm.Signature.KeyFile)
if err != nil {
return err
}

Check warning on line 158 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L157-L158

Added lines #L157 - L158 were not covered by tests

// Create the source RPM package.
info := &nfpm.Info{
Name: srpm.PackageName,
Epoch: srpm.Epoch,
Version: ctx.Version,
Section: srpm.Section,
Maintainer: srpm.Maintainer,
Description: srpm.Description,
Vendor: srpm.Vendor,
Homepage: srpm.URL,
License: srpm.License,
Overridables: nfpm.Overridables{
Contents: contents,
RPM: nfpm.RPM{
Group: srpm.Group,
Summary: srpm.Summary,
Compression: srpm.Compression,
Packager: srpm.Packager,
Signature: nfpm.RPMSignature{
PackageSignature: nfpm.PackageSignature{
KeyFile: keyFile,
KeyPassphrase: ctx.Env[fmt.Sprintf("SRPM_%s_PASSPHRASE", srpm.ID)],
// TODO: KeyID
},
},
},
},
}

if skips.Any(ctx, skips.Sign) {
info.RPM.Signature = nfpm.RPMSignature{}
}

Check warning on line 191 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L190-L191

Added lines #L190 - L191 were not covered by tests

packager, err := nfpm.Get("rpm")
if err != nil {
return err
}

Check warning on line 196 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L195-L196

Added lines #L195 - L196 were not covered by tests
info = nfpm.WithDefaults(info)

// Write the source RPM.
srpmFileName, err := t.Apply(srpm.FileNameTemplate)
if err != nil {
return err
}

Check warning on line 203 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L202-L203

Added lines #L202 - L203 were not covered by tests
if !strings.HasSuffix(srpmFileName, ".src.rpm") {
srpmFileName += ".src.rpm"
}

Check warning on line 206 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L205-L206

Added lines #L205 - L206 were not covered by tests
srpmPath := filepath.Join(ctx.Config.Dist, srpmFileName)
log.WithField("file", srpmPath).Info("creating")
srpmFile, err := os.Create(srpmPath)
if err != nil {
return err
}

Check warning on line 212 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L211-L212

Added lines #L211 - L212 were not covered by tests
defer srpmFile.Close()
if err := packager.Package(info, srpmFile); err != nil {
return fmt.Errorf("nfpm failed: %w", err)
}

Check warning on line 216 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L215-L216

Added lines #L215 - L216 were not covered by tests
if err := srpmFile.Close(); err != nil {
return fmt.Errorf("could not close package file: %w", err)
}

Check warning on line 219 in internal/pipe/srpm/srpm.go

View check run for this annotation

Codecov / codecov/patch

internal/pipe/srpm/srpm.go#L218-L219

Added lines #L218 - L219 were not covered by tests
srpmArtifact := &artifact.Artifact{
Type: artifact.SourceRPM,
Name: srpmFileName,
Path: srpmPath,
}

ctx.Artifacts.Add(specFileArtifact)
ctx.Artifacts.Add(srpmArtifact)
return nil
}

0 comments on commit 80fd5c8

Please sign in to comment.