1#!/bin/bash 2 3# Copyright 2022 Google LLC 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16################################################################################ 17 18# Deploys a Maven library. 19# 20# NOTE: 21# - This must be run from the root of the library workspace. 22 23usage() { 24 cat <<EOF 25Usage: $0 [-dh] [-n jars_name_prefix] [-u github_url] [-c bazel_cache_name] 26 <action (install|snapshot|release)> <library name> 27 <pom file> <version>" 28 -d: Dry run. Only execute idempotent commands (default: false). 29 -n: JARs name prefix. Prefix to apply to JAR names (default: <library name>). 30 -u: GitHub URL. GitHub URL for Javadoc publishing; it is mandatory when 31 <action> is "snaphot" or "release". 32 -c: Bazel cache to use; credentials are expected to be in the file 33 ./cache_key. 34 -h: Help. Print this usage information. 35EOF 36 exit 1 37} 38 39# Arguments to use for all git invocations. 40readonly GIT_ARGS=( 41 -c user.email=noreply@google.com 42 -c user.name="Tink Team" 43) 44 45to_absolute_path() { 46 local -r path="$1" 47 echo "$(cd "$(dirname "${path}")" && pwd)/$(basename "${path}")" 48} 49 50# Options. 51DRY_RUN="false" 52GIT_URL= 53JAR_NAME_PREFIX= 54 55# Positional arguments. 56LIBRARY_NAME= 57POM_FILE= 58ARTIFACT_VERSION= 59 60# Other. 61BAZEL_CMD="bazel" 62MAVEN_ARGS=() 63CACHE_FLAGS=() 64 65parse_args() { 66 # Parse options. 67 while getopts "dhn::u::c:" opt; do 68 case "${opt}" in 69 d) DRY_RUN="true" ;; 70 n) JAR_NAME_PREFIX="${OPTARG}" ;; 71 u) GIT_URL="${OPTARG}" ;; 72 c) CACHE_FLAGS=( 73 "--remote_cache=https://storage.googleapis.com/${OPTARG}" 74 "--google_credentials=$(to_absolute_path ./cache_key)" 75 ) ;; 76 *) usage ;; 77 esac 78 done 79 shift $((OPTIND - 1)) 80 81 readonly DRY_RUN 82 readonly JAR_NAME_PREFIX 83 readonly GIT_URL 84 readonly CACHE_FLAGS 85 86 # Parse args. 87 if (( $# < 4 )); then 88 usage 89 fi 90 ACTION="$1" 91 LIBRARY_NAME="$2" 92 POM_FILE="$3" 93 ARTIFACT_VERSION="$4" 94 95 # Make sure the version has the correct format. 96 if [[ ! "${ARTIFACT_VERSION}" =~ (^HEAD$|^[0-9]+\.[0-9]+\.[0-9]$) ]]; then 97 usage 98 fi 99 100 if [[ ! -f "${POM_FILE}" ]]; then 101 echo "ERROR: The POM file doesn't exist: ${POM_FILE}" >&2 102 usage 103 fi 104 105 local -r maven_scripts_dir="$(cd "$(dirname "${POM_FILE}")" && pwd)" 106 case "${ACTION}" in 107 install) 108 MAVEN_ARGS+=( "install:install-file" ) 109 ARTIFACT_VERSION="${ARTIFACT_VERSION}-SNAPSHOT" 110 ;; 111 snapshot) 112 if [[ -z "${GIT_URL}" ]]; then 113 usage 114 fi 115 MAVEN_ARGS+=( 116 "deploy:deploy-file" 117 "-DrepositoryId=ossrh" 118 "-Durl=https://oss.sonatype.org/content/repositories/snapshots" 119 "--settings=${maven_scripts_dir}/settings.xml" 120 ) 121 ARTIFACT_VERSION="${ARTIFACT_VERSION}-SNAPSHOT" 122 ;; 123 release) 124 if [[ -z "${GIT_URL}" ]]; then 125 usage 126 fi 127 MAVEN_ARGS+=( 128 "gpg:sign-and-deploy-file" 129 "-DrepositoryId=ossrh" 130 "-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/" 131 "-Dgpg.keyname=tink-dev@google.com" 132 "--settings=${maven_scripts_dir}/settings.xml" 133 ) 134 ;; 135 *) 136 usage 137 ;; 138 esac 139 140 if command -v "bazelisk" &> /dev/null; then 141 BAZEL_CMD="bazelisk" 142 fi 143 readonly BAZEL_CMD 144 145 readonly ACTION 146 readonly LIBRARY_NAME 147 readonly POM_FILE 148 readonly ARTIFACT_VERSION 149 readonly MAVEN_ARGS 150} 151 152do_run_command() { 153 if ! "$@"; then 154 echo "*** Failed executing command. ***" 155 echo "Failed command: $@" 156 exit 1 157 fi 158 return $? 159} 160 161print_command() { 162 printf '%q ' '+' "$@" 163 echo 164} 165 166print_and_do() { 167 print_command "$@" 168 do_run_command "$@" 169 return $? 170} 171 172####################################### 173# Runs a given command if DRY_RUN isn't true. 174# Globals: 175# DRY_RUN 176# Arguments: 177# The command to run and its arguments. 178####################################### 179do_run_if_not_dry_run() { 180 print_command "$@" 181 if [[ "${DRY_RUN}" == "true" ]]; then 182 echo " *** Dry run, command not executed. ***" 183 return 0 184 fi 185 do_run_command "$@" 186 return $? 187} 188 189echo_output_file() { 190 local workspace_dir="$1" 191 local library="$2" 192 193 ( 194 cd "${workspace_dir}" 195 local file="bazel-bin/${library}" 196 if [[ ! -e "${file}" ]]; then 197 file="bazel-genfiles/${library}" 198 fi 199 if [[ ! -e "${file}" ]]; then 200 echo "Could not find Bazel output file for ${library}" 201 exit 1 202 fi 203 echo -n "${workspace_dir}/${file}" 204 ) 205} 206 207####################################### 208# Pusblishes Javadoc to GitHub pages. 209# 210# Globals: 211# ACTION 212# GIT_ARGS 213# GIT_URL 214# LIBRARY_NAME 215# ARTIFACT_VERSION 216# Arguments: 217# workspace_dir: Workspace directory for the library. 218# javadoc: Javadoc library name. 219####################################### 220publish_javadoc_to_github_pages() { 221 if [[ "${ACTION}" == "install" ]]; then 222 echo "Local deployment, skipping publishing javadoc to GitHub Pages..." 223 return 0 224 fi 225 226 local workspace_dir="$1" 227 local javadoc="$2" 228 229 local -r javadoc_file="$(echo_output_file "${workspace_dir}" "${javadoc}")" 230 231 print_and_do rm -rf gh-pages 232 print_and_do git "${GIT_ARGS[@]}" clone \ 233 --quiet --branch=gh-pages "${GIT_URL}" gh-pages > /dev/null 234 ( 235 print_and_do cd gh-pages 236 if [ -d "javadoc/${LIBRARY_NAME}/${ARTIFACT_VERSION}" ]; then 237 print_and_do git "${GIT_ARGS[@]}" rm -rf \ 238 "javadoc/${LIBRARY_NAME}/${ARTIFACT_VERSION}" 239 fi 240 print_and_do mkdir -p "javadoc/${LIBRARY_NAME}/${ARTIFACT_VERSION}" 241 print_and_do unzip "${javadoc_file}" \ 242 -d "javadoc/${LIBRARY_NAME}/${ARTIFACT_VERSION}" 243 print_and_do rm -rf "javadoc/${LIBRARY_NAME}/${ARTIFACT_VERSION}/META-INF/" 244 print_and_do git "${GIT_ARGS[@]}" add \ 245 -f "javadoc/${LIBRARY_NAME}/${ARTIFACT_VERSION}" 246 if [[ "$(git "${GIT_ARGS[@]}" status --porcelain)" ]]; then 247 # Changes exist. 248 do_run_if_not_dry_run \ 249 git "${GIT_ARGS[@]}" commit \ 250 -m "${LIBRARY_NAME}-${ARTIFACT_VERSION} Javadoc auto-pushed to gh-pages" 251 252 do_run_if_not_dry_run \ 253 git "${GIT_ARGS[@]}" push -fq origin gh-pages > /dev/null 254 echo -e "Published Javadoc to gh-pages.\n" 255 else 256 # No changes exist. 257 echo -e "No changes in ${LIBRARY_NAME}-${ARTIFACT_VERSION} Javadoc.\n" 258 fi 259 ) 260} 261 262main() { 263 parse_args "$@" 264 265 local -r jars_name_prefix="${JAR_NAME_PREFIX:-${LIBRARY_NAME}}" 266 local -r library="${jars_name_prefix}.jar" 267 local -r src_jar="${jars_name_prefix}-src.jar" 268 local -r javadoc="${jars_name_prefix}-javadoc.jar" 269 270 local -r workspace_dir="$(pwd)" 271 272 print_and_do "${BAZEL_CMD}" build "${CACHE_FLAGS[@]}" "${library}" \ 273 "${src_jar}" "${javadoc}" 274 275 local -r library_file="$(echo_output_file "${workspace_dir}" "${library}")" 276 local -r src_jar_file="$(echo_output_file "${workspace_dir}" "${src_jar}")" 277 local -r javadoc_file="$(echo_output_file "${workspace_dir}" "${javadoc}")" 278 279 # Update the version in the POM file. 280 do_run_if_not_dry_run sed -i \ 281 's/VERSION_PLACEHOLDER/'"${ARTIFACT_VERSION}"'/' "${POM_FILE}" 282 283 do_run_if_not_dry_run mvn "${MAVEN_ARGS[@]}" -Dfile="${library_file}" \ 284 -Dsources="${src_jar_file}" -Djavadoc="${javadoc_file}" \ 285 -DpomFile="${POM_FILE}" 286 287 # Add the placeholder back in the POM file. 288 do_run_if_not_dry_run sed -i \ 289 's/'"${ARTIFACT_VERSION}"'/VERSION_PLACEHOLDER/' "${POM_FILE}" 290 291 publish_javadoc_to_github_pages "${workspace_dir}" "${javadoc}" 292} 293 294main "$@" 295