Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 80
tab_width = 2
trim_trailing_whitespace = true

[*.py]
indent_size = 4
max_line_length = 120

[*.{yaml,yml}]
max_line_length = 120
4 changes: 2 additions & 2 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CONTRIBUTORS

This file is automatically generated. DO NOT EDIT MANUALLY.
Generated on: 2025-10-24T15:34:41.239499Z
Generated on: 2025-10-27T10:25:18.606681Z

Upstream project: https://github.com/janeczku/calibre-web
Fork project (Calibre-Web Automated, since 2024): https://github.com/crocodilestick/calibre-web-automated
Expand Down Expand Up @@ -298,7 +298,7 @@ Copyright (C) 2024-2025 Calibre-Web Automated contributors
- zhiyue (1 commits)
# Fork Contributors (crocodilestick/calibre-web-automated)

- crocodilestick (729 commits)
- crocodilestick (730 commits)
- jmarmstrong1207 (73 commits)
- demitrix (30 commits)
- sirwolfgang (22 commits)
Expand Down
259 changes: 171 additions & 88 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,66 @@ if [ -z "${BASH_VERSION:-}" ]; then
fi
fi

set -u

usage() {
printf 'Usage: %s [-l]\n' "${0}"
printf '\t-l\t\tLocal build mode (skip git clone)\n'
printf '\t-u DH_USER\tDocker Hub username\n'
printf '\t-v VERSION\tVersion number (e.g., v2.0.1)\n'
printf '\t-r TESTNUM\tTest version number (numeric only, for dev builds)\n'
printf '\t-d REPO_DIR\tDirectory to clone repo into if not doing a local build\n'
printf '\t-c CLONE_URL\tGit URL to clone from if not doing a local build\n'
printf '\t-h\t\tShow this help message and exit\n'
}

while getopts "lu:v:r:d:c:h" opt; do
case $opt in
l)
LOCAL_BUILD=1
build_type="dev"
;;
u)
DH_USER="$OPTARG"
DH_USER_FROM_ARG=1
;;
v)
version="$OPTARG"
;;
r)
testnum="$OPTARG"
;;
d)
REPO_DIR="$OPTARG"
;;
c)
REPO_URL="$OPTARG"
;;
h)
usage
exit 0
;;
*)
usage
exit 1
;;
esac
done

: "${LOCAL_BUILD:=0}" # Set to 1 to skip git clone (for local dev/testing)
: "${DH_USER:=}"
: "${DH_USER_FROM_ARG:=0}"
: "${REPO_DIR:=}"
: "${REPO_URL:=https://github.com/crocodilestick/calibre-web-automated.git}"
: "${build_type:=}"
: "${version:=}"
: "${testnum:=}"

# ---- Pre-flight checks ----
die() { echo "❌ $*" >&2; exit 1; }
die() {
echo "❌ $*" >&2
exit 1
}

for dep in git docker; do
command -v "$dep" >/dev/null 2>&1 || die "Missing dependency: $dep (install it and re-run)."
Expand All @@ -45,131 +103,156 @@ if ! docker info >/dev/null 2>&1; then
fi

# ---- REPO_DIR selection ----
DEFAULT_HOME="${HOME:-}"
[ -z "$DEFAULT_HOME" ] && DEFAULT_HOME="changeme"
DEFAULT_REPO_DIR="$DEFAULT_HOME/cwa-repo-download"

if [ -n "${REPO_DIR:-}" ]; then
echo "The CWA repo will be cloned into: $REPO_DIR (configured via \$REPO_DIR)"
read -r -p "Confirm location? [y/N]: " confirm
case "$confirm" in
[Yy]*) ;;
*) read -r -p "Enter new directory [ENTER for default: $DEFAULT_REPO_DIR]: " input_dir
REPO_DIR="${input_dir:-$DEFAULT_REPO_DIR}"
;;
esac
if [ ${LOCAL_BUILD} -eq 1 ]; then
REPO_DIR="$(cd "$(dirname "${0}")" && pwd)"
printf 'Doing local build from repo directory: %s\n' "${REPO_DIR}"
else
read -r -p "Enter directory for repo files [ENTER for default: $DEFAULT_REPO_DIR]: " input_dir
REPO_DIR="${input_dir:-$DEFAULT_REPO_DIR}"
fi
if [ -n "${REPO_DIR}" ]; then
echo "The CWA repo will be cloned into: ${REPO_DIR} (configured via \$REPO_DIR)"
read -r -p "Confirm location? [y/N]: " confirm
case "$confirm" in
[Yy]*) ;;
*)
read -r -p "Enter new directory [ENTER for default: ${REPO_DIR}]: " input_dir
REPO_DIR="${input_dir:-${REPO_DIR}}"
;;
esac
else
DEFAULT_HOME="${HOME:-}"
[ -z "${DEFAULT_HOME}" ] && die "Cannot find your home directory, set \$REPO_DIR manually."
DEFAULT_REPO_DIR="${DEFAULT_HOME}/cwa-repo-download"

