Files
nostr_terminal/increment_and_push.sh

384 lines
10 KiB
Bash
Executable File

#!/bin/bash
set -e
# nt increment + push script
# Canonical version source is latest git tag (vX.Y.Z)
# This script increments the tag and updates NT_VERSION macros in src/main.c
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_status() { echo -e "${BLUE}[INFO]${NC} $1" >&2; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" >&2; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" >&2; }
print_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
COMMIT_MESSAGE=""
VERSION_INCREMENT_TYPE="patch" # patch|minor|major
RELEASE_MODE=false
show_usage() {
echo "nt increment and push"
echo ""
echo "USAGE:"
echo " $0 [OPTIONS] \"commit message\""
echo ""
echo "OPTIONS:"
echo " -p, --patch Increment patch version (default)"
echo " -m, --minor Increment minor version"
echo " -M, --major Increment major version"
echo " -r, --release After bump+push, build/upload release assets to Gitea"
echo " -h, --help Show help"
echo ""
echo "EXAMPLES:"
echo " $0 \"Fix relay reconnect bug\""
echo " $0 -m \"Add profile editing\""
echo " $0 -r -p \"Release patch build\""
echo " $0 -r -m \"Release minor build\""
echo ""
echo "RELEASE MODE (-r):"
echo " 1) Normal bump + commit + tag + push runs first"
echo " 2) Build x86_64 static binary as ./nt (required)"
echo " 3) Build arm64 static binary as ./nt (warning only on failure)"
echo " 4) Snapshot release assets under build/"
echo " 5) Create source tarball"
echo " 6) Create/upload Gitea release assets if ~/.gitea_token exists"
}
while [[ $# -gt 0 ]]; do
case "$1" in
-p|--patch)
VERSION_INCREMENT_TYPE="patch"
shift
;;
-m|--minor)
VERSION_INCREMENT_TYPE="minor"
shift
;;
-M|--major)
VERSION_INCREMENT_TYPE="major"
shift
;;
-r|--release)
RELEASE_MODE=true
shift
;;
-h|--help)
show_usage
exit 0
;;
*)
if [[ -z "$COMMIT_MESSAGE" ]]; then
COMMIT_MESSAGE="$1"
fi
shift
;;
esac
done
if [[ -z "$COMMIT_MESSAGE" ]]; then
print_error "Commit message is required"
echo ""
show_usage
exit 1
fi
if ! git rev-parse --git-dir > /dev/null 2>&1; then
print_error "Not in a git repository"
exit 1
fi
get_and_increment_version() {
LATEST_TAG=$(git tag -l 'v*.*.*' | sort -V | tail -n 1 || true)
if [[ -z "$LATEST_TAG" ]]; then
LATEST_TAG="v0.0.0"
print_warning "No version tags found, starting from $LATEST_TAG"
fi
VERSION=${LATEST_TAG#v}
if [[ $VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
else
print_error "Invalid version format in tag: $LATEST_TAG"
exit 1
fi
case "$VERSION_INCREMENT_TYPE" in
major)
NEW_MAJOR=$((MAJOR + 1))
NEW_MINOR=0
NEW_PATCH=0
;;
minor)
NEW_MAJOR=$MAJOR
NEW_MINOR=$((MINOR + 1))
NEW_PATCH=0
;;
*)
NEW_MAJOR=$MAJOR
NEW_MINOR=$MINOR
NEW_PATCH=$((PATCH + 1))
;;
esac
NEW_VERSION="v${NEW_MAJOR}.${NEW_MINOR}.${NEW_PATCH}"
print_status "Current version: $LATEST_TAG"
print_status "New version: $NEW_VERSION"
}
update_version_macros() {
if [[ ! -f "src/main.c" ]]; then
print_error "src/main.c not found"
exit 1
fi
print_status "Updating version macros in src/main.c"
sed -i "s/^#define NT_VERSION_MAJOR .*/#define NT_VERSION_MAJOR ${NEW_MAJOR}/" src/main.c
sed -i "s/^#define NT_VERSION_MINOR .*/#define NT_VERSION_MINOR ${NEW_MINOR}/" src/main.c
sed -i "s/^#define NT_VERSION_PATCH .*/#define NT_VERSION_PATCH ${NEW_PATCH}/" src/main.c
sed -i "s/^#define NT_VERSION \".*\"/#define NT_VERSION \"${NEW_VERSION}\"/" src/main.c
print_success "Updated version in src/main.c to $NEW_VERSION"
}
git_commit_tag_push() {
print_status "Staging changes"
git add src/main.c CMakeLists.txt build.sh increment_and_push.sh README.md plans/planning.md include/*.h src/*.c .test_mnemonic 2>/dev/null || git add .
if git diff --staged --quiet; then
print_warning "No changes to commit"
else
git commit -m "$NEW_VERSION - $COMMIT_MESSAGE"
print_success "Committed changes"
fi
if git rev-parse "$NEW_VERSION" >/dev/null 2>&1; then
print_warning "Tag $NEW_VERSION already exists locally; recreating"
git tag -d "$NEW_VERSION" >/dev/null 2>&1 || true
fi
git tag "$NEW_VERSION"
print_success "Created tag: $NEW_VERSION"
print_status "Pushing commit and tag"
git push
git push origin "$NEW_VERSION"
print_success "Pushed $NEW_VERSION"
}
build_release_binary() {
print_status "Building release binaries"
if [[ ! -x "./build.sh" ]]; then
print_error "./build.sh not found or not executable"
return 1
fi
mkdir -p build
if ./build.sh; then
cp -f nt build/nt_x86_64
print_success "Built x86_64 static binary"
else
print_error "x86_64 build failed; aborting release mode"
return 1
fi
if ./build.sh --arch arm64; then
cp -f nt build/nt_arm64
print_success "Built arm64 static binary"
else
print_warning "arm64 build failed (continuing release with available assets)"
fi
return 0
}
create_source_tarball() {
local tarball_name="nostr_terminal-${NEW_VERSION#v}.tar.gz"
print_status "Creating source tarball: $tarball_name"
if tar -czf "$tarball_name" \
--exclude='build/*' \
--exclude='.git*' \
--exclude='*.db' \
--exclude='*.db-*' \
--exclude='*.log' \
--exclude='*.tar.gz' \
.; then
print_success "Created source tarball: $tarball_name"
echo "$tarball_name"
return 0
else
print_error "Failed to create source tarball"
return 1
fi
}
create_gitea_release() {
if [[ ! -f "$HOME/.gitea_token" ]]; then
print_warning "No $HOME/.gitea_token found. Skipping release creation/upload."
return 0
fi
local token
token=$(tr -d '\n\r' < "$HOME/.gitea_token")
local api_url="https://git.laantungir.net/api/v1/repos/laantungir/nostr_terminal"
print_status "Creating Gitea release: $NEW_VERSION"
local response
response=$(curl -s -X POST "$api_url/releases" \
-H "Authorization: token $token" \
-H "Content-Type: application/json" \
-d "{\"tag_name\": \"$NEW_VERSION\", \"name\": \"$NEW_VERSION\", \"body\": \"$COMMIT_MESSAGE\"}")
if echo "$response" | grep -q '"id"'; then
local release_id
release_id=$(echo "$response" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
print_success "Created release $NEW_VERSION (id=$release_id)"
echo "$release_id"
return 0
fi
if echo "$response" | grep -qi "already exists"; then
print_warning "Release $NEW_VERSION already exists; resolving release id"
local existing
existing=$(curl -s -H "Authorization: token $token" "$api_url/releases/tags/$NEW_VERSION")
if echo "$existing" | grep -q '"id"'; then
local release_id
release_id=$(echo "$existing" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
print_status "Using existing release id=$release_id"
echo "$release_id"
return 0
fi
print_error "Could not resolve existing release ID for $NEW_VERSION"
return 1
fi
print_error "Failed to create release"
print_error "Response: $response"
return 1
}
upload_one_asset_with_retry() {
local assets_url="$1"
local token="$2"
local file_path="$3"
local max_attempts=3
local attempt=1
while [[ $attempt -le $max_attempts ]]; do
print_status "Uploading $(basename "$file_path") (attempt $attempt/$max_attempts)"
local response
response=$(curl -s -X POST "$assets_url" \
-H "Authorization: token $token" \
-F "attachment=@$file_path;filename=$(basename "$file_path")")
if echo "$response" | grep -q '"id"'; then
print_success "Uploaded $(basename "$file_path")"
return 0
fi
if [[ $attempt -lt $max_attempts ]]; then
print_warning "Upload attempt failed for $(basename "$file_path"), retrying..."
sleep 2
else
print_error "Failed to upload $(basename "$file_path") after $max_attempts attempts"
print_error "Response: $response"
fi
attempt=$((attempt + 1))
done
return 1
}
upload_release_assets() {
local release_id="$1"
local tarball_path="$2"
if [[ ! -f "$HOME/.gitea_token" ]]; then
print_warning "No $HOME/.gitea_token found. Skipping asset uploads."
return 0
fi
local token
token=$(tr -d '\n\r' < "$HOME/.gitea_token")
local api_url="https://git.laantungir.net/api/v1/repos/laantungir/nostr_terminal"
local assets_url="$api_url/releases/$release_id/assets"
if [[ -f "build/nt_x86_64" ]]; then
upload_one_asset_with_retry "$assets_url" "$token" "build/nt_x86_64" || true
else
print_warning "Asset missing: build/nt_x86_64"
fi
if [[ -f "build/nt_arm64" ]]; then
upload_one_asset_with_retry "$assets_url" "$token" "build/nt_arm64" || true
else
print_warning "Asset missing: build/nt_arm64 (skipping)"
fi
if [[ -n "$tarball_path" && -f "$tarball_path" ]]; then
print_status "Uploading $(basename "$tarball_path")"
local response
response=$(curl -s -X POST "$assets_url" \
-H "Authorization: token $token" \
-F "attachment=@$tarball_path;filename=$(basename "$tarball_path")")
if echo "$response" | grep -q '"id"'; then
print_success "Uploaded $(basename "$tarball_path")"
else
print_warning "Failed to upload $(basename "$tarball_path"): $response"
fi
else
print_warning "Tarball missing, skipping upload"
fi
}
main() {
get_and_increment_version
update_version_macros
git_commit_tag_push
if [[ "$RELEASE_MODE" == true ]]; then
print_status "Release mode enabled"
if ! build_release_binary; then
print_error "Release mode aborted due to required x86_64 build failure"
exit 1
fi
local tarball_path=""
if tarball_path=$(create_source_tarball); then
:
else
print_warning "Proceeding without source tarball"
fi
local release_id=""
if release_id=$(create_gitea_release); then
if [[ "$release_id" =~ ^[0-9]+$ ]]; then
upload_release_assets "$release_id" "$tarball_path"
print_success "Release workflow finished for $NEW_VERSION"
else
print_warning "Release creation/upload skipped (no release id)"
fi
else
print_error "Release creation failed"
exit 1
fi
fi
print_success "Done. Pushed $NEW_VERSION"
}
main