The single-quoted bash string passed to sed -i prevented FRONT_VERSION from
being interpolated, so the file content was being silently rewritten to
the literal text "${FRONT_VERSION}". Likewise the double-quoted sed for
pyproject.toml would silently do nothing if the [project] section was
absent while still printing a misleading 'updated' success line.
Replace both with python: json.load/dump for package.json (so the JSON
remains well-formed and 2-space-indented), and a regex section-aware
edit for pyproject.toml that exits non-zero with a warning if no
`version = "..."` line is found, so the success message only prints
when something actually changed.
193 lines
6.2 KiB
Bash
193 lines
6.2 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Bump the project version and push images to the registry.
|
|
#
|
|
# Usage:
|
|
# ./release.sh
|
|
#
|
|
# The current version is stored in VERSION (next to this script).
|
|
# You will be asked whether to bump major, minor, or patch.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VERSION_FILE="${SCRIPT_DIR}/VERSION"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Read current version
|
|
# ---------------------------------------------------------------------------
|
|
if [[ ! -f "${VERSION_FILE}" ]]; then
|
|
echo "0.0.0" > "${VERSION_FILE}"
|
|
fi
|
|
|
|
CURRENT="$(cat "${VERSION_FILE}")"
|
|
# Strip leading 'v' for arithmetic
|
|
VERSION="${CURRENT#v}"
|
|
|
|
IFS='.' read -r MAJOR MINOR PATCH <<< "${VERSION}"
|
|
|
|
echo "============================================"
|
|
echo " AniWorld — Release"
|
|
echo " Current version: v${MAJOR}.${MINOR}.${PATCH}"
|
|
echo "============================================"
|
|
echo ""
|
|
echo "Which image(s) would you like to release?"
|
|
echo " 1) app (Dockerfile.app)"
|
|
echo " 2) vpn (Containerfile)"
|
|
echo " 3) all (both images)"
|
|
echo ""
|
|
read -rp "Enter choice [1/2/3]: " TARGET_CHOICE
|
|
|
|
case "${TARGET_CHOICE}" in
|
|
1) TARGET="app" ;;
|
|
2) TARGET="vpn" ;;
|
|
3) TARGET="all" ;;
|
|
*)
|
|
echo "Invalid choice. Aborting." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo ""
|
|
echo "How would you like to bump the version?"
|
|
echo " 1) patch (v${MAJOR}.${MINOR}.${PATCH} → v${MAJOR}.${MINOR}.$((PATCH + 1)))"
|
|
echo " 2) minor (v${MAJOR}.${MINOR}.${PATCH} → v${MAJOR}.$((MINOR + 1)).0)"
|
|
echo " 3) major (v${MAJOR}.${MINOR}.${PATCH} → v$((MAJOR + 1)).0.0)"
|
|
echo ""
|
|
read -rp "Enter choice [1/2/3]: " CHOICE
|
|
|
|
case "${CHOICE}" in
|
|
1) NEW_TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))" ;;
|
|
2) NEW_TAG="v${MAJOR}.$((MINOR + 1)).0" ;;
|
|
3) NEW_TAG="v$((MAJOR + 1)).0.0" ;;
|
|
*)
|
|
echo "Invalid choice. Aborting." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo ""
|
|
echo "New version: ${NEW_TAG}"
|
|
echo "Target: ${TARGET}"
|
|
read -rp "Confirm? [y/N]: " CONFIRM
|
|
if [[ ! "${CONFIRM}" =~ ^[yY]$ ]]; then
|
|
echo "Aborted."
|
|
exit 0
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Write new version
|
|
# ---------------------------------------------------------------------------
|
|
echo "${NEW_TAG}" > "${VERSION_FILE}"
|
|
echo "Version file updated → ${VERSION_FILE}"
|
|
|
|
# Keep root package.json in sync.
|
|
FRONT_VERSION="${NEW_TAG#v}"
|
|
FRONT_PKG="${SCRIPT_DIR}/../package.json"
|
|
if [[ -f "${FRONT_PKG}" ]]; then
|
|
# Use a python one-liner for portable, safe JSON editing. The previous
|
|
# `sed -i` used single-quoted bash strings, which prevented
|
|
# ${FRONT_VERSION} from being interpolated and silently rewrote the file
|
|
# to the literal string "${FRONT_VERSION}".
|
|
python3 - "$FRONT_PKG" "$FRONT_VERSION" <<'PY'
|
|
import json, sys
|
|
path, new_version = sys.argv[1], sys.argv[2]
|
|
with open(path, encoding="utf-8") as fh:
|
|
data = json.load(fh)
|
|
data["version"] = new_version
|
|
with open(path, "w", encoding="utf-8") as fh:
|
|
json.dump(data, fh, indent=2)
|
|
fh.write("\n")
|
|
PY
|
|
echo "package.json version updated → ${FRONT_VERSION}"
|
|
else
|
|
echo "Warning: package.json not found, skipping package.json version sync" >&2
|
|
fi
|
|
|
|
# Keep root pyproject.toml in sync.
|
|
BACKEND_PYPROJECT="${SCRIPT_DIR}/../pyproject.toml"
|
|
if [[ -f "${BACKEND_PYPROJECT}" ]]; then
|
|
# Use python instead of sed: the previous `sed -i` used double-quoted
|
|
# patterns whose `&` and `\` characters would have to be escaped, and
|
|
# more importantly it could silently do nothing if the [project] section
|
|
# was missing. python reads/writes the file as a string, preserving
|
|
# the existing format, and reports whether anything changed.
|
|
if FRONT_VERSION="$FRONT_VERSION" BACKEND_PYPROJECT="$BACKEND_PYPROJECT" python3 <<'PY'
|
|
import os, re, sys
|
|
|
|
path = os.environ["BACKEND_PYPROJECT"]
|
|
new_version = os.environ["FRONT_VERSION"]
|
|
with open(path, encoding="utf-8") as fh:
|
|
text = fh.read()
|
|
|
|
# If there is a [project] table, update only the `version = "..."` line
|
|
# inside it; otherwise update the first top-level `version = "..."` line.
|
|
project_match = re.search(r"^\[project\]\s*$", text, re.MULTILINE)
|
|
if project_match:
|
|
start = project_match.end()
|
|
end = re.search(r"^\[", text[start:], re.MULTILINE)
|
|
section_end = start + end.start() if end else len(text)
|
|
section = text[start:section_end]
|
|
new_section, n = re.subn(
|
|
r'^version = ".*"$',
|
|
f'version = "{new_version}"',
|
|
section,
|
|
count=1,
|
|
flags=re.MULTILINE,
|
|
)
|
|
if n == 0:
|
|
print(
|
|
f"Warning: no `version = ...` line found under [project] in {path}",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(2)
|
|
text = text[:start] + new_section + text[section_end:]
|
|
else:
|
|
new_text, n = re.subn(
|
|
r'^version = ".*"$',
|
|
f'version = "{new_version}"',
|
|
text,
|
|
count=1,
|
|
flags=re.MULTILINE,
|
|
)
|
|
if n == 0:
|
|
print(
|
|
f"Warning: no `version = ...` line found in {path}",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(2)
|
|
text = new_text
|
|
|
|
with open(path, "w", encoding="utf-8") as fh:
|
|
fh.write(text)
|
|
PY
|
|
then
|
|
echo "pyproject.toml version updated → ${FRONT_VERSION}"
|
|
fi
|
|
else
|
|
echo "Warning: pyproject.toml not found, skipping pyproject.toml version sync" >&2
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Push containers
|
|
# ---------------------------------------------------------------------------
|
|
bash "${SCRIPT_DIR}/push.sh" "${TARGET}" "${NEW_TAG}"
|
|
bash "${SCRIPT_DIR}/push.sh" "${TARGET}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Git tag (local only; push after container build)
|
|
# ---------------------------------------------------------------------------
|
|
cd "${SCRIPT_DIR}/.."
|
|
git add Docker/VERSION package.json pyproject.toml
|
|
git commit -m "chore: bump version"
|
|
git tag -a "${NEW_TAG}" -m "Release ${NEW_TAG}"
|
|
echo "Local git commit + tag ${NEW_TAG} created."
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Push git commits & tag
|
|
# ---------------------------------------------------------------------------
|
|
git push origin HEAD
|
|
git push origin "${NEW_TAG}"
|
|
echo "Git commit and tag ${NEW_TAG} pushed."
|