feat: static binary builds and automated release script
Switch reqwest from native-tls (openssl) to rustls-tls for a pure-Rust TLS stack, enabling fully static musl builds. Add `nix build .#static` for portable Linux binaries and `scripts/release.sh` for automated Gitea releases with changelog generation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
175
scripts/release.sh
Executable file
175
scripts/release.sh
Executable file
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Lux Release Script
|
||||
# Builds a static binary, generates changelog, and creates a Gitea release.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/release.sh [version]
|
||||
#
|
||||
# Environment:
|
||||
# GITEA_TOKEN - API token for git.qrty.ink (prompted if not set)
|
||||
# GITEA_URL - Gitea instance URL (default: https://git.qrty.ink)
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://git.qrty.ink}"
|
||||
REPO_OWNER="blu"
|
||||
REPO_NAME="lux"
|
||||
API_BASE="$GITEA_URL/api/v1"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { printf "${CYAN}::${NC} %s\n" "$1"; }
|
||||
ok() { printf "${GREEN}ok${NC} %s\n" "$1"; }
|
||||
warn() { printf "${YELLOW}!!${NC} %s\n" "$1"; }
|
||||
err() { printf "${RED}error:${NC} %s\n" "$1" >&2; exit 1; }
|
||||
|
||||
# --- Determine version ---
|
||||
VERSION="${1:-}"
|
||||
if [ -z "$VERSION" ]; then
|
||||
VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
info "Version from Cargo.toml: v$VERSION"
|
||||
fi
|
||||
# Ensure v prefix
|
||||
[[ "$VERSION" == v* ]] || VERSION="v$VERSION"
|
||||
TAG="$VERSION"
|
||||
|
||||
# --- Check for clean working tree ---
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
warn "Working tree has uncommitted changes:"
|
||||
git status --short
|
||||
printf "\n"
|
||||
read -rp "Continue anyway? [y/N] " confirm
|
||||
[[ "$confirm" =~ ^[Yy]$ ]] || exit 1
|
||||
fi
|
||||
|
||||
# --- Check if tag already exists ---
|
||||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||
err "Tag $TAG already exists. Bump version in Cargo.toml or choose a different version."
|
||||
fi
|
||||
|
||||
# --- Generate changelog ---
|
||||
info "Generating changelog..."
|
||||
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
||||
if [ -n "$LAST_TAG" ]; then
|
||||
RANGE="$LAST_TAG..HEAD"
|
||||
info "Changes since $LAST_TAG:"
|
||||
else
|
||||
RANGE="HEAD"
|
||||
info "First release — summarizing recent commits:"
|
||||
fi
|
||||
|
||||
CHANGELOG=$(git log "$RANGE" --pretty=format:"- %s" --no-merges 2>/dev/null | head -50 || true)
|
||||
if [ -z "$CHANGELOG" ]; then
|
||||
CHANGELOG="- Initial release"
|
||||
fi
|
||||
|
||||
# --- Build static binary ---
|
||||
info "Building static binary (nix build .#static)..."
|
||||
nix build .#static
|
||||
BINARY="result/bin/lux"
|
||||
if [ ! -f "$BINARY" ]; then
|
||||
err "Static binary not found at $BINARY"
|
||||
fi
|
||||
|
||||
BINARY_SIZE=$(ls -lh "$BINARY" | awk '{print $5}')
|
||||
BINARY_TYPE=$(file "$BINARY" | sed 's/.*: //')
|
||||
ok "Binary: $BINARY_SIZE, $BINARY_TYPE"
|
||||
|
||||
# --- Prepare release artifact ---
|
||||
ARTIFACT="/tmp/lux-${TAG}-linux-x86_64"
|
||||
cp "$BINARY" "$ARTIFACT"
|
||||
chmod +x "$ARTIFACT"
|
||||
|
||||
# --- Show release summary ---
|
||||
printf "\n"
|
||||
printf "${BOLD}═══ Release Summary ═══${NC}\n"
|
||||
printf "\n"
|
||||
printf " ${BOLD}Tag:${NC} %s\n" "$TAG"
|
||||
printf " ${BOLD}Binary:${NC} %s (%s)\n" "lux-${TAG}-linux-x86_64" "$BINARY_SIZE"
|
||||
printf " ${BOLD}Commit:${NC} %s\n" "$(git rev-parse --short HEAD)"
|
||||
printf "\n"
|
||||
printf "${BOLD}Changelog:${NC}\n"
|
||||
printf "%s\n" "$CHANGELOG"
|
||||
printf "\n"
|
||||
|
||||
# --- Confirm ---
|
||||
read -rp "Create release $TAG? [y/N] " confirm
|
||||
[[ "$confirm" =~ ^[Yy]$ ]] || { info "Aborted."; exit 0; }
|
||||
|
||||
# --- Get Gitea token ---
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
printf "\n"
|
||||
info "Gitea API token required (create at $GITEA_URL/user/settings/applications)"
|
||||
read -rsp "Token: " GITEA_TOKEN
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
if [ -z "$GITEA_TOKEN" ]; then
|
||||
err "No token provided"
|
||||
fi
|
||||
|
||||
# --- Create and push tag ---
|
||||
info "Creating tag $TAG..."
|
||||
git tag -a "$TAG" -m "Release $TAG" --no-sign
|
||||
ok "Tag created"
|
||||
|
||||
info "Pushing tag to origin..."
|
||||
git push origin "$TAG"
|
||||
ok "Tag pushed"
|
||||
|
||||
# --- Create Gitea release ---
|
||||
info "Creating release on Gitea..."
|
||||
|
||||
RELEASE_BODY=$(printf "## Lux %s\n\n### Changes\n\n%s\n\n### Installation\n\n\`\`\`bash\ncurl -Lo lux %s/%s/%s/releases/download/%s/lux-linux-x86_64\nchmod +x lux\n./lux --version\n\`\`\`" \
|
||||
"$TAG" "$CHANGELOG" "$GITEA_URL" "$REPO_OWNER" "$REPO_NAME" "$TAG")
|
||||
|
||||
RELEASE_JSON=$(jq -n \
|
||||
--arg tag "$TAG" \
|
||||
--arg name "Lux $TAG" \
|
||||
--arg body "$RELEASE_BODY" \
|
||||
'{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')
|
||||
|
||||
RELEASE_RESPONSE=$(curl -s -X POST \
|
||||
"$API_BASE/repos/$REPO_OWNER/$REPO_NAME/releases" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$RELEASE_JSON")
|
||||
|
||||
RELEASE_ID=$(echo "$RELEASE_RESPONSE" | jq -r '.id // empty')
|
||||
if [ -z "$RELEASE_ID" ]; then
|
||||
echo "$RELEASE_RESPONSE" | jq . 2>/dev/null || echo "$RELEASE_RESPONSE"
|
||||
err "Failed to create release"
|
||||
fi
|
||||
ok "Release created (id: $RELEASE_ID)"
|
||||
|
||||
# --- Upload binary ---
|
||||
info "Uploading binary..."
|
||||
UPLOAD_RESPONSE=$(curl -s -X POST \
|
||||
"$API_BASE/repos/$REPO_OWNER/$REPO_NAME/releases/$RELEASE_ID/assets?name=lux-linux-x86_64" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@$ARTIFACT")
|
||||
|
||||
ASSET_NAME=$(echo "$UPLOAD_RESPONSE" | jq -r '.name // empty')
|
||||
if [ -z "$ASSET_NAME" ]; then
|
||||
echo "$UPLOAD_RESPONSE" | jq . 2>/dev/null || echo "$UPLOAD_RESPONSE"
|
||||
err "Failed to upload binary"
|
||||
fi
|
||||
ok "Binary uploaded: $ASSET_NAME"
|
||||
|
||||
# --- Done ---
|
||||
printf "\n"
|
||||
printf "${GREEN}${BOLD}Release $TAG published!${NC}\n"
|
||||
printf "\n"
|
||||
printf " ${BOLD}URL:${NC} %s/%s/%s/releases/tag/%s\n" "$GITEA_URL" "$REPO_OWNER" "$REPO_NAME" "$TAG"
|
||||
printf " ${BOLD}Download:${NC} %s/%s/%s/releases/download/%s/lux-linux-x86_64\n" "$GITEA_URL" "$REPO_OWNER" "$REPO_NAME" "$TAG"
|
||||
printf "\n"
|
||||
|
||||
# Cleanup
|
||||
rm -f "$ARTIFACT"
|
||||
Reference in New Issue
Block a user