Add Magefile and release target

This commit is contained in:
2019-05-24 19:29:22 +02:00
parent eba02717cf
commit e6b5c55df8
13 changed files with 829 additions and 167 deletions

115
mage/gitea/option.go Normal file
View File

@ -0,0 +1,115 @@
package gitea
import (
"bufio"
"fmt"
"os"
"strings"
"syscall"
"time"
"code.gitea.io/gitea/modules/structs"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh/terminal"
)
type Options struct {
structs.CreateReleaseOption
Attachments []string
Token string
Username string
Password string
BaseURL string
}
type OptionFunc func(*Options)
func WithAttachments(attachments ...string) OptionFunc {
return func(opts *Options) {
opts.Attachments = attachments
}
}
func WithBaseURL(baseURL string) OptionFunc {
return func(opts *Options) {
opts.BaseURL = baseURL
}
}
func WithInteractivePassword() OptionFunc {
return func(opts *Options) {
fmt.Print("Enter Password: ")
password, err := terminal.ReadPassword(syscall.Stdin)
if err != nil {
panic(errors.Wrap(err, "error while asking password"))
}
opts.Password = strings.TrimSpace(string(password))
}
}
func WithInteractiveUsername() OptionFunc {
return func(opts *Options) {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Username: ")
username, err := reader.ReadString('\n')
if err != nil {
panic(errors.Wrap(err, "error while asking username"))
}
opts.Username = strings.TrimSpace(username)
}
}
func WithEnvUsername() OptionFunc {
return func(opts *Options) {
opts.Username = os.Getenv("GITEA_USERNAME")
}
}
func WithEnvPassword() OptionFunc {
return func(opts *Options) {
opts.Password = os.Getenv("GITEA_PASSWORD")
}
}
func WithAutoUsername() OptionFunc {
envUsername := WithEnvUsername()
interactiveUsername := WithInteractiveUsername()
return func(opts *Options) {
envUsername(opts)
if opts.Username != "" {
return
}
interactiveUsername(opts)
}
}
func WithAutoPassword() OptionFunc {
envPassword := WithEnvPassword()
interactivePassword := WithInteractivePassword()
return func(opts *Options) {
envPassword(opts)
if opts.Password != "" {
return
}
interactivePassword(opts)
}
}
func DefaultTagName() string {
now := time.Now()
return fmt.Sprintf("r%s", now.Format("20060102150405"))
}
func defaultOptions() *Options {
return &Options{
CreateReleaseOption: structs.CreateReleaseOption{
IsDraft: false,
IsPrerelease: true,
Note: "test",
Target: "master",
Title: "test",
TagName: "test",
},
Attachments: make([]string, 0),
}
}

61
mage/gitea/release.go Normal file
View File

@ -0,0 +1,61 @@
package gitea
import (
"fmt"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/sdk/gitea"
"github.com/pkg/errors"
)
const (
AccessTokenName = "mage-gitea"
)
func Release(user, repo string, opts ...OptionFunc) error {
options := defaultOptions()
for _, o := range opts {
o(options)
}
client := gitea.NewClient(options.BaseURL, options.Token)
if options.Token == "" {
accessToken, err := retrieveAccessToken(client, options.Username, options.Password)
if err != nil {
return errors.Wrap(err, "error while retrieving gitea access token")
}
client = gitea.NewClient(options.BaseURL, accessToken.Token)
}
release, err := client.CreateRelease(
user,
repo,
options.CreateReleaseOption,
)
if err != nil {
return errors.Wrap(err, "error while creating gitea release")
}
fmt.Println(release)
return nil
}
func retrieveAccessToken(client *gitea.Client, username, password string) (*gitea.AccessToken, error) {
tokens, err := client.ListAccessTokens(username, password)
if err != nil {
return nil, err
}
for _, at := range tokens {
if at.Name == AccessTokenName {
return at, nil
}
}
accessToken, err := client.CreateAccessToken(username, password, structs.CreateAccessTokenOption{
Name: AccessTokenName,
})
if err != nil {
return nil, err
}
return accessToken, nil
}

24
mage/release/fs.go Normal file
View File

@ -0,0 +1,24 @@
package release
import (
"fmt"
"github.com/magefile/mage/mg"
"github.com/otiai10/copy"
)
func Copy(src, dst string) error {
if mg.Verbose() {
fmt.Printf("Copying file from '%s' to '%s'\n", src, dst)
}
return copy.Copy(dst, src)
}
func MultiCopy(files map[string]string) error {
for dst, src := range files {
if err := Copy(src, dst); err != nil {
return err
}
}
return nil
}

