name: Update Cursor Version on: schedule: - cron: '0 12 * * *' # Run daily at 12:00 UTC workflow_dispatch: # Allow manual triggering jobs: update-cursor: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Nix uses: cachix/install-nix-action@v25 with: nix_path: nixpkgs=channel:nixpkgs-unstable - name: Install dependencies run: | nix-env -iA nixpkgs.curl nixpkgs.jq nixpkgs.nix-prefetch-url - name: Get latest Cursor version id: get_version run: | set -euo pipefail # Get the latest version from Cursor's API redirect with retries for i in {1..3}; do echo "Attempt $i: Fetching latest version from Cursor API..." if REDIRECT_URL=$(curl -s -I --max-time 30 "https://api2.cursor.sh/updates/download/golden/linux-x64/cursor/latest" | grep -i location | cut -d' ' -f2 | tr -d '\r\n' 2>/dev/null); then if [[ -n "$REDIRECT_URL" ]]; then # Extract version from URL like: .../Cursor-1.7.39-x86_64.AppImage LATEST_VERSION=$(echo "$REDIRECT_URL" | grep -o 'Cursor-[0-9]\+\.[0-9]\+\.[0-9]\+' | sed 's/Cursor-//' 2>/dev/null) if [[ -n "$LATEST_VERSION" ]]; then echo "Latest version: $LATEST_VERSION" echo "version=$LATEST_VERSION" >> $GITHUB_OUTPUT break fi fi fi if [[ $i -eq 3 ]]; then echo "Error: Failed to fetch latest version after 3 attempts" exit 1 fi echo "Retrying in 10 seconds..." sleep 10 done # Get current version from flake.nix CURRENT_VERSION=$(grep -o 'version = "[^"]*"' flake.nix | head -1 | cut -d'"' -f2) echo "Current version: $CURRENT_VERSION" echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT - name: Check if update is needed id: check_update run: | if [ "${{ steps.get_version.outputs.version }}" != "${{ steps.get_version.outputs.current_version }}" ]; then echo "update_needed=true" >> $GITHUB_OUTPUT echo "Update needed: ${{ steps.get_version.outputs.current_version }} -> ${{ steps.get_version.outputs.version }}" else echo "update_needed=false" >> $GITHUB_OUTPUT echo "No update needed. Current version is up to date." fi - name: Update flake.nix if: steps.check_update.outputs.update_needed == 'true' run: | set -euo pipefail VERSION="${{ steps.get_version.outputs.version }}" # Construct the download URL for the AppImage APPIMAGE_URL="https://api2.cursor.sh/updates/download/golden/linux-x64/cursor/$VERSION" echo "Fetching AppImage from: $APPIMAGE_URL" # Get the actual download URL by following redirects ACTUAL_URL=$(curl -s -I "$APPIMAGE_URL" | grep -i location | cut -d' ' -f2 | tr -d '\r\n') if [[ -z "$ACTUAL_URL" ]]; then echo "Error: Could not get actual download URL" exit 1 fi echo "Actual download URL: $ACTUAL_URL" # Get the SHA256 hash with retries for i in {1..3}; do echo "Attempt $i: Calculating SHA256 hash..." if SHA256=$(nix-prefetch-url --type sha256 "$ACTUAL_URL" 2>/dev/null); then if [[ "$SHA256" != "" && ${#SHA256} -eq 52 ]]; then echo "SHA256: $SHA256" break fi fi if [[ $i -eq 3 ]]; then echo "Error: Failed to calculate SHA256 after 3 attempts" exit 1 fi echo "Retrying in 5 seconds..." sleep 5 done # Create backup cp flake.nix flake.nix.backup # Update flake.nix with new version and hash - be more specific to avoid replacing nixpkgs URL sed -i "s/version = \"[^\"]*\" # Will be updated by GitHub Actions/version = \"$VERSION\"/" flake.nix sed -i "/buildCursor = {/,/};/s|url = \"[^\"]*\"|url = \"$ACTUAL_URL\"|" flake.nix sed -i "/buildCursor = {/,/};/s/sha256 = \"[^\"]*\"/sha256 = \"$SHA256\"/" flake.nix echo "Updated flake.nix with version $VERSION" - name: Test the updated flake if: steps.check_update.outputs.update_needed == 'true' run: | nix flake check nix build .#cursor --dry-run - name: Commit and push changes if: steps.check_update.outputs.update_needed == 'true' run: | git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add flake.nix git commit -m "Update Cursor to version ${{ steps.get_version.outputs.version }}" git push - name: Create release if: steps.check_update.outputs.update_needed == 'true' uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: "cursor-${{ steps.get_version.outputs.version }}" release_name: "Cursor ${{ steps.get_version.outputs.version }}" body: | Automated update to Cursor version ${{ steps.get_version.outputs.version }} Changes: - Updated version to ${{ steps.get_version.outputs.version }} - Updated download URL and SHA256 hash - Tested flake build draft: false prerelease: false