pass hook configuration through CLI arguments
This commit is contained in:
@@ -96,21 +96,15 @@ simpleci 提供集成适配器 `pkgs/simpleci/simplegit-hook.sh`。联合部署
|
||||
显式使用该脚本,并配置:
|
||||
|
||||
```sh
|
||||
export SIMPLECI_URL=http://simpleci:8095
|
||||
export SIMPLECI_HOOK_TOKEN=replace-with-a-shared-secret
|
||||
export SIMPLECI_WORKFLOW=.github/workflows/deploy.yml # 可选
|
||||
simplegit daemon -hook-script /path/to/simplegit-hook.sh
|
||||
simplegit daemon \
|
||||
-hook-script=/path/to/simplegit-hook.sh \
|
||||
-hook-arg=--url=http://simpleci:8095 \
|
||||
-hook-arg=--workflow=.github/workflows/deploy.yml \
|
||||
-hook-arg=--
|
||||
```
|
||||
|
||||
tag push 和分支删除不会触发构建;simpleci 不可用时通知最多等待 5 秒,且不影响
|
||||
push 的成功结果。simpleci 使用相同 secret 启动:
|
||||
|
||||
```sh
|
||||
simpleci -hook-token replace-with-a-shared-secret
|
||||
```
|
||||
|
||||
`SIMPLECI_HOOK_TOKEN` 和 `-hook-token` 都为空时不启用鉴权,适合仅在受信任的
|
||||
本机或内部网络开发;生产环境应从同一个 Secret 分别注入两端。
|
||||
push 的成功结果。`POST /runs` 应只暴露在受信任的内部网络。
|
||||
|
||||
---
|
||||
|
||||
|
||||
+29
-19
@@ -33,6 +33,10 @@ func Run(args []string) {
|
||||
return nil
|
||||
})
|
||||
fs.StringVar(&cfg.HookScript, "hook-script", "./hook.sh", "script run by every Git hook; receives hook type and owner/name as its first two arguments")
|
||||
fs.Func("hook-arg", "fixed argument passed to -hook-script before hook type and owner/name (repeatable)", func(arg string) error {
|
||||
cfg.HookArgs = append(cfg.HookArgs, arg)
|
||||
return nil
|
||||
})
|
||||
fs.StringVar(&cfg.DBUri, "db", "sqlite://./db.sqlite", "private state DB URI (sqlite://<path> or postgres://<dsn>) - backs PAT/SSH-key ACLs and repo metadata")
|
||||
fs.Parse(args)
|
||||
|
||||
@@ -51,9 +55,6 @@ func Run(args []string) {
|
||||
app := NewApp(cfg.RepoRoot(), store)
|
||||
server := gitrpc.NewServer(&cfg, store)
|
||||
|
||||
if _, err := ensureHookTemplate(cfg.Root); err != nil {
|
||||
log.Printf("simplegit: hook template: %v (hooks disabled)", err)
|
||||
}
|
||||
if cfg.HookScript != "" {
|
||||
hookScript, err := resolveHookScript(cfg.HookScript)
|
||||
if err != nil {
|
||||
@@ -67,15 +68,10 @@ func Run(args []string) {
|
||||
log.Fatalf("simplegit: hook script %s is not executable", hookScript)
|
||||
}
|
||||
cfg.HookScript = hookScript
|
||||
_ = os.Setenv("SIMPLEGIT_HOOK_SCRIPT", hookScript)
|
||||
repoRoot, err := filepath.Abs(cfg.RepoRoot())
|
||||
if err != nil {
|
||||
log.Fatalf("simplegit: resolve repository root: %v", err)
|
||||
log.Printf("simplegit: Git hooks execute %s %s", hookScript, strings.Join(cfg.HookArgs, " "))
|
||||
}
|
||||
_ = os.Setenv("SIMPLEGIT_REPO_ROOT", repoRoot)
|
||||
log.Printf("simplegit: Git hooks execute %s", hookScript)
|
||||
} else {
|
||||
_ = os.Unsetenv("SIMPLEGIT_HOOK_SCRIPT")
|
||||
if _, err := ensureHookTemplate(cfg.Root, cfg.HookScript, cfg.HookArgs); err != nil {
|
||||
log.Printf("simplegit: hook template: %v (hooks disabled)", err)
|
||||
}
|
||||
|
||||
// gitrpc mux: Connect-RPC (GitService + ManageService) + the binary content
|
||||
@@ -153,16 +149,18 @@ var gitHookNames = []string{
|
||||
"p4-prepare-changelist", "p4-changelist",
|
||||
}
|
||||
|
||||
const hookWrapper = `#!/bin/sh
|
||||
# Generated by simplegit. The operator controls hook behavior with -hook-script.
|
||||
test -n "$SIMPLEGIT_HOOK_SCRIPT" || exit 0
|
||||
const hookWrapperTemplate = `#!/bin/sh
|
||||
# Generated by simplegit. The operator controls behavior with -hook-script.
|
||||
repo_dir=$(pwd -P)
|
||||
repo=${repo_dir#"$SIMPLEGIT_REPO_ROOT"/}
|
||||
repo=${repo%%.git}
|
||||
exec "$SIMPLEGIT_HOOK_SCRIPT" %s "$repo" "$@"
|
||||
repo_name=${repo_dir##*/}
|
||||
repo_name=${repo_name%%.git}
|
||||
owner_dir=${repo_dir%%/*}
|
||||
owner=${owner_dir##*/}
|
||||
repo=$owner/$repo_name
|
||||
exec %s %s "$repo" "$@"
|
||||
`
|
||||
|
||||
func ensureHookTemplate(root string) (string, error) {
|
||||
func ensureHookTemplate(root, script string, args []string) (string, error) {
|
||||
dir := filepath.Join(root, "template")
|
||||
hooksDir := filepath.Join(dir, "hooks")
|
||||
if err := os.MkdirAll(hooksDir, 0o755); err != nil {
|
||||
@@ -170,7 +168,15 @@ func ensureHookTemplate(root string) (string, error) {
|
||||
}
|
||||
for _, name := range gitHookNames {
|
||||
path := filepath.Join(hooksDir, name)
|
||||
if err := os.WriteFile(path, []byte(fmt.Sprintf(hookWrapper, name)), 0o755); err != nil {
|
||||
body := "#!/bin/sh\nexit 0\n"
|
||||
if script != "" {
|
||||
command := shellQuote(script)
|
||||
for _, arg := range args {
|
||||
command += " " + shellQuote(arg)
|
||||
}
|
||||
body = fmt.Sprintf(hookWrapperTemplate, command, shellQuote(name))
|
||||
}
|
||||
if err := os.WriteFile(path, []byte(body), 0o755); err != nil {
|
||||
return "", fmt.Errorf("write hook %s: %w", name, err)
|
||||
}
|
||||
}
|
||||
@@ -180,6 +186,10 @@ func ensureHookTemplate(root string) (string, error) {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func shellQuote(value string) string {
|
||||
return "'" + strings.ReplaceAll(value, "'", `'"'"'`) + "'"
|
||||
}
|
||||
|
||||
func refreshRepositoryHooks(reposRoot, templateHooks string) error {
|
||||
if _, err := os.Stat(reposRoot); os.IsNotExist(err) {
|
||||
return nil
|
||||
|
||||
@@ -27,6 +27,8 @@ type Config struct {
|
||||
// The hook name is its first argument; Git's original args, stdin and
|
||||
// environment are preserved. Empty disables hook effects.
|
||||
HookScript string
|
||||
// HookArgs are fixed CLI arguments placed before the hook type and repo.
|
||||
HookArgs []string
|
||||
DBUri string
|
||||
|
||||
preparedDbUri string
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
#!/bin/sh
|
||||
# Default standalone policy: append the hook invocation and its stdin to a log.
|
||||
# Integrations can supply another script with simplegit daemon -hook-script.
|
||||
# Default standalone policy. Optional CLI: --log=/path/to/hooks.log --
|
||||
|
||||
log_file=${SIMPLEGIT_HOOK_LOG:-${SIMPLEGIT_REPO_ROOT%/repos}/hooks.log}
|
||||
log_file=
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--log=*) log_file=${1#--log=}; shift ;;
|
||||
--log) log_file=$2; shift 2 ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
[ "$#" -ge 2 ] || exit 0
|
||||
if [ -z "$log_file" ]; then
|
||||
repo_dir=$(pwd -P)
|
||||
log_file=${repo_dir%/*/*}/hooks.log
|
||||
fi
|
||||
{
|
||||
printf '%s\t%s\t%s' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$1" "$2"
|
||||
shift 2
|
||||
|
||||
Reference in New Issue
Block a user