#!/usr/bin/env bash # Release automation script for token lists # Handles version bumping, validation, and release preparation set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TOKEN_LISTS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" LISTS_DIR="$TOKEN_LISTS_DIR/lists" TOKEN_LIST_FILE="$LISTS_DIR/dbis-138.tokenlist.json" CHANGELOG_FILE="$TOKEN_LISTS_DIR/docs/CHANGELOG.md" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } # Check if jq is available if ! command -v jq &> /dev/null; then log_error "jq is required but not installed" exit 1 fi # Check if node is available if ! command -v node &> /dev/null; then log_error "node is required but not installed" exit 1 fi # Get current version get_current_version() { jq -r '.version | "\(.major).\(.minor).\(.patch)"' "$TOKEN_LIST_FILE" } # Bump version bump_version() { local bump_type="${1:-patch}" # major, minor, patch local current_major current_minor current_patch current_major=$(jq -r '.version.major' "$TOKEN_LIST_FILE") current_minor=$(jq -r '.version.minor' "$TOKEN_LIST_FILE") current_patch=$(jq -r '.version.patch' "$TOKEN_LIST_FILE") case "$bump_type" in major) ((current_major++)) current_minor=0 current_patch=0 ;; minor) ((current_minor++)) current_patch=0 ;; patch) ((current_patch++)) ;; *) log_error "Invalid bump type: $bump_type (must be major, minor, or patch)" exit 1 ;; esac # Update version in JSON local tmp_file=$(mktemp) jq --arg major "$current_major" --arg minor "$current_minor" --arg patch "$current_patch" \ '.version.major = ($major | tonumber) | .version.minor = ($minor | tonumber) | .version.patch = ($patch | tonumber)' \ "$TOKEN_LIST_FILE" > "$tmp_file" mv "$tmp_file" "$TOKEN_LIST_FILE" echo "$current_major.$current_minor.$current_patch" } # Update timestamp update_timestamp() { local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") local tmp_file=$(mktemp) jq --arg ts "$timestamp" '.timestamp = $ts' "$TOKEN_LIST_FILE" > "$tmp_file" mv "$tmp_file" "$TOKEN_LIST_FILE" log_success "Updated timestamp to: $timestamp" } # Run all validations run_validations() { log_info "Running validations..." # JSON schema and basic validation log_info "Validating token list schema..." if ! node "$SCRIPT_DIR/validate-token-list.js" "$TOKEN_LIST_FILE"; then log_error "Schema validation failed" return 1 fi # Checksum validation log_info "Validating address checksums..." if ! node "$SCRIPT_DIR/checksum-addresses.js" "$TOKEN_LIST_FILE"; then log_error "Checksum validation failed" return 1 fi # Logo validation (non-blocking) log_info "Validating logos..." node "$SCRIPT_DIR/validate-logos.js" "$TOKEN_LIST_FILE" || log_warn "Logo validation had issues (continuing)" log_success "All critical validations passed" return 0 } # Generate release notes from CHANGELOG generate_release_notes() { local version="$1" if [[ ! -f "$CHANGELOG_FILE" ]]; then log_warn "CHANGELOG.md not found, skipping release notes generation" return fi # Extract section for this version log_info "Extracting release notes for version $version from CHANGELOG.md" # This is a simple implementation - you might want to use a more sophisticated parser if grep -q "## \[$version\]" "$CHANGELOG_FILE"; then log_success "Release notes found in CHANGELOG.md" else log_warn "No release notes found for version $version in CHANGELOG.md" fi } # Main release function main() { local bump_type="${1:-patch}" local skip_validation="${2:-}" log_info "=========================================" log_info "Token List Release Preparation" log_info "=========================================" log_info "" # Check if file exists if [[ ! -f "$TOKEN_LIST_FILE" ]]; then log_error "Token list file not found: $TOKEN_LIST_FILE" exit 1 fi local current_version=$(get_current_version) log_info "Current version: $current_version" # Bump version log_info "Bumping $bump_type version..." local new_version=$(bump_version "$bump_type") log_success "New version: $new_version" # Update timestamp update_timestamp # Run validations (unless skipped) if [[ -z "$skip_validation" ]]; then if ! run_validations; then log_error "Validation failed. Release aborted." log_info "You can fix the issues and run again, or use --skip-validation to bypass" exit 1 fi else log_warn "Skipping validations (--skip-validation flag)" fi # Generate release notes generate_release_notes "$new_version" log_info "" log_success "Release preparation complete!" log_info "" log_info "Next steps:" log_info "1. Review changes: git diff $TOKEN_LIST_FILE" log_info "2. Commit: git add $TOKEN_LIST_FILE" log_info "3. Create tag: git tag -a v$new_version -m \"Release v$new_version\"" log_info "4. Push: git push && git push --tags" log_info "" log_info "Or run the signing script: $SCRIPT_DIR/sign-list.sh" } # Parse arguments if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then echo "Usage: $0 [bump-type] [--skip-validation]" echo "" echo "Bump types: major, minor, patch (default: patch)" echo "" echo "Examples:" echo " $0 patch # Bump patch version" echo " $0 minor # Bump minor version" echo " $0 major # Bump major version" echo " $0 patch --skip-validation # Skip validation checks" exit 0 fi main "${1:-patch}" "${2:-}"