verstak/scripts/release.sh

303 lines
8.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# release.sh — Verstak release script
# Builds all binaries, packages, signs Firefox XPI, creates git tag.
#
# Usage:
# ./scripts/release.sh # Full release (requires AMO tokens for Firefox signing)
# ./scripts/release.sh --skip-firefox-sign # Skip Firefox XPI signing
# ./scripts/release.sh --publish # Push git tag + create GitHub release
# ./scripts/release.sh --help # Show usage
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"
# --- Config ---
SKIP_FIREFOX_SIGN=false
PUBLISH=false
for arg in "$@"; do
case "$arg" in
--skip-firefox-sign) SKIP_FIREFOX_SIGN=true ;;
--publish) PUBLISH=true ;;
--help)
echo "Usage: $0 [--skip-firefox-sign] [--publish]"
echo ""
echo " --skip-firefox-sign Skip Firefox extension signing (fails by default if AMO tokens missing)"
echo " --publish Push git tag and create GitHub release"
exit 0
;;
esac
done
VERSION="$(cat VERSION 2>/dev/null || echo "0.1.0-dev")"
RELEASE_DIR="release"
LINUX_DIR="$RELEASE_DIR/linux"
BUILD_DIR="build"
echo "============================================"
echo " Verstak Release v$VERSION"
echo "============================================"
echo ""
# --- Pre-flight checks ---
echo "==> Pre-flight checks..."
if ! git diff --quiet --exit-code 2>/dev/null; then
echo "ERROR: working tree is dirty. Commit or stash changes first."
git diff --stat
exit 1
fi
if ! git diff --cached --quiet --exit-code 2>/dev/null; then
echo "ERROR: staged but uncommitted changes. Commit first."
exit 1
fi
echo " Working tree clean ✓"
if ! go version &>/dev/null; then
echo "ERROR: go not found"
exit 1
fi
echo " Go: $(go version)"
# --- Run tests ---
echo ""
echo "==> Running tests..."
go vet ./...
go test ./... -count=1
echo " Tests: all passed ✓"
# --- Build ---
echo ""
echo "==> Building all binaries..."
mkdir -p "$BUILD_DIR" "$LINUX_DIR"
rm -f "$LINUX_DIR"/*
./scripts/build.sh release
echo " Build complete ✓"
# --- VERSION file ---
echo "$VERSION" > "$LINUX_DIR/VERSION"
# --- DEB package: GUI ---
echo ""
echo "==> Building DEB packages..."
build_deb() {
local binary="$1"
local pkg_name="$2"
local description="$3"
local systemd_unit="${4:-}"
local deb_dir="$BUILD_DIR/deb-tmp/$pkg_name"
mkdir -p "$deb_dir/DEBIAN"
mkdir -p "$deb_dir/usr/local/bin"
mkdir -p "$deb_dir/usr/share/doc/$pkg_name"
cp "$BUILD_DIR/$binary" "$deb_dir/usr/local/bin/$pkg_name"
chmod 755 "$deb_dir/usr/local/bin/$pkg_name"
if [[ -n "$systemd_unit" && -f "$systemd_unit" ]]; then
mkdir -p "$deb_dir/lib/systemd/system"
cp "$systemd_unit" "$deb_dir/lib/systemd/system/"
fi
# Simple control file
cat > "$deb_dir/DEBIAN/control" <<CTRL
Package: $pkg_name
Version: $VERSION
Section: utils
Priority: optional
Architecture: amd64
Maintainer: Verstak <verstak@mirv.top>
Description: $description
CTRL
# Copy README if exists
[[ -f "README.md" ]] && cp "README.md" "$deb_dir/usr/share/doc/$pkg_name/"
dpkg-deb --root-owner-group --build "$deb_dir" "$LINUX_DIR/${pkg_name}.deb" >/dev/null
rm -rf "$BUILD_DIR/deb-tmp"
echo " $LINUX_DIR/${pkg_name}.deb"
}
build_deb "verstak" "verstak" "Verstak — local-first working vault GUI"
build_deb "verstak-server" "verstak-server" "Verstak Sync Server" "cmd/verstak-server/verstak-server.service"
# --- RPM package: GUI ---
echo ""
echo "==> Building RPM packages..."
build_rpm() {
local binary="$1"
local pkg_name="$2"
local description="$3"
local systemd_unit="${4:-}"
local rpm_dir="$BUILD_DIR/rpm-tmp"
mkdir -p "$rpm_dir/RPMS/x86_64"
mkdir -p "$rpm_dir/BUILD"
mkdir -p "$rpm_dir/SOURCES"
# Build root for rpmbuild
local buildroot="$rpm_dir/buildroot"
mkdir -p "$buildroot/usr/local/bin"
mkdir -p "$buildroot/usr/share/doc/$pkg_name"
# Copy binary and systemd unit into the buildroot
cp "$BUILD_DIR/$binary" "$buildroot/usr/local/bin/$pkg_name"
chmod 755 "$buildroot/usr/local/bin/$pkg_name"
if [[ -n "$systemd_unit" && -f "$systemd_unit" ]]; then
mkdir -p "$buildroot/lib/systemd/system"
cp "$systemd_unit" "$buildroot/lib/systemd/system/"
fi
[[ -f "README.md" ]] && cp "README.md" "$buildroot/usr/share/doc/$pkg_name/"
# Also copy into SOURCES so rpmbuild %install can find them
cp "$BUILD_DIR/$binary" "$rpm_dir/SOURCES/$pkg_name"
if [[ -n "$systemd_unit" && -f "$systemd_unit" ]]; then
cp "$systemd_unit" "$rpm_dir/SOURCES/$(basename "$systemd_unit")"
fi
[[ -f "README.md" ]] && cp "README.md" "$rpm_dir/SOURCES/README.md"
# File list
local file_list
file_list="%attr(755, root, root) /usr/local/bin/$pkg_name"
file_list+="%attr(644, root, root) /usr/share/doc/$pkg_name/*"
if [[ -n "$systemd_unit" && -f "$systemd_unit" ]]; then
# systemd file will be included via %files section
file_list+="%attr(644, root, root) /lib/systemd/system/$(basename "$systemd_unit")"
fi
local spec_file="$rpm_dir/SPECS/${pkg_name}.spec"
mkdir -p "$(dirname "$spec_file")"
cat > "$spec_file" <<SPEC
Summary: $description
Name: $pkg_name
Version: $VERSION
Release: 1
License: MIT
Group: Utilities
BuildArch: x86_64
AutoReqProv: no
Prefix: /usr
%description
$description
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/usr/local/bin
cp %{_sourcedir}/$pkg_name %{buildroot}/usr/local/bin/$pkg_name
chmod 755 %{buildroot}/usr/local/bin/$pkg_name
SPEC
if [[ -n "$systemd_unit" && -f "$systemd_unit" ]]; then
cat >> "$spec_file" <<SPEC
mkdir -p %{buildroot}/lib/systemd/system
cp %{_sourcedir}/$(basename "$systemd_unit") %{buildroot}/lib/systemd/system/
SPEC
fi
cat >> "$spec_file" <<SPEC
mkdir -p %{buildroot}/usr/share/doc/$pkg_name
cp -r %{_sourcedir}/README.md %{buildroot}/usr/share/doc/$pkg_name/ 2>/dev/null || true
%files
/usr/local/bin/$pkg_name
SPEC
if [[ -n "$systemd_unit" && -f "$systemd_unit" ]]; then
echo "/lib/systemd/system/$(basename "$systemd_unit")" >> "$spec_file"
fi
cat >> "$spec_file" <<SPEC
%doc /usr/share/doc/$pkg_name/*
SPEC
rpmbuild --define "_topdir $rpm_dir" \
--define "_builddir $rpm_dir/BUILD" \
--define "_sourcedir $rpm_dir/SOURCES" \
--define "_rpmdir $rpm_dir/RPMS" \
--define "_specdir $rpm_dir/SPECS" \
--define "_buildrootdir $rpm_dir/buildroot" \
-bb "$spec_file" >/dev/null
cp "$rpm_dir/RPMS/x86_64/${pkg_name}-${VERSION}-1.x86_64.rpm" \
"$LINUX_DIR/${pkg_name}.rpm"
rm -rf "$rpm_dir"
echo " $LINUX_DIR/${pkg_name}.rpm"
}
build_rpm "verstak" "verstak" "Verstak — local-first working vault GUI"
build_rpm "verstak-server" "verstak-server" "Verstak Sync Server" "cmd/verstak-server/verstak-server.service"
# --- Firefox signed XPI ---
echo ""
if [[ "$SKIP_FIREFOX_SIGN" == "true" ]]; then
echo "==> Firefox extension signing skipped (--skip-firefox-sign)"
elif [[ -f ".env" ]] && grep -q "WEB_EXT_API_KEY" ".env" 2>/dev/null; then
echo "==> Signing Firefox extension..."
./scripts/release-firefox-xpi.sh
else
echo "ERROR: AMO tokens not found (WEB_EXT_API_KEY / WEB_EXT_API_SECRET in .env)." >&2
echo " Firefox signing is required for a full release." >&2
echo " To skip: run with --skip-firefox-sign" >&2
echo " To sign: copy .env.example -> .env and fill in AMO credentials from" >&2
echo " https://addons.mozilla.org/developers/" >&2
exit 1
fi
# --- Checksums ---
echo ""
echo "==> Generating checksums..."
cd "$LINUX_DIR"
sha256sum verstak verstak-server *.deb *.rpm 2>/dev/null > checksums.txt || true
cd "$ROOT_DIR"
echo " $LINUX_DIR/checksums.txt"
# --- Summary ---
echo ""
echo "============================================"
echo " Release v$VERSION artifacts"
echo "============================================"
echo ""
echo "Linux binaries:"
ls -lh "$LINUX_DIR/" 2>/dev/null
echo ""
if [[ -d "$RELEASE_DIR/firefox" ]]; then
echo "Firefox extension:"
ls -lh "$RELEASE_DIR/firefox/" 2>/dev/null
echo ""
fi
echo "============================================"
# --- Git tag + release ---
if [[ "$PUBLISH" == "true" ]]; then
echo ""
echo "==> Creating git tag v$VERSION..."
git tag -s "v$VERSION" -m "Verstak v$VERSION"
git push origin "v$VERSION"
echo "==> Creating GitHub release..."
gh release create "v$VERSION" \
--title "Verstak v$VERSION" \
--notes "See CHANGELOG.md for details" \
"$LINUX_DIR"/* \
$([[ -d "$RELEASE_DIR/firefox" ]] && echo "$RELEASE_DIR/firefox/"* || true)
echo " GitHub release created: https://github.com/$(git remote get-url origin | sed 's|.*github.com[:/]||;s|\\.git$||')/releases/tag/v$VERSION"
else
echo ""
echo "Dry-run: use --publish to create git tag + GitHub release."
echo "Run: git tag -s v$VERSION -m \"Verstak v$VERSION\""
fi
echo ""
echo "Done."