From 8e197fe8ec1b586429fb0935ddb71d8e9056a7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Steinbr=C3=BCck?= Date: Sun, 29 Jun 2025 20:18:06 +0200 Subject: [PATCH] feat: add post_exec_script support (#520) --- Dockerfile | 2 +- README.md | 29 +++++++++++++++++++++++++++++ cmd/reclone.go | 21 +++++++++++++++++++-- sample-reclone.yaml | 1 + 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 669c4f5..576cc59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ ENV GHORG_CONFIG=/config/conf.yaml ENV GHORG_RECLONE_PATH=/config/reclone.yaml ENV GHORG_ABSOLUTE_PATH_TO_CLONE_TO=/data -RUN apk add -U --no-cache ca-certificates openssh-client tzdata git \ +RUN apk add -U --no-cache ca-certificates openssh-client tzdata git curl \ && mkdir -p /data $XDG_CONFIG_HOME \ && addgroup --gid $GID $GROUP \ && adduser -D -H --gecos "" \ diff --git a/README.md b/README.md index 5152616..1ad74a0 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,35 @@ The `ghorg reclone` command is a way to store all your `ghorg clone` commands in Once your [reclone.yaml](https://github.com/gabrie30/ghorg/blob/master/sample-reclone.yaml) configuration is set you can call `ghorg reclone` to clone each entry individually or clone all at once, see examples below. +Each reclone entry can have: +- `cmd`: The ghorg clone command to execute (required) +- `description`: A description of what the command does (optional) +- `post_exec_script`: Path to a script that will be called after the clone command finishes (optional). The script will always be called, regardless of success or failure, and receives two arguments: the status (`success` or `fail`) and the name of the reclone entry. This allows you to implement custom notifications, monitoring, or other automation (optional) + +Example `reclone.yaml` entry: + +```yaml +gitlab-examples: + cmd: "ghorg clone gitlab-examples --scm=gitlab --token=XXXXXXX" + post_exec_script: "/path/to/notify.sh" +``` + +Example script for `post_exec_script` (e.g. `/path/to/notify.sh`): + +```sh +#!/bin/sh +STATUS="$1" +NAME="$2" + +if [ "$STATUS" = "success" ]; then + # Success webhook + curl -fsS https://hc-ping.com/your-uuid-here +else + # Failure webhook + curl -fsS https://hc-ping.com/your-uuid-here/fail +fi +``` + ``` # To clone all the entries in your reclone.yaml omit any arguments ghorg reclone diff --git a/cmd/reclone.go b/cmd/reclone.go index dea4247..f905068 100644 --- a/cmd/reclone.go +++ b/cmd/reclone.go @@ -20,8 +20,9 @@ var reCloneCmd = &cobra.Command{ } type ReClone struct { - Cmd string `yaml:"cmd"` - Description string `yaml:"description"` + Cmd string `yaml:"cmd"` + Description string `yaml:"description"` + PostExecScript string `yaml:"post_exec_script"` // optional } func isQuietReClone() bool { @@ -196,6 +197,22 @@ func runReClone(rc ReClone, rcIdentifier string) { } err = ghorgClone.Wait() + status := "success" + if err != nil { + status = "fail" + } + + if rc.PostExecScript != "" { + postCmd := exec.Command(rc.PostExecScript, status, rcIdentifier) + postCmd.Stdout = os.Stdout + postCmd.Stderr = os.Stderr + errPost := postCmd.Run() + if errPost != nil { + colorlog.PrintError(fmt.Sprintf("ERROR: Running post_exec_script %s: %v", rc.PostExecScript, errPost)) + } + } + + if err != nil { spinningSpinner.Stop() colorlog.PrintErrorAndExit(fmt.Sprintf("ERROR: Running ghorg clone cmd: %v, err: %v", safeToLogCmd, err)) diff --git a/sample-reclone.yaml b/sample-reclone.yaml index f8eddee..4b125ac 100644 --- a/sample-reclone.yaml +++ b/sample-reclone.yaml @@ -16,6 +16,7 @@ # Example for gitlab; update with your gitlab cloud token gitlab-examples: cmd: "ghorg clone gitlab-examples --scm=gitlab --preserve-dir --token=XXXXXXX" + post_exec_script: "/path/to/notify.sh" # Examples from README.md; update with your github cloud token kubernetes: