Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 36 additions & 19 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
tags:
- 'v*'
- 'Beta_v*'
workflow_dispatch:

# Reduce redundancy and improve caching
Expand All @@ -21,12 +22,9 @@ jobs:
- os: windows
arch: amd64
runs-on: windows-latest
- os: darwin
- os: macos
arch: amd64
runs-on: macos-latest
- os: darwin
arch: arm64
runs-on: macos-latest

runs-on: ${{ matrix.runs-on }}

Expand Down Expand Up @@ -68,7 +66,7 @@ jobs:
- name: Build GUI application
shell: bash
env:
GOOS: ${{ matrix.os }}
GOOS: ${{ matrix.os == 'macos' && 'darwin' || matrix.os }}
GOARCH: ${{ matrix.arch }}
run: |
# Ensure Fyne CLI is in PATH
Expand All @@ -93,13 +91,13 @@ jobs:

# Find and rename the exe (handle different possible names)
if [ -f "ScoreScrape Bridge.exe" ]; then
mv "ScoreScrape Bridge.exe" "ScoreScrape-Bridge-windows-${{ matrix.arch }}.exe"
mv "ScoreScrape Bridge.exe" "ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.exe"
elif [ -f "bridge.exe" ]; then
mv "bridge.exe" "ScoreScrape-Bridge-windows-${{ matrix.arch }}.exe"
mv "bridge.exe" "ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.exe"
elif [ -f "cmd/bridge/ScoreScrape Bridge.exe" ]; then
mv "cmd/bridge/ScoreScrape Bridge.exe" "ScoreScrape-Bridge-windows-${{ matrix.arch }}.exe"
mv "cmd/bridge/ScoreScrape Bridge.exe" "ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.exe"
elif [ -f "cmd/bridge/bridge.exe" ]; then
mv "cmd/bridge/bridge.exe" "ScoreScrape-Bridge-windows-${{ matrix.arch }}.exe"
mv "cmd/bridge/bridge.exe" "ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.exe"
else
echo "ERROR: Could not find built exe file"
find . -name "*.exe" -type f
Expand All @@ -121,12 +119,11 @@ jobs:
echo "=== Files in cmd/bridge ==="
ls -la cmd/bridge || true

ARCH_SUFFIX=${{ matrix.arch }}
# Find and copy the app bundle
if [ -d "ScoreScrape Bridge.app" ]; then
ditto "ScoreScrape Bridge.app" "ScoreScrape-Bridge-macOS-${ARCH_SUFFIX}.app"
ditto "ScoreScrape Bridge.app" "ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.app"
elif [ -d "cmd/bridge/ScoreScrape Bridge.app" ]; then
ditto "cmd/bridge/ScoreScrape Bridge.app" "ScoreScrape-Bridge-macOS-${ARCH_SUFFIX}.app"
ditto "cmd/bridge/ScoreScrape Bridge.app" "ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.app"
else
echo "ERROR: Could not find built app bundle"
find . -name "*.app" -type d
Expand All @@ -140,8 +137,8 @@ jobs:
with:
name: gui-${{ matrix.os }}-${{ matrix.arch }}
path: |
ScoreScrape-Bridge-windows-${{ matrix.arch }}.exe
ScoreScrape-Bridge-macOS-${{ matrix.arch }}.app
ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.exe
ScoreScrape-Bridge-${{ matrix.os }}-${{ matrix.arch }}.app
if-no-files-found: ignore
retention-days: 30

Expand All @@ -165,12 +162,33 @@ jobs:
path: artifacts
merge-multiple: true

- name: Debug artifacts
run: |
echo "=== All downloaded content ==="
find artifacts -type f -ls
find artifacts -type d -name "*.app" -ls

- name: Prepare release assets
run: |
mkdir -p release-assets
find artifacts -type f -name "ScoreScrape-Bridge-*" -exec cp {} release-assets/ \;
# Also copy .app directories
find artifacts -type d -name "*.app" -exec cp -r {} release-assets/ \;

# Debug: show what we downloaded
echo "=== Downloaded artifacts ==="
find artifacts -type f -name "ScoreScrape-Bridge-*" -o -name "*.exe" -o -name "*.app"
find artifacts -type d -name "*.app"

# Copy executable files
find artifacts -type f -name "ScoreScrape-Bridge-*.exe" -exec cp {} release-assets/ \;

# Copy .app directories and create zip archives for easier download
find artifacts -type d -name "ScoreScrape-Bridge-*.app" | while read app_path; do
app_name=$(basename "$app_path")
cp -r "$app_path" release-assets/
# Also create a zip for easier download
(cd release-assets && zip -r "${app_name}.zip" "$app_name")
done

echo "=== Final release assets ==="
ls -lh release-assets/

- name: Generate release notes
Expand All @@ -191,7 +209,6 @@ jobs:
### Downloads
- Windows (64-bit) - .exe
- macOS Intel (64-bit) - .app
- macOS Apple Silicon (ARM64) - .app

### Changes
$COMMITS"
Expand All @@ -203,6 +220,6 @@ jobs:
uses: softprops/action-gh-release@v1
with:
files: release-assets/*
body_file: release-notes.md
body_path: release-notes.md
draft: false
prerelease: false
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.7.2
0.7.3
60 changes: 49 additions & 11 deletions cmd/bridge/run_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,26 @@ Ex: /dev/<YOUR_SERIAL_PORT>:/dev/ttyUSB0

b := bridge.New(bridgeID)

// Track rapid disconnections to detect session takeover
var lastDisconnectTime time.Time
var rapidDisconnectCount int

b.SetConnectionLostHandler(func(err error) {
log.Printf("Connection lost: %v", err)
now := time.Now()

// Detect rapid disconnections (likely session takeover)
if !lastDisconnectTime.IsZero() && now.Sub(lastDisconnectTime) < 5*time.Second {
rapidDisconnectCount++
} else {
rapidDisconnectCount = 0
}
lastDisconnectTime = now

if rapidDisconnectCount >= 2 {
log.Printf("Connection lost: %v (rapid disconnections detected - possible session takeover, will auto-recover)", err)
} else {
log.Printf("Connection lost: %v (MQTT will auto-reconnect)", err)
}
})

// Enhanced reconnection logic with circuit breaker
Expand Down Expand Up @@ -100,7 +118,7 @@ Ex: /dev/<YOUR_SERIAL_PORT>:/dev/ttyUSB0
lastSuccessTime = time.Now()

errChan := make(chan error, 1)
healthCheckTicker := time.NewTicker(30 * time.Second)
healthCheckTicker := time.NewTicker(60 * time.Second) // Increased from 30s to give MQTT more time
defer healthCheckTicker.Stop()

go func() {
Expand All @@ -112,7 +130,7 @@ Ex: /dev/<YOUR_SERIAL_PORT>:/dev/ttyUSB0

// Health monitoring loop
healthCheckFailures := 0
maxHealthCheckFailures := 5
maxHealthCheckFailures := 10 // Increased from 5 to be more tolerant

for {
select {
Expand Down Expand Up @@ -159,18 +177,38 @@ Ex: /dev/<YOUR_SERIAL_PORT>:/dev/ttyUSB0
goto reconnectLoop
}
case <-healthCheckTicker.C:
// Periodic health check
// Periodic health check with smarter MQTT reconnection awareness
if !b.IsHealthy() {
healthCheckFailures++
log.Printf("Health check failed (%d/%d)", healthCheckFailures, maxHealthCheckFailures)

if healthCheckFailures >= maxHealthCheckFailures {
log.Printf("Device appears to be in unrecoverable state after %d failed health checks", healthCheckFailures)
b.Disconnect()
// Check if MQTT is actively attempting to auto-reconnect
isMQTTReconnecting := b.IsMQTTReconnecting()
disconnectedDuration, reconnectAttempts := b.GetMQTTReconnectionInfo()

// Be more tolerant if MQTT is actively reconnecting
effectiveMaxFailures := maxHealthCheckFailures
if isMQTTReconnecting {
// Give MQTT more time to recover during session takeover scenarios
effectiveMaxFailures = maxHealthCheckFailures * 2
log.Printf("Health check failed (%d/%d) - MQTT reconnecting (disconnected for %v, attempt %d)",
healthCheckFailures, effectiveMaxFailures, disconnectedDuration, reconnectAttempts)
} else {
log.Printf("Health check failed (%d/%d)", healthCheckFailures, effectiveMaxFailures)
}

// Force a longer delay and reset to try recovery
consecutiveFailures = maxConsecutiveFailures - 1 // Trigger near-circuit-breaker behavior
goto reconnectLoop
if healthCheckFailures >= effectiveMaxFailures {
if isMQTTReconnecting && disconnectedDuration < 10*time.Minute {
// MQTT is still trying and hasn't been disconnected too long
// Log but don't force reconnection yet
log.Printf("MQTT actively reconnecting for %v - allowing more time before forcing reset", disconnectedDuration)
} else {
log.Printf("Device appears to be in unrecoverable state after %d failed health checks", healthCheckFailures)
b.Disconnect()

// Force a longer delay and reset to try recovery
consecutiveFailures = maxConsecutiveFailures - 1 // Trigger near-circuit-breaker behavior
goto reconnectLoop
}
}
} else {
// Reset health check failures on successful check
Expand Down
Loading
Loading