REPO_DIR="$(realpath -m "$REPO_DIR")"
read -r -p "Enter directory for repo files [ENTER for default: ${DEFAULT_REPO_DIR}]: " input_dir
REPO_DIR="${input_dir:-${DEFAULT_REPO_DIR}}"
fi

# ---- Docker Hub username ----
DEFAULT_DH_USER="${USER:-}"
if [ -z "$DEFAULT_DH_USER" ]; then
GH_USER="$(git config --global user.name 2>/dev/null || true)"
DEFAULT_DH_USER="${GH_USER:-}"
REPO_DIR="$(realpath -m "${REPO_DIR}")"
fi
[ -z "$DEFAULT_DH_USER" ] && DEFAULT_DH_USER="changeme"

if [ -n "${DH_USER:-}" ]; then
echo "Docker images will be tagged under: $DH_USER (configured via \$DH_USER)"
read -r -p "Confirm Docker Hub username? [y/N]: " confirm
case "$confirm" in
# ---- Docker Hub username ----
if [ -n "${DH_USER}" ]; then
echo "Docker images will be tagged under: ${DH_USER} (configured via \$DH_USER)"
if [ "${DH_USER_FROM_ARG}" -eq 0 ]; then
read -r -p "Confirm Docker Hub username? [y/N]: " confirm
case "$confirm" in
[Yy]*) ;;
*) read -r -p "Enter Docker Hub username [ENTER for default: $DEFAULT_DH_USER]: " input_user
DH_USER="${input_user:-$DEFAULT_DH_USER}"
;;
esac
*)
read -r -p "Enter Docker Hub username [ENTER for default: ${DH_USER}]: " input_user
DH_USER="${input_user:-${DH_USER}}"
;;
esac
fi
else
read -r -p "Enter Docker Hub username [ENTER for default: $DEFAULT_DH_USER]: " input_user
DH_USER="${input_user:-$DEFAULT_DH_USER}"
DEFAULT_DH_USER="${USER:-}"
if [ -z "$DEFAULT_DH_USER" ]; then
GH_USER="$(git config --global user.name 2>/dev/null || true)"
DEFAULT_DH_USER="${GH_USER:-}"
fi
[ -z "$DEFAULT_DH_USER" ] && die "Cannot find your username, set \$DH_USER manually."

read -r -p "Enter Docker Hub username [ENTER for default: ${DEFAULT_DH_USER}]: " input_user
DH_USER="${input_user:-${DEFAULT_DH_USER}}"
fi

# ---- Build mode & version prompts ----
while true; do
echo "Select build type:"
echo " [1] Development image"
echo " [2] Production image"
read -r -p "Enter 1 or 2: " build_choice
case "$build_choice" in
1) build_type="dev"; break ;;
2) build_type="prod"; break ;;
*) echo "Invalid choice. Please enter 1 or 2."; echo ;;
esac
done
if [ "${LOCAL_BUILD}" -eq 1 ]; then
printf 'Local build mode, building development image\n'
else
while true; do
echo "Select build type:"
echo " [1] Development image"
echo " [2] Production image"
read -r -p "Enter 1 or 2: " build_choice
case "${build_choice}" in
1)
build_type="dev"
break
;;
2)
build_type="prod"
break
;;
*)
echo "Invalid choice. Please enter 1 or 2."
echo
;;
esac
done
fi

while true; do
while [ -z "${version}" ]; do
read -r -p 'Enter Version Number (e.g., "V2.0.1"): ' version
[ -n "$version" ] && break
echo "Version cannot be empty."
[ -z "${version}" ] && echo "Version cannot be empty."
done

