mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-20 08:30:29 +00:00
64 lines
2.1 KiB
Bash
Executable File
64 lines
2.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
# Serialize across parallel invocations from goreleaser to avoid slamming the
|
|
# PDS with simultaneous uploads. `goat account login` happens once in the
|
|
# release workflow before goreleaser runs, so this script just reuses the
|
|
# existing session.
|
|
exec 9>/tmp/atcr-publish-artifact.lock
|
|
flock 9
|
|
|
|
retry() {
|
|
local max=5 attempt=1
|
|
while true; do
|
|
if "$@"; then return 0; fi
|
|
[ $attempt -ge $max ] && { echo "giving up after $max attempts: $*" >&2; return 1; }
|
|
local sleep_s=$((attempt * 3))
|
|
echo "attempt $attempt failed; retrying in ${sleep_s}s..." >&2
|
|
sleep $sleep_s
|
|
attempt=$((attempt + 1))
|
|
done
|
|
}
|
|
|
|
TAG_HASH=$(git rev-parse "$TANGLED_REF_NAME")
|
|
TAG_BYTES=$(printf "$(printf '%s' "$TAG_HASH" | sed 's/../\\x&/g')" | base64 | tr -d '=')
|
|
|
|
BLOB_OUTPUT=$(retry goat blob upload "$ARTIFACT_PATH")
|
|
echo "$BLOB_OUTPUT"
|
|
|
|
# Deterministic rkey from (tag, artifact name) makes record create idempotent.
|
|
# Needed because tangled's PDS returns HTTP 500 (not 409) on duplicate rkey,
|
|
# so a retry after a mid-write 500 would otherwise create a duplicate record.
|
|
RKEY=$(printf '%s|%s' "$TANGLED_REF_NAME" "$ARTIFACT_NAME" | sha256sum | cut -c1-24)
|
|
RECORD_URI="at://${TANGLED_REPO_DID}/sh.tangled.repo.artifact/${RKEY}"
|
|
|
|
CREATED_AT=$(date -Iseconds)
|
|
cat > temp_artifact.json <<EOF
|
|
{
|
|
"\$type": "sh.tangled.repo.artifact",
|
|
"tag": {"\$bytes": "${TAG_BYTES}"},
|
|
"name": "${ARTIFACT_NAME}",
|
|
"repo": "${REPO_URL}",
|
|
"artifact": ${BLOB_OUTPUT},
|
|
"createdAt": "${CREATED_AT}"
|
|
}
|
|
EOF
|
|
cat temp_artifact.json
|
|
|
|
# Attempt create; on failure, check whether the record actually landed.
|
|
# Handles both transient 5xx and tangled's 500-on-duplicate-rkey behaviour.
|
|
for attempt in 1 2 3 4 5; do
|
|
if goat record create --rkey "$RKEY" temp_artifact.json -n; then
|
|
break
|
|
fi
|
|
if goat record get "$RECORD_URI" >/dev/null 2>&1; then
|
|
echo "record already exists at $RECORD_URI — treating as success"
|
|
break
|
|
fi
|
|
[ $attempt -eq 5 ] && { echo "record create failed and record does not exist" >&2; exit 1; }
|
|
sleep $((attempt * 3))
|
|
done
|
|
|
|
rm temp_artifact.json
|
|
sleep 2
|