Skip to content

Commit

Permalink
Add a magefile for plugins
Browse files Browse the repository at this point in the history
Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
  • Loading branch information
carolynvs committed Jul 1, 2022
1 parent 5a76d0f commit d3ff393
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 1 deletion.
2 changes: 1 addition & 1 deletion mixins/magefile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestInstall(t *testing.T) {
func TestInstallMixin(t *testing.T) {
magefile := NewMagefile("github.com/mymixin/test-mixin", "testmixin", "testdata/bin/mixins/testmixin")

// Change the porter home to a safe place for the test to write to
Expand Down
1 change: 1 addition & 0 deletions plugins/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
porter_home
3 changes: 3 additions & 0 deletions plugins/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package plugins contains magefile targets that perform common tasks
// that all plugins need to support
package plugins
121 changes: 121 additions & 0 deletions plugins/magefile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package plugins

import (
"fmt"
"os"
"path/filepath"

"get.porter.sh/magefiles/ci"
"get.porter.sh/magefiles/porter"
"get.porter.sh/magefiles/releases"
"github.com/carolynvs/magex/mgx"
"github.com/carolynvs/magex/shx"
"github.com/carolynvs/magex/xplat"
"github.com/magefile/mage/mg"
)

// Magefile provides implementations for required mage targets needed by a Porter plugin.
type Magefile struct {
// Pkg is the plugin's go module package name
// For example, github.com/yourname/yourplugin
Pkg string

// PluginName is the name of the plugin binary
PluginName string

// OutDir is the path to the directory the plugin binary should be output.
OutDir string
}

// NewMagefile creates a Magefile helper for a plugin.
func NewMagefile(pkg, pluginName, binDir string) Magefile {
return Magefile{
Pkg: pkg,
PluginName: pluginName,
OutDir: filepath.Join(binDir, "plugins", pluginName)}
}

var must = shx.CommandBuilder{StopOnError: true}

// ConfigureAgent sets up a CI worker to use Go and mage.
func (m Magefile) ConfigureAgent() {
mgx.Must(ci.ConfigureAgent())
}

// Build the plugin
func (m Magefile) Build() {
must.RunV("go", "mod", "tidy")
releases.BuildPlugin(m.PluginName)
}

// XBuildAll cross-compiles the plugin before a release
func (m Magefile) XBuildAll() {
releases.XBuildAll(m.Pkg, m.PluginName, m.OutDir)
releases.PrepareMixinForPublish(m.PluginName)
}

// TestUnit runs unit tests
func (m Magefile) TestUnit() {
v := ""
if mg.Verbose() {
v = "-v"
}
must.Command("go", "test", v, "./...").CollapseArgs().RunV()
}

// Test runs a full suite of tests
func (m Magefile) Test() {
m.TestUnit()

// Check that we can call `plugin version`
m.Build()
must.RunV(filepath.Join(m.OutDir, m.PluginName+xplat.FileExt()), "version")
}

// Publish the plugin and its plugin feed
func (m Magefile) Publish() {
mg.SerialDeps(m.PublishBinaries, m.PublishPluginFeed)
}

// PublishBinaries uploads cross-compiled binaries to a GitHub release
// Requires PORTER_RELEASE_REPOSITORY to be set to github.com/USERNAME/REPO
func (m Magefile) PublishBinaries() {
mg.SerialDeps(porter.UseBinForPorterHome, porter.EnsurePorter)
releases.PreparePluginForPublish(m.PluginName)
releases.PublishPlugin(m.PluginName)
}

// Publish a plugin feed
// Requires PORTER_PACKAGES_REMOTE to be set to git@github.com:USERNAME/REPO.git
func (m Magefile) PublishPluginFeed() {
mg.SerialDeps(porter.UseBinForPorterHome, porter.EnsurePorter)
releases.PublishPluginFeed(m.PluginName)
}

// TestPublish uploads release artifacts to a fork of the pluin's repo.
// If your plugin is officially hosted in a repository under your username, you will need to manually
// override PORTER_RELEASE_REPOSITORY and PORTER_PACKAGES_REMOTE to test out publishing safely.
func (m Magefile) TestPublish(username string) {
pluginRepo := fmt.Sprintf("github.com/%s/%s-plugins", username, m.PluginName)
pkgRepo := fmt.Sprintf("https://github.com/%s/packages.git", username)
fmt.Printf("Publishing a release to %s and committing a plugin feed to %s\n", pluginRepo, pkgRepo)
fmt.Printf("If you use different repository names, set %s and %s then call mage Publish instead.\n", releases.ReleaseRepository, releases.PackagesRemote)
os.Setenv(releases.ReleaseRepository, pluginRepo)
os.Setenv(releases.PackagesRemote, pkgRepo)

m.Publish()
}

// Install the plugin
func (m Magefile) Install() {
porterHome := porter.GetPorterHome()
fmt.Printf("Installing the %s plugin into %s\n", m.PluginName, porterHome)

os.MkdirAll(filepath.Join(porterHome, "plugins", m.PluginName), 0770)
mgx.Must(shx.Copy(filepath.Join(m.OutDir, m.PluginName+xplat.FileExt()), filepath.Join(porterHome, "plugins", m.PluginName)))
}

// Clean removes generated build files
func (m Magefile) Clean() {
os.RemoveAll("bin")
}
23 changes: 23 additions & 0 deletions plugins/magefile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package plugins

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestInstallPlugin(t *testing.T) {
magefile := NewMagefile("github.com/myplugin/test-plugin", "testplugin", "testdata/bin")

// Change the porter home to a safe place for the test to write to
require.NoError(t, os.MkdirAll("testdata/porter_home", 0770))
os.Setenv("PORTER_HOME", "testdata/porter_home")
defer os.Unsetenv("PORTER_HOME")

magefile.Install()

assert.DirExists(t, "testdata/porter_home/plugins/testplugin", "The plugin directory doesn't exist")
assert.FileExists(t, "testdata/porter_home/plugins/testplugin/testplugin", "The plugin wasn't installed")
}
Empty file.
21 changes: 21 additions & 0 deletions releases/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ func getLDFLAGS(pkg string) string {
return fmt.Sprintf("-w -X %s/pkg.Version=%s -X %s/pkg.Commit=%s", pkg, info.Version, pkg, info.Commit)
}

func getPluginLDFLAGS() string {
info := LoadMetadata()

pkg := "get.porter.sh/porter/pkg/plugins/pluginbuilder"
return fmt.Sprintf("-w -X %s.Version=%s -X %s.Commit=%s", pkg, info.Version, pkg, info.Commit)
}

func build(pkgName, cmd, outPath, goos, goarch string) error {
ldflags := getLDFLAGS(pkgName)

Expand Down Expand Up @@ -51,6 +58,20 @@ func BuildClient(pkg string, name string, binDir string) error {
return build(pkg, name, outPath, runtime.GOOS, runtime.GOARCH)
}

func BuildPlugin(name string) error {
srcPath := "."
goos := runtime.GOOS
goarch := runtime.GOARCH
ldflags := getPluginLDFLAGS()

outPath := filepath.Join("bin/plugins/", name, name, fileExt(goos))
os.MkdirAll(filepath.Dir(outPath), 0770)

return shx.Command("go", "build", "-ldflags", ldflags, "-o", outPath, srcPath).
Env("CGO_ENABLED=0", "GO111MODULE=on", "GOOS="+goos, "GOARCH="+goarch).
RunV()
}

func BuildAll(pkg string, name string, binDir string) error {
var g errgroup.Group
g.Go(func() error {
Expand Down

0 comments on commit d3ff393

Please sign in to comment.