From f42589d1ed61f7caf6cf40f0e2d000aea9dda8f4 Mon Sep 17 00:00:00 2001 From: Astound Date: Mon, 6 May 2024 09:11:32 +0800 Subject: [PATCH] improve and relax make-hyperbola.sh --- make-hyperbola.sh | 246 +++++++++++++++++++++++++++------------------- 1 file changed, 146 insertions(+), 100 deletions(-) diff --git a/make-hyperbola.sh b/make-hyperbola.sh index 14a853a..a029583 100644 --- a/make-hyperbola.sh +++ b/make-hyperbola.sh @@ -1,122 +1,97 @@ #!/bin/bash -# Default tag -default_tag="v0.4.3" -default_release="2023.09.25" -latest_tag="latest" +# Variables +DEFAULT_TAG="v0.4.4" +DEFAULT_RELEASE="2024.05.06" +LATEST_TAG="latest" # Function to display help show_help() { - echo "Usage: $0 [-t TAG] [-h]" - echo " -t TAG Specify the tag (default: $default_tag)" - echo " -r VERSION Specify the release version (default: $default_release)" + 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" } -# Process command line options -while getopts ":t:h" opt; do - case $opt in - r) - release="$OPTARG" - ;; - t) - tag="$OPTARG" - ;; - h) - show_help && exit 0 - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - show_help && exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument." >&2 - show_help && exit 1 - ;; - esac -done +# Function to handle errors +handle_error() { + echo "Error: $1" >&2 + exit 1 +} -# Use default tag if not specified -tag="${tag:-$default_tag}" +# Function to download files +download_files() { + local release="$1" + local script_dir="$2" -# Use default release version if not specified -release="${release:-$default_release}" + 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." +} -# Working directory -script_dir="$(cd "$(dirname "$0")" && pwd)" +# Function to check if files exist +check_files_exist() { + local script_dir="$1" -# Check if files exist in the current directory -if [[ ! -e "$script_dir/hyperbola-bootstrap-i686.tar.gz" || ! -e "$script_dir/hyperbola-bootstrap-x86_64.tar.gz" ]]; then - echo "Downloading files for version $release..." + [[ -e "$script_dir/hyperbola-bootstrap-i686.tar.gz" && -e "$script_dir/hyperbola-bootstrap-x86_64.tar.gz" ]] +} - # Download files from the provided link - wget -P "$script_dir" "https://archive.fridu.us/hyperbola/iso/$release/hyperbola-bootstrap-i686.tar.gz" - wget -P "$script_dir" "https://archive.fridu.us/hyperbola/iso/$release/hyperbola-bootstrap-x86_64.tar.gz" +# Function to remove tag from Docker Hub +remove_tag() { + local username="$1" + local token="$2" + local tag="$3" - echo "Files downloaded successfully for version $release." -else - echo "Files already exist in the current directory. No download is required." -fi + 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.") +} -# Logout docker -docker logout > /dev/null 2>&1 +# Function to remove manifest locally +remove_manifest() { + local tag="$1" -# Prompt user for credentials -if [[ -z "$DOCKER_USERNAME" ]]; then - read -p "Enter your Docker Hub username: " DOCKER_USERNAME -fi + docker manifest rm "$tag" > /dev/null 2>&1 +} -if [[ -z "$DOCKER_PASSWORD" ]]; then - read -sp "Enter your Docker Hub password: " DOCKER_PASSWORD - echo -fi +# Function to push manifest to Docker Hub +push_manifest() { + local username="$1" + local tag="$2" + local latest_tag="$3" -# Log in to Docker Hub -echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin + docker manifest create "$username/hyperbola:$tag" \ + --amend "$username/hyperbola:$tag-386" \ + --amend "$username/hyperbola:$tag-amd64" -# Build the images -docker build --no-cache --platform=linux/amd64 --tag "$DOCKER_USERNAME/hyperbola:$tag-amd64" -f Dockerfile.amd64 . -docker build --no-cache --platform=linux/386 --tag "$DOCKER_USERNAME/hyperbola:$tag-386" -f Dockerfile.386 . + docker manifest annotate "$username/hyperbola:$tag" \ + "$username/hyperbola:$tag-amd64" --os linux --arch amd64 -# Push the images to Docker Hub -docker push "$DOCKER_USERNAME/hyperbola:$tag-amd64" -docker push "$DOCKER_USERNAME/hyperbola:$tag-386" + docker manifest push "$username/hyperbola:$tag" -# Create and push the manifest to specified tag -docker manifest create "$DOCKER_USERNAME/hyperbola:$tag" \ - --amend "$DOCKER_USERNAME/hyperbola:$tag-386" \ - --amend "$DOCKER_USERNAME/hyperbola:$tag-amd64" + # 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" -# Set amd64 leader to specified tag -docker manifest annotate "$DOCKER_USERNAME/hyperbola:$tag" \ - "$DOCKER_USERNAME/hyperbola:$tag-amd64" --os linux --arch amd64 + docker manifest annotate "$username/hyperbola:$latest_tag" \ + "$username/hyperbola:$tag-amd64" --os linux --arch amd64 -# Push specified tag -docker manifest push "$DOCKER_USERNAME/hyperbola:$tag" - -# Create and push the manifest for "latest" -docker manifest create "$DOCKER_USERNAME/hyperbola:$latest_tag" \ - --amend "$DOCKER_USERNAME/hyperbola:$tag-386" \ - --amend "$DOCKER_USERNAME/hyperbola:$tag-amd64" - -# Set amd64 leader to latest -docker manifest annotate "$DOCKER_USERNAME/hyperbola:$latest_tag" \ - "$DOCKER_USERNAME/hyperbola:$tag-amd64" --os linux --arch amd64 - -# Push to latest -docker manifest push "$DOCKER_USERNAME/hyperbola:$latest_tag" - -# Get the token -token=$(curl -s -H 'Content-Type: application/json' -X POST -H 'Content-Type: application/json' -d "{\"username\":\"$DOCKER_USERNAME\", \"password\":\"$DOCKER_PASSWORD\"}" "https://hub.docker.com/v2/users/login/" | jq -r .token) + docker manifest push "$username/hyperbola:$latest_tag" + fi +} # Function to perform a curl with retries -function curl_with_retry() { +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 DELETE -H "Authorization: JWT $token" "$url") + response=$(curl -s -X "$method" -H "Authorization: JWT $token" "$url") if [ $? -eq 0 ]; then echo "$response" return 0 @@ -130,15 +105,86 @@ function curl_with_retry() { return 1 } -# Delete tags on Docker Hub -if curl_with_retry "https://hub.docker.com/v2/repositories/$DOCKER_USERNAME/hyperbola/tags/$tag-amd64/"; then - echo "Tag $tag-amd64 deleted successfully." -else - echo "Failed to delete tag $tag-amd64." -fi +# Function to get the authentication token from Docker Hub +get_docker_auth_token() { + local docker_username="$1" + local docker_password="$2" + local token -if curl_with_retry "https://hub.docker.com/v2/repositories/$DOCKER_USERNAME/hyperbola/tags/$tag-386/"; then - echo "Tag $tag-386 deleted successfully." -else - echo "Failed to delete tag $tag-386." -fi + 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 "$@"