Commit 423fd53

Eric Bower  ·  2026-05-26 21:41:38 -0400 EDT
parent c03514f
refactor: post-receive hook updates

We now look for a git config pici.upload for the rsync destination

We also support git.tag events
2 files changed,  +48, -27
+42, -26
  1@@ -1,21 +1,29 @@
  2 #!/usr/bin/env bash
  3-# post-receive hook — archives the pushed commit and uploads to pgs.sh,
  4-# then publishes a build event to pici via ssh pipe.
  5+# post-receive hook — archives the pushed commit, uploads to the configured
  6+# pici.upload destination, and publishes a build event via ssh pipe.
  7 #
  8 # Install: ./install-hooks.sh /path/to/bare-repos
  9+# Opt-in:  git -C /path/to/repo.git config pici.upload pgs.sh:/private-ci/myrepo
 10 #
 11 # stdin format (per ref pushed): <old-sha> <new-sha> <ref-name>
 12 
 13 set -euo pipefail
 14 
 15 PIPE_HOST="${PIPE_HOST:-pipe.pico.sh}"
 16-PGS_HOST="${PGS_HOST:-pgs.sh}"
 17-PGS_PROJECT_BASE="${PGS_PROJECT_BASE:-public-ci}"
 18 
 19 log() {
 20   echo "[post-receive] $*" >&2
 21 }
 22 
 23+repo="$(basename "$(pwd)" .git)"
 24+
 25+# Read upload base from git config — noop if unset
 26+upload_base="$(git config --get pici.upload 2>/dev/null)" || true
 27+if [ -z "$upload_base" ]; then
 28+  log "pici.upload not set, skipping $repo"
 29+  exit 0
 30+fi
 31+
 32 while read -r old_sha new_sha ref; do
 33   # Skip delete refs
 34   if [ "$new_sha" = "0000000000000000000000000000000000000000" ]; then
 35@@ -23,39 +31,47 @@ while read -r old_sha new_sha ref; do
 36     continue
 37   fi
 38 
 39-  # Extract branch name from ref (e.g. refs/heads/main → main)
 40-  branch="${ref#refs/heads/}"
 41-
 42-  # Repo name and short SHA from bare repo
 43-  repo="$(basename "$(pwd)" .git)"
 44-  pgs_project="${PGS_PROJECT_BASE}-${repo}"
 45   short_sha="${new_sha:0:8}"
 46 
 47-  log "repo=$repo branch=$branch commit=$new_sha"
 48+  case "$ref" in
 49+    refs/heads/*)
 50+      event_type="git.push"
 51+      ref_name="${ref#refs/heads/}"
 52+      ;;
 53+    refs/tags/*)
 54+      event_type="git.tag"
 55+      ref_name="${ref#refs/tags/}"
 56+      ;;
 57+    *)
 58+      log "unknown ref: $ref"
 59+      continue
 60+      ;;
 61+  esac
 62 
 63-  pgs_path="/${pgs_project}/${short_sha}/"
 64-  tar_path="${pgs_path}workspace.tar"
 65-  log "upload: git archive $new_sha → $PGS_HOST:$tar_path"
 66+  log "repo=$repo type=$event_type name=$ref_name commit=$new_sha"
 67 
 68-  if ! git archive "$new_sha" | ssh -T "$PGS_HOST" "$tar_path"; then
 69+  # upload_base is "host:path", e.g. pgs.sh:/private-ci/myrepo
 70+  upload_host="${upload_base%%:*}"
 71+  upload_dir="${upload_base#*:}/${short_sha}/"
 72+  tar_path="${upload_dir}workspace.tar"
 73+  log "upload: git archive $new_sha → $upload_host:$tar_path"
 74+
 75+  if ! git archive "$new_sha" | ssh -T "$upload_host" "$tar_path"; then
 76     log "ERROR: upload failed" >&2
 77     continue
 78   fi
 79 
 80-  # Workspace points to the tar on pgs.sh
 81-  workspace="${PGS_HOST}:${tar_path}"
 82+  workspace="${upload_host}:${tar_path}"
 83+  artifact_dest="${upload_host}:${upload_dir}"
 84 
 85-  # Detect force push: old SHA is not an ancestor of new SHA
 86-  is_force_push=false
 87-  if [ "$old_sha" != "0000000000000000000000000000000000000000" ]; then
 88-    if ! git merge-base --is-ancestor "$old_sha" "$new_sha" 2>/dev/null; then
 89-      is_force_push=true
 90-    fi
 91+  if [ "$event_type" = "git.tag" ]; then
 92+    event=$(printf '{"type":"%s","name":"%s","tag":"%s","commit":"%s","workspace":"%s","artifact_dest":"%s"}' \
 93+      "$event_type" "$repo" "$ref_name" "$new_sha" "$workspace" "$artifact_dest")
 94+  else
 95+    event=$(printf '{"type":"%s","name":"%s","branch":"%s","commit":"%s","workspace":"%s","artifact_dest":"%s"}' \
 96+      "$event_type" "$repo" "$ref_name" "$new_sha" "$workspace" "$artifact_dest")
 97   fi
 98 
 99-  event=$(printf '{"type":"git.push","name":"%s","workspace":"%s","branch":"%s","commit":"%s","artifact_dest":"%s:%s","force_push":%s}' \
100-    "$repo" "$workspace" "$branch" "$new_sha" "$PGS_HOST" "$pgs_path" "$is_force_push")
101-
102   log "publish: $event"
103   echo "$event" | ssh -T "$PIPE_HOST" pub -b=false build.event
104   log "done"
+6, -1
 1@@ -67,6 +67,7 @@ type Event struct {
 2 	Name         string `json:"name"`
 3 	Workspace    string `json:"workspace"`
 4 	Branch       string `json:"branch"`
 5+	Tag          string `json:"tag"`
 6 	Commit       string `json:"commit"`
 7 	ArtifactDest string `json:"artifact_dest"`
 8 	ForcePush    bool   `json:"force_push,omitempty"`
 9@@ -259,7 +260,8 @@ ENV VARS IN pico.sh
10   The runner exports these environment variables for your pico.sh script:
11     PICO_CI_JOB_ID      Unique job identifier (e.g. "a3f2b8c1")
12     PICO_CI_REPO        Repository name (from event "name" field)
13-    PICO_CI_EVENT_TYPE  Event type (from event "type" field)
14+    PICO_CI_EVENT_TYPE  Event type (e.g. "git.push", "git.tag")
15+    PICO_CI_TAG_NAME    Tag name (set only for git.tag events)
16 
17   Note: pico.sh runs with the workspace as its working directory, so
18   $(pwd) gives you the workspace path directly.
19@@ -542,6 +544,9 @@ func (eng *JobEngine) Run(manifest string) error {
20 		fmt.Sprintf("PICO_CI_REPO=%s", eng.Ev.Name),
21 		fmt.Sprintf("PICO_CI_EVENT_TYPE=%s", eng.Ev.Type),
22 	)
23+	if eng.Ev.Tag != "" {
24+		cmdEnv = append(cmdEnv, fmt.Sprintf("PICO_CI_TAG_NAME=%s", eng.Ev.Tag))
25+	}
26 
27 	zmxPrefixStr := fmt.Sprintf("ZMX_SESSION_PREFIX=%s", childPrefix)
28 	cmd := exec.Command("zmx", "run", runnerName, "-d", zmxPrefixStr, "bash", manifest)