build.sh 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/bin/bash
  2. set -eo pipefail
  3. # Initialize variables with default values
  4. image_name=""
  5. org_name=""
  6. push=0
  7. load=0
  8. tag_suffix=""
  9. # Function to display usage information
  10. usage() {
  11. echo "Usage: $0 -i <image_name> [-o <org_name>] [--push] [--load] [-t <tag_suffix>]"
  12. echo " -i: Image name (required)"
  13. echo " -o: Organization name"
  14. echo " --push: Push the image"
  15. echo " --load: Load the image"
  16. echo " -t: Tag suffix"
  17. exit 1
  18. }
  19. # Parse command-line options
  20. while [[ $# -gt 0 ]]; do
  21. case $1 in
  22. -i) image_name="$2"; shift 2 ;;
  23. -o) org_name="$2"; shift 2 ;;
  24. --push) push=1; shift ;;
  25. --load) load=1; shift ;;
  26. -t) tag_suffix="$2"; shift 2 ;;
  27. *) usage ;;
  28. esac
  29. done
  30. # Check if required arguments are provided
  31. if [[ -z "$image_name" ]]; then
  32. echo "Error: Image name is required."
  33. usage
  34. fi
  35. echo "Building: $image_name"
  36. tags=()
  37. OPENHANDS_BUILD_VERSION="dev"
  38. cache_tag_base="buildcache"
  39. cache_tag="$cache_tag_base"
  40. if [[ -n $RELEVANT_SHA ]]; then
  41. git_hash=$(git rev-parse --short "$RELEVANT_SHA")
  42. tags+=("$git_hash")
  43. tags+=("$RELEVANT_SHA")
  44. fi
  45. if [[ -n $GITHUB_REF_NAME ]]; then
  46. # check if ref name is a version number
  47. if [[ $GITHUB_REF_NAME =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  48. major_version=$(echo "$GITHUB_REF_NAME" | cut -d. -f1)
  49. minor_version=$(echo "$GITHUB_REF_NAME" | cut -d. -f1,2)
  50. tags+=("$major_version" "$minor_version")
  51. tags+=("latest")
  52. fi
  53. sanitized_ref_name=$(echo "$GITHUB_REF_NAME" | sed 's/[^a-zA-Z0-9.-]\+/-/g')
  54. OPENHANDS_BUILD_VERSION=$sanitized_ref_name
  55. sanitized_ref_name=$(echo "$sanitized_ref_name" | tr '[:upper:]' '[:lower:]') # lower case is required in tagging
  56. tags+=("$sanitized_ref_name")
  57. cache_tag+="-${sanitized_ref_name}"
  58. fi
  59. if [[ -n $tag_suffix ]]; then
  60. cache_tag+="-${tag_suffix}"
  61. for i in "${!tags[@]}"; do
  62. tags[$i]="${tags[$i]}-$tag_suffix"
  63. done
  64. fi
  65. echo "Tags: ${tags[@]}"
  66. if [[ "$image_name" == "openhands" ]]; then
  67. dir="./containers/app"
  68. elif [[ "$image_name" == "runtime" ]]; then
  69. dir="./containers/runtime"
  70. else
  71. dir="./containers/$image_name"
  72. fi
  73. if [[ (! -f "$dir/Dockerfile") && "$image_name" != "runtime" ]]; then
  74. # Allow runtime to be built without a Dockerfile
  75. echo "No Dockerfile found"
  76. exit 1
  77. fi
  78. if [[ ! -f "$dir/config.sh" ]]; then
  79. echo "No config.sh found for Dockerfile"
  80. exit 1
  81. fi
  82. source "$dir/config.sh"
  83. if [[ -n "$org_name" ]]; then
  84. DOCKER_ORG="$org_name"
  85. fi
  86. # If $DOCKER_IMAGE_SOURCE_TAG is set, add it to the tags
  87. if [[ -n "$DOCKER_IMAGE_SOURCE_TAG" ]]; then
  88. tags+=("$DOCKER_IMAGE_SOURCE_TAG")
  89. fi
  90. # If $DOCKER_IMAGE_TAG is set, add it to the tags
  91. if [[ -n "$DOCKER_IMAGE_TAG" ]]; then
  92. tags+=("$DOCKER_IMAGE_TAG")
  93. fi
  94. DOCKER_REPOSITORY="$DOCKER_REGISTRY/$DOCKER_ORG/$DOCKER_IMAGE"
  95. DOCKER_REPOSITORY=${DOCKER_REPOSITORY,,} # lowercase
  96. echo "Repo: $DOCKER_REPOSITORY"
  97. echo "Base dir: $DOCKER_BASE_DIR"
  98. args=""
  99. for tag in "${tags[@]}"; do
  100. args+=" -t $DOCKER_REPOSITORY:$tag"
  101. done
  102. if [[ $push -eq 1 ]]; then
  103. args+=" --push"
  104. args+=" --cache-to=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag,mode=max"
  105. fi
  106. if [[ $load -eq 1 ]]; then
  107. args+=" --load"
  108. fi
  109. echo "Args: $args"
  110. # Modify the platform selection based on --load flag
  111. if [[ $load -eq 1 ]]; then
  112. # When loading, build only for the current platform
  113. platform=$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')
  114. else
  115. # For push or without load, build for multiple platforms
  116. platform="linux/amd64,linux/arm64"
  117. fi
  118. echo "Building for platform(s): $platform"
  119. docker buildx build \
  120. $args \
  121. --build-arg OPENHANDS_BUILD_VERSION="$OPENHANDS_BUILD_VERSION" \
  122. --cache-from=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag \
  123. --cache-from=type=registry,ref=$DOCKER_REPOSITORY:$cache_tag_base-main \
  124. --platform $platform \
  125. --provenance=false \
  126. -f "$dir/Dockerfile" \
  127. "$DOCKER_BASE_DIR"
  128. # If load was requested, print the loaded images
  129. if [[ $load -eq 1 ]]; then
  130. echo "Local images built:"
  131. docker images "$DOCKER_REPOSITORY" --format "{{.Repository}}:{{.Tag}}"
  132. fi