| #!/bin/bash |
| |
| # Abort script if a command fails |
| set -e |
| |
| export CASSANDRA_USE_JDK11=true |
| export CASSANDRA_WEBSITE_DIR="${BUILD_DIR}/cassandra-website" |
| export CASSANDRA_SOURCE_DIR="${BUILD_DIR}/cassandra" |
| export CASSANDRA_WORKING_DIR="${BUILD_DIR}/working/cassandra" |
| export CASSANDRA_WORKING_DOC="${CASSANDRA_WORKING_DIR}/doc" |
| GIT_USER_SETUP="false" |
| |
| setup_git_user() { |
| if [ "${GIT_USER_SETUP}" = "false" ] |
| then |
| # Setup git so we can commit back to the Cassandra repository locally |
| git config --global user.email "${GIT_EMAIL_ADDRESS}" |
| git config --global user.name "${GIT_USER_NAME}" |
| GIT_USER_SETUP="true" |
| fi |
| } |
| |
| generate_cassandra_versioned_docs() { |
| mkdir -p "${CASSANDRA_WORKING_DIR}" |
| # Check if the Cassandra repository is mounted as a volume or if it needs to be cloned. In either case we need to make |
| # a local copy as some of the pages need to be generated from the source code. |
| if [ "$(find "${CASSANDRA_SOURCE_DIR}" -mindepth 1 -type f | wc -l)" -eq 0 ] |
| then |
| log_message "INFO" "Cloning ${ANTORA_CONTENT_SOURCES_CASSANDRA_URL} to working directory" |
| git clone "${ANTORA_CONTENT_SOURCES_CASSANDRA_URL}" "${CASSANDRA_WORKING_DIR}" |
| else |
| log_message "INFO" "Copying ${CASSANDRA_SOURCE_DIR} to working directory" |
| cp -a "${CASSANDRA_SOURCE_DIR}/." "${CASSANDRA_WORKING_DIR}/" |
| fi |
| |
| # Once the repository has been cloned/copied set the Antora Cassandra source URL to be the local working copy in |
| # the container. This is so it will be used as the version documentation source by Antora if we are generating the |
| # website HTML. |
| ANTORA_CONTENT_SOURCES_CASSANDRA_URL="${CASSANDRA_WORKING_DIR}" |
| |
| # Make sure Antora includes the versioned Cassandra documentation as part of the output. |
| ANTORA_CONTENT_SOURCE_REPOSITORIES+=(CASSANDRA) |
| |
| local commit_changes_to_branch="" |
| if [ "$(wc -w <<< "${GENERATE_CASSANDRA_VERSIONS}")" -gt 1 ] |
| then |
| commit_changes_to_branch="enabled" |
| else |
| commit_changes_to_branch="disabled" |
| fi |
| |
| for version in ${GENERATE_CASSANDRA_VERSIONS} |
| do |
| log_message "INFO" "Checking out '${version}'" |
| pushd "${CASSANDRA_WORKING_DIR}" > /dev/null |
| git clean -xdff |
| git checkout "${version}" |
| |
| log_message "INFO" "Building JAR files" |
| # Nodetool docs are autogenerated, and that needs nodetool to be built. However, before we can build nodetool we |
| # need to select the correct Java version |
| local doc_version="" |
| doc_version=$(ant echo-base-version | grep "\[echo\]" | tr -s ' ' | cut -d' ' -f3) |
| |
| local java_version="" |
| local javac_version="" |
| local ant_cmd_options="" |
| if [ "$(cut -d'.' -f1 <<< "${doc_version}")" -lt 4 ] |
| then |
| # For Cassandra 3.11 docs use JDK 8 |
| java_version="/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java" |
| javac_version="/usr/lib/jvm/java-8-openjdk-amd64/bin/javac" |
| ant_cmd_options="" |
| else |
| # For Cassandra 4.0+ docs use JDK 11 |
| java_version="/usr/lib/jvm/java-11-openjdk-amd64/bin/java" |
| javac_version="/usr/lib/jvm/java-11-openjdk-amd64/bin/javac" |
| ant_cmd_options="-Duse.jdk11=true" |
| fi |
| sudo update-alternatives --set java ${java_version} |
| sudo update-alternatives --set javac ${javac_version} |
| |
| log_message "INFO" "Using Java compiler version $(javac -version) to compile Cassandra JARs" |
| ant realclean |
| ant "${ant_cmd_options}" gen-asciidoc |
| popd > /dev/null |
| |
| pushd "${CASSANDRA_WORKING_DIR}" > /dev/null |
| if [ "${commit_changes_to_branch}" = "enabled" ] |
| then |
| # Remove the doc/* directory entries in the .gitignore file so we can commit the generated docs to the working |
| # Cassandra repository. This needs to be done so Antora can retrieve the generated docs from each branch when |
| # generating the HTML. |
| sed -i '/^doc/d' .gitignore |
| git add . |
| git commit -m "Automated commit: Generated nodetool and configuration documentation for version ${doc_version}." || log_message "INFO" "No new changes to commit." |
| fi |
| popd > /dev/null |
| done |
| } |
| |
| string_to_json() { |
| local key="${1}" |
| local value="${2}" |
| |
| echo -e "\"${key}\":\"${value}\"" |
| } |
| |
| list_to_json() { |
| local key="${1}" |
| local value="${2}" |
| |
| echo -e "\"${key}\":[$(echo \""${value}"\" | sed 's~\ ~\",\"~g')]" |
| } |
| |
| generate_json() { |
| local json_output |
| local count |
| |
| json_output="{" |
| count=1 |
| while true |
| do |
| local arg |
| local json_type |
| local key |
| local value |
| |
| arg="${!count}" |
| |
| if [ -z "${arg}" ] |
| then |
| break |
| fi |
| |
| json_type="$(cut -d':' -f1 <<< ${arg})" |
| key="$(cut -d':' -f2 <<< ${arg})" |
| value=${arg//${json_type}:${key}:/} |
| if [ -n "${value}" ] |
| then |
| json_obj=$("${json_type}_to_json" "${key}" "${value}") |
| |
| if [ "${json_output}" = "{" ] |
| then |
| json_output="${json_output}${json_obj}" |
| else |
| json_output="${json_output},${json_obj}" |
| fi |
| fi |
| count=$((count + 1)) |
| done |
| json_output="${json_output}}" |
| |
| echo -e "${json_output}" |
| } |
| |
| generate_site_yaml() { |
| pushd "${CASSANDRA_WEBSITE_DIR}/site-content" > /dev/null |
| |
| local repository_url="" |
| local start_path="" |
| local branches="" |
| local tags="" |
| local content_source_options=() |
| for repo in ${ANTORA_CONTENT_SOURCE_REPOSITORIES[*]} |
| do |
| repository_url=$(eval echo "$"ANTORA_CONTENT_SOURCES_${repo}_URL"") |
| start_path=$(eval echo "$"ANTORA_CONTENT_SOURCES_${repo}_START_PATH"") |
| branches=$(eval echo "$"ANTORA_CONTENT_SOURCES_${repo}_BRANCHES"") |
| tags=$(eval echo "$"ANTORA_CONTENT_SOURCES_${repo}_TAGS"") |
| |
| if [ -n "${repository_url}" ] && [ -n "${start_path}" ] && { [ -n "${branches}" ] || [ -n "${tags}" ]; } |
| then |
| content_source_options+=("-c") |
| content_source_options+=("$(generate_json \ |
| "string:url:${repository_url}" \ |
| "string:start_path:${start_path}" \ |
| "list:branches:${branches}" \ |
| "list:tags:${tags}")") |
| fi |
| done |
| |
| log_message "INFO" "Building site.yaml" |
| rm -f site.yaml |
| python3 ./bin/site_yaml_generator.py \ |
| -s "$(generate_json \ |
| "string:title:${ANTORA_SITE_TITLE}" \ |
| "string:url:${ANTORA_SITE_URL}" \ |
| "string:start_page:${ANTORA_SITE_START_PAGE}") "\ |
| "${content_source_options[@]}" \ |
| -u "${ANTORA_UI_BUNDLE_URL}" \ |
| -r "${CASSANDRA_DOWNLOADS_URL}" \ |
| site.template.yaml |
| popd > /dev/null |
| } |
| |
| render_site_content_to_html() { |
| pushd "${CASSANDRA_WEBSITE_DIR}/site-content" > /dev/null |
| log_message "INFO" "Building the site HTML content." |
| antora --generator antora-site-generator-lunr site.yaml |
| log_message "INFO" "Rendering complete!" |
| popd > /dev/null |
| } |
| |
| |
| prepare_site_html_for_publication() { |
| pushd "${CASSANDRA_WEBSITE_DIR}" > /dev/null |
| |
| # copy everything to content/ directory |
| log_message "INFO" "Moving site HTML to content/" |
| mkdir -p content/doc |
| cp -r site-content/build/html/* content/ |
| |
| # remove hardcoded domain name, and empty domain names first before we duplicate and documentation |
| content_files_to_change=($(grep -rl 'https://cassandra.apache.org/' content/)) |
| log_message "INFO" "Removing hardcoded domain names in ${#content_files_to_change[*]} files" |
| for content_file in ${content_files_to_change[*]} |
| do |
| log_message "DEBUG" "Processing file ${content_file}" |
| # sed automatically uses the character following the 's' as a delimiter. |
| # In this case we will use the ',' so we can avoid the need to escape the '/' characters |
| sed -i 's,https://cassandra.apache.org/,/,g' ${content_file} |
| done |
| |
| content_files_to_change=($(grep -rl 'href="//' content/)) |
| log_message "INFO" "Removing empty domain names in ${#content_files_to_change[*]} files" |
| for content_file in ${content_files_to_change[*]} |
| do |
| log_message "DEBUG" "Processing file ${content_file}" |
| sed -i 's,href="//,href="/,g' ${content_file} |
| done |
| |
| # move around the in-tree docs if generated |
| if [ "${COMMAND_GENERATE_DOCS}" = "run" ] |
| then |
| log_message "INFO" "Moving versioned documentation HTML to content/doc" |
| move_intree_document_directories "3.11" "3.11.11" "3.11.12" |
| move_intree_document_directories "4.0" "4.0.0" "4.0.1" "4.0.2" "4.0.3" "stable" |
| move_intree_document_directories "trunk" "4.1" "latest" |
| fi |
| |
| popd > /dev/null |
| } |
| |
| |
| move_intree_document_directories() { |
| local source_doc_dir="$1" |
| shift |
| local target_doc_versions=("$@") |
| |
| local source_base_dir="content/Cassandra" |
| local target_base_dir="content/doc" |
| |
| if [ ${#target_doc_versions[*]} -eq 0 ] || [ "${source_doc_dir}" = "" ] |
| then |
| return |
| fi |
| |
| if [ -d "${source_base_dir}/${source_doc_dir}" ] |
| then |
| for cas_ver in ${target_doc_versions[*]} |
| do |
| rm -fR ${target_base_dir}/${cas_ver} |
| cp -r ${source_base_dir}/${source_doc_dir} ${target_base_dir}/${cas_ver} |
| done |
| rm -fR ${target_base_dir}/${source_doc_dir} |
| mv ${source_base_dir}/${source_doc_dir} ${target_base_dir}/ |
| fi |
| |
| # Check if our source directory is empty and if it is clean it up. |
| # Otherwise, leave it as is so we can see if we have missed a version. |
| if [ -z "$(ls -A ${source_base_dir})" ] |
| then |
| rmdir "${source_base_dir}" |
| fi |
| } |
| |
| run_preview_mode() { |
| log_message "INFO" "Entering preview mode!" |
| |
| export -f render_site_content_to_html |
| |
| local on_change_functions="render_site_content_to_html" |
| local find_paths="${CASSANDRA_WEBSITE_DIR}/${ANTORA_CONTENT_SOURCES_CASSANDRA_WEBSITE_START_PATH}" |
| |
| if [ "${COMMAND_GENERATE_DOCS}" = "run" ] |
| then |
| on_change_functions="generate_cassandra_versioned_docs && ${on_change_functions}" |
| find_paths="${find_paths} ${CASSANDRA_WORKING_DIR}/${ANTORA_CONTENT_SOURCES_CASSANDRA_START_PATH}" |
| |
| export -f generate_cassandra_versioned_docs |
| |
| # Ensure we only have one branch to generate docs for |
| GENERATE_CASSANDRA_VERSIONS=$(cut -d' ' -f1 <<< "${GENERATE_CASSANDRA_VERSIONS}") |
| fi |
| |
| if [ "${COMMAND_BUILD_SITE}" != "run" ] |
| then |
| generate_site_yaml |
| |
| export DOCSEARCH_ENABLED=true |
| export DOCSEARCH_ENGINE=lunr |
| export NODE_PATH="$(npm -g root)" |
| export DOCSEARCH_INDEX_VERSION=latest |
| |
| render_site_content_to_html |
| fi |
| |
| pushd "${CASSANDRA_WEBSITE_DIR}/site-content/build/html" > /dev/null |
| live-server --port=5151 --host=0.0.0.0 --no-browser --no-css-inject --wait=2000 & |
| popd > /dev/null |
| |
| find "${find_paths}" -type f | entr /bin/bash -c "${on_change_functions}" |
| } |
| |
| |
| log_level_str_to_int() { |
| local log_level_int |
| case $1 in |
| "OFF") |
| log_level_int=0 |
| ;; |
| "ERROR") |
| log_level_int=1 |
| ;; |
| "WARN") |
| log_level_int=2 |
| ;; |
| "INFO") |
| log_level_int=3 |
| ;; |
| "DEBUG"|"*") |
| log_level_int=4 |
| ;; |
| esac |
| echo ${log_level_int} |
| } |
| |
| |
| log_message() { |
| if [ ${LOG_LEVEL_INT} -ne 0 ] && [ $(log_level_str_to_int $1) -le ${LOG_LEVEL_INT} ] |
| then |
| echo "container: $1: $2" |
| fi |
| } |
| |
| # ============ MAIN ============ |
| |
| GENERATE_CASSANDRA_VERSIONS=$(sed 's/^[[:space:]]]*//' <<< "${ANTORA_CONTENT_SOURCES_CASSANDRA_BRANCHES} ${ANTORA_CONTENT_SOURCES_CASSANDRA_TAGS}") |
| export GENERATE_CASSANDRA_VERSIONS |
| export LOG_LEVEL_INT=$(log_level_str_to_int "${LOG_LEVEL}") |
| |
| ANTORA_CONTENT_SOURCE_REPOSITORIES=( |
| CASSANDRA_WEBSITE |
| ) |
| |
| # Initialise commands and assume none of them will run |
| COMMAND_GENERATE_DOCS="skip" |
| COMMAND_BUILD_SITE="skip" |
| COMMAND_PREVIEW="skip" |
| |
| # Work out which commands the caller has requested. We need to do this first as the commands should be run in a certain order |
| while [ "$1" != "" ] |
| do |
| case $1 in |
| "generate-docs") |
| COMMAND_GENERATE_DOCS="run" |
| ;; |
| "build-site") |
| COMMAND_BUILD_SITE="run" |
| ;; |
| "preview") |
| COMMAND_PREVIEW="run" |
| ;; |
| *) |
| log_message "WARN" "Skipping unrecognised command '$1'." |
| ;; |
| esac |
| |
| shift |
| done |
| |
| # Execute the commands as requested by the caller. |
| if [ "${COMMAND_GENERATE_DOCS}" = "run" ] |
| then |
| setup_git_user |
| generate_cassandra_versioned_docs |
| fi |
| |
| if [ "${COMMAND_BUILD_SITE}" = "run" ] |
| then |
| generate_site_yaml |
| |
| export DOCSEARCH_ENABLED=true |
| export DOCSEARCH_ENGINE=lunr |
| export NODE_PATH="$(npm -g root)" |
| export DOCSEARCH_INDEX_VERSION=latest |
| |
| render_site_content_to_html |
| |
| prepare_site_html_for_publication |
| fi |
| |
| if [ "${COMMAND_PREVIEW}" = "run" ] |
| then |
| run_preview_mode |
| fi |