This commit is contained in:
Mateusz Gruszczyński committed 2026-11-01 00:25:29 +01:00
1 parent 99a5700caa
commit b752f52fd8
22 files changed
+313 -138

No files matched your search

+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT"
DIST="$ROOT/dist"
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT/target}"
export CARGO_TARGET_DIR
fail() {
printf 'error: %s\n' "$*" >&2
exit 1
}
need() {
command -v "$1" >/dev/null 2>&1 || fail "$1 is required"
}
need cargo
need rustc
need python3
need sha256sum
need tar
need git
python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3,10) else 1)' \
|| fail 'Python 3.10+ is required'
cargo fmt --version >/dev/null 2>&1 \
|| fail 'rustfmt component is required (rustup component add rustfmt)'
cargo clippy --version >/dev/null 2>&1 \
|| fail 'clippy component is required (rustup component add clippy)'
[[ -f Cargo.toml ]] || fail 'run this script from the RustPad project root'
[[ -f Cargo.lock ]] || fail 'Cargo.lock is required for a reproducible release'
[[ -f make_zip.py ]] || fail 'make_zip.py is missing'
[[ -f scripts/update_browser_libs.py ]] || fail 'scripts/update_browser_libs.py is missing'
[[ -f scripts/browser-libs.lock.json ]] || fail 'scripts/browser-libs.lock.json is missing'
[[ -d static ]] || fail 'static directory is missing'
[[ -d migrations ]] || fail 'migrations directory is missing'
git rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|| fail 'release source archive requires a Git working tree'
METADATA="$(cargo metadata --locked --no-deps --format-version 1)"
read -r PACKAGE VERSION REQUIRED_RUST < <(
printf '%s' "$METADATA" | python3 -c '
import json, sys
data = json.load(sys.stdin)
packages = data.get("packages", [])
pkg = next((p for p in packages if p.get("name") == "rustpad"), None)
if pkg is None:
raise SystemExit("rustpad package not found in Cargo metadata")
print(pkg["name"], pkg["version"], pkg.get("rust_version") or "0")
'
)
[[ "$PACKAGE" == "rustpad" ]] || fail 'Cargo package rustpad was not found'
[[ -n "$VERSION" ]] || fail 'could not determine project version'
RUSTC_VERSION="$(rustc -V | awk '{print $2}')"
HOST="$(rustc -vV | sed -n 's/^host: //p')"
[[ -n "$RUSTC_VERSION" ]] || fail 'could not determine rustc version'
[[ -n "$HOST" ]] || fail 'could not determine Rust host target'
python3 - "$RUSTC_VERSION" "$REQUIRED_RUST" <<'PY' \
|| fail "Rust $REQUIRED_RUST+ is required (found $RUSTC_VERSION)"
import re
import sys
def version_tuple(value: str) -> tuple[int, int, int]:
match = re.match(r"^(\d+)\.(\d+)(?:\.(\d+))?", value)
if not match:
raise SystemExit(1)
major, minor, patch = match.groups(default="0")
return int(major), int(minor), int(patch)
raise SystemExit(0 if version_tuple(sys.argv[1]) >= version_tuple(sys.argv[2]) else 1)
PY
printf 'RustPad %s release build for %s\n' "$VERSION" "$HOST"
printf 'Preparing locked browser libraries...\n'
python3 scripts/update_browser_libs.py --locked --strict
printf '\nChecking formatting...\n'
cargo fmt --all -- --check
printf '\nRunning tests...\n'
cargo test --locked --all-targets
printf '\nRunning clippy...\n'
cargo clippy --locked --all-targets -- -D warnings
printf '\nBuilding release binary...\n'
rm -rf "$CARGO_TARGET_DIR/release"
cargo build --locked --release --bin rustpad
BIN="$CARGO_TARGET_DIR/release/rustpad"
[[ -x "$BIN" ]] || fail "release binary was not created: $BIN"
ACTUAL_VERSION="$("$BIN" --version)"
EXPECTED_VERSION="rustpad $VERSION"
[[ "$ACTUAL_VERSION" == "$EXPECTED_VERSION" ]] \
|| fail "built binary reports '$ACTUAL_VERSION', expected '$EXPECTED_VERSION'"
printf 'Built: %s\n' "$ACTUAL_VERSION"
rm -rf "$DIST"
mkdir -p "$DIST"
# Source archive. dist/ is ignored by Git, so generated release files are not included.
SOURCE_ZIP="$DIST/RustPad-${VERSION}-source.zip"
python3 make_zip.py "$SOURCE_ZIP"
[[ -s "$SOURCE_ZIP" ]] || fail "source archive was not created: $SOURCE_ZIP"
sha256sum "$SOURCE_ZIP" > "$SOURCE_ZIP.sha256"
BINARY_ARTIFACT="rustpad-${VERSION}-${HOST}"
cp "$BIN" "$DIST/$BINARY_ARTIFACT"
chmod 0755 "$DIST/$BINARY_ARTIFACT"
sha256sum "$DIST/$BINARY_ARTIFACT" > "$DIST/$BINARY_ARTIFACT.sha256"
# RustPad needs static assets and SQL migrations at runtime.
BUNDLE_NAME="RustPad-${VERSION}-${HOST}"
BUNDLE_DIR="$DIST/$BUNDLE_NAME"
BUNDLE_ARCHIVE="$DIST/$BUNDLE_NAME.tar.gz"
mkdir -p "$BUNDLE_DIR/data/db" "$BUNDLE_DIR/data/files"
cp "$BIN" "$BUNDLE_DIR/rustpad"
chmod 0755 "$BUNDLE_DIR/rustpad"
cp -a static "$BUNDLE_DIR/static"
cp -a migrations "$BUNDLE_DIR/migrations"
[[ -d systemd ]] && cp -a systemd "$BUNDLE_DIR/systemd"
[[ -f README.md ]] && cp README.md "$BUNDLE_DIR/README.md"
[[ -f LICENSE.md ]] && cp LICENSE.md "$BUNDLE_DIR/LICENSE.md"
[[ -f .env.example ]] && cp .env.example "$BUNDLE_DIR/.env.example"
cat > "$BUNDLE_DIR/RELEASE.txt" <<EOF_RELEASE
RustPad $VERSION
Target: $HOST
Rust: $RUSTC_VERSION
Run RustPad from this directory, or configure STATIC_DIR, FILES_DIR and DATABASE_URL
with absolute paths appropriate for the installation.
EOF_RELEASE
tar -C "$DIST" -czf "$BUNDLE_ARCHIVE" "$BUNDLE_NAME"
[[ -s "$BUNDLE_ARCHIVE" ]] || fail "runtime archive was not created: $BUNDLE_ARCHIVE"
sha256sum "$BUNDLE_ARCHIVE" > "$BUNDLE_ARCHIVE.sha256"
rm -rf "$BUNDLE_DIR"
printf '\nRelease ready:\n'
printf ' binary: %s\n' "$DIST/$BINARY_ARTIFACT"
printf ' checksum: %s\n' "$DIST/$BINARY_ARTIFACT.sha256"
printf ' runtime: %s\n' "$BUNDLE_ARCHIVE"
printf ' checksum: %s\n' "$BUNDLE_ARCHIVE.sha256"
printf ' source zip: %s\n' "$SOURCE_ZIP"
printf ' checksum: %s\n' "$SOURCE_ZIP.sha256"