testnum=""
if [ "$build_type" = "dev" ]; then
while true; do
while [[ ! "${testnum}" =~ ^[0-9]+$ ]]; do
read -r -p "Enter test version number (numeric only): " testnum
[[ "$testnum" =~ ^[0-9]+$ ]] && break
echo "Test number must be numeric (e.g., 1, 2, 10)."
[[ ! "${testnum}" =~ ^[0-9]+$ ]] && echo "Test number must be numeric (e.g., 1, 2, 10)."
done
fi

# ---- Summary & confirmation ----
NOW="$(date +"%Y-%m-%d %H:%M:%S")"

if [ "$build_type" = "dev" ]; then
image_preview="$DH_USER/calibre-web-automated:dev-$testnum"
build_cmd="docker build --tag \"$image_preview\" --build-arg \"BUILD_DATE=$NOW\" --build-arg \"VERSION=${version}-TEST-${testnum}\" ."
if [ "${build_type}" = "dev" ]; then
image_preview="${DH_USER}/calibre-web-automated:dev-$testnum"
version_str="${version}-TEST-${testnum}"
else
image_preview="$DH_USER/calibre-web-automated:$version"
build_cmd="docker build --tag \"$image_preview\" --build-arg \"BUILD_DATE=$NOW\" --build-arg \"VERSION=$version\" ."
image_preview="${DH_USER}/calibre-web-automated:$version"
version_str="${version}"
fi

build_cmd="docker build --tag \"${image_preview}\" --build-arg \"BUILD_DATE=${NOW}\" --build-arg \"VERSION=${version_str}\" ."

echo
echo "============================================================"
echo "The script is ready to clone into: $REPO_DIR"
echo "A Docker image will be built as: $image_preview"
echo
echo "⚠️ WARNING: Any existing files/code at:"
echo " $REPO_DIR"
echo " will be WIPED CLEAN in favor of a fresh clone."
[ "${LOCAL_BUILD}" -eq 0 ] && echo "The script is ready to clone into: ${REPO_DIR}"
echo "A Docker image will be built as: ${image_preview}"
echo
if [ "${LOCAL_BUILD}" -eq 0 ]; then
echo "⚠️ WARNING: Any existing files/code at:"
echo " ${REPO_DIR}"
echo " will be WIPED CLEAN in favor of a fresh clone."
echo
fi
echo "Planned build command:"
echo " $build_cmd"
echo " ${build_cmd}"
echo "============================================================"
echo

# ---- Execute (destructive clone, then build) ----
read -r -p "Proceed? [Y/n]: " confirm
case "$confirm" in
[Yy]* | "" )
case "${confirm}" in
[Yy]* | "")
if [ "${LOCAL_BUILD}" -eq 0 ]; then
echo "Proceeding with clone and build..."

REPO_URL="${REPO_URL:-https://github.com/crocodilestick/calibre-web-automated.git}"

rm -rf -- "$REPO_DIR" # destructive: matches warning above
git clone --depth=1 "$REPO_URL" "$REPO_DIR"
cd "$REPO_DIR"
rm -rf -- "${REPO_DIR}" # destructive: matches warning above
git clone --depth=1 "${REPO_URL}" "${REPO_DIR}"
else
printf 'Proceeding with local build from: %s\n' "${REPO_DIR}"
fi
cd "${REPO_DIR}" || die "Failed to change to directory: ${REPO_DIR}"

echo
echo "Running build command:"
echo " $build_cmd"
echo
echo
echo "Running build command:"
echo " ${build_cmd}"
echo

eval "$build_cmd" # single source of truth
eval "${build_cmd}" # single source of truth

if [ "$build_type" = "dev" ]; then
TYPE_LABEL="Dev image Version ${version} - Test ${testnum}"
else
TYPE_LABEL="Prod image Version ${version}"
fi
if [ "${build_type}" = "dev" ]; then
TYPE_LABEL="Dev image Version ${version} - Test ${testnum}"
else
TYPE_LABEL="Prod image Version ${version}"
fi

echo
echo "✅ $TYPE_LABEL created! Exiting now..."
;;
* )
echo "Cancelling build."
exit 1
;;
echo
echo "✅ ${TYPE_LABEL} created! Exiting now..."
;;
*)
echo "Cancelling build."
exit 1
;;
esac