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,21 +1,29 @@ | |
| 1 | 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. | |
| 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 | 4 | # | |
| 5 | 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 | |
| 6 | 7 | # | |
| 7 | 8 | # stdin format (per ref pushed): <old-sha> <new-sha> <ref-name> | |
| 8 | 9 | ||
| 9 | 10 | set -euo pipefail | |
| 10 | 11 | ||
| 11 | 12 | PIPE_HOST="${PIPE_HOST:-pipe.pico.sh}" | |
| 12 | - | PGS_HOST="${PGS_HOST:-pgs.sh}" | |
| 13 | - | PGS_PROJECT_BASE="${PGS_PROJECT_BASE:-public-ci}" | |
| 14 | 13 | ||
| 15 | 14 | log() { | |
| 16 | 15 | echo "[post-receive] $*" >&2 | |
| 17 | 16 | } | |
| 18 | 17 | ||
| 18 | + | repo="$(basename "$(pwd)" .git)" | |
| 19 | + | ||
| 20 | + | # Read upload base from git config — noop if unset | |
| 21 | + | upload_base="$(git config --get pici.upload 2>/dev/null)" || true | |
| 22 | + | if [ -z "$upload_base" ]; then | |
| 23 | + | log "pici.upload not set, skipping $repo" | |
| 24 | + | exit 0 | |
| 25 | + | fi | |
| 26 | + | ||
| 19 | 27 | while read -r old_sha new_sha ref; do | |
| 20 | 28 | # Skip delete refs | |
| 21 | 29 | if [ "$new_sha" = "0000000000000000000000000000000000000000" ]; then |
| ... | ... | @@ -23,39 +31,47 @@ while read -r old_sha new_sha ref; do | |
| 23 | 31 | continue | |
| 24 | 32 | fi | |
| 25 | 33 | ||
| 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 | 34 | short_sha="${new_sha:0:8}" | |
| 33 | 35 | ||
| 34 | - | log "repo=$repo branch=$branch commit=$new_sha" | |
| 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 | |
| 35 | 50 | ||
| 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" | |
| 51 | + | log "repo=$repo type=$event_type name=$ref_name commit=$new_sha" | |
| 39 | 52 | ||
| 40 | - | if ! git archive "$new_sha" | ssh -T "$PGS_HOST" "$tar_path"; then | |
| 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 | |
| 41 | 60 | log "ERROR: upload failed" >&2 | |
| 42 | 61 | continue | |
| 43 | 62 | fi | |
| 44 | 63 | ||
| 45 | - | # Workspace points to the tar on pgs.sh | |
| 46 | - | workspace="${PGS_HOST}:${tar_path}" | |
| 64 | + | workspace="${upload_host}:${tar_path}" | |
| 65 | + | artifact_dest="${upload_host}:${upload_dir}" | |
| 47 | 66 | ||
| 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 | |
| 67 | + | if [ "$event_type" = "git.tag" ]; then | |
| 68 | + | event=$(printf '{"type":"%s","name":"%s","tag":"%s","commit":"%s","workspace":"%s","artifact_dest":"%s"}' \ | |
| 69 | + | "$event_type" "$repo" "$ref_name" "$new_sha" "$workspace" "$artifact_dest") | |
| 70 | + | else | |
| 71 | + | event=$(printf '{"type":"%s","name":"%s","branch":"%s","commit":"%s","workspace":"%s","artifact_dest":"%s"}' \ | |
| 72 | + | "$event_type" "$repo" "$ref_name" "$new_sha" "$workspace" "$artifact_dest") | |
| 54 | 73 | fi | |
| 55 | 74 | ||
| 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 | 75 | log "publish: $event" | |
| 60 | 76 | echo "$event" | ssh -T "$PIPE_HOST" pub -b=false build.event | |
| 61 | 77 | log "done" |
M
main.go
+6,
-1
| ... | ... | @@ -67,6 +67,7 @@ type Event struct { | |
| 67 | 67 | Name string `json:"name"` | |
| 68 | 68 | Workspace string `json:"workspace"` | |
| 69 | 69 | Branch string `json:"branch"` | |
| 70 | + | Tag string `json:"tag"` | |
| 70 | 71 | Commit string `json:"commit"` | |
| 71 | 72 | ArtifactDest string `json:"artifact_dest"` | |
| 72 | 73 | ForcePush bool `json:"force_push,omitempty"` |
| ... | ... | @@ -259,7 +260,8 @@ ENV VARS IN pico.sh | |
| 259 | 260 | The runner exports these environment variables for your pico.sh script: | |
| 260 | 261 | PICO_CI_JOB_ID Unique job identifier (e.g. "a3f2b8c1") | |
| 261 | 262 | PICO_CI_REPO Repository name (from event "name" field) | |
| 262 | - | PICO_CI_EVENT_TYPE Event type (from event "type" field) | |
| 263 | + | PICO_CI_EVENT_TYPE Event type (e.g. "git.push", "git.tag") | |
| 264 | + | PICO_CI_TAG_NAME Tag name (set only for git.tag events) | |
| 263 | 265 | ||
| 264 | 266 | Note: pico.sh runs with the workspace as its working directory, so | |
| 265 | 267 | $(pwd) gives you the workspace path directly. |
| ... | ... | @@ -542,6 +544,9 @@ func (eng *JobEngine) Run(manifest string) error { | |
| 542 | 544 | fmt.Sprintf("PICO_CI_REPO=%s", eng.Ev.Name), | |
| 543 | 545 | fmt.Sprintf("PICO_CI_EVENT_TYPE=%s", eng.Ev.Type), | |
| 544 | 546 | ) | |
| 547 | + | if eng.Ev.Tag != "" { | |
| 548 | + | cmdEnv = append(cmdEnv, fmt.Sprintf("PICO_CI_TAG_NAME=%s", eng.Ev.Tag)) | |
| 549 | + | } | |
| 545 | 550 | ||
| 546 | 551 | zmxPrefixStr := fmt.Sprintf("ZMX_SESSION_PREFIX=%s", childPrefix) | |
| 547 | 552 | cmd := exec.Command("zmx", "run", runnerName, "-d", zmxPrefixStr, "bash", manifest) |