A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

serialize goreleaser

+45 -3
+45 -3
scripts/publish-artifact.sh
··· 1 1 #!/usr/bin/env bash 2 2 set -e 3 - goat account login -u "${TANGLED_REPO_DID}" -p "${APP_PASSWORD}" 3 + 4 + # Serialize across parallel invocations from goreleaser. goat stores its session 5 + # in a single file (~/.local/state/goat/auth-session.json), so concurrent logins 6 + # race on it, and the PDS gets slammed by simultaneous uploads. 7 + exec 9>/tmp/atcr-publish-artifact.lock 8 + flock 9 9 + 10 + retry() { 11 + local max=5 attempt=1 12 + while true; do 13 + if "$@"; then return 0; fi 14 + [ $attempt -ge $max ] && { echo "giving up after $max attempts: $*" >&2; return 1; } 15 + local sleep_s=$((attempt * 3)) 16 + echo "attempt $attempt failed; retrying in ${sleep_s}s..." >&2 17 + sleep $sleep_s 18 + attempt=$((attempt + 1)) 19 + done 20 + } 21 + 22 + retry goat account login -u "${TANGLED_REPO_DID}" -p "${APP_PASSWORD}" 23 + 4 24 TAG_HASH=$(git rev-parse "$TANGLED_REF_NAME") 5 25 TAG_BYTES=$(printf "$(printf '%s' "$TAG_HASH" | sed 's/../\\x&/g')" | base64 | tr -d '=') 6 - BLOB_OUTPUT=$(goat blob upload "$ARTIFACT_PATH") 26 + 27 + BLOB_OUTPUT=$(retry goat blob upload "$ARTIFACT_PATH") 7 28 echo "$BLOB_OUTPUT" 29 + 30 + # Deterministic rkey from (tag, artifact name) makes record create idempotent. 31 + # Needed because tangled's PDS returns HTTP 500 (not 409) on duplicate rkey, 32 + # so a retry after a mid-write 500 would otherwise create a duplicate record. 33 + RKEY=$(printf '%s|%s' "$TANGLED_REF_NAME" "$ARTIFACT_NAME" | sha256sum | cut -c1-24) 34 + RECORD_URI="at://${TANGLED_REPO_DID}/sh.tangled.repo.artifact/${RKEY}" 35 + 8 36 CREATED_AT=$(date -Iseconds) 9 37 cat > temp_artifact.json <<EOF 10 38 { ··· 17 45 } 18 46 EOF 19 47 cat temp_artifact.json 20 - goat record create temp_artifact.json -n 48 + 49 + # Attempt create; on failure, check whether the record actually landed. 50 + # Handles both transient 5xx and tangled's 500-on-duplicate-rkey behaviour. 51 + for attempt in 1 2 3 4 5; do 52 + if goat record create --rkey "$RKEY" temp_artifact.json -n; then 53 + break 54 + fi 55 + if goat record get "$RECORD_URI" >/dev/null 2>&1; then 56 + echo "record already exists at $RECORD_URI — treating as success" 57 + break 58 + fi 59 + [ $attempt -eq 5 ] && { echo "record create failed and record does not exist" >&2; exit 1; } 60 + sleep $((attempt * 3)) 61 + done 62 + 21 63 rm temp_artifact.json 22 64 sleep 2