blob: 584fe0f04fc1724a679307f208f8358def26f297 [file] [log] [blame]
#!/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