#!/bin/bash # Variables DEFAULT_TAG="v0.4.4" DEFAULT_RELEASE="2024.07.21" LATEST_TAG="latest" # Function to display help show_help() { echo "Usage: $0 [-t TAG] [-r VERSION] [-h]" echo " -t TAG Specify the tag (default: $DEFAULT_TAG)" echo " -r VERSION Specify the release version (default: $DEFAULT_RELEASE)" echo " -h Show this help" } # Function to handle errors handle_error() { echo "Error: $1" >&2 exit 1 } # Function to download files download_files() { local release="$1" local script_dir="$2" echo "Downloading files for version $release..." wget -P "$script_dir" "https://archive.fridu.us/hyperbola/iso/$release/hyperbola-bootstrap-i686.tar.gz" || handle_error "Failed to download files." wget -P "$script_dir" "https://archive.fridu.us/hyperbola/iso/$release/hyperbola-bootstrap-x86_64.tar.gz" || handle_error "Failed to download files." echo "Files downloaded successfully for version $release." } # Function to check if files exist check_files_exist() { local script_dir="$1" [[ -e "$script_dir/hyperbola-bootstrap-i686.tar.gz" && -e "$script_dir/hyperbola-bootstrap-x86_64.tar.gz" ]] } # Function to remove tag from Docker Hub remove_tag() { local username="$1" local token="$2" local tag="$3" curl_with_retry "https://hub.docker.com/v2/repositories/$username/hyperbola/tags/$tag" "$token" DELETE \ && (echo -n "Temporal tag $tag removed successfully." || echo -n "Failed to remove temporal tag $tag.") } # Function to remove manifest locally remove_manifest() { local tag="$1" docker manifest rm "$tag" > /dev/null 2>&1 } # Function to push manifest to Docker Hub push_manifest() { local username="$1" local tag="$2" local latest_tag="$3" docker manifest create "$username/hyperbola:$tag" \ --amend "$username/hyperbola:$tag-386" \ --amend "$username/hyperbola:$tag-amd64" docker manifest annotate "$username/hyperbola:$tag" \ "$username/hyperbola:$tag-amd64" --os linux --arch amd64 docker manifest push "$username/hyperbola:$tag" # Push to latest if not already latest tag if [ "$tag" != "$latest_tag" ]; then docker manifest create "$username/hyperbola:$latest_tag" \ --amend "$username/hyperbola:$tag-386" \ --amend "$username/hyperbola:$tag-amd64" docker manifest annotate "$username/hyperbola:$latest_tag" \ "$username/hyperbola:$tag-amd64" --os linux --arch amd64 docker manifest push "$username/hyperbola:$latest_tag" fi } # Function to perform a curl with retries curl_with_retry() { local url="$1" local token="$2" local method="$3" local retries=3 # Number of retries local delay=5 # Delay between retries in seconds for ((i = 0; i < retries; i++)); do response=$(curl -s -X "$method" -H "Authorization: JWT $token" "$url") if [ $? -eq 0 ]; then echo "$response" return 0 else echo "Attempt $((i+1)) failed. Retrying in $delay seconds..." sleep $delay fi done echo "All attempts failed. Curl command with URL '$url' has failed." return 1 } # Function to get the authentication token from Docker Hub get_docker_auth_token() { local docker_username="$1" local docker_password="$2" local token token=$(curl -s -H 'Content-Type: application/json' -X POST -d "{\"username\":\"$docker_username\", \"password\":\"$docker_password\"}" "https://hub.docker.com/v2/users/login/" | jq -r .token) if [ -z "$token" ]; then handle_error "Failed to obtain Docker authentication token." fi echo "$token" } # Main main() { local tag="$DEFAULT_TAG" local release="$DEFAULT_RELEASE" local script_dir="$(cd "$(dirname "$0")" && pwd)" local docker_username="$DOCKER_USERNAME" local docker_password # Process command line options while getopts ":t:r:h" opt; do case $opt in r) release="$OPTARG" ;; t) tag="$OPTARG" ;; h) show_help && exit 0 ;; \?) handle_error "Invalid option: -$OPTARG" ;; :) handle_error "Option -$OPTARG requires an argument." ;; esac done # Download files if not exist if ! check_files_exist "$script_dir"; then download_files "$release" "$script_dir" else echo "Files already exist in the current directory. No download is required." fi # Retrieve Docker credentials from ~/.docker/config.json if exists if [ -f "$HOME/.docker/config.json" ]; then docker_username="$(jq -r '.auths."https://index.docker.io/v1/".auth' < "$HOME/.docker/config.json" | base64 -d | cut -d ':' -f1)" docker_password="$(jq -r '.auths."https://index.docker.io/v1/".auth' < "$HOME/.docker/config.json" | base64 -d | cut -d ':' -f2)" echo "$docker_password" | docker login --username "$docker_username" --password-stdin || handle_error "Docker login failed." else # Prompt for Docker credentials if ~/.docker/config.json doesn't exist read -p "Enter your Docker Hub username: " docker_username read -sp "Enter your Docker Hub password: " docker_password echo # Login to Docker Hub echo "$docker_password" | docker login --username "$docker_username" --password-stdin || handle_error "Docker login failed." fi # Get Docker authentication token local docker_token=$(get_docker_auth_token "$docker_username" "$docker_password") # Build and push images docker build --no-cache --platform=linux/amd64 --tag "$docker_username/hyperbola:$tag-amd64" -f Dockerfile.amd64 . || handle_error "Failed to build amd64 image." docker build --no-cache --platform=linux/386 --tag "$docker_username/hyperbola:$tag-386" -f Dockerfile.386 . || handle_error "Failed to build 386 image." docker push "$docker_username/hyperbola:$tag-amd64" || handle_error "Failed to push amd64 image." docker push "$docker_username/hyperbola:$tag-386" || handle_error "Failed to push 386 image." # Remove old manifests remove_manifest "$docker_username/hyperbola:$tag" remove_manifest "$docker_username/hyperbola:$LATEST_TAG" # Push manifests push_manifest "$docker_username" "$tag" "$LATEST_TAG" echo -n "Cleaning up temporary images..." # Remove old tags remove_tag "$docker_username" "$docker_token" "$tag-amd64" remove_tag "$docker_username" "$docker_token" "$tag-386" echo "" echo "Hyperbola images for version $release with tag $tag have been successfully pushed to Docker Hub." } # Execute main function main "$@"