add exec script

This commit is contained in:
AJ ONeal 2020-09-28 21:15:30 -06:00
parent f4cda06e64
commit cad179977c
8 changed files with 157 additions and 18 deletions

View File

@ -1 +1,2 @@
Ryan Burnette <ryan.burnette@gmail.com> (https://ryanburnette.com)
AJ ONeal <aj@therootcompany.com> (https://therootcompany.com) AJ ONeal <aj@therootcompany.com> (https://therootcompany.com)

View File

@ -1 +1,3 @@
Copyright 2020 AJ ONeal. All rights reserved. This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.

View File

@ -2,6 +2,32 @@
**git-deploy** is an app for handling continuous deployment of static websites. **git-deploy** is an app for handling continuous deployment of static websites.
## Usage
```bash
echo 'GITHUB_SECRET=xxxxxxx' >> .env
./git-deploy init
./git-deploy run --listen :3000 --serve-path ./overrides --exec ./path/to/script.sh
```
To manage `git credentials`
see [The Vanilla DevOps Git Credentials Cheatsheet][1]
[1]: https://coolaj86.com/articles/vanilla-devops-git-credentials-cheatsheet/
## Git Info
The exec script will receive the parent environment as well as
```bash
GIT_DEPLOY_JOB_ID=xxxxxx
GIT_REF_NAME=master
GIT_REF_TYPE=branch
GIT_REPO_OWNER=example
GIT_REPO_NAME=example
GIT_CLONE_URL=https://github.com/example/example
```
## Build ## Build
```bash ```bash
@ -18,10 +44,6 @@ go generate -mod=vendor ./...
go build -mod=vendor . go build -mod=vendor .
``` ```
```bash
./git-deploy run --listen :3000 --serve-path ./overrides
```
## Add Webhooks ## Add Webhooks
To add a webhook you'll first need a secret To add a webhook you'll first need a secret
@ -104,4 +126,8 @@ crypto
## License ## License
Copyright 2020. All rights reserved. Copyright 2020 The git-deploy Authors
This Source Code Form is subject to the terms of the Mozilla Public \
License, v. 2.0. If a copy of the MPL was not distributed with this \
file, You can obtain one at https://mozilla.org/MPL/2.0/.

18
example.sh Normal file
View File

@ -0,0 +1,18 @@
#!/bin/bash
for x in $@; do
echo "$x"
done
my_envs='GIT_REF_NAME
GIT_REF_TYPE
GIT_REPO_OWNER
GIT_REPO_NAME
GIT_CLONE_URL'
echo 'Doing "work" ...'
sleep 5
for x in $my_envs; do
echo "$x=${!x}"
done

View File

@ -11,6 +11,7 @@ type ServerConfig struct {
TrustProxy bool TrustProxy bool
Compress bool Compress bool
ServePath string ServePath string
Exec string
} }
var ServerFlags *flag.FlagSet var ServerFlags *flag.FlagSet

View File

@ -6,6 +6,7 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"strings"
"git.ryanburnette.com/ryanburnette/git-deploy/internal/options" "git.ryanburnette.com/ryanburnette/git-deploy/internal/options"
"git.ryanburnette.com/ryanburnette/git-deploy/internal/webhooks" "git.ryanburnette.com/ryanburnette/git-deploy/internal/webhooks"
@ -63,16 +64,33 @@ func InitWebhook(providername string, secret *string, envname string) func() {
switch e := event.(type) { switch e := event.(type) {
case *github.PushEvent: case *github.PushEvent:
// this is a commit push, do something with it var branch string
var tag string
ref := e.GetRef() // *e.Ref ref := e.GetRef() // *e.Ref
branch := ref[len("refs/heads/"):] parts := strings.Split(ref, "/")
refType := parts[1]
prefixLen := len("refs/") + len(refType) + len("/")
refName := ref[prefixLen:]
switch refType {
case "tags":
refType = "tag"
tag = refName
case "heads":
refType = "branch"
branch = refName
}
webhooks.Hook(webhooks.Ref{ webhooks.Hook(webhooks.Ref{
Rev: e.GetAfter(), // *e.After HTTPSURL: e.GetRepo().GetCloneURL(),
Ref: ref, SSHURL: e.GetRepo().GetSSHURL(),
Branch: branch, Rev: e.GetAfter(), // *e.After
Repo: e.GetRepo().GetName(), // *e.Repo.Name Ref: ref,
Org: e.GetRepo().GetOrganization(), // *e.Repo.Organization RefType: refType,
RefName: refName,
Branch: branch,
Tag: tag,
Repo: e.GetRepo().GetName(), // *e.Repo.Name
Owner: e.GetRepo().GetOwner().GetLogin(),
}) })
/* /*
case *github.PullRequestEvent: case *github.PullRequestEvent:

View File

@ -17,9 +17,12 @@ type Ref struct {
SSHURL string SSHURL string
Rev string Rev string
Ref string Ref string
RefType string // tags, heads
RefName string
Branch string Branch string
Tag string
Owner string
Repo string Repo string
Org string
} }
var Providers = make(map[string]func()) var Providers = make(map[string]func())

78
main.go
View File

@ -2,10 +2,13 @@ package main
import ( import (
"compress/flate" "compress/flate"
"encoding/base64"
"flag" "flag"
"fmt" "fmt"
"log"
"net/http" "net/http"
"os" "os"
"os/exec"
"time" "time"
"git.ryanburnette.com/ryanburnette/git-deploy/assets" "git.ryanburnette.com/ryanburnette/git-deploy/assets"
@ -37,6 +40,14 @@ func ver() {
fmt.Printf("%s v%s %s (%s)\n", name, version, commit[:7], date) fmt.Printf("%s v%s %s (%s)\n", name, version, commit[:7], date)
} }
type job struct {
ID string // {HTTPSURL}#{BRANCH}
Cmd *exec.Cmd
Ref webhooks.Ref
}
var jobs = make(map[string]*job)
var runOpts *options.ServerConfig var runOpts *options.ServerConfig
var runFlags *flag.FlagSet var runFlags *flag.FlagSet
var initFlags *flag.FlagSet var initFlags *flag.FlagSet
@ -48,7 +59,12 @@ func init() {
runFlags.StringVar(&runOpts.Addr, "listen", ":3000", "the address and port on which to listen") runFlags.StringVar(&runOpts.Addr, "listen", ":3000", "the address and port on which to listen")
runFlags.BoolVar(&runOpts.TrustProxy, "trust-proxy", false, "trust X-Forwarded-For header") runFlags.BoolVar(&runOpts.TrustProxy, "trust-proxy", false, "trust X-Forwarded-For header")
runFlags.BoolVar(&runOpts.Compress, "compress", true, "enable compression for text,html,js,css,etc") runFlags.BoolVar(&runOpts.Compress, "compress", true, "enable compression for text,html,js,css,etc")
runFlags.StringVar(&runOpts.ServePath, "serve-path", "", "path to serve, falls back to built-in web app") runFlags.StringVar(
&runOpts.ServePath, "serve-path", "",
"path to serve, falls back to built-in web app")
runFlags.StringVar(
&runOpts.Exec, "exec", "",
"path to bash script to run with git info as arguments")
} }
func main() { func main() {
@ -80,6 +96,11 @@ func main() {
initFlags.Parse(args[2:]) initFlags.Parse(args[2:])
case "run": case "run":
runFlags.Parse(args[2:]) runFlags.Parse(args[2:])
if "" == runOpts.Exec {
fmt.Printf("--exec <path/to/script.sh> is a required flag")
os.Exit(1)
return
}
webhooks.MustRegisterAll() webhooks.MustRegisterAll()
serve() serve()
default: default:
@ -141,9 +162,58 @@ func serve() {
for { for {
hook := webhooks.Accept() hook := webhooks.Accept()
// TODO os.Exec // TODO os.Exec
fmt.Println(hook.Org) fmt.Printf("%#v\n", hook)
fmt.Println(hook.Repo) jobID := base64.URLEncoding.EncodeToString([]byte(
fmt.Println(hook.Branch) fmt.Sprintf("%s#%s", hook.HTTPSURL, hook.RefName),
))
args := []string{
runOpts.Exec,
jobID,
hook.RefName,
hook.RefType,
hook.Owner,
hook.Repo,
hook.HTTPSURL,
}
cmd := exec.Command("bash", args...)
env := os.Environ()
envs := []string{
"GIT_DEPLOY_JOB_ID=" + jobID,
"GIT_REF_NAME=" + hook.RefName,
"GIT_REF_TYPE=" + hook.RefType,
"GIT_REPO_OWNER=" + hook.Owner,
"GIT_REPO_NAME=" + hook.Repo,
"GIT_CLONE_URL=" + hook.HTTPSURL,
}
cmd.Env = append(env, envs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if _, exists := jobs[jobID]; exists {
// TODO put job in backlog
log.Printf("git-deploy job already started for %s#%s\n", hook.HTTPSURL, hook.RefName)
return
}
if err := cmd.Start(); nil != err {
log.Printf("git-deploy exec error: %s\n", err)
return
}
jobs[jobID] = &job{
ID: jobID,
Cmd: cmd,
Ref: hook,
}
go func() {
log.Printf("git-deploy job for %s#%s started\n", hook.HTTPSURL, hook.RefName)
cmd.Wait()
delete(jobs, jobID)
log.Printf("git-deploy job for %s#%s finished\n", hook.HTTPSURL, hook.RefName)
}()
} }
}() }()