67
mage/release/option.go Normal file
View File

@ -0,0 +1,67 @@
package release
type Options struct {
Systems []OS
Archs []Arch
DefaultArchiveType string
ArchiveTypeMap map[OS]string
BaseDir string
ProjectName string
Env map[string]string
}
type OptionFunc func(*Options)
func WithEnv(env map[string]string) OptionFunc {
return func(opts *Options) {
opts.Env = env
}
}
func WithSystems(systems ...OS) OptionFunc {
return func(opts *Options) {
opts.Systems = systems
}
}
func WithArchs(archs ...Arch) OptionFunc {
return func(opts *Options) {
opts.Archs = archs
}
}
func WithProjectName(projectName string) OptionFunc {
return func(opts *Options) {
opts.ProjectName = projectName
}
}
func WithBaseDir(baseDir string) OptionFunc {
return func(opts *Options) {
opts.BaseDir = baseDir
}
}
func defaultOptions() *Options {
return &Options{
Systems: []OS{
OSLinux,
OSWindows,
OSDarwin,
},
Archs: []Arch{
Arch386,
ArchAMD64,
ArchARM,
},
DefaultArchiveType: "tar.gz",
ArchiveTypeMap: map[OS]string{
OSWindows: "zip",
OSLinux: "tar.gz",
OSDarwin: "zip",
},
BaseDir: "release",
ProjectName: "my-project",
Env: make(map[string]string),
}
}

131
mage/release/release.go Normal file
View File

@ -0,0 +1,131 @@
package release
import (
"fmt"
"os"
"path"
"strings"
"github.com/magefile/mage/mg"
"github.com/magefile/mage/sh"
"github.com/mholt/archiver"
)
type OS string
const (
OSAix OS = "aix"
OSAndroid OS = "android"
OSDarwin OS = "darwin"
OSDragonfly OS = "dragonfly"
OSFreeBSD OS = "freebsd"
OSHurd OS = "hurd"
OSIllumos OS = "illumos"
OSJavascript OS = "js"
OSLinux OS = "linux"
OSNacl OS = "nacl"
OSNetBSD OS = "netbsd"
OSOpenBSD OS = "openbsd"
OSPlan9 OS = "plan9"
OSSolaris OS = "solaris"
OSWindows OS = "windows"
OSZos OS = "zos"
)
type Arch string
// 386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm
const (
Arch386 Arch = "386"
ArchAMD64 Arch = "amd64"
ArchARM Arch = "arm"
)
type Handler func(env map[string]string, destDir string) error
func EachTarget(handler Handler, opts ...OptionFunc) error {
options := defaultOptions()
for _, o := range opts {
o(options)
}
// Clean up existing directory
if err := sh.Rm(options.BaseDir); err != nil {
return err
}
baseEnv := environment()
for _, system := range options.Systems {
for _, arch := range options.Archs {
dirName := fmt.Sprintf("%s-%s-%s", options.ProjectName, system, arch)
destDir := path.Join(options.BaseDir, dirName)
if mg.Verbose() {
fmt.Printf("Generating release '%s'...\n", dirName)
}
// (Re)create destination directory
if err := os.MkdirAll(destDir, os.ModePerm); err != nil {
return err
}
// Generate Go build-related environment variables
env := override(
baseEnv,
options.Env,
map[string]string{
"GOOS": string(system),
"GOARCH": string(arch),
},
)
if err := handler(env, destDir); err != nil {
return err
}
archiveType := getArchiveType(system, options.DefaultArchiveType, options.ArchiveTypeMap)
archiveDest := fmt.Sprintf("%s.%s", destDir, archiveType)
if mg.Verbose() {
fmt.Printf("Generating archive '%s'...\n", archiveDest)
}
if err := archiver.Archive([]string{destDir}, archiveDest); err != nil {
return err
}
}
}
return nil
}
func environment() map[string]string {
env := make(map[string]string)
for _, o := range os.Environ() {
tokens := strings.SplitN(o, "=", 2)
env[tokens[0]] = tokens[1]
}
return env
}
func override(base map[string]string, overrides ...map[string]string) map[string]string {
env := make(map[string]string)
for k, v := range base {
env[k] = v
}
for _, o := range overrides {
for k, v := range o {
env[k] = v
}
}
return env
}
func getArchiveType(system OS, defaultArchiveType string, archiveTypeMap map[OS]string) string {
archiveType, exists := archiveTypeMap[system]
if !exists {
return defaultArchiveType
}
return archiveType
}