Eric Bower
·
2026-07-22
1#!/usr/bin/env bash
2# post-receive hook — archives the pushed commit, uploads to the configured
3# pici.upload destination, and publishes a build event via ssh pipe.
4#
5# Install: ./install-hooks.sh /path/to/bare-repos
6# Opt-in: git -C /path/to/repo.git config pici.upload pgs.sh:/private-ci/myrepo
7#
8# stdin format (per ref pushed): <old-sha> <new-sha> <ref-name>
9
10set -euo pipefail
11
12PIPE_HOST="${PIPE_HOST:-pipe.pico.sh}"
13
14log() {
15 echo "[post-receive] $*" >&2
16}
17
18repo="$(basename "$(pwd)" .git)"
19
20# Read upload base from git config — noop if unset
21upload_base="$(git config --get pici.upload 2>/dev/null)" || true
22if [ -z "$upload_base" ]; then
23 log "pici.upload not set, skipping $repo"
24 exit 0
25fi
26
27while read -r old_sha new_sha ref; do
28 # Skip delete refs
29 if [ "$new_sha" = "0000000000000000000000000000000000000000" ]; then
30 log "skip delete ref: $ref"
31 continue
32 fi
33
34 short_sha="${new_sha:0:8}"
35
36 case "$ref" in
37 refs/heads/*)
38 event_type="git.push"
39 ref_name="${ref#refs/heads/}"
40 ;;
41 refs/tags/*)
42 event_type="git.tag"
43 ref_name="${ref#refs/tags/}"
44 ;;
45 *)
46 log "unknown ref: $ref"
47 continue
48 ;;
49 esac
50
51 log "repo=$repo type=$event_type name=$ref_name commit=$new_sha"
52
53 # upload_base is "host:path", e.g. pgs.sh:/private-ci/myrepo
54 upload_host="${upload_base%%:*}"
55 upload_dir="${upload_base#*:}/${short_sha}/"
56 tar_path="${upload_dir}workspace.tar"
57 log "upload: git archive $new_sha → $upload_host:$tar_path"
58
59 if ! git archive "$new_sha" | ssh -T "$upload_host" "$tar_path"; then
60 log "ERROR: upload failed" >&2
61 continue
62 fi
63
64 workspace="${upload_host}:${tar_path}"
65 artifact_dest="${upload_host}:${upload_dir}"
66 job_id="$short_sha"
67
68 if [ "$event_type" = "git.tag" ]; then
69 event=$(printf '{"type":"%s","name":"%s","job_id":"%s","tag":"%s","commit":"%s","workspace":"%s","artifact_dest":"%s"}' \
70 "$event_type" "$repo" "$job_id" "$ref_name" "$new_sha" "$workspace" "$artifact_dest")
71 else
72 event=$(printf '{"type":"%s","name":"%s","job_id":"%s","branch":"%s","commit":"%s","workspace":"%s","artifact_dest":"%s"}' \
73 "$event_type" "$repo" "$job_id" "$ref_name" "$new_sha" "$workspace" "$artifact_dest")
74 fi
75
76 log "publish: $event"
77 echo "$event" | ssh -T "$PIPE_HOST" pub -b=false pici
78 log "done"
79done