mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2026-09-13 18:46:17 +05:00
271 lines
8.6 KiB
Bash
Executable File
271 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -Eeuo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
ARCHIVEBOX_REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
WORKSPACE_DIR="$(cd "${ARCHIVEBOX_REPO}/.." && pwd)"
|
|
DOCKER_IMAGE_REPOS="${DOCKER_IMAGE_REPOS:-archivebox/archivebox ghcr.io/archivebox/archivebox}"
|
|
|
|
cd "${WORKSPACE_DIR}"
|
|
|
|
repo_dir() {
|
|
local repo="$1"
|
|
printf '%s/%s\n' "${WORKSPACE_DIR}" "${repo}"
|
|
}
|
|
|
|
ABXPKG_LIB_DIR="${ABXPKG_LIB_DIR:-${LIB_DIR:-$HOME/.config/archivebox/lib}}"
|
|
locked_archivebox_abxpkg_version() {
|
|
local line package=""
|
|
while IFS= read -r line; do
|
|
case "$line" in
|
|
'[[package]]') package="" ;;
|
|
'name = "abxpkg"') package="abxpkg" ;;
|
|
'version = "'*'"')
|
|
[[ "$package" == "abxpkg" ]] || continue
|
|
line="${line#version = \"}"
|
|
printf '%s\n' "${line%\"}"
|
|
return 0
|
|
;;
|
|
esac
|
|
done < "$ARCHIVEBOX_REPO/uv.lock"
|
|
return 1
|
|
}
|
|
BOOTSTRAP_ABXPKG_VERSION="$(locked_archivebox_abxpkg_version)"
|
|
mkdir -p "$ABXPKG_LIB_DIR/env/bin"
|
|
uv run --no-project --with "abxpkg==$BOOTSTRAP_ABXPKG_VERSION" abxpkg env \
|
|
--install \
|
|
--lib="$ABXPKG_LIB_DIR" \
|
|
--deps-from="$ARCHIVEBOX_REPO/.github/configs/ci-tooling.json:release_binaries" \
|
|
>/dev/null
|
|
GIT_BINARY="$ABXPKG_LIB_DIR/env/bin/git"
|
|
PYTHON_BINARY="$ABXPKG_LIB_DIR/env/bin/python"
|
|
UV_BINARY="$ABXPKG_LIB_DIR/env/bin/uv"
|
|
test -x "$GIT_BINARY"
|
|
test -x "$PYTHON_BINARY"
|
|
test -x "$UV_BINARY"
|
|
|
|
current_version() {
|
|
local repo="$1"
|
|
"$PYTHON_BINARY" - "$repo" <<'PY'
|
|
from pathlib import Path
|
|
import re
|
|
import sys
|
|
|
|
text = Path(sys.argv[1], "pyproject.toml").read_text()
|
|
match = re.search(r'^version = "([^"]+)"$', text, re.MULTILINE)
|
|
if not match:
|
|
raise SystemExit(f"Failed to find version in {sys.argv[1]}/pyproject.toml")
|
|
print(match.group(1))
|
|
PY
|
|
}
|
|
|
|
bump_patch_to() {
|
|
local repo="$1"
|
|
local version="$2"
|
|
"$PYTHON_BINARY" - "$repo" "$version" <<'PY'
|
|
from pathlib import Path
|
|
import re
|
|
import sys
|
|
|
|
path = Path(sys.argv[1], "pyproject.toml")
|
|
version = sys.argv[2]
|
|
text = path.read_text()
|
|
path.write_text(re.sub(r'^version = "[^"]+"$', f'version = "{version}"', text, count=1, flags=re.MULTILINE))
|
|
PY
|
|
}
|
|
|
|
next_patch_version() {
|
|
"$PYTHON_BINARY" - "$@" <<'PY'
|
|
import re
|
|
import sys
|
|
|
|
versions = sys.argv[1:]
|
|
parts = []
|
|
for version in versions:
|
|
match = re.fullmatch(r"(\d+)\.(\d+)\.(\d+)", version)
|
|
if not match:
|
|
raise SystemExit(f"Expected patch version, got {version}")
|
|
parts.append(tuple(int(part) for part in match.groups()))
|
|
major, minor, patch = max(parts)
|
|
print(f"{major}.{minor}.{patch + 1}")
|
|
PY
|
|
}
|
|
|
|
bump_archivebox_rc() {
|
|
"$PYTHON_BINARY" - "${ARCHIVEBOX_REPO}" <<'PY'
|
|
from pathlib import Path
|
|
import json
|
|
import re
|
|
import sys
|
|
|
|
repo = Path(sys.argv[1])
|
|
pyproject_path = repo / "pyproject.toml"
|
|
package_path = repo / "etc" / "package.json"
|
|
pyproject_text = pyproject_path.read_text()
|
|
match = re.search(r'^version = "(\d+)\.(\d+)\.(\d+)(?:-?rc(\d+))?"$', pyproject_text, re.MULTILINE)
|
|
if not match:
|
|
raise SystemExit("Expected ArchiveBox version like 0.9.31rc15")
|
|
|
|
major, minor, patch, rc = match.groups()
|
|
next_version = f"{major}.{minor}.{patch}rc{int(rc or 0) + 1}"
|
|
pyproject_path.write_text(re.sub(r'^version = "[^"]+"$', f'version = "{next_version}"', pyproject_text, count=1, flags=re.MULTILINE))
|
|
|
|
package_json = json.loads(package_path.read_text())
|
|
package_json["version"] = next_version
|
|
package_path.write_text(json.dumps(package_json, indent=2) + "\n")
|
|
print(next_version)
|
|
PY
|
|
}
|
|
|
|
set_dependency_version() {
|
|
local repo="$1"
|
|
local package="$2"
|
|
local version="$3"
|
|
"$PYTHON_BINARY" - "$repo" "$package" "$version" <<'PY'
|
|
from pathlib import Path
|
|
import re
|
|
import sys
|
|
|
|
repo, package, version = sys.argv[1:]
|
|
path = Path(repo, "pyproject.toml")
|
|
text = path.read_text()
|
|
updated, count = re.subn(rf'("{re.escape(package)}>=)[^"]+(")', rf'\g<1>{version}\2', text)
|
|
if count:
|
|
path.write_text(updated)
|
|
PY
|
|
}
|
|
|
|
assert_branch() {
|
|
local repo="$1"
|
|
local branch="$2"
|
|
local actual
|
|
actual="$("$GIT_BINARY" -C "$repo" branch --show-current)"
|
|
if [[ "$actual" != "$branch" ]]; then
|
|
echo "[X] Expected $(basename "$repo") on ${branch}, found ${actual}" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
build_and_prek() {
|
|
local repo="$1"
|
|
(
|
|
cd "$repo"
|
|
rm -rf dist .pdm-build
|
|
"$UV_BINARY" --no-cache build --out-dir dist
|
|
"$UV_BINARY" --no-cache run prek run --all-files
|
|
rm -rf dist .pdm-build
|
|
"$UV_BINARY" --no-cache build --out-dir dist
|
|
)
|
|
}
|
|
|
|
commit_push_publish() {
|
|
local repo="$1"
|
|
local branch="$2"
|
|
local package="$3"
|
|
local version="$4"
|
|
local tag="v${version}"
|
|
|
|
(
|
|
cd "$repo"
|
|
"$GIT_BINARY" add -u
|
|
while IFS= read -r path; do
|
|
"$GIT_BINARY" add -- "$path"
|
|
done < <("$GIT_BINARY" ls-files --others --exclude-standard)
|
|
if ! "$GIT_BINARY" diff --cached --quiet; then
|
|
"$GIT_BINARY" commit -m "release: ${package} ${version}"
|
|
else
|
|
echo "[*] No staged changes in ${package}; reusing existing commit."
|
|
fi
|
|
"$GIT_BINARY" push origin "$branch"
|
|
if "$GIT_BINARY" rev-parse -q --verify "refs/tags/${tag}" >/dev/null; then
|
|
if [[ "$("$GIT_BINARY" rev-list -n1 "${tag}")" != "$("$GIT_BINARY" rev-parse HEAD)" ]]; then
|
|
echo "[X] Tag ${tag} already exists but does not point at HEAD in ${package}" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
"$GIT_BINARY" tag -a "${tag}" -m "release: ${package} ${version}"
|
|
fi
|
|
"$GIT_BINARY" push origin "refs/tags/${tag}"
|
|
if pypi_has_release "$package" "$version"; then
|
|
echo "[*] ${package}==${version} is already on PyPI; skipping upload."
|
|
else
|
|
"$UV_BINARY" --no-cache publish --trusted-publishing always dist/*
|
|
fi
|
|
)
|
|
}
|
|
|
|
pypi_has_release() {
|
|
local package="$1"
|
|
local version="$2"
|
|
|
|
"$PYTHON_BINARY" - "$package" "$version" <<'PY'
|
|
import sys
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
package, version = sys.argv[1:]
|
|
try:
|
|
with urllib.request.urlopen(f"https://pypi.org/pypi/{package}/{version}/json", timeout=10):
|
|
raise SystemExit(0)
|
|
except urllib.error.HTTPError as err:
|
|
raise SystemExit(1 if err.code == 404 else 2)
|
|
PY
|
|
}
|
|
|
|
release_python_repo() {
|
|
local repo_name="$1"
|
|
local branch="$2"
|
|
local package="$3"
|
|
local version="$4"
|
|
local repo
|
|
repo="$(repo_dir "$repo_name")"
|
|
|
|
echo "[+] Releasing ${package} ${version} from ${repo_name}:${branch}"
|
|
assert_branch "$repo" "$branch"
|
|
build_and_prek "$repo"
|
|
commit_push_publish "$repo" "$branch" "$package" "$version"
|
|
}
|
|
|
|
ABXPKG_VERSION="${ABXPKG_VERSION:-$(next_patch_version "$(current_version "$(repo_dir abxpkg)")")}"
|
|
ABX_SHARED_VERSION="${ABX_SHARED_VERSION:-$(next_patch_version "$(current_version "$(repo_dir abx-plugins)")" "$(current_version "$(repo_dir abx-dl)")")}"
|
|
|
|
bump_patch_to "$(repo_dir abxpkg)" "$ABXPKG_VERSION"
|
|
release_python_repo abxpkg main abxpkg "$ABXPKG_VERSION"
|
|
|
|
bump_patch_to "$(repo_dir abx-plugins)" "$ABX_SHARED_VERSION"
|
|
set_dependency_version "$(repo_dir abx-plugins)" abxpkg "$ABXPKG_VERSION"
|
|
release_python_repo abx-plugins main abx-plugins "$ABX_SHARED_VERSION"
|
|
|
|
bump_patch_to "$(repo_dir abx-dl)" "$ABX_SHARED_VERSION"
|
|
set_dependency_version "$(repo_dir abx-dl)" abxpkg "$ABXPKG_VERSION"
|
|
set_dependency_version "$(repo_dir abx-dl)" abx-plugins "$ABX_SHARED_VERSION"
|
|
release_python_repo abx-dl main abx-dl "$ABX_SHARED_VERSION"
|
|
|
|
ARCHIVEBOX_VERSION="$(bump_archivebox_rc)"
|
|
set_dependency_version "$ARCHIVEBOX_REPO" abxpkg "$ABXPKG_VERSION"
|
|
set_dependency_version "$ARCHIVEBOX_REPO" abx-plugins "$ABX_SHARED_VERSION"
|
|
set_dependency_version "$ARCHIVEBOX_REPO" abx-dl "$ABX_SHARED_VERSION"
|
|
|
|
echo "[+] Releasing archivebox ${ARCHIVEBOX_VERSION} from archivebox:dev"
|
|
assert_branch "$ARCHIVEBOX_REPO" dev
|
|
build_and_prek "$ARCHIVEBOX_REPO"
|
|
commit_push_publish "$ARCHIVEBOX_REPO" dev archivebox "$ARCHIVEBOX_VERSION"
|
|
|
|
(
|
|
cd "$ARCHIVEBOX_REPO"
|
|
ABXPKG_LIB_DIR="${ABXPKG_LIB_DIR:-${LIB_DIR:-$HOME/.config/archivebox/lib}}"
|
|
mkdir -p "$ABXPKG_LIB_DIR/env/bin"
|
|
"$UV_BINARY" run --no-project --with "abxpkg==$ABXPKG_VERSION" abxpkg env \
|
|
--install \
|
|
--lib="$ABXPKG_LIB_DIR" \
|
|
--deps-from="$ARCHIVEBOX_REPO/.github/configs/ci-tooling.json:docker_binaries" \
|
|
>/dev/null
|
|
DOCKER_BINARY="$ABXPKG_LIB_DIR/env/bin/docker"
|
|
test -x "$DOCKER_BINARY"
|
|
./bin/release_docker.sh dev "$ARCHIVEBOX_VERSION" "sha-$("$GIT_BINARY" rev-parse --short HEAD)"
|
|
DEPLOY_IMAGE="${DOCKER_IMAGE_REPOS%% *}:dev" DEPLOY_EXPECT_VERSION="$ARCHIVEBOX_VERSION" SKIP_DOCKER=1 ./bin/deploy_dev_demo.sh
|
|
)
|
|
|
|
echo "[√] Released abxpkg ${ABXPKG_VERSION}, abx-plugins/abx-dl ${ABX_SHARED_VERSION}, archivebox ${ARCHIVEBOX_VERSION}"
|