diff --git a/.roo/commands/push.md b/.roo/commands/push.md index b9f1e17..8488d18 100644 --- a/.roo/commands/push.md +++ b/.roo/commands/push.md @@ -2,6 +2,6 @@ description: "Brief description of what this command does" --- -Run build_and_push.sh, and supply a good git commit message. For example: +Run increment_and_push.sh, and supply a good git commit message. For example: -./build_and_push.sh "Fixed the bug with nip05 implementation" \ No newline at end of file +./increment_and_push.sh "Fixed the bug with nip05 implementation" \ No newline at end of file diff --git a/api/index.css b/api/index.css index 08ea8e1..e6c3b60 100644 --- a/api/index.css +++ b/api/index.css @@ -326,6 +326,24 @@ button:disabled { border-color: var(--accent-color); } +/* Authentication warning message */ +.auth-warning-message { + margin-bottom: 15px; + padding: 12px; + background-color: #fff3cd; + border: 1px solid #ffeaa7; + border-radius: var(--border-radius); + color: #856404; +} + +.warning-content { + line-height: 1.4; +} + +.warning-content strong { + color: #d68910; +} + .config-table { border: 1px solid var(--border-color); border-radius: var(--border-radius); diff --git a/api/index.js b/api/index.js index 2d010f8..da122ca 100644 --- a/api/index.js +++ b/api/index.js @@ -83,6 +83,41 @@ function log(message, type = 'INFO') { // UI logging removed - using console only } +// Show authentication warning message +function showAuthenticationWarning(message) { + // Remove any existing warning + hideAuthenticationWarning(); + + // Create warning element + const warningDiv = document.createElement('div'); + warningDiv.id = 'auth-warning-message'; + warningDiv.className = 'auth-warning-message'; + warningDiv.innerHTML = ` +
+ ⚠️ Authentication Issue: ${message} +

+ This usually means your pubkey is not authorized as an admin for this relay. + Please check that you are using the correct admin pubkey that was shown during relay startup. +
+ `; + + // Insert warning at the top of the relay connection section + const relaySection = document.getElementById('relay-connection-section'); + if (relaySection) { + relaySection.insertBefore(warningDiv, relaySection.firstChild); + } + + log(`Authentication warning displayed: ${message}`, 'WARNING'); +} + +// Hide authentication warning message +function hideAuthenticationWarning() { + const warningDiv = document.getElementById('auth-warning-message'); + if (warningDiv) { + warningDiv.remove(); + } +} + // NIP-59 helper: randomize created_at to thwart time-analysis (past 2 days) function randomNow() { const TWO_DAYS = 2 * 24 * 60 * 60; // 172800 seconds @@ -216,6 +251,9 @@ async function connectToRelay() { log(`Connecting to relay: ${url}`, 'INFO'); + // Clear any previous authentication warnings + hideAuthenticationWarning(); + let fetchedRelayInfo; try { @@ -326,7 +364,18 @@ async function connectToRelay() { } catch (error) { log(`Failed to connect to relay: ${error.message}`, 'ERROR'); - updateRelayConnectionStatus('error'); + + // Check if this is an authentication-related error + if (error.message.includes('authentication') || + error.message.includes('auth') || + error.message.includes('permission') || + error.message.includes('unauthorized') || + error.message.includes('forbidden')) { + updateRelayConnectionStatus('auth_error'); + showAuthenticationWarning(error.message); + } else { + updateRelayConnectionStatus('error'); + } // Reset state on failure relayInfo = null; @@ -363,6 +412,9 @@ function disconnectFromRelay() { hideRelayInfo(); updateAdminSectionsVisibility(); + // Hide any authentication warnings + hideAuthenticationWarning(); + log('Disconnected from relay', 'INFO'); } catch (error) { @@ -403,6 +455,13 @@ function updateRelayConnectionStatus(status) { disconnectRelayBtn.disabled = true; restartRelayBtn.disabled = true; break; + case 'auth_error': + relayConnectionStatus.textContent = 'AUTHENTICATION FAILED'; + relayConnectionStatus.className = 'status error'; + connectRelayBtn.disabled = false; + disconnectRelayBtn.disabled = true; + restartRelayBtn.disabled = true; + break; } } @@ -569,9 +628,20 @@ function handleAuthEvent(event) { showProfileInHeader(); loadUserProfile(); - // Note: Configuration fetching now requires explicit relay connection - // User must connect to relay manually after login - console.log('Login successful. Connect to relay to access admin functions.'); + // Automatically attempt to connect to relay after successful login + console.log('Login successful. Automatically attempting to connect to relay...'); + setTimeout(() => { + connectToRelay().catch(error => { + console.log(`Automatic relay connection failed: ${error.message}`); + // Check if this is an authentication-related error + if (error.message.includes('authentication') || + error.message.includes('auth') || + error.message.includes('permission') || + error.message.includes('unauthorized')) { + showAuthenticationWarning(error.message); + } + }); + }, 500); // Small delay to allow profile loading to complete } else if (error) { console.log(`Authentication error: ${error}`); @@ -589,6 +659,9 @@ function handleLogoutEvent() { // Clean up relay connection disconnectFromRelay(); + // Hide any authentication warnings + hideAuthenticationWarning(); + // Reset UI - hide profile and show login modal hideProfileFromHeader(); showLoginModal(); @@ -882,6 +955,9 @@ async function logout() { isLoggedIn = false; currentConfig = null; + // Hide any authentication warnings + hideAuthenticationWarning(); + // Reset UI - hide profile and show login modal hideProfileFromHeader(); // showLoginModal() removed - handled by handleLogoutEvent() diff --git a/build_and_push.sh b/build_and_push.sh deleted file mode 100755 index 6a979dc..0000000 --- a/build_and_push.sh +++ /dev/null @@ -1,616 +0,0 @@ -#!/bin/bash -set -e - -# Colors for output -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"; } -print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } -print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } -print_error() { echo -e "${RED}[ERROR]${NC} $1"; } - -# Global variables -COMMIT_MESSAGE="" -RELEASE_MODE=false - -show_usage() { - echo "C-Relay Build and Push Script" - echo "" - echo "Usage:" - echo " $0 \"commit message\" - Default: compile, increment patch, commit & push" - echo " $0 -r \"commit message\" - Release: compile x86+arm64, increment minor, create release" - echo "" - echo "Examples:" - echo " $0 \"Fixed event validation bug\"" - echo " $0 --release \"Major release with new features\"" - echo "" - echo "Default Mode (patch increment):" - echo " - Compile C-Relay" - echo " - Increment patch version (v1.2.3 → v1.2.4)" - echo " - Git add, commit with message, and push" - echo "" - echo "Release Mode (-r flag):" - echo " - Compile C-Relay for x86_64 and arm64 (dynamic and static versions)" - echo " - Increment minor version, zero patch (v1.2.3 → v1.3.0)" - echo " - Git add, commit, push, and create Gitea release" - echo "" - echo "Requirements for Release Mode:" - echo " - For ARM64 builds: make install-arm64-deps (optional - will build x86_64 only if missing)" - echo " - For static builds: sudo apt-get install musl-dev libcap-dev libuv1-dev libev-dev" - echo " - Gitea token in ~/.gitea_token for release uploads" -} - -# Parse command line arguments -while [[ $# -gt 0 ]]; do - case $1 in - -r|--release) - RELEASE_MODE=true - shift - ;; - -h|--help) - show_usage - exit 0 - ;; - *) - # First non-flag argument is the commit message - if [[ -z "$COMMIT_MESSAGE" ]]; then - COMMIT_MESSAGE="$1" - fi - shift - ;; - esac -done - -# Validate inputs -if [[ -z "$COMMIT_MESSAGE" ]]; then - print_error "Commit message is required" - echo "" - show_usage - exit 1 -fi - -# Check if we're in a git repository -check_git_repo() { - if ! git rev-parse --git-dir > /dev/null 2>&1; then - print_error "Not in a git repository" - exit 1 - fi -} - -# Function to get current version and increment appropriately -increment_version() { - local increment_type="$1" # "patch" or "minor" - - print_status "Getting current version..." - - # Get the highest version tag (not chronologically latest) - LATEST_TAG=$(git tag -l 'v*.*.*' | sort -V | tail -n 1 || echo "") - if [[ -z "$LATEST_TAG" ]]; then - LATEST_TAG="v0.0.0" - print_warning "No version tags found, starting from $LATEST_TAG" - fi - - # Extract version components (remove 'v' prefix) - VERSION=${LATEST_TAG#v} - - # Parse major.minor.patch using regex - 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" - print_error "Expected format: v0.1.0" - exit 1 - fi - - # Increment version based on type - if [[ "$increment_type" == "minor" ]]; then - # Minor release: increment minor, zero patch - NEW_MINOR=$((MINOR + 1)) - NEW_PATCH=0 - NEW_VERSION="v${MAJOR}.${NEW_MINOR}.${NEW_PATCH}" - print_status "Release mode: incrementing minor version" - else - # Default: increment patch - NEW_PATCH=$((PATCH + 1)) - NEW_VERSION="v${MAJOR}.${MINOR}.${NEW_PATCH}" - print_status "Default mode: incrementing patch version" - fi - - print_status "Current version: $LATEST_TAG" - print_status "New version: $NEW_VERSION" - - # Export for use in other functions - export NEW_VERSION -} - -# Function to compile the C-Relay project -compile_project() { - print_status "Compiling C-Relay..." - - # Clean previous build - if make clean > /dev/null 2>&1; then - print_success "Cleaned previous build" - else - print_warning "Clean failed or no Makefile found" - fi - - # Force regenerate main.h to pick up new tags - if make force-version > /dev/null 2>&1; then - print_success "Regenerated main.h" - else - print_warning "Failed to regenerate main.h" - fi - - # Compile the project - if make > /dev/null 2>&1; then - print_success "C-Relay compiled successfully" - else - print_error "Compilation failed" - exit 1 - fi -} - -# Function to build release binaries -build_release_binaries() { - print_status "Building release binaries..." - - # Build x86_64 version - print_status "Building x86_64 version..." - make clean > /dev/null 2>&1 - if make x86 > /dev/null 2>&1; then - if [[ -f "build/c_relay_x86" ]]; then - cp build/c_relay_x86 c-relay-x86_64 - print_success "x86_64 binary created: c-relay-x86_64" - else - print_error "x86_64 binary not found after compilation" - exit 1 - fi - else - print_error "x86_64 build failed" - exit 1 - fi - - # Try to build ARM64 version - print_status "Attempting ARM64 build..." - make clean > /dev/null 2>&1 - if make arm64 > /dev/null 2>&1; then - if [[ -f "build/c_relay_arm64" ]]; then - cp build/c_relay_arm64 c-relay-arm64 - print_success "ARM64 binary created: c-relay-arm64" - else - print_warning "ARM64 binary not found after compilation" - fi - else - print_warning "ARM64 build failed - ARM64 cross-compilation not properly set up" - print_status "Only x86_64 binary will be included in release" - fi - - # Build static x86_64 version - print_status "Building static x86_64 version..." - make clean > /dev/null 2>&1 - if make static-musl-x86_64 > /dev/null 2>&1; then - if [[ -f "build/c_relay_static_musl_x86_64" ]]; then - cp build/c_relay_static_musl_x86_64 c-relay-static-x86_64 - print_success "Static x86_64 binary created: c-relay-static-x86_64" - else - print_warning "Static x86_64 binary not found after compilation" - fi - else - print_warning "Static x86_64 build failed - MUSL development packages may not be installed" - print_status "Run 'sudo apt-get install musl-dev libcap-dev libuv1-dev libev-dev' to enable static builds" - fi - - # Try to build static ARM64 version - print_status "Attempting static ARM64 build..." - make clean > /dev/null 2>&1 - if make static-musl-arm64 > /dev/null 2>&1; then - if [[ -f "build/c_relay_static_musl_arm64" ]]; then - cp build/c_relay_static_musl_arm64 c-relay-static-arm64 - print_success "Static ARM64 binary created: c-relay-static-arm64" - else - print_warning "Static ARM64 binary not found after compilation" - fi - else - print_warning "Static ARM64 build failed - ARM64 cross-compilation or MUSL ARM64 packages not set up" - fi - - # Restore normal build - make clean > /dev/null 2>&1 - make > /dev/null 2>&1 -} - -# Function to commit and push changes -git_commit_and_push() { - print_status "Preparing git commit..." - - # Stage all changes - if git add . > /dev/null 2>&1; then - print_success "Staged all changes" - else - print_error "Failed to stage changes" - exit 1 - fi - - # Check if there are changes to commit - if git diff --staged --quiet; then - print_warning "No changes to commit" - else - # Commit changes - if git commit -m "$NEW_VERSION - $COMMIT_MESSAGE" > /dev/null 2>&1; then - print_success "Committed changes" - else - print_error "Failed to commit changes" - exit 1 - fi - fi - - # Create new git tag - if git tag "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Created tag: $NEW_VERSION" - else - print_warning "Tag $NEW_VERSION already exists" - fi - - # Push changes and tags - print_status "Pushing to remote repository..." - if git push > /dev/null 2>&1; then - print_success "Pushed changes" - else - print_error "Failed to push changes" - exit 1 - fi - - # Push only the new tag to avoid conflicts with existing tags - if git push origin "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Pushed tag: $NEW_VERSION" - else - print_warning "Tag push failed, trying force push..." - if git push --force origin "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Force-pushed updated tag: $NEW_VERSION" - else - print_error "Failed to push tag: $NEW_VERSION" - exit 1 - fi - fi -} - -# Function to commit and push changes without creating a tag (tag already created) -git_commit_and_push_no_tag() { - print_status "Preparing git commit..." - - # Stage all changes - if git add . > /dev/null 2>&1; then - print_success "Staged all changes" - else - print_error "Failed to stage changes" - exit 1 - fi - - # Check if there are changes to commit - if git diff --staged --quiet; then - print_warning "No changes to commit" - else - # Commit changes - if git commit -m "$NEW_VERSION - $COMMIT_MESSAGE" > /dev/null 2>&1; then - print_success "Committed changes" - else - print_error "Failed to commit changes" - exit 1 - fi - fi - - # Push changes and tags - print_status "Pushing to remote repository..." - if git push > /dev/null 2>&1; then - print_success "Pushed changes" - else - print_error "Failed to push changes" - exit 1 - fi - - # Push only the new tag to avoid conflicts with existing tags - if git push origin "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Pushed tag: $NEW_VERSION" - else - print_warning "Tag push failed, trying force push..." - if git push --force origin "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Force-pushed updated tag: $NEW_VERSION" - else - print_error "Failed to push tag: $NEW_VERSION" - exit 1 - fi - fi -} - -# Function to create Gitea release -create_gitea_release() { - print_status "Creating Gitea release..." - - # Check for Gitea token - if [[ ! -f "$HOME/.gitea_token" ]]; then - print_warning "No ~/.gitea_token found. Skipping release creation." - print_warning "Create ~/.gitea_token with your Gitea access token to enable releases." - return 0 - fi - - local token=$(cat "$HOME/.gitea_token" | tr -d '\n\r') - local api_url="https://git.laantungir.net/api/v1/repos/laantungir/c-relay" - - # Create release - print_status "Creating release $NEW_VERSION..." - local 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\"}") - - local upload_result=false - - if echo "$response" | grep -q '"id"'; then - print_success "Created release $NEW_VERSION" - if upload_release_binaries "$api_url" "$token"; then - upload_result=true - fi - elif echo "$response" | grep -q "already exists"; then - print_warning "Release $NEW_VERSION already exists" - if upload_release_binaries "$api_url" "$token"; then - upload_result=true - fi - else - print_error "Failed to create release $NEW_VERSION" - print_error "Response: $response" - - # Try to check if the release exists anyway - print_status "Checking if release exists..." - local check_response=$(curl -s -H "Authorization: token $token" "$api_url/releases/tags/$NEW_VERSION") - if echo "$check_response" | grep -q '"id"'; then - print_warning "Release exists but creation response was unexpected" - if upload_release_binaries "$api_url" "$token"; then - upload_result=true - fi - else - print_error "Release does not exist and creation failed" - return 1 - fi - fi - - # Return based on upload success - if [[ "$upload_result" == true ]]; then - return 0 - else - print_error "Binary upload failed" - return 1 - fi -} - -# Function to upload release binaries -upload_release_binaries() { - local api_url="$1" - local token="$2" - local upload_success=true - - # Get release ID with more robust parsing - print_status "Getting release ID for $NEW_VERSION..." - local response=$(curl -s -H "Authorization: token $token" "$api_url/releases/tags/$NEW_VERSION") - local release_id=$(echo "$response" | grep -o '"id":[0-9]*' | head -n1 | cut -d: -f2) - - if [[ -z "$release_id" ]]; then - print_error "Could not get release ID for $NEW_VERSION" - print_error "API Response: $response" - - # Try to list all releases to debug - print_status "Available releases:" - curl -s -H "Authorization: token $token" "$api_url/releases" | grep -o '"tag_name":"[^"]*"' | head -5 - return 1 - fi - - print_success "Found release ID: $release_id" - - # Upload x86_64 binary - if [[ -f "c-relay-x86_64" ]]; then - print_status "Uploading x86_64 binary..." - local upload_response=$(curl -s -w "\n%{http_code}" -X POST "$api_url/releases/$release_id/assets" \ - -H "Authorization: token $token" \ - -F "attachment=@c-relay-x86_64;filename=c-relay-${NEW_VERSION}-linux-x86_64") - - local http_code=$(echo "$upload_response" | tail -n1) - local response_body=$(echo "$upload_response" | head -n -1) - - if [[ "$http_code" == "201" ]]; then - print_success "Uploaded x86_64 binary successfully" - else - print_error "Failed to upload x86_64 binary (HTTP $http_code)" - print_error "Response: $response_body" - upload_success=false - fi - else - print_warning "x86_64 binary not found: c-relay-x86_64" - fi - - # Upload ARM64 binary - if [[ -f "c-relay-arm64" ]]; then - print_status "Uploading ARM64 binary..." - local upload_response=$(curl -s -w "\n%{http_code}" -X POST "$api_url/releases/$release_id/assets" \ - -H "Authorization: token $token" \ - -F "attachment=@c-relay-arm64;filename=c-relay-${NEW_VERSION}-linux-arm64") - - local http_code=$(echo "$upload_response" | tail -n1) - local response_body=$(echo "$upload_response" | head -n -1) - - if [[ "$http_code" == "201" ]]; then - print_success "Uploaded ARM64 binary successfully" - else - print_error "Failed to upload ARM64 binary (HTTP $http_code)" - print_error "Response: $response_body" - upload_success=false - fi - else - print_warning "ARM64 binary not found: c-relay-arm64" - fi - - # Upload static x86_64 binary - if [[ -f "c-relay-static-x86_64" ]]; then - print_status "Uploading static x86_64 binary..." - local upload_response=$(curl -s -w "\n%{http_code}" -X POST "$api_url/releases/$release_id/assets" \ - -H "Authorization: token $token" \ - -F "attachment=@c-relay-static-x86_64;filename=c-relay-${NEW_VERSION}-linux-x86_64-static") - - local http_code=$(echo "$upload_response" | tail -n1) - local response_body=$(echo "$upload_response" | head -n -1) - - if [[ "$http_code" == "201" ]]; then - print_success "Uploaded static x86_64 binary successfully" - else - print_error "Failed to upload static x86_64 binary (HTTP $http_code)" - print_error "Response: $response_body" - upload_success=false - fi - else - print_warning "Static x86_64 binary not found: c-relay-static-x86_64" - fi - - # Upload static ARM64 binary - if [[ -f "c-relay-static-arm64" ]]; then - print_status "Uploading static ARM64 binary..." - local upload_response=$(curl -s -w "\n%{http_code}" -X POST "$api_url/releases/$release_id/assets" \ - -H "Authorization: token $token" \ - -F "attachment=@c-relay-static-arm64;filename=c-relay-${NEW_VERSION}-linux-arm64-static") - - local http_code=$(echo "$upload_response" | tail -n1) - local response_body=$(echo "$upload_response" | head -n -1) - - if [[ "$http_code" == "201" ]]; then - print_success "Uploaded static ARM64 binary successfully" - else - print_error "Failed to upload static ARM64 binary (HTTP $http_code)" - print_error "Response: $response_body" - upload_success=false - fi - else - print_warning "Static ARM64 binary not found: c-relay-static-arm64" - fi - - # Return success/failure status - if [[ "$upload_success" == true ]]; then - return 0 - else - return 1 - fi -} - -# Function to clean up release binaries -cleanup_release_binaries() { - local force_cleanup="$1" # Optional parameter to force cleanup even on failure - - if [[ "$force_cleanup" == "force" ]] || [[ "$upload_success" == true ]]; then - if [[ -f "c-relay-x86_64" ]]; then - rm -f c-relay-x86_64 - print_status "Cleaned up x86_64 binary" - fi - if [[ -f "c-relay-arm64" ]]; then - rm -f c-relay-arm64 - print_status "Cleaned up ARM64 binary" - fi - if [[ -f "c-relay-static-x86_64" ]]; then - rm -f c-relay-static-x86_64 - print_status "Cleaned up static x86_64 binary" - fi - if [[ -f "c-relay-static-arm64" ]]; then - rm -f c-relay-static-arm64 - print_status "Cleaned up static ARM64 binary" - fi - else - print_warning "Keeping binary files due to upload failures" - print_status "Files available for manual upload:" - if [[ -f "c-relay-x86_64" ]]; then - print_status " - c-relay-x86_64" - fi - if [[ -f "c-relay-arm64" ]]; then - print_status " - c-relay-arm64" - fi - if [[ -f "c-relay-static-x86_64" ]]; then - print_status " - c-relay-static-x86_64" - fi - if [[ -f "c-relay-static-arm64" ]]; then - print_status " - c-relay-static-arm64" - fi - fi -} - -# Main execution -main() { - print_status "C-Relay Build and Push Script" - - # Check prerequisites - check_git_repo - - if [[ "$RELEASE_MODE" == true ]]; then - print_status "=== RELEASE MODE ===" - - # Increment minor version for releases - increment_version "minor" - - # Create new git tag BEFORE compilation so version.h picks it up - if git tag "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Created tag: $NEW_VERSION" - else - print_warning "Tag $NEW_VERSION already exists, removing and recreating..." - git tag -d "$NEW_VERSION" > /dev/null 2>&1 - git tag "$NEW_VERSION" > /dev/null 2>&1 - fi - - # Compile project first (will now pick up the new tag) - compile_project - - # Build release binaries - build_release_binaries - - # Commit and push (but skip tag creation since we already did it) - git_commit_and_push_no_tag - - # Create Gitea release with binaries - if create_gitea_release; then - print_success "Release $NEW_VERSION completed successfully!" - print_status "Binaries uploaded to Gitea release" - upload_success=true - else - print_error "Release creation or binary upload failed" - upload_success=false - fi - - # Cleanup (only if upload was successful) - cleanup_release_binaries - - else - print_status "=== DEFAULT MODE ===" - - # Increment patch version for regular commits - increment_version "patch" - - # Create new git tag BEFORE compilation so version.h picks it up - if git tag "$NEW_VERSION" > /dev/null 2>&1; then - print_success "Created tag: $NEW_VERSION" - else - print_warning "Tag $NEW_VERSION already exists, removing and recreating..." - git tag -d "$NEW_VERSION" > /dev/null 2>&1 - git tag "$NEW_VERSION" > /dev/null 2>&1 - fi - - # Compile project (will now pick up the new tag) - compile_project - - # Commit and push (but skip tag creation since we already did it) - git_commit_and_push_no_tag - - print_success "Build and push completed successfully!" - print_status "Version $NEW_VERSION pushed to repository" - fi -} - -# Execute main function -main diff --git a/increment_and_push.sh b/increment_and_push.sh new file mode 100755 index 0000000..7f21286 --- /dev/null +++ b/increment_and_push.sh @@ -0,0 +1,331 @@ +#!/bin/bash +set -e + +# Colors for output +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"; } +print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } +print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } +print_error() { echo -e "${RED}[ERROR]${NC} $1"; } + +# Global variables +COMMIT_MESSAGE="" +RELEASE_MODE=false + +show_usage() { + echo "C-Relay Increment and Push Script" + echo "" + echo "Usage:" + echo " $0 \"commit message\" - Default: increment patch, commit & push" + echo " $0 -r \"commit message\" - Release: increment minor, create release" + echo "" + echo "Examples:" + echo " $0 \"Fixed event validation bug\"" + echo " $0 --release \"Major release with new features\"" + echo "" + echo "Default Mode (patch increment):" + echo " - Increment patch version (v1.2.3 → v1.2.4)" + echo " - Git add, commit with message, and push" + echo "" + echo "Release Mode (-r flag):" + echo " - Increment minor version, zero patch (v1.2.3 → v1.3.0)" + echo " - Git add, commit, push, and create Gitea release" + echo "" + echo "Requirements for Release Mode:" + echo " - Gitea token in ~/.gitea_token for release uploads" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -r|--release) + RELEASE_MODE=true + shift + ;; + -h|--help) + show_usage + exit 0 + ;; + *) + # First non-flag argument is the commit message + if [[ -z "$COMMIT_MESSAGE" ]]; then + COMMIT_MESSAGE="$1" + fi + shift + ;; + esac +done + +# Validate inputs +if [[ -z "$COMMIT_MESSAGE" ]]; then + print_error "Commit message is required" + echo "" + show_usage + exit 1 +fi + +# Check if we're in a git repository +check_git_repo() { + if ! git rev-parse --git-dir > /dev/null 2>&1; then + print_error "Not in a git repository" + exit 1 + fi +} + +# Function to get current version and increment appropriately +increment_version() { + local increment_type="$1" # "patch" or "minor" + + print_status "Getting current version..." + + # Get the highest version tag (not chronologically latest) + LATEST_TAG=$(git tag -l 'v*.*.*' | sort -V | tail -n 1 || echo "") + if [[ -z "$LATEST_TAG" ]]; then + LATEST_TAG="v0.0.0" + print_warning "No version tags found, starting from $LATEST_TAG" + fi + + # Extract version components (remove 'v' prefix) + VERSION=${LATEST_TAG#v} + + # Parse major.minor.patch using regex + 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" + print_error "Expected format: v0.1.0" + exit 1 + fi + + # Increment version based on type + if [[ "$increment_type" == "minor" ]]; then + # Minor release: increment minor, zero patch + NEW_MINOR=$((MINOR + 1)) + NEW_PATCH=0 + NEW_VERSION="v${MAJOR}.${NEW_MINOR}.${NEW_PATCH}" + print_status "Release mode: incrementing minor version" + else + # Default: increment patch + NEW_PATCH=$((PATCH + 1)) + NEW_VERSION="v${MAJOR}.${MINOR}.${NEW_PATCH}" + print_status "Default mode: incrementing patch version" + fi + + print_status "Current version: $LATEST_TAG" + print_status "New version: $NEW_VERSION" + + # Export for use in other functions + export NEW_VERSION +} + +# Function to commit and push changes +git_commit_and_push() { + print_status "Preparing git commit..." + + # Stage all changes + if git add . > /dev/null 2>&1; then + print_success "Staged all changes" + else + print_error "Failed to stage changes" + exit 1 + fi + + # Check if there are changes to commit + if git diff --staged --quiet; then + print_warning "No changes to commit" + else + # Commit changes + if git commit -m "$NEW_VERSION - $COMMIT_MESSAGE" > /dev/null 2>&1; then + print_success "Committed changes" + else + print_error "Failed to commit changes" + exit 1 + fi + fi + + # Create new git tag + if git tag "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Created tag: $NEW_VERSION" + else + print_warning "Tag $NEW_VERSION already exists" + fi + + # Push changes and tags + print_status "Pushing to remote repository..." + if git push > /dev/null 2>&1; then + print_success "Pushed changes" + else + print_error "Failed to push changes" + exit 1 + fi + + # Push only the new tag to avoid conflicts with existing tags + if git push origin "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Pushed tag: $NEW_VERSION" + else + print_warning "Tag push failed, trying force push..." + if git push --force origin "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Force-pushed updated tag: $NEW_VERSION" + else + print_error "Failed to push tag: $NEW_VERSION" + exit 1 + fi + fi +} + +# Function to commit and push changes without creating a tag (tag already created) +git_commit_and_push_no_tag() { + print_status "Preparing git commit..." + + # Stage all changes + if git add . > /dev/null 2>&1; then + print_success "Staged all changes" + else + print_error "Failed to stage changes" + exit 1 + fi + + # Check if there are changes to commit + if git diff --staged --quiet; then + print_warning "No changes to commit" + else + # Commit changes + if git commit -m "$NEW_VERSION - $COMMIT_MESSAGE" > /dev/null 2>&1; then + print_success "Committed changes" + else + print_error "Failed to commit changes" + exit 1 + fi + fi + + # Push changes and tags + print_status "Pushing to remote repository..." + if git push > /dev/null 2>&1; then + print_success "Pushed changes" + else + print_error "Failed to push changes" + exit 1 + fi + + # Push only the new tag to avoid conflicts with existing tags + if git push origin "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Pushed tag: $NEW_VERSION" + else + print_warning "Tag push failed, trying force push..." + if git push --force origin "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Force-pushed updated tag: $NEW_VERSION" + else + print_error "Failed to push tag: $NEW_VERSION" + exit 1 + fi + fi +} + +# Function to create Gitea release +create_gitea_release() { + print_status "Creating Gitea release..." + + # Check for Gitea token + if [[ ! -f "$HOME/.gitea_token" ]]; then + print_warning "No ~/.gitea_token found. Skipping release creation." + print_warning "Create ~/.gitea_token with your Gitea access token to enable releases." + return 0 + fi + + local token=$(cat "$HOME/.gitea_token" | tr -d '\n\r') + local api_url="https://git.laantungir.net/api/v1/repos/laantungir/c-relay" + + # Create release + print_status "Creating release $NEW_VERSION..." + local 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 + print_success "Created release $NEW_VERSION" + return 0 + elif echo "$response" | grep -q "already exists"; then + print_warning "Release $NEW_VERSION already exists" + return 0 + else + print_error "Failed to create release $NEW_VERSION" + print_error "Response: $response" + + # Try to check if the release exists anyway + print_status "Checking if release exists..." + local check_response=$(curl -s -H "Authorization: token $token" "$api_url/releases/tags/$NEW_VERSION") + if echo "$check_response" | grep -q '"id"'; then + print_warning "Release exists but creation response was unexpected" + return 0 + else + print_error "Release does not exist and creation failed" + return 1 + fi + fi +} + +# Main execution +main() { + print_status "C-Relay Increment and Push Script" + + # Check prerequisites + check_git_repo + + if [[ "$RELEASE_MODE" == true ]]; then + print_status "=== RELEASE MODE ===" + + # Increment minor version for releases + increment_version "minor" + + # Create new git tag BEFORE compilation so version.h picks it up + if git tag "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Created tag: $NEW_VERSION" + else + print_warning "Tag $NEW_VERSION already exists, removing and recreating..." + git tag -d "$NEW_VERSION" > /dev/null 2>&1 + git tag "$NEW_VERSION" > /dev/null 2>&1 + fi + + # Commit and push (but skip tag creation since we already did it) + git_commit_and_push_no_tag + + # Create Gitea release + if create_gitea_release; then + print_success "Release $NEW_VERSION completed successfully!" + else + print_error "Release creation failed" + fi + + else + print_status "=== DEFAULT MODE ===" + + # Increment patch version for regular commits + increment_version "patch" + + # Create new git tag BEFORE compilation so version.h picks it up + if git tag "$NEW_VERSION" > /dev/null 2>&1; then + print_success "Created tag: $NEW_VERSION" + else + print_warning "Tag $NEW_VERSION already exists, removing and recreating..." + git tag -d "$NEW_VERSION" > /dev/null 2>&1 + git tag "$NEW_VERSION" > /dev/null 2>&1 + fi + + # Commit and push (but skip tag creation since we already did it) + git_commit_and_push_no_tag + + print_success "Increment and push completed successfully!" + print_status "Version $NEW_VERSION pushed to repository" + fi +} + +# Execute main function +main \ No newline at end of file