Files
dify/cli/scripts/release-upload-tarballs.sh

100 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# scripts/release-upload-tarballs.sh — idempotent gh release upload of
# tarballs + checksum file (sha256-strict; skip on match, fail on mismatch)
# and cosign .sig/.pem signatures (overwrite-allowed; bytes vary per run).
#
# Required env: DIFY_TAG, CLI_VERSION, GH_TOKEN.
set -euo pipefail
_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/common.sh
source "${_dir}/lib/common.sh"
require gh
require jq
: "${DIFY_TAG:?DIFY_TAG is required}"
: "${CLI_VERSION:?CLI_VERSION is required}"
cd "$(cli::root)"
REPO_FLAG=(--repo langgenius/dify)
if command -v sha256sum >/dev/null 2>&1; then
hash_cmd() { sha256sum "$1" | awk '{print $1}'; }
elif command -v shasum >/dev/null 2>&1; then
hash_cmd() { shasum -a 256 "$1" | awk '{print $1}'; }
else
die "no sha256 hasher found (need sha256sum or shasum)"
fi
remote_json=$(gh release view "$DIFY_TAG" "${REPO_FLAG[@]}" --json assets -q '.assets')
upload_one() {
local file="$1"
local mode="${2:-strict}" # strict | clobber
local name
name=$(basename "$file")
local local_sha
local_sha=$(hash_cmd "$file")
local remote_entry
remote_entry=$(printf '%s' "$remote_json" | jq -c --arg n "$name" '.[] | select(.name == $n)')
if [[ -z "$remote_entry" ]]; then
log::info "uploading ${name}"
gh release upload "$DIFY_TAG" "$file" "${REPO_FLAG[@]}"
return
fi
if [[ "$mode" == "clobber" ]]; then
log::info "overwriting ${name} (clobber mode — cosign sig/cert)"
gh release upload "$DIFY_TAG" "$file" "${REPO_FLAG[@]}" --clobber
return
fi
local remote_digest remote_sha=""
remote_digest=$(printf '%s' "$remote_entry" | jq -r '.digest // ""')
if [[ "$remote_digest" == sha256:* ]]; then
remote_sha="${remote_digest#sha256:}"
else
local tmp download_url
tmp=$(mktemp)
download_url=$(printf '%s' "$remote_entry" | jq -r '.url')
gh api -H 'Accept: application/octet-stream' "$download_url" > "$tmp"
remote_sha=$(hash_cmd "$tmp")
rm -f "$tmp"
fi
if [[ "$local_sha" == "$remote_sha" ]]; then
log::info "skip ${name} (sha256 matches)"
return
fi
die "asset ${name} already on ${DIFY_TAG} with different sha256 (local=${local_sha}, remote=${remote_sha}); refusing to overwrite"
}
shopt -s nullglob
tars=(dist/difyctl-v"${CLI_VERSION}"-*.tar.xz)
checksum_file="dist/difyctl-v${CLI_VERSION}-checksums.txt"
sigs=(dist/difyctl-v"${CLI_VERSION}"-*.sig dist/difyctl-v"${CLI_VERSION}"-checksums.txt.sig)
pems=(dist/difyctl-v"${CLI_VERSION}"-*.pem dist/difyctl-v"${CLI_VERSION}"-checksums.txt.pem)
shopt -u nullglob
[[ ${#tars[@]} -gt 0 ]] || die "no tarballs in dist/ matching difyctl-v${CLI_VERSION}-*.tar.xz"
[[ -f "$checksum_file" ]] || die "checksum file missing: ${checksum_file}"
for f in "${tars[@]}" "$checksum_file"; do
upload_one "$f" strict
done
# Cosign signatures + certs are keyless and re-generated per run with fresh
# timestamps; their bytes change each run but verify the same blob. Allow
# overwrite via --clobber so re-runs converge cleanly.
for f in "${sigs[@]}" "${pems[@]}"; do
[[ -f "$f" ]] || continue
upload_one "$f" clobber
done
log::info "uploaded ${#tars[@]} tarballs + checksums.txt + signatures to dify release ${DIFY_TAG}"