A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
76
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