273 lines
5.6 KiB
Go
273 lines
5.6 KiB
Go
// Copyright 2020 the Drone Authors. All rights reserved.
|
|
// Use of this source code is governed by the Blue Oak Model License
|
|
// that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/kelseyhightower/envconfig"
|
|
|
|
"github.com/appleboy/drone-git-push/repo"
|
|
)
|
|
|
|
// Args provides plugin execution arguments.
|
|
type Args struct {
|
|
Folder string `required:"true" envconfig:"INPUT_FOLDER"`
|
|
RemoteFolder string `envconfig:"INPUT_REMOTE_FOLDER" default:"/"`
|
|
SshKey string `envconfig:"INPUT_SSH_KEY"`
|
|
GitRemote string `envconfig:"INPUT_GIT_REMOTE"`
|
|
GitBranch string `envconfig:"INPUT_GIT_BRANCH"`
|
|
GitName string `envconfig:"INPUT_GIT_NAME" default:"[BOT] pages deployer"`
|
|
GitEmail string `envconfig:"INPUT_GIT_EMAIL" default:"noreply@pages.bot"`
|
|
Token string `envconfig:"INPUT_TOKEN"`
|
|
Username string `envconfig:"INPUT_USERNAME"`
|
|
Force bool `envconfig:"INPUT_FORCE" default:"false"`
|
|
|
|
GithubToken string `envconfig:"GITHUB_TOKEN"`
|
|
GithubTokenActor string `envconfig:"GITHUB_ACTOR"`
|
|
GithubRepository string `envconfig:"GITHUB_REPOSITORY"`
|
|
GithubServerUrl string `envconfig:"GITHUB_SERVER_URL"`
|
|
}
|
|
|
|
const BRANCH_NAME = "pages"
|
|
|
|
func main() {
|
|
var args Args
|
|
if err := envconfig.Process("", &args); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
if err := Exec(args); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
}
|
|
|
|
// Exec executes the plugin.
|
|
func Exec(args Args) error {
|
|
if err := checkArgs(&args); err != nil {
|
|
return err
|
|
}
|
|
|
|
if args.SshKey != "" {
|
|
if err := repo.WriteKey(strings.ReplaceAll(args.SshKey, "\\n", "\n") + "\n"); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
var err error
|
|
args.GitRemote, err = repo.WriteToken(args.GitRemote, args.Username, args.Token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := cleanTempDir(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if args.Force {
|
|
if err := initRepo(args); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if err := cloneRepo(args); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := copyFiles(args); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := writeConfig(args); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := doCommit(args); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := push(args); err != nil {
|
|
return err
|
|
}
|
|
|
|
// write code here
|
|
return nil
|
|
}
|
|
|
|
func checkArgs(args *Args) error {
|
|
if args.Token == "" && args.GithubToken != "" {
|
|
args.Token = args.GithubToken
|
|
}
|
|
|
|
if args.Username == "" && args.GithubTokenActor != "" {
|
|
args.Username = args.GithubTokenActor
|
|
}
|
|
|
|
if (args.Token == "" || args.Username == "") && args.SshKey == "" {
|
|
return errors.New("(INPUT_TOKEN and INPUT_USERNAME) or INPUT_SSH_KEY is required!")
|
|
}
|
|
|
|
if folderInfo, err := os.Stat(args.Folder); os.IsNotExist(err) || !folderInfo.IsDir() {
|
|
return errors.New("INPUT_FOLDER is not a folder!")
|
|
}
|
|
|
|
if args.GitRemote == "" && (args.GithubServerUrl == "" || args.GithubRepository == "") {
|
|
return errors.New("INPUT_GIT_REMOTE is required!")
|
|
}
|
|
|
|
if args.GitRemote == "" {
|
|
args.GitRemote = fmt.Sprintf("%s/%s.git", args.GithubServerUrl, args.GithubRepository)
|
|
}
|
|
|
|
if args.GitBranch == "" {
|
|
args.GitBranch = BRANCH_NAME
|
|
}
|
|
|
|
folder, err := filepath.Abs(args.Folder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
args.Folder = folder
|
|
|
|
_, err = os.Stat(args.Folder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func writeConfig(args Args) error {
|
|
if err := execute(exec.Command("git", "config", "user.name", args.GitName)); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := execute(exec.Command("git", "config", "user.email", args.GitEmail)); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func cleanTempDir() error {
|
|
if err := os.RemoveAll("/tmp/pages"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := os.MkdirAll("/tmp", 777); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func copyFiles(args Args) error {
|
|
if args.Folder[len(args.Folder)-1:] != "/" {
|
|
args.Folder += "/"
|
|
}
|
|
|
|
if args.RemoteFolder[:1] != "/" {
|
|
args.RemoteFolder = "/" + args.RemoteFolder
|
|
}
|
|
|
|
cmd := exec.Command("rsync", "-av", args.Folder, "/tmp/pages"+args.RemoteFolder, "--exclude", ".git", "--ignore-times", "--delete")
|
|
if err := execute(cmd); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := os.Chown("/tmp/pages", os.Getuid(), os.Getgid()); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func initRepo(args Args) error {
|
|
cmd := exec.Command(
|
|
"git",
|
|
"init", "-b", args.GitBranch, "/tmp/pages")
|
|
|
|
if err := execute(cmd); err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.Chdir("/tmp/pages")
|
|
}
|
|
|
|
func cloneRepo(args Args) error {
|
|
cmd := exec.Command(
|
|
"git",
|
|
"clone", args.GitRemote, "/tmp/pages")
|
|
|
|
if err := execute(cmd); err != nil {
|
|
return err
|
|
}
|
|
|
|
// check if branch exists and create if not
|
|
cmd = exec.Command(
|
|
"git",
|
|
"ls-remote", "--heads", args.GitRemote, args.GitBranch)
|
|
|
|
out, err := cmd.Output()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("remote branch: ", string(out))
|
|
|
|
if err := os.Chdir("/tmp/pages"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(out) == 0 {
|
|
cmd = exec.Command(
|
|
"git",
|
|
"checkout", "-b", args.GitBranch)
|
|
} else {
|
|
cmd = exec.Command(
|
|
"git",
|
|
"checkout", args.GitBranch)
|
|
}
|
|
|
|
if err := execute(cmd); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func doCommit(args Args) error {
|
|
if err := execute(repo.Add()); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := execute(repo.ForceCommit("Update pages 🚀", true, args.GitName, args.GitEmail)); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func push(args Args) error {
|
|
return execute(repo.RemotePushNamedBranch(args.GitRemote, args.GitBranch, args.GitBranch, args.Force, false))
|
|
}
|
|
|
|
func execute(cmd *exec.Cmd) error {
|
|
fmt.Println("+", strings.Join(cmd.Args, " "))
|
|
|
|
cmd.Env = os.Environ()
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Stdin = os.Stdin
|
|
|
|
return cmd.Run()
|
|
}
|