0
0
mirror of https://github.com/thegeeklab/wp-git-action.git synced 2024-06-02 18:29:41 +02:00

refactor: rework plugin structure and add pages action (#7)

This commit is contained in:
Robert Kaussow 2022-12-02 22:21:35 +01:00 committed by GitHub
parent 686de4edfd
commit e8c4aad467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 507 additions and 240 deletions

View File

@ -3,3 +3,4 @@ github
url
gh
drone-git-action
rsync

View File

@ -24,9 +24,12 @@ kind: pipeline
name: default
steps:
- name: commit artifact
- name: commit changelog
image: thegeeklab/drone-git-action
settings:
action:
- commit
- push
netrc_password: ghp_3LbMg9Kncpdkhjp3bh3dMnKNXLjVMTsXk4sM
author_name: octobot
author_email: octobot@example.com
@ -41,6 +44,30 @@ steps:
<!-- spellchecker-enable -->
<!-- prettier-ignore-end -->
### Examples
#### Publish GitHub pages
The plugin can be used to publish GitHub pages to the pages branch. Remember that the `pages` action cannot be combined with other actions.
```YAML
kind: pipeline
name: default
steps:
- name: publish
image: thegeeklab/drone-git-action
settings:
action:
- pages
author_email: bot@thegeeklab.de
author_name: thegeeklab-bot
message: "update pages"
branch: gh-pages
pages_directory: docs/
netrc_password: ghp_3LbMg9Kncpdkhjp3bh3dMnKNXLjVMTsXk4sM
```
## Build
Build the binary with the following command:

View File

@ -1,7 +1,14 @@
---
properties:
- name: actions
description: "Git actions to to execute. Supported actions: `clone|commit|push`."
- name: action
description: |
Git actions to be executed. Supported actions: `clone | commit | push | pages`. Specified actions are executed in the specified order
- **clone:** Clones the repository in `remote` and checks out the `branch` to `path`.
- **commit:** Adds a commit to the default drone repository or the repository in `remote`.
- **push:** Pushes all commits to the default drone repository or the repository set in `remote`.
- **pages:** The `pages` action is a special action that cannot be combined with other actions. It is intended for use for
GitHub pages. It synchronizes the contents of `pages_directory` with the target `branch` using `rsync` and pushes the changes automatically.
required: true
type: list
@ -43,7 +50,7 @@ properties:
type: string
- name: path
description: Path to git repository.
description: Path to clone the git repository.
type: string
- name: message
@ -75,3 +82,17 @@ properties:
description: Bypass the pre-commit and commit-msg hooks.
defaultvalue: false
type: bool
- name: pages_directory
description: Source directory to be synchronized with the pages `branch`.
defaultvalue: docs/
type: string
- name: pages_exclude
description: Files or directories to exclude from the rsync command.
type: list
- name: pages_delete
description: When set to `true`, the `--delete` flag is added to the rsync command to remove files from the `branch` that do not exist in the `pages_directory` either.
defaultvalue: true
type: bool

View File

@ -9,33 +9,32 @@ import (
func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.StringSliceFlag{
Name: "actions",
Usage: "git actions to to execute",
EnvVars: []string{"PLUGIN_ACTIONS"},
Destination: &settings.Actions,
Name: "action",
Usage: "git action to to execute",
EnvVars: []string{"PLUGIN_ACTION"},
Destination: &settings.Action,
Required: true,
Category: category,
},
&cli.StringFlag{
Name: "commit-author-name",
Name: "author-name",
Usage: "git author name",
EnvVars: []string{"PLUGIN_AUTHOR_NAME", "DRONE_COMMIT_AUTHOR"},
Destination: &settings.Commit.Author.Name,
Destination: &settings.Repo.Author.Name,
Required: true,
Category: category,
},
&cli.StringFlag{
Name: "commit-author-email",
Name: "author-email",
Usage: "git author email",
EnvVars: []string{"PLUGIN_AUTHOR_EMAIL", "DRONE_COMMIT_AUTHOR_EMAIL"},
Destination: &settings.Commit.Author.Email,
Destination: &settings.Repo.Author.Email,
Required: true,
Category: category,
},
&cli.StringFlag{
Name: "netrc-machine",
Name: "netrc.machine",
Usage: "netrc remote machine name",
EnvVars: []string{"PLUGIN_NETRC_MACHINE", "DRONE_NETRC_MACHINE"},
Destination: &settings.Netrc.Machine,
@ -43,7 +42,7 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Category: category,
},
&cli.StringFlag{
Name: "netrc-username",
Name: "netrc.username",
Usage: "netrc login user on the remote machine",
EnvVars: []string{"PLUGIN_NETRC_USERNAME", "DRONE_NETRC_USERNAME"},
Destination: &settings.Netrc.Login,
@ -51,7 +50,7 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Category: category,
},
&cli.StringFlag{
Name: "netrc-password",
Name: "netrc.password",
Usage: "netrc login password on the remote machine",
EnvVars: []string{"PLUGIN_NETRC_PASSWORD", "DRONE_NETRC_PASSWORD"},
Destination: &settings.Netrc.Password,
@ -68,41 +67,38 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
&cli.StringFlag{
Name: "remote",
Usage: "url of the remote repository",
EnvVars: []string{"PLUGIN_REMOTE"},
Destination: &settings.Remote,
EnvVars: []string{"PLUGIN_REMOTE", "DRONE_REMOTE_URL"},
Destination: &settings.Repo.RemoteURL,
Category: category,
},
&cli.StringFlag{
Name: "branch",
Usage: "name of the git branch",
Usage: "name of the git source branch",
EnvVars: []string{"PLUGIN_BRANCH"},
Destination: &settings.Branch,
Destination: &settings.Repo.Branch,
Value: "main",
Category: category,
},
&cli.StringFlag{
Name: "path",
Usage: "path to git repository",
Usage: "path to clone git repository",
EnvVars: []string{"PLUGIN_PATH"},
Destination: &settings.Path,
Destination: &settings.Repo.WorkDir,
Category: category,
},
&cli.StringFlag{
Name: "message",
Name: "commit-message",
Usage: "commit message",
EnvVars: []string{"PLUGIN_MESSAGE"},
Destination: &settings.Message,
Destination: &settings.Repo.CommitMsg,
Value: "[skip ci] commit dirty state",
Category: category,
},
&cli.BoolFlag{
Name: "force",
Name: "force-push",
Usage: "enable force push to remote repository",
EnvVars: []string{"PLUGIN_FORCE"},
Destination: &settings.Force,
Destination: &settings.Repo.ForcePush,
Value: false,
Category: category,
},
@ -110,7 +106,7 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Name: "followtags",
Usage: "follow tags for pushes to remote repository",
EnvVars: []string{"PLUGIN_FOLLOWTAGS"},
Destination: &settings.FollowTags,
Destination: &settings.Repo.PushFollowTags,
Value: false,
Category: category,
},
@ -118,7 +114,7 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Name: "insecure-ssl-verify",
Usage: "set SSL verification of the remote machine",
EnvVars: []string{"PLUGIN_INSECURE_SSL_VERIFY"},
Destination: &settings.InsecureSSLVerify,
Destination: &settings.Repo.InsecureSSLVerify,
Value: false,
Category: category,
},
@ -126,7 +122,7 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Name: "empty-commit",
Usage: "allow empty commits",
EnvVars: []string{"PLUGIN_EMPTY_COMMIT"},
Destination: &settings.EmptyCommit,
Destination: &settings.Repo.EmptyCommit,
Value: false,
Category: category,
},
@ -134,9 +130,32 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Name: "no-verify",
Usage: "bypass the pre-commit and commit-msg hooks",
EnvVars: []string{"PLUGIN_NO_VERIFY"},
Destination: &settings.NoVerify,
Destination: &settings.Repo.NoVerify,
Value: false,
Category: category,
},
&cli.StringFlag{
Name: "pages.directory",
Usage: "source directory for pages sync",
EnvVars: []string{"PLUGIN_PAGES_DIRECTORY"},
Destination: &settings.Pages.Directory,
Value: "docs/",
Category: category,
},
&cli.StringSliceFlag{
Name: "pages.exclude",
Usage: "exclude flag added to pages rsnyc command",
EnvVars: []string{"PLUGIN_PAGES_EXCLUDE"},
Destination: &settings.Pages.Exclude,
Category: category,
},
&cli.BoolFlag{
Name: "pages.delete",
Usage: "delete flag added to pages rsync command",
EnvVars: []string{"PLUGIN_PAGES_DELETE"},
Destination: &settings.Pages.Delete,
Value: true,
Category: category,
},
}
}

