From ca7e51e0b642b21fe119acf5e13c2d261e6cb35b Mon Sep 17 00:00:00 2001 From: Joseph Cayouette Date: Fri, 7 Feb 2025 14:42:49 +0100 Subject: [PATCH 1/4] update --- uyuni-docs-helper | 238 ++++++++++++---------------------------------- 1 file changed, 60 insertions(+), 178 deletions(-) diff --git a/uyuni-docs-helper b/uyuni-docs-helper index f551413..24f96a4 100755 --- a/uyuni-docs-helper +++ b/uyuni-docs-helper @@ -13,34 +13,38 @@ # You should have received a copy of the GNU General Public License along # with this program. If not, see . -# Language (force it so getopt messages are always in english, as the script) LANG=en_EN -# Get script name SCRIPT=$(basename ${0}) - -# By default, do not serve the doc using HTTP SERVE=0 - PROJECT='uyuni-project' - -# Default tag TAG='main' - -# Default Git repository GITREPO='https://github.com/uyuni-project/uyuni-docs.git' +GITREF='master' # Default branch is master +PRODUCT='uyuni' # Default product is uyuni -# Default Git reference -GITREF='master' +print_help() { + echo -e "\nUsage: ${SCRIPT} [OPTIONS]\n" + echo "Build the Uyuni documentation using a container." + echo -e "\nOptions:" + echo " -h, --help Show this help message and exit" + echo " -g, --gitrepo Specify the Git repository (default: ${GITREPO})" + echo " -r, --gitref Specify the Git branch or tag (default: ${GITREF})" + echo " -l, --localclone Use a local clone of the Uyuni docs repository" + echo " -o, --output Specify an output directory" + echo " -p, --product Choose a product: uyuni, mlm, suma" + echo " -c, --command Build command (e.g., all-uyuni, all-mlm)" + echo " -t, --tag Container image tag (default: ${TAG})" + echo " -j, --project Specify a GitHub project" + echo " -s, --serve Serve the documentation via HTTP after building" + echo -e "\nExamples:" + echo " ${SCRIPT} -l /path/to/uyuni-docs -p mlm -c all-mlm" + echo " ${SCRIPT} -g https://github.com/uyuni-project/uyuni-docs.git -p uyuni -c all-uyuni" +} -# use gnu-getopt on macOS getopt_for_macos() { if [ "$(uname -s)" == 'Darwin' ]; then if [ ! -f /usr/local/opt/gnu-getopt/bin/getopt ]; then - if [ "${SHELL}" == "/usr/local/bin/fish" ]; then - print_error "The fish shell is not supported (yet), please use bash or zsh for now" - exit 1 - fi print_error "Please install gnu-getopt via Homebrew with: brew install gnu-getopt" exit 1 else @@ -49,16 +53,12 @@ getopt_for_macos() { fi } -print_info() { - echo -e "\033[1;36m[INFO] ${1}\033[0m" -} - print_error() { echo -e "\033[1;31m[ERROR] ${1}\033[0m" } -print_ok() { - echo -e "\033[1;32m[INFO] ${1}\033[0m" +print_info() { + echo -e "\033[1;36m[INFO] ${1}\033[0m" } print_incorrect_syntax() { @@ -66,186 +66,68 @@ print_incorrect_syntax() { exit 1 } -get_dir_abs_path() { - ( - cd "$(dirname ${1})" - echo "${PWD}/$(basename $1)" - ) -} - -print_help() { - echo "" - echo "Build the Uyuni doc using a container and (optionally) serve it for verification via HTTP" - echo "" - echo "Syntax: " - echo "" - echo "${SCRIPT} " - echo "" - echo "Mandatory arguments:" - echo "" - echo "-p|--product Build the documentation for either Uyuni or SUSE Multi-Linux Manager" - echo "-c|--command Use the desired command to build html/pdf, html&pdf, etc..." - echo " for example: 'all-uyuni'. You can use 'help' to list all" - echo " possible commands. Be aware you still need to specify" - echo " one source for this to work" - echo "" - echo "${SCRIPT} can build documentation from two sources. Different parameters apply for each case." - echo "If both a local git repository and a remote git repository are specified, the local git" - echo "repository is used" - echo "" - echo "Remote Git repository:" - echo "-g|--gitrepo A path to a HTTP git repository where the code for the" - echo " documentation is." - echo " If the value does not start with 'https://'" - echo " then the value is considered as a GitHUb user/organization and" - echo " the URL in the form https://github.com//uyuni-docs.git" - echo " will be used" - echo " If not specified at all, the default value will be" - echo " ${GITREPO}" - echo "-r|--gitref A git branch (${GITREF} by default)" - echo "-o|--output An existing path to store the output of the build. A directory" - echo " 'build' will be created inside. Optional" - echo "" - echo "Local Git repository:" - echo "-l|--localclone A path to a local git repository. The output of the build will" - echo " be placed inside this path as a 'build' directory" - echo "" - echo "Optional arguments:" - echo "-t|--tag Use a secific tag for the container image. Can be useful if you" - echo " want to build an old documentation using an old version of the" - echo " toolchain. (${TAG} used by default)" - echo "-j|--project Specify a GitHub project. It can be useful if you want to use" - echo " a container image in a forked repository in your personal project" - echo "-s|--serve Start a HTTP server at the end of the build so the" - echo " documentation can be inspected (disabled by default)" -} - -# adjustments for macOS getopt_for_macos - -# read the options ARGS=$(getopt -o hg:r:l:o:p:c:t:j:s --long help,gitrepo:,gitref:,localclone:,output:,product:,command:,tag:,project:,serve -n "${SCRIPT}" -- "$@") -if [ $? -ne 0 ]; -then - print_incorrect_syntax "Invalid getopt call, notify this to the script maintainers" +if [ $? -ne 0 ]; then + print_incorrect_syntax "Invalid getopt call" fi -eval set -- "${ARGS}" -# extract options and their arguments into variables -while true ; do +eval set -- "${ARGS}" +while true; do case "${1}" in - -h|--help) print_help; exit 1;; - -g|--gitrepo) GITREPO="${2}"; shift 2;; - -r|--gitref) GITREF="${2}"; shift 2;; + -h|--help) print_help; exit 1;; + -g|--gitrepo) GITREPO="${2}"; shift 2;; + -r|--gitref) GITREF="${2}"; shift 2;; -l|--localclone) LOCALCLONE="${2}"; shift 2;; - -o|--output) OUTPUT="${2}"; shift 2;; - -p|--product) PRODUCT="${2}"; shift 2;; - -c|--command) COMMAND="${2}"; shift 2;; - -t|--tag) TAG="${2}"; shift 2;; - -j|--project) PROJECT="${2}"; shift 2;; - -s|--serve) SERVE=1; PORTS='-p 8000:8000'; shift 1;; - --) shift ; break ;; - *) print_incorrect_syntax "Invalid arguements in the call"; exit 1;; + -o|--output) OUTPUT="${2}"; shift 2;; + -p|--product) PRODUCT="${2}"; shift 2;; + -c|--command) COMMAND="${2}"; shift 2;; + -t|--tag) TAG="${2}"; shift 2;; + -j|--project) PROJECT="${2}"; shift 2;; + -s|--serve) SERVE=1; PORTS='-p 8000:8000'; shift 1;; + --) shift; break;; + *) print_incorrect_syntax "Invalid arguments"; exit 1;; esac done -# Image -IMAGE="ghcr.io/${PROJECT}/uyuni-docs-helper:${TAG}" - -# Command is mandatory -if [ -z ${COMMAND} ]; then - print_incorrect_syntax "-c is mandatory" -fi - -# Print a special error for the help command -if [ "${COMMAND}" == "help" ]; then - if [ -z ${LOCALCLONE} ] && [ -z ${GITREPO} ]; then - print_incorrect_syntax "A source (a remote or local git repository) is needed for this." - # Define a default product, if none is available, so we can show the help - elif [ -z ${PRODUCT} ]; then - PRODUCT='mlm' +# Validate product selection based on the branch +if [ "${GITREF}" == "master" ]; then + if [[ "${PRODUCT}" != "uyuni" && "${PRODUCT}" != "mlm" ]]; then + print_error "Invalid product for master branch. Allowed: uyuni, mlm" + exit 1 fi -fi - -# Product is mandatory -if [ -z ${PRODUCT} ]; then - print_incorrect_syntax "Product (-p) is mandatory" -fi - -# Check if SELinux is present and Enforcing -if [ -f /etc/selinux/config ]; then - if [ selinuxenabled ]; then - print_info "Enabling SELinux flags for volume" - SELINUXMOUNT=':Z' +else + if [[ "${PRODUCT}" != "uyuni" && "${PRODUCT}" != "suma" ]]; then + print_error "Invalid product for non-master branches. Allowed: uyuni, suma" + exit 1 fi fi -# Either a remote source or a local one must be used -if [ -z ${LOCALCLONE} ]; then - SOURCE="-e GITREPO=${GITREPO} -e GITREF=${GITREF}" - if [ ! -z ${OUTPUT} ]; then - if [ ! -d ${OUTPUT} ]; then - print_error "${OUTPUT} is not a directory or does not exist" - exit 2 - else - OUTPUT="$(get_dir_abs_path ${OUTPUT})" - SOURCE="${SOURCE} -v ${OUTPUT}:/tmp/output${SELINUXMOUNT} --userns=keep-id" - if [ "${COMMAND}" != "help" ]; then - print_info "Output will be stored at ${OUTPUT}/build" - fi - OUTDIR="${OUTPUT}/build" - fi - fi +# Determine output directory +if [ -n "${LOCALCLONE}" ]; then + OUTPUT_DIR="$(realpath ${LOCALCLONE})/build" +elif [ -n "${OUTPUT}" ]; then + OUTPUT_DIR="$(realpath ${OUTPUT})/build" else - if [ ! -z ${OUTPUT} ]; then - print_incorrect_syntax "Using -o together with -l is invalid" - fi - if [ ! -d ${LOCALCLONE} ]; then - print_error "${LOCALCLONE} is not a directory or does not exist" - exit 2 - elif [ ! -d ${LOCALCLONE}/.git ]; then - print_error "${LOCALCLONE} is not a Git repository" - exit 2 - else - SOURCE="-v ${LOCALCLONE}:/tmp/uyuni-docs${SELINUXMOUNT} --userns=keep-id" - if [ "${COMMAND}" != "help" ]; then - print_info "Output will be stored at ${LOCALCLONE}/build" - fi - OUTDIR="${LOCALCLONE}/build" - fi + OUTPUT_DIR="$(realpath /home/docs/uyuni-docs)/build" fi -# Guess the GitHub URL -if [[ ! "${GITREPO}" =~ ^https:// ]]; then - GITREPO="https://github.com/${GITREPO}/uyuni-docs.git" -fi +IMAGE="ghcr.io/${PROJECT}/uyuni-docs-helper:${TAG}" -if [ -z ${LOCALCLONE} ]; then - SOURCE="${SOURCE} -e GITREPO=${GITREPO} -e GITREF=${GITREF}" +if [ -z ${COMMAND} ]; then + print_incorrect_syntax "-c is mandatory" fi print_info "Pulling the latest container image ${IMAGE}..." podman pull ${IMAGE} -if [ ${SERVE} -eq 1 ] && [ "${COMMAND}" != "help" ]; then - print_info "The documentation will be served via HTTP. To stop the container when you are done, use CTRL+C" -fi -if [ "${COMMAND}" == "help" ]; then - print_info "Showing the help..." -else - print_info "Bulding the doc..." -fi -podman run -ti --rm ${SOURCE} -e PRODUCT=${PRODUCT} -e COMMAND=${COMMAND} -e SERVE=${SERVE} ${PORTS} ${IMAGE} -RET=${?} +print_info "Building the doc..." +mkdir -p ${OUTPUT_DIR} && chmod 777 ${OUTPUT_DIR} && podman run -ti --rm --userns=keep-id --user $(id -u):$(id -g) -v ${OUTPUT_DIR}:/tmp/output:z -e GITREF=${GITREF} -e PRODUCT=${PRODUCT} -e COMMAND=${COMMAND} -e SERVE=${SERVE} ${PORTS} ${IMAGE} +RET=$? if [ ${RET} -eq 0 ]; then - if [ ! -z ${OUTDIR} ] && [ "${COMMAND}" != "help" ]; then - print_info "You can find find the build output at ${OUTDIR}" - fi + chown -R $(id -u):$(id -g) ${OUTPUT_DIR} && print_info "Build successful. Output is available at: ${OUTPUT_DIR}" else - print_error "There were errors! Please review the log!" - if [ ! -z ${OUTDIR} ] && [ "${COMMAND}" != "help" ]; then - print_error "Depending on the error, there could also be build outputs at ${OUTDIR}" - fi + print_error "Build failed. Check logs." fi exit ${RET} From 6323e04ce1b1e39b2e00b1cee09029e5e41cf5c7 Mon Sep 17 00:00:00 2001 From: Joseph Cayouette Date: Fri, 7 Feb 2025 15:50:44 +0100 Subject: [PATCH 2/4] update logic --- uyuni-docs-helper | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/uyuni-docs-helper b/uyuni-docs-helper index 24f96a4..e79d266 100755 --- a/uyuni-docs-helper +++ b/uyuni-docs-helper @@ -90,17 +90,10 @@ while true; do esac done -# Validate product selection based on the branch -if [ "${GITREF}" == "master" ]; then - if [[ "${PRODUCT}" != "uyuni" && "${PRODUCT}" != "mlm" ]]; then - print_error "Invalid product for master branch. Allowed: uyuni, mlm" - exit 1 - fi -else - if [[ "${PRODUCT}" != "uyuni" && "${PRODUCT}" != "suma" ]]; then - print_error "Invalid product for non-master branches. Allowed: uyuni, suma" - exit 1 - fi +# Allow all three product options for any branch +if [[ "${PRODUCT}" != "uyuni" && "${PRODUCT}" != "mlm" && "${PRODUCT}" != "suma" ]]; then + print_error "Invalid product. Allowed: Master: uyuni, mlm | Non Master branches: uyuni, suma" + exit 1 fi # Determine output directory @@ -121,11 +114,19 @@ fi print_info "Pulling the latest container image ${IMAGE}..." podman pull ${IMAGE} print_info "Building the doc..." -mkdir -p ${OUTPUT_DIR} && chmod 777 ${OUTPUT_DIR} && podman run -ti --rm --userns=keep-id --user $(id -u):$(id -g) -v ${OUTPUT_DIR}:/tmp/output:z -e GITREF=${GITREF} -e PRODUCT=${PRODUCT} -e COMMAND=${COMMAND} -e SERVE=${SERVE} ${PORTS} ${IMAGE} +mkdir -p ${OUTPUT_DIR} && chmod 777 ${OUTPUT_DIR} && chown $(id -u):$(id -g) ${OUTPUT_DIR} && podman run -ti --rm --userns=keep-id --user $(id -u):$(id -g) -v ${OUTPUT_DIR}:/tmp/output:z -e GITREF=${GITREF} -e PRODUCT=${PRODUCT} -e COMMAND=${COMMAND} -e SERVE=${SERVE} ${PORTS} ${IMAGE} RET=$? if [ ${RET} -eq 0 ]; then chown -R $(id -u):$(id -g) ${OUTPUT_DIR} && print_info "Build successful. Output is available at: ${OUTPUT_DIR}" + if [ -f "${OUTPUT_DIR}/en/index.html" ]; then + if [ "${SERVE}" -eq 1 ]; then + print_info "Serving documentation at http://localhost:8000" + fi +else + print_error "index.html not found. Check if the build completed successfully." + + fi else print_error "Build failed. Check logs." fi From ad6a1f77f12f4bbf34915d433d9ea0e731a8e8f8 Mon Sep 17 00:00:00 2001 From: Joseph Cayouette Date: Fri, 7 Feb 2025 15:55:52 +0100 Subject: [PATCH 3/4] search recursively in directory for index.html --- uyuni-docs-helper | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uyuni-docs-helper b/uyuni-docs-helper index e79d266..531a5c7 100755 --- a/uyuni-docs-helper +++ b/uyuni-docs-helper @@ -119,12 +119,13 @@ RET=$? if [ ${RET} -eq 0 ]; then chown -R $(id -u):$(id -g) ${OUTPUT_DIR} && print_info "Build successful. Output is available at: ${OUTPUT_DIR}" - if [ -f "${OUTPUT_DIR}/en/index.html" ]; then + INDEX_FILE=$(find ${OUTPUT_DIR} -name index.html | head -n 1) + if [ -n "${INDEX_FILE}" ]; then if [ "${SERVE}" -eq 1 ]; then print_info "Serving documentation at http://localhost:8000" fi else - print_error "index.html not found. Check if the build completed successfully." + print_error "index.html not found. Check if the build completed successfully and verify the build output at ${OUTPUT_DIR}" fi else From 000385622d067c01518e2b6102bda652fbda8838 Mon Sep 17 00:00:00 2001 From: Joseph Cayouette Date: Tue, 11 Feb 2025 09:56:52 +0100 Subject: [PATCH 4/4] update code, seems to be building fine --- uyuni-docs-helper | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/uyuni-docs-helper b/uyuni-docs-helper index 531a5c7..83e76cc 100755 --- a/uyuni-docs-helper +++ b/uyuni-docs-helper @@ -122,7 +122,12 @@ if [ ${RET} -eq 0 ]; then INDEX_FILE=$(find ${OUTPUT_DIR} -name index.html | head -n 1) if [ -n "${INDEX_FILE}" ]; then if [ "${SERVE}" -eq 1 ]; then + if [ ! -d "${OUTPUT_DIR}/en" ]; then + print_error "Error: ${OUTPUT_DIR}/en/ does not exist. Ensure the build was successful before serving." + exit 1 + fi print_info "Serving documentation at http://localhost:8000" + mkdir -p ${OUTPUT_DIR}/en/ && podman run -ti --rm -p 8000:8000 -v ${OUTPUT_DIR}/en/:/usr/share/nginx/html:ro -w /usr/share/nginx/html docker.io/library/nginx fi else print_error "index.html not found. Check if the build completed successfully and verify the build output at ${OUTPUT_DIR}"