Compare commits
No commits in common. "6622ea0e1cb22687791c26b60381b138cbbb8098" and "d83517f67ba638abed1d76541068413e60142194" have entirely different histories.
6622ea0e1c
...
d83517f67b
50
acid.go
50
acid.go
@ -30,6 +30,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
ttemplate "text/template"
|
ttemplate "text/template"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
@ -153,14 +154,6 @@ var shellFuncs = ttemplate.FuncMap{
|
|||||||
|
|
||||||
// --- Utilities ---------------------------------------------------------------
|
// --- Utilities ---------------------------------------------------------------
|
||||||
|
|
||||||
func localShell() string {
|
|
||||||
if shell := os.Getenv("SHELL"); shell != "" {
|
|
||||||
return shell
|
|
||||||
}
|
|
||||||
// The os/user package doesn't store the parsed out shell field.
|
|
||||||
return "/bin/sh"
|
|
||||||
}
|
|
||||||
|
|
||||||
func giteaSign(b []byte) string {
|
func giteaSign(b []byte) string {
|
||||||
payloadHmac := hmac.New(sha256.New, []byte(getConfig().Secret))
|
payloadHmac := hmac.New(sha256.New, []byte(getConfig().Secret))
|
||||||
payloadHmac.Write(b)
|
payloadHmac.Write(b)
|
||||||
@ -313,7 +306,9 @@ function get(id) {
|
|||||||
return document.getElementById(id)
|
return document.getElementById(id)
|
||||||
}
|
}
|
||||||
function getLog(id) {
|
function getLog(id) {
|
||||||
const header = get(id), log = get(id + 'log'), text = log.textContent
|
const header = document.getElementById(id)
|
||||||
|
const log = document.getElementById(id + 'log')
|
||||||
|
const text = log.textContent
|
||||||
// lines[-1] is an implementation detail of terminalWriter.Serialize,
|
// lines[-1] is an implementation detail of terminalWriter.Serialize,
|
||||||
// lines[-2] is the actual last line.
|
// lines[-2] is the actual last line.
|
||||||
const last = Math.max(0, text.split('\n').length - 2)
|
const last = Math.max(0, text.split('\n').length - 2)
|
||||||
@ -331,7 +326,8 @@ function refreshLog(log, top, changed) {
|
|||||||
log.log.hidden = empty
|
log.log.hidden = empty
|
||||||
}
|
}
|
||||||
let refresher = setInterval(() => {
|
let refresher = setInterval(() => {
|
||||||
const run = getLog('run'), task = getLog('task'), deploy = getLog('deploy')
|
let run = getLog('run'), task = getLog('task'), deploy = getLog('deploy')
|
||||||
|
|
||||||
const url = new URL(window.location.href)
|
const url = new URL(window.location.href)
|
||||||
url.search = ''
|
url.search = ''
|
||||||
url.searchParams.set('json', '')
|
url.searchParams.set('json', '')
|
||||||
@ -370,8 +366,8 @@ let refresher = setInterval(() => {
|
|||||||
if (!data.IsRunning)
|
if (!data.IsRunning)
|
||||||
clearInterval(refresher)
|
clearInterval(refresher)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
clearInterval(refresher)
|
|
||||||
alert(error)
|
alert(error)
|
||||||
|
clearInterval(refresher)
|
||||||
})
|
})
|
||||||
}, 1000 /* For faster updates than this, we should use WebSockets. */)
|
}, 1000 /* For faster updates than this, we should use WebSockets. */)
|
||||||
</script>
|
</script>
|
||||||
@ -846,7 +842,7 @@ func notifierRunCommand(ctx context.Context, task Task) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, localShell())
|
cmd := exec.CommandContext(ctx, "sh")
|
||||||
cmd.Stdin = script
|
cmd.Stdin = script
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@ -1170,6 +1166,14 @@ func executorDownload(client *ssh.Client, remoteRoot, localRoot string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func executorLocalShell() string {
|
||||||
|
if shell := os.Getenv("SHELL"); shell != "" {
|
||||||
|
return shell
|
||||||
|
}
|
||||||
|
// The os/user package doesn't store the parsed out shell field.
|
||||||
|
return "/bin/sh"
|
||||||
|
}
|
||||||
|
|
||||||
func executorTmpDir(fallback string) string {
|
func executorTmpDir(fallback string) string {
|
||||||
// See also: https://systemd.io/TEMPORARY_DIRECTORIES/
|
// See also: https://systemd.io/TEMPORARY_DIRECTORIES/
|
||||||
if tmp := os.Getenv("TMPDIR"); tmp != "" {
|
if tmp := os.Getenv("TMPDIR"); tmp != "" {
|
||||||
@ -1205,10 +1209,9 @@ func executorDeploy(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, localShell())
|
cmd := exec.CommandContext(ctx, executorLocalShell(), "-c", script.String())
|
||||||
cmd.Env = rt.localEnv()
|
cmd.Env = rt.localEnv()
|
||||||
cmd.Dir = dir
|
cmd.Dir = dir
|
||||||
cmd.Stdin = script
|
|
||||||
cmd.Stdout = &rt.DeployLog
|
cmd.Stdout = &rt.DeployLog
|
||||||
cmd.Stderr = &rt.DeployLog
|
cmd.Stderr = &rt.DeployLog
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
@ -1602,15 +1605,18 @@ func (t *Task) CloneURL() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func shortDurationString(d time.Duration) string {
|
func shortDurationString(d time.Duration) string {
|
||||||
if d.Abs() >= 24*time.Hour {
|
rs := []rune(d.Truncate(time.Second).String())
|
||||||
return strconv.FormatInt(int64(d/time.Hour/24), 10) + "d"
|
for i, r := range rs {
|
||||||
} else if d.Abs() >= time.Hour {
|
if !unicode.IsLetter(r) {
|
||||||
return strconv.FormatInt(int64(d/time.Hour), 10) + "h"
|
continue
|
||||||
} else if d.Abs() >= time.Minute {
|
}
|
||||||
return strconv.FormatInt(int64(d/time.Minute), 10) + "m"
|
i++
|
||||||
} else {
|
for i < len(rs) && unicode.IsLetter(rs[i]) {
|
||||||
return strconv.FormatInt(int64(d/time.Second), 10) + "s"
|
i++
|
||||||
|
}
|
||||||
|
return string(rs[:i])
|
||||||
}
|
}
|
||||||
|
return string(rs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) Created() *time.Time {
|
func (t *Task) Created() *time.Time {
|
||||||
|
17
acid_test.go
17
acid_test.go
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
ttemplate "text/template"
|
ttemplate "text/template"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTemplateQuote(t *testing.T) {
|
func TestTemplateQuote(t *testing.T) {
|
||||||
@ -31,19 +30,3 @@ func TestTemplateQuote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShortDurationString(t *testing.T) {
|
|
||||||
for _, test := range []struct {
|
|
||||||
d time.Duration
|
|
||||||
expect string
|
|
||||||
}{
|
|
||||||
{72 * time.Hour, "3d"},
|
|
||||||
{-3 * time.Hour, "-3h"},
|
|
||||||
{12 * time.Minute, "12m"},
|
|
||||||
{time.Millisecond, "0s"},
|
|
||||||
} {
|
|
||||||
if sd := shortDurationString(test.d); sd != test.expect {
|
|
||||||
t.Errorf("%s = %s; want %s\n", test.d, sd, test.expect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user