2022-11-27 13:33:39 +00:00
|
|
|
package plugin
|
|
|
|
|
|
|
|
import (
|
2023-02-08 09:16:10 +00:00
|
|
|
"errors"
|
2022-11-27 13:33:39 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2022-12-02 21:21:35 +00:00
|
|
|
"path/filepath"
|
2022-11-27 13:33:39 +00:00
|
|
|
|
|
|
|
"github.com/thegeeklab/drone-git-action/git"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Netrc struct {
|
|
|
|
Machine string
|
|
|
|
Login string
|
|
|
|
Password string
|
|
|
|
}
|
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
type Pages struct {
|
|
|
|
Directory string
|
|
|
|
Exclude cli.StringSlice
|
|
|
|
Delete bool
|
2022-11-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Settings for the Plugin.
|
|
|
|
type Settings struct {
|
2022-12-02 21:21:35 +00:00
|
|
|
Action cli.StringSlice
|
|
|
|
SSHKey string
|
|
|
|
|
|
|
|
Netrc Netrc
|
|
|
|
Pages Pages
|
|
|
|
Repo git.Repository
|
2022-11-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
|
2023-02-08 09:16:10 +00:00
|
|
|
var (
|
|
|
|
ErrAuthSourceNotSet = errors.New("either SSH key or netrc password is required")
|
|
|
|
ErrPagesDirectoryNotExist = errors.New("pages directory must exist")
|
|
|
|
ErrPagesDirectoryNotValid = errors.New("pages directory not valid")
|
|
|
|
ErrPagesSourceNotSet = errors.New("pages source directory must be set")
|
|
|
|
ErrPagesActionNotExclusive = errors.New("pages action is mutual exclusive")
|
|
|
|
ErrActionUnknown = errors.New("action not found")
|
|
|
|
ErrGitCloneDestintionNotValid = errors.New("destination not valid")
|
|
|
|
)
|
|
|
|
|
2022-11-27 13:33:39 +00:00
|
|
|
// Validate handles the settings validation of the plugin.
|
|
|
|
func (p *Plugin) Validate() error {
|
2022-12-02 21:21:35 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
p.settings.Repo.Autocorrect = "never"
|
|
|
|
p.settings.Repo.RemoteName = "origin"
|
|
|
|
p.settings.Repo.Add = ""
|
|
|
|
|
|
|
|
if p.settings.Repo.WorkDir == "" {
|
|
|
|
p.settings.Repo.WorkDir, err = os.Getwd()
|
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, action := range p.settings.Action.Value() {
|
2022-11-29 09:40:42 +00:00
|
|
|
switch action {
|
|
|
|
case "clone":
|
|
|
|
continue
|
|
|
|
case "commit":
|
|
|
|
continue
|
|
|
|
case "push":
|
|
|
|
if p.settings.SSHKey == "" && p.settings.Netrc.Password == "" {
|
2023-02-08 09:16:10 +00:00
|
|
|
return ErrAuthSourceNotSet
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
case "pages":
|
|
|
|
p.settings.Pages.Directory = filepath.Join(p.settings.Repo.WorkDir, p.settings.Pages.Directory)
|
|
|
|
p.settings.Repo.WorkDir = filepath.Join(p.settings.Repo.WorkDir, ".tmp")
|
|
|
|
|
|
|
|
if _, err := os.Stat(p.settings.Pages.Directory); os.IsNotExist(err) {
|
2023-02-08 09:16:10 +00:00
|
|
|
return fmt.Errorf("%w: '%s' not found", ErrPagesDirectoryNotExist, p.settings.Pages.Directory)
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if info, _ := os.Stat(p.settings.Pages.Directory); !info.IsDir() {
|
2023-02-08 09:16:10 +00:00
|
|
|
return fmt.Errorf("%w: '%s' not a directory", ErrPagesDirectoryNotValid, p.settings.Pages.Directory)
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if p.settings.SSHKey == "" && p.settings.Netrc.Password == "" {
|
2023-02-08 09:16:10 +00:00
|
|
|
return ErrAuthSourceNotSet
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if p.settings.Pages.Directory == "" {
|
2023-02-08 09:16:10 +00:00
|
|
|
return ErrPagesSourceNotSet
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(p.settings.Action.Value()) > 1 {
|
2023-02-08 09:16:10 +00:00
|
|
|
return ErrPagesActionNotExclusive
|
2022-11-29 09:40:42 +00:00
|
|
|
}
|
|
|
|
default:
|
2023-02-08 09:16:10 +00:00
|
|
|
return fmt.Errorf("%w: %s", ErrActionUnknown, action)
|
2022-11-29 09:40:42 +00:00
|
|
|
}
|
2022-11-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute provides the implementation of the plugin.
|
|
|
|
func (p *Plugin) Execute() error {
|
2022-11-29 10:12:03 +00:00
|
|
|
gitEnv := []string{
|
|
|
|
"GIT_AUTHOR_NAME",
|
|
|
|
"GIT_AUTHOR_EMAIL",
|
|
|
|
"GIT_AUTHOR_DATE",
|
|
|
|
"GIT_COMMITTER_NAME",
|
|
|
|
"GIT_COMMITTER_EMAIL",
|
|
|
|
"GIT_COMMITTER_DATE",
|
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-11-29 10:12:03 +00:00
|
|
|
for _, env := range gitEnv {
|
2022-11-29 09:40:42 +00:00
|
|
|
if err := os.Unsetenv(env); err != nil {
|
2022-11-27 13:33:39 +00:00
|
|
|
return err
|
|
|
|
}
|
2022-11-29 09:40:42 +00:00
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-11-29 09:40:42 +00:00
|
|
|
if err := os.Setenv("GIT_TERMINAL_PROMPT", "0"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-11-27 13:33:39 +00:00
|
|
|
|
2023-02-08 09:16:10 +00:00
|
|
|
if err := p.handleInit(); err != nil {
|
2022-12-02 21:21:35 +00:00
|
|
|
return err
|
2022-11-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
if err := git.ConfigAutocorrect(p.settings.Repo).Run(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
if err := git.ConfigUserName(p.settings.Repo).Run(); err != nil {
|
2022-11-27 13:33:39 +00:00
|
|
|
return err
|
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
if err := git.ConfigUserEmail(p.settings.Repo).Run(); err != nil {
|
2022-11-27 13:33:39 +00:00
|
|
|
return err
|
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
if err := git.ConfigSSLVerify(p.settings.Repo).Run(); err != nil {
|
2022-11-29 09:40:42 +00:00
|
|
|
return err
|
2022-11-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if p.settings.SSHKey != "" {
|
|
|
|
if err := git.WriteSSHKey(p.settings.SSHKey); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := git.WriteNetrc(p.settings.Netrc.Machine, p.settings.Netrc.Login, p.settings.Netrc.Password); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
for _, action := range p.settings.Action.Value() {
|
2022-11-27 13:33:39 +00:00
|
|
|
switch action {
|
|
|
|
case "clone":
|
|
|
|
if err := p.handleClone(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case "commit":
|
|
|
|
if err := p.handleCommit(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case "push":
|
|
|
|
if err := p.handlePush(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-12-02 21:21:35 +00:00
|
|
|
case "pages":
|
|
|
|
if err := p.handlePages(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-11-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2022-12-02 21:21:35 +00:00
|
|
|
|
2023-02-08 09:16:10 +00:00
|
|
|
// handleInit initializes the repository.
|
|
|
|
func (p *Plugin) handleInit() error {
|
2022-12-02 21:21:35 +00:00
|
|
|
path := filepath.Join(p.settings.Repo.WorkDir, ".git")
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
if err := os.MkdirAll(p.settings.Repo.WorkDir, os.ModePerm); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
|
|
|
p.settings.Repo.InitExists = true
|
2023-02-08 09:16:10 +00:00
|
|
|
|
2022-12-02 21:21:35 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-02-08 09:16:10 +00:00
|
|
|
if err := execute(git.Init(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-12-02 21:21:35 +00:00
|
|
|
|
2023-02-08 09:16:10 +00:00
|
|
|
return nil
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// HandleClone clones remote.
|
|
|
|
func (p *Plugin) handleClone() error {
|
|
|
|
if p.settings.Repo.InitExists {
|
2023-02-08 09:16:10 +00:00
|
|
|
return fmt.Errorf("%w: %s exists and not empty", ErrGitCloneDestintionNotValid, p.settings.Repo.WorkDir)
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if p.settings.Repo.RemoteURL != "" {
|
|
|
|
if err := execute(git.RemoteAdd(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := execute(git.FetchSource(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := execute(git.CheckoutHead(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleCommit commits changes locally.
|
|
|
|
func (p *Plugin) handleCommit() error {
|
|
|
|
if err := execute(git.Add(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := execute(git.TestCleanTree(p.settings.Repo)); err != nil {
|
|
|
|
if err := execute(git.ForceCommit(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-08 09:16:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if p.settings.Repo.EmptyCommit {
|
|
|
|
if err := execute(git.EmptyCommit(p.settings.Repo)); err != nil {
|
|
|
|
return err
|
2022-12-02 21:21:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandlePush pushs changes to remote.
|
|
|
|
func (p *Plugin) handlePush() error {
|
|
|
|
return execute(git.RemotePush(p.settings.Repo))
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandlePages syncs, commits and pushes the changes from the pages directory to the pages branch.
|
|
|
|
func (p *Plugin) handlePages() error {
|
|
|
|
defer os.RemoveAll(p.settings.Repo.WorkDir)
|
|
|
|
|
|
|
|
if err := p.handleClone(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := execute(
|
|
|
|
rsyncDirectories(p.settings.Pages, p.settings.Repo),
|
|
|
|
); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := p.handleCommit(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.handlePush()
|
|
|
|
}
|