View File

@ -7,7 +7,7 @@ LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-git-acti
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-git-action"
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-git-action"
RUN apk --update add --no-cache git && \
RUN apk --update add --no-cache git rsync && \
rm -rf /var/cache/apk/* && \
rm -rf /tmp/*

View File

@ -7,7 +7,7 @@ LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-git-acti
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-git-action"
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-git-action"
RUN apk --update add --no-cache git && \
RUN apk --update add --no-cache git rsync && \
rm -rf /var/cache/apk/* && \
rm -rf /tmp/*

View File

@ -7,7 +7,7 @@ LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-git-acti
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-git-action"
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-git-action"
RUN apk --update add --no-cache git && \
RUN apk --update add --no-cache git rsync && \
rm -rf /var/cache/apk/* && \
rm -rf /tmp/*

35
git/clone.go Normal file
View File

@ -0,0 +1,35 @@
package git
import (
"fmt"
"os"
"os/exec"
)
// FetchSource fetches the source from remote.
func FetchSource(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"fetch",
"origin",
fmt.Sprintf("+%s:", repo.Branch),
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// CheckoutHead handles branch checkout.
func CheckoutHead(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"checkout",
"-qf",
repo.Branch,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}

View File

@ -1,74 +1,89 @@
package git
import (
"os"
"os/exec"
)
// ForceAdd forces the addition of all dirty files.
func ForceAdd() *exec.Cmd {
func ForceAdd(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"add",
"--all",
"--force")
"--force",
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// Add updates the index to match the working tree.
func Add() *exec.Cmd {
func Add(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"add",
"--all")
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
if repo.Add != "" {
cmd.Args = append(cmd.Args, repo.Add)
} else {
cmd.Args = append(cmd.Args, "--all")
}
return cmd
}
// TestCleanTree returns non-zero if diff between index and local repository
func TestCleanTree() *exec.Cmd {
func TestCleanTree(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"diff-index",
"--quiet",
"HEAD",
"--ignore-submodules")
"--ignore-submodules",
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// EmptyCommit simply create an empty commit
func EmptyCommit(msg string, noVerify bool) *exec.Cmd {
func EmptyCommit(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"commit",
"--allow-empty",
"-m",
msg,
repo.CommitMsg,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
if noVerify {
cmd.Args = append(
cmd.Args,
"--no-verify")
if repo.NoVerify {
cmd.Args = append(cmd.Args, "--no-verify")
}
return cmd
}
// ForceCommit commits every change while skipping CI.
func ForceCommit(msg string, noVerify bool) *exec.Cmd {
func ForceCommit(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"commit",
"-m",
msg,
repo.CommitMsg,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
if noVerify {
cmd.Args = append(
cmd.Args,
"--no-verify")
if repo.NoVerify {
cmd.Args = append(cmd.Args, "--no-verify")
}
return cmd

View File

@ -1,42 +1,67 @@
package git
import (
"os"
"os/exec"
"strconv"
)
// SetUserEmail sets the global git author email.
func SetUserEmail(email string) *exec.Cmd {
// repoUserEmail sets the global git author email.
func ConfigAutocorrect(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"config",
"--local",
"help.autocorrect",
repo.Autocorrect,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// repoUserEmail sets the global git author email.
func ConfigUserEmail(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"config",
"--local",
"user.email",
email)
repo.Author.Email,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// SetUserName sets the global git author name.
func SetUserName(author string) *exec.Cmd {
// repoUserName sets the global git author name.
func ConfigUserName(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"config",
"--local",
"user.name",
author)
repo.Author.Name,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// SetSSLSkipVerify disables globally the git ssl verification.
func SetSSLVerify(sslVerify bool) *exec.Cmd {
// repoSSLVerify disables globally the git ssl verification.
func ConfigSSLVerify(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"config",
"--local",
"http.sslVerify",
strconv.FormatBool(sslVerify))
strconv.FormatBool(repo.SSLVerify),
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}

View File

@ -1,52 +1,59 @@
package git
import (
"fmt"
"os"
"os/exec"
)
// RemoteRemove drops the defined remote from a git repo.
func RemoteRemove(name string) *exec.Cmd {
func RemoteRemove(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"remote",
"rm",
name)
repo.RemoteName,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// RemoteAdd adds an additional remote to a git repo.
func RemoteAdd(name, url string) *exec.Cmd {
func RemoteAdd(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"remote",
"add",
name,
url)
repo.RemoteName,
repo.RemoteURL,
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
// RemotePush pushs the changes from the local head to a remote branch.
func RemotePush(remote, branch string, force, followtags bool) *exec.Cmd {
return RemotePushNamedBranch(remote, "HEAD", branch, force, followtags)
}
// RemotePushNamedBranch puchs changes from a local to a remote branch.
func RemotePushNamedBranch(remote, localbranch, branch string, force, followtags bool) *exec.Cmd {
func RemotePush(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"push",
remote,
localbranch+":"+branch)
repo.RemoteName,
fmt.Sprintf("HEAD:%s", repo.Branch),
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
if force {
if repo.ForcePush {
cmd.Args = append(
cmd.Args,
"--force")
"--force",
)
}
if followtags {
if repo.PushFollowTags {
cmd.Args = append(
cmd.Args,
"--follow-tags")

42
git/status.go Normal file
View File

@ -0,0 +1,42 @@
package git
import (
"bytes"
"fmt"
"os"
"os/exec"
)
func Status(repo Repository) *exec.Cmd {
cmd := exec.Command(
"git",
"status",
"--porcelain",
)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
return cmd
}
func IsDirty(repo Repository) bool {
res := bytes.NewBufferString("")
cmd := Status(repo)
cmd.Dir = repo.WorkDir
cmd.Stderr = os.Stderr
cmd.Stdout = res
cmd.Stderr = res
err := runCommand(cmd)
if err != nil {
return false
}
if res.Len() > 0 {
fmt.Print(res.String())
return true
}
return false
}

27
git/type.go Normal file
View File

@ -0,0 +1,27 @@
package git
type Author struct {
Name string
Email string
}
type Repository struct {
RemoteName string
RemoteURL string
Branch string
Add string
CommitMsg string
Autocorrect string
NoVerify bool
InsecureSSLVerify bool
EmptyCommit bool
PushFollowTags bool
ForcePush bool
SSLVerify bool
WorkDir string
InitExists bool
Author Author
}

View File

@ -3,8 +3,10 @@ package git
import (
"fmt"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
)
const netrcFile = `
@ -27,17 +29,13 @@ func WriteSSHKey(privateKey string) error {
home = currentUser.HomeDir
}
sshpath := filepath.Join(
home,
".ssh")
sshpath := filepath.Join(home, ".ssh")
if err := os.MkdirAll(sshpath, 0o700); err != nil {
return err
}
confpath := filepath.Join(
sshpath,
"config")
confpath := filepath.Join(sshpath, "config")
if err := os.WriteFile(
confpath,
@ -47,10 +45,7 @@ func WriteSSHKey(privateKey string) error {
return err
}
privpath := filepath.Join(
sshpath,
"id_rsa",
)
privpath := filepath.Join(sshpath, "id_rsa")
if err := os.WriteFile(
privpath,
@ -89,3 +84,20 @@ func WriteNetrc(machine, login, password string) error {
0o600,
)
}
func trace(cmd *exec.Cmd) {
fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " "))
}
func runCommand(cmd *exec.Cmd) error {
if cmd.Stdout == nil {
cmd.Stdout = os.Stdout
}
if cmd.Stderr == nil {
cmd.Stderr = os.Stderr
}
trace(cmd)
return cmd.Run()
}

View File

@ -1,111 +0,0 @@
package plugin
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"github.com/thegeeklab/drone-git-action/git"
)
// InitRepo initializes the repository.
func (p Plugin) initRepo() error {
path := filepath.Join(p.settings.Path, ".git")
if err := os.MkdirAll(p.settings.Path, os.ModePerm); err != nil {
return err
}
if err := os.Chdir(p.settings.Path); err != nil {
return err
}
if isDirEmpty(path) {
return execute(exec.Command(
"git",
"init",
))
}
return nil
}
// AddRemote adds a remote to repository.
func (p Plugin) addRemote() error {
if p.settings.Remote != "" {
if err := execute(git.RemoteAdd("origin", p.settings.Remote)); err != nil {
return err
}
}
return nil
}
// FetchSource fetches the source from remote.
func (p Plugin) fetchSource() error {
return execute(exec.Command(
"git",
"fetch",
"origin",
fmt.Sprintf("+%s:", p.settings.Branch),
))
}
// CheckoutHead handles branch checkout.
func (p Plugin) checkoutHead() error {
return execute(exec.Command(
"git",
"checkout",
"-qf",
p.settings.Branch,
))
}
// HandleClone clones remote.
func (p Plugin) handleClone() error {
if err := p.addRemote(); err != nil {
return err
}
if err := p.fetchSource(); err != nil {
return err
}
if err := p.checkoutHead(); err != nil {
return err
}
return nil
}
// HandleCommit commits changes locally.
func (p Plugin) handleCommit() error {
if err := execute(git.Add()); err != nil {
return err
}
if err := execute(git.TestCleanTree()); err != nil {
if err := execute(git.ForceCommit(p.settings.Message, p.settings.NoVerify)); err != nil {
return err
}
} else {
if p.settings.EmptyCommit {
if err := execute(git.EmptyCommit(p.settings.Message, p.settings.NoVerify)); err != nil {
return err
}
}
}
return nil
}
// HandlePush pushs changes to remote.
func (p Plugin) handlePush() error {
return execute(git.RemotePushNamedBranch(
"origin",
p.settings.Branch,
p.settings.Branch,
p.settings.Force,
p.settings.FollowTags,
))
}

View File

@ -3,6 +3,8 @@ package plugin
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"github.com/thegeeklab/drone-git-action/git"
"github.com/urfave/cli/v2"
@ -14,37 +16,38 @@ type Netrc struct {
Password string
}
type Commit struct {
Author Author
}
type Author struct {
Name string
Email string
type Pages struct {
Directory string
Exclude cli.StringSlice
Delete bool
}
// Settings for the Plugin.
type Settings struct {
Actions cli.StringSlice
SSHKey string
Remote string
Branch string
Path string
Message string
Force bool
FollowTags bool
InsecureSSLVerify bool
EmptyCommit bool
NoVerify bool
Action cli.StringSlice
SSHKey string
Netrc Netrc
Commit Commit
Author Author
Netrc Netrc
Pages Pages
Repo git.Repository
}
// Validate handles the settings validation of the plugin.
func (p *Plugin) Validate() error {
for _, action := range p.settings.Actions.Value() {
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()
}
if err != nil {
return err
}
for _, action := range p.settings.Action.Value() {
switch action {
case "clone":
continue
@ -52,7 +55,30 @@ func (p *Plugin) Validate() error {
continue
case "push":
if p.settings.SSHKey == "" && p.settings.Netrc.Password == "" {
return fmt.Errorf("either SSH key or netrc password are required")
return fmt.Errorf("either SSH key or netrc password is required")
}
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) {
return fmt.Errorf("pages directory '%s' must exist", p.settings.Pages.Directory)
}
if info, _ := os.Stat(p.settings.Pages.Directory); !info.IsDir() {
return fmt.Errorf("pages directory '%s' is not a directory", p.settings.Pages.Directory)
}
if p.settings.SSHKey == "" && p.settings.Netrc.Password == "" {
return fmt.Errorf("either SSH key or netrc password is required")
}
if p.settings.Pages.Directory == "" {
return fmt.Errorf("pages source directory needs to be set")
}
if len(p.settings.Action.Value()) > 1 {
return fmt.Errorf("pages action can not be combined with other actions")
}
default:
return fmt.Errorf("unknown action %s", action)
@ -81,19 +107,20 @@ func (p *Plugin) Execute() error {
return err
}
if p.settings.Path != "" {
if err := p.initRepo(); err != nil {
return err
}
if err := p.initRepo(); err != nil {
return err
}
if err := git.SetUserName(p.settings.Commit.Author.Name).Run(); err != nil {
if err := git.ConfigAutocorrect(p.settings.Repo).Run(); err != nil {
return err
}
if err := git.SetUserEmail(p.settings.Commit.Author.Email).Run(); err != nil {
if err := git.ConfigUserName(p.settings.Repo).Run(); err != nil {
return err
}
if err := git.SetSSLVerify(p.settings.InsecureSSLVerify).Run(); err != nil {
if err := git.ConfigUserEmail(p.settings.Repo).Run(); err != nil {
return err
}
if err := git.ConfigSSLVerify(p.settings.Repo).Run(); err != nil {
return err
}
@ -107,7 +134,7 @@ func (p *Plugin) Execute() error {
return err
}
for _, action := range p.settings.Actions.Value() {
for _, action := range p.settings.Action.Value() {
switch action {
case "clone":
if err := p.handleClone(); err != nil {
@ -121,8 +148,103 @@ func (p *Plugin) Execute() error {
if err := p.handlePush(); err != nil {
return err
}
case "pages":
if err := p.handlePages(); err != nil {
return err
}
}
}
return nil
}
// InitRepo initializes the repository.
func (p *Plugin) initRepo() error {
path := filepath.Join(p.settings.Repo.WorkDir, ".git")
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
return nil
}
cmd := exec.Command(
"git",
"init",
)
cmd.Dir = p.settings.Repo.WorkDir
return execute(cmd)
}
// HandleClone clones remote.
func (p *Plugin) handleClone() error {
if p.settings.Repo.InitExists {
return fmt.Errorf("destination '%s' already exists and is not an empty directory", p.settings.Repo.WorkDir)
}
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
}
} else {
if p.settings.Repo.EmptyCommit {
if err := execute(git.EmptyCommit(p.settings.Repo)); err != nil {
return err
}
}
}
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()
}

View File

@ -2,10 +2,11 @@ package plugin
import (
"fmt"
"io"
"os"
"os/exec"
"strings"
"github.com/thegeeklab/drone-git-action/git"
)
// helper function to simply wrap os execte command.
@ -19,15 +20,39 @@ func execute(cmd *exec.Cmd) error {
return cmd.Run()
}
// helper function returns true if directory dir is empty.
func isDirEmpty(dir string) bool {
f, err := os.Open(dir)
if err != nil {
return true
func rsyncDirectories(pages Pages, repo git.Repository) *exec.Cmd {
args := []string{
"-r",
"--exclude",
".git",
}
defer f.Close()
for _, item := range pages.Exclude.Value() {
args = append(
args,
"--exclude",
item,
)
}
_, err = f.Readdir(1)
return err == io.EOF
if pages.Delete {
args = append(
args,
"--delete",
)
}
args = append(
args,
".",
repo.WorkDir,
)
cmd := exec.Command(
"rsync",
args...,
)
cmd.Dir = pages.Directory
return cmd
}