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"
M
main.go
+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)