1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-02-05 13:15:26 +02:00

feat: Support custom command and extra files in snaps (#1553)

This commit is contained in:
Aggelos Kolaitis 2020-06-06 21:07:18 +03:00 committed by GitHub
parent 9af64723fc
commit 0c0063a5b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 173 additions and 1 deletions

View File

@ -173,6 +173,21 @@ func create(ctx *context.Context, snap config.Snapcraft, arch string, binaries [
return err
}
for _, file := range snap.Files {
if file.Destination == "" {
file.Destination = file.Source
}
if file.Mode == 0 {
file.Mode = 0644
}
if err := os.MkdirAll(filepath.Join(primeDir, filepath.Dir(file.Destination)), 0755); err != nil {
return errors.Wrapf(err, "failed to link extra file '%s'", file.Source)
}
if err := link(file.Source, filepath.Join(primeDir, file.Destination), os.FileMode(file.Mode)); err != nil {
return errors.Wrapf(err, "failed to link extra file '%s'", file.Source)
}
}
var file = filepath.Join(primeDir, "meta", "snap.yaml")
log.WithField("file", file).Debug("creating snap metadata")
@ -231,11 +246,16 @@ func create(ctx *context.Context, snap config.Snapcraft, arch string, binaries [
WithField("name", name).
Debug("passed binary to snapcraft")
command := name
if config.Command != "" {
command = config.Command
}
// TODO: test that the correct binary is used in Command
// See https://github.com/goreleaser/goreleaser/pull/1449
appMetadata := AppMetadata{
Command: strings.TrimSpace(strings.Join([]string{
name,
command,
config.Args,
}, " ")),
Plugs: config.Plugs,
@ -314,3 +334,29 @@ func push(ctx *context.Context, snap *artifact.Artifact) error {
ctx.Artifacts.Add(snap)
return nil
}
// walks the src, recreating dirs and hard-linking files.
func link(src, dest string, mode os.FileMode) error {
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// We have the following:
// - src = "a/b"
// - dest = "dist/linuxamd64/b"
// - path = "a/b/c.txt"
// So we join "a/b" with "c.txt" and use it as the destination.
var dst = filepath.Join(dest, strings.Replace(path, src, "", 1))
log.WithFields(log.Fields{
"src": path,
"dst": dst,
}).Debug("extra file")
if info.IsDir() {
return os.MkdirAll(dst, info.Mode())
}
if err := os.Link(path, dst); err != nil {
return err
}
return os.Chmod(dst, mode)
})
}

View File

@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"syscall"
"testing"
"github.com/goreleaser/goreleaser/internal/artifact"
@ -327,6 +328,100 @@ func TestCompleter(t *testing.T) {
assert.Equal(t, "testdata/mybin-completer.bash", metadata.Apps["mybin"].Completer)
}
func TestCommand(t *testing.T) {
folder, err := ioutil.TempDir("", "archivetest")
require.NoError(t, err)
defer os.RemoveAll(folder)
var dist = filepath.Join(folder, "dist")
require.NoError(t, os.Mkdir(dist, 0755))
require.NoError(t, err)
var ctx = context.New(config.Project{
ProjectName: "testprojectname",
Dist: dist,
Snapcrafts: []config.Snapcraft{
{
NameTemplate: "foo_{{.Arch}}",
Summary: "test summary",
Description: "test description",
Apps: map[string]config.SnapcraftAppMetadata{
"mybin": {
Daemon: "simple",
Args: "",
Command: "custom command",
},
},
Builds: []string{"foo"},
},
},
})
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
addBinaries(t, ctx, "foo", dist, "mybin")
require.NoError(t, Pipe{}.Run(ctx))
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
require.NoError(t, err)
var metadata Metadata
err = yaml.Unmarshal(yamlFile, &metadata)
require.NoError(t, err)
assert.Equal(t, "custom command", metadata.Apps["mybin"].Command)
}
func TestExtraFile(t *testing.T) {
folder, err := ioutil.TempDir("", "archivetest")
require.NoError(t, err)
defer os.RemoveAll(folder)
var dist = filepath.Join(folder, "dist")
require.NoError(t, os.Mkdir(dist, 0755))
require.NoError(t, err)
var ctx = context.New(config.Project{
ProjectName: "testprojectname",
Dist: dist,
Snapcrafts: []config.Snapcraft{
{
NameTemplate: "foo_{{.Arch}}",
Summary: "test summary",
Description: "test description",
Apps: map[string]config.SnapcraftAppMetadata{
"mybin": {
Daemon: "simple",
Args: "",
Command: "custom command",
},
},
Files: []config.SnapcraftExtraFiles{
{
Source: "testdata/extra-file.txt",
Destination: "a/b/c/extra-file.txt",
Mode: 0755,
},
{
Source: "testdata/extra-file-2.txt",
},
},
Builds: []string{"foo"},
},
},
})
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
addBinaries(t, ctx, "foo", dist, "mybin")
require.NoError(t, Pipe{}.Run(ctx))
srcFile, err := os.Stat("testdata/extra-file.txt")
require.NoError(t, err)
destFile, err := os.Stat(filepath.Join(dist, "foo_amd64", "prime", "a", "b", "c", "extra-file.txt"))
require.NoError(t, err)
assert.Equal(t, inode(srcFile), inode(destFile))
assert.Equal(t, destFile.Mode(), os.FileMode(0755))
srcFile, err = os.Stat("testdata/extra-file-2.txt")
require.NoError(t, err)
destFileWithDefaults, err := os.Stat(filepath.Join(dist, "foo_amd64", "prime", "testdata", "extra-file-2.txt"))
require.NoError(t, err)
assert.Equal(t, destFileWithDefaults.Mode(), os.FileMode(0644))
assert.Equal(t, inode(srcFile), inode(destFileWithDefaults))
}
func TestDefault(t *testing.T) {
var ctx = context.New(config.Project{
Builds: []config.Build{
@ -439,3 +534,8 @@ func Test_isValidArch(t *testing.T) {
})
}
}
func inode(info os.FileInfo) uint64 {
stat := info.Sys().(*syscall.Stat_t)
return stat.Ino
}

View File

@ -0,0 +1 @@
test2

View File

@ -0,0 +1 @@
test

View File

@ -329,6 +329,7 @@ type SnapcraftAppMetadata struct {
Daemon string
Args string
Completer string `yaml:",omitempty"`
Command string `yaml:"command"`
}
// Snapcraft config.
@ -348,6 +349,15 @@ type Snapcraft struct {
Confinement string `yaml:",omitempty"`
Apps map[string]SnapcraftAppMetadata `yaml:",omitempty"`
Plugs map[string]interface{} `yaml:",omitempty"`
Files []SnapcraftExtraFiles `yaml:"extra_files,omitempty"`
}
// SnapcraftExtraFiles config.
type SnapcraftExtraFiles struct {
Source string `yaml:"source"`
Destination string `yaml:"destination,omitempty"`
Mode uint32 `yaml:"mode,omitempty"`
}
// Snapshot config.

View File

@ -88,6 +88,16 @@ snapcrafts:
# Default is empty.
base: core18
# Add extra files on the resulting snap. Useful for including wrapper
# scripts or other useful static files. Source filenames are relative to the
# project directory. Destination filenames are relative to the snap prime
# directory.
# Default is empty.
extra_files:
- source: drumroll.wrapper
destination: bin/drumroll.wrapper
mode: 0755
# Each binary built by GoReleaser is an app inside the snap. In this section
# you can declare extra details for those binaries. It is optional.
apps:
@ -114,6 +124,10 @@ snapcrafts:
# https://docs.snapcraft.io/tab-completion-for-snaps.
completer: drumroll-completion.bash
# You can override the command name.
# Defaults is the app name.
command: bin/drumroll.wrapper
# Allows plugs to be configured. Plugs like system-files and personal-files
# require this.
# Default is empty.