main pici / hooks / post-receive
Eric Bower  ·  2026-05-11
 1#!/usr/bin/env bash
 2# post-receive hook — archives the pushed commit and uploads to pgs.sh,
 3# then publishes a build event to pici via ssh pipe.
 4#
 5# Install: ./install-hooks.sh /path/to/bare-repos
 6#
 7# stdin format (per ref pushed): <old-sha> <new-sha> <ref-name>
 8
 9set -euo pipefail
10
11PIPE_HOST="${PIPE_HOST:-pipe.pico.sh}"
12PGS_HOST="${PGS_HOST:-pgs.sh}"
13PGS_PROJECT_BASE="${PGS_PROJECT_BASE:-public-ci}"
14
15log() {
16  echo "[post-receive] $*" >&2
17}
18
19while read -r old_sha new_sha ref; do
20  # Skip delete refs
21  if [ "$new_sha" = "0000000000000000000000000000000000000000" ]; then
22    log "skip delete ref: $ref"
23    continue
24  fi
25
26  # Extract branch name from ref (e.g. refs/heads/main → main)
27  branch="${ref#refs/heads/}"
28
29  # Repo name and short SHA from bare repo
30  repo="$(basename "$(pwd)" .git)"
31  pgs_project="${PGS_PROJECT_BASE}-${repo}"
32  short_sha="${new_sha:0:8}"
33
34  log "repo=$repo branch=$branch commit=$new_sha"
35
36  pgs_path="/${pgs_project}/${short_sha}/"
37  tar_path="${pgs_path}workspace.tar"
38  log "upload: git archive $new_sha$PGS_HOST:$tar_path"
39
40  if ! git archive "$new_sha" | ssh -T "$PGS_HOST" "$tar_path"; then
41    log "ERROR: upload failed" >&2
42    continue
43  fi
44
45  # Workspace points to the tar on pgs.sh
46  workspace="${PGS_HOST}:${tar_path}"
47
48  # Detect force push: old SHA is not an ancestor of new SHA
49  is_force_push=false
50  if [ "$old_sha" != "0000000000000000000000000000000000000000" ]; then
51    if ! git merge-base --is-ancestor "$old_sha" "$new_sha" 2>/dev/null; then
52      is_force_push=true
53    fi
54  fi
55
56  event=$(printf '{"type":"git.push","name":"%s","workspace":"%s","branch":"%s","commit":"%s","artifact_dest":"%s:%s","force_push":%s}' \
57    "$repo" "$workspace" "$branch" "$new_sha" "$PGS_HOST" "$pgs_path" "$is_force_push")
58
59  log "publish: $event"
60  echo "$event" | ssh -T "$PIPE_HOST" pub -b=false build.event
61  log "done"
62done