Skip to content

Commit 774e69f

Browse files
authored
Merge pull request #132 from thawn/copilot/add-ffmpeg-install-timeout
Add timeout and retry for ffmpeg installation in CI workflows
2 parents da01406 + cf4908e commit 774e69f

File tree

6 files changed

+204
-50
lines changed

6 files changed

+204
-50
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
# Script to install ffmpeg on Linux with timeout and retry
3+
# Usage: install-ffmpeg-linux.sh
4+
5+
set -e
6+
7+
TIMEOUT_SECONDS=60
8+
URL="https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz"
9+
PATTERN="ffmpeg-*-amd64-static"
10+
11+
echo "Downloading and installing ffmpeg..."
12+
13+
# Try to download and install ffmpeg with timeout
14+
if timeout "$TIMEOUT_SECONDS" wget -q "$URL" && \
15+
timeout "$TIMEOUT_SECONDS" tar -xf ffmpeg-release-amd64-static.tar.xz; then
16+
sudo mv ${PATTERN}/ffmpeg /usr/local/bin/
17+
sudo mv ${PATTERN}/ffprobe /usr/local/bin/
18+
rm -rf ${PATTERN}*
19+
echo "ffmpeg installed successfully on first attempt"
20+
else
21+
echo "First attempt failed or timed out, retrying..."
22+
# Clean up any partial downloads
23+
rm -rf ${PATTERN}* 2>/dev/null || true
24+
# Retry with timeout
25+
if timeout "$TIMEOUT_SECONDS" wget -q "$URL" && \
26+
timeout "$TIMEOUT_SECONDS" tar -xf ffmpeg-release-amd64-static.tar.xz; then
27+
sudo mv ${PATTERN}/ffmpeg /usr/local/bin/
28+
sudo mv ${PATTERN}/ffprobe /usr/local/bin/
29+
rm -rf ${PATTERN}*
30+
echo "ffmpeg installed successfully on second attempt"
31+
else
32+
echo "ffmpeg installation failed after 2 attempts"
33+
exit 1
34+
fi
35+
fi
36+
37+
# Verify installation
38+
ffmpeg -version | head -n1
39+
echo "ffmpeg installation complete"
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/bin/bash
2+
# Script to install ffmpeg on macOS with timeout and retry
3+
# Usage: install-ffmpeg-macos.sh <target_dir>
4+
# Example: install-ffmpeg-macos.sh lib/mac
5+
6+
set -e
7+
8+
TARGET_DIR="${1:-lib/mac}"
9+
TIMEOUT_SECONDS=60
10+
URL="https://evermeet.cx/ffmpeg/getrelease/ffmpeg/zip"
11+
12+
echo "Downloading and installing ffmpeg for macOS..."
13+
14+
# Function to run command with timeout using Python
15+
# Only used internally with controlled commands (no user input)
16+
run_with_timeout() {
17+
local timeout=$1
18+
shift
19+
# Pass command as separate arguments to avoid injection issues
20+
python3 -c '
21+
import subprocess
22+
import sys
23+
24+
timeout = int(sys.argv[1])
25+
cmd = sys.argv[2:]
26+
27+
try:
28+
result = subprocess.run(
29+
cmd,
30+
timeout=timeout,
31+
capture_output=False
32+
)
33+
sys.exit(result.returncode)
34+
except subprocess.TimeoutExpired:
35+
sys.exit(124)
36+
' "$timeout" "$@"
37+
}
38+
39+
# Function to attempt download and extraction
40+
attempt_install() {
41+
local TEMP_DIR=$(mktemp -d)
42+
cd "$TEMP_DIR"
43+
44+
if run_with_timeout "$TIMEOUT_SECONDS" wget -q "$URL" -O ffmpeg.zip && \
45+
run_with_timeout "$TIMEOUT_SECONDS" unzip -q ffmpeg.zip; then
46+
chmod +x ffmpeg
47+
mv ffmpeg "$GITHUB_WORKSPACE/$TARGET_DIR/ffmpeg"
48+
cd "$GITHUB_WORKSPACE"
49+
chmod -R u+w "$TEMP_DIR" || true
50+
rm -rf "$TEMP_DIR"
51+
return 0
52+
else
53+
cd "$GITHUB_WORKSPACE"
54+
chmod -R u+w "$TEMP_DIR" || true
55+
rm -rf "$TEMP_DIR"
56+
return 1
57+
fi
58+
}
59+
60+
# First attempt
61+
if attempt_install; then
62+
echo "ffmpeg downloaded successfully on first attempt"
63+
else
64+
echo "First attempt failed or timed out, retrying..."
65+
# Retry
66+
if attempt_install; then
67+
echo "ffmpeg downloaded successfully on second attempt"
68+
else
69+
echo "ffmpeg installation failed after 2 attempts"
70+
exit 1
71+
fi
72+
fi
73+
74+
# Verify installation
75+
"$GITHUB_WORKSPACE/$TARGET_DIR/ffmpeg" -version | head -n1
76+
echo "ffmpeg installation complete"

.github/workflows/copilot-setup-steps.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,7 @@ jobs:
8282
tttool --help || { echo "Error: tttool installation failed"; exit 1; }
8383
8484
- name: Install ffmpeg (static build)
85-
run: |
86-
wget -q https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
87-
tar -xf ffmpeg-release-amd64-static.tar.xz
88-
sudo mv ffmpeg-*-amd64-static/ffmpeg /usr/local/bin/
89-
sudo mv ffmpeg-*-amd64-static/ffprobe /usr/local/bin/
90-
rm -rf ffmpeg-*-amd64-static*
85+
run: .github/scripts/install-ffmpeg-linux.sh
9186

9287
- name: Install Python dependencies
9388
run: |

.github/workflows/e2e-tests.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,7 @@ jobs:
9090
tttool --help || { echo "Error: tttool installation failed"; exit 1; }
9191
9292
- name: Install ffmpeg (static build)
93-
run: |
94-
wget -q https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
95-
tar -xf ffmpeg-release-amd64-static.tar.xz
96-
sudo mv ffmpeg-*-amd64-static/ffmpeg /usr/local/bin/
97-
sudo mv ffmpeg-*-amd64-static/ffprobe /usr/local/bin/
98-
rm -rf ffmpeg-*-amd64-static*
93+
run: .github/scripts/install-ffmpeg-linux.sh
9994

10095
- name: Install Python dependencies
10196
run: |

.github/workflows/release-executables.yml

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,76 @@ jobs:
6767
run: |
6868
Write-Host "Downloading ffmpeg for Windows"
6969
70-
# Download ffmpeg to temp directory
71-
$tempDir = New-Item -ItemType Directory -Path (Join-Path $env:TEMP "ffmpeg-temp-$(Get-Random)")
72-
$url = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip"
73-
$zipPath = Join-Path $tempDir "ffmpeg.zip"
74-
Invoke-WebRequest -Uri $url -OutFile $zipPath
75-
76-
# Extract to temp directory
77-
Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force
78-
79-
# Find and move ffmpeg.exe
80-
$ffmpegDir = Get-ChildItem -Path $tempDir -Directory -Filter "ffmpeg-*" | Select-Object -First 1
81-
Move-Item -Path (Join-Path $ffmpegDir.FullName "bin/ffmpeg.exe") -Destination lib/win/ffmpeg.exe -Force
70+
# Function to download and extract ffmpeg with timeout
71+
function Install-Ffmpeg {
72+
param([int]$TimeoutSeconds = 60)
73+
74+
$tempDir = New-Item -ItemType Directory -Path (Join-Path $env:TEMP "ffmpeg-temp-$(Get-Random)")
75+
$url = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip"
76+
$zipPath = Join-Path $tempDir "ffmpeg.zip"
77+
78+
try {
79+
# Download with timeout
80+
$job = Start-Job -ScriptBlock {
81+
param($url, $zipPath)
82+
Invoke-WebRequest -Uri $url -OutFile $zipPath
83+
} -ArgumentList $url, $zipPath
84+
85+
if (Wait-Job -Job $job -Timeout $TimeoutSeconds) {
86+
Receive-Job -Job $job
87+
Remove-Job -Job $job -Force
88+
89+
# Extract with timeout
90+
$extractJob = Start-Job -ScriptBlock {
91+
param($zipPath, $tempDir)
92+
Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force
93+
} -ArgumentList $zipPath, $tempDir
94+
95+
if (Wait-Job -Job $extractJob -Timeout $TimeoutSeconds) {
96+
Receive-Job -Job $extractJob
97+
Remove-Job -Job $extractJob -Force
98+
99+
# Find and move ffmpeg.exe
100+
$ffmpegDir = Get-ChildItem -Path $tempDir -Directory -Filter "ffmpeg-*" | Select-Object -First 1
101+
Move-Item -Path (Join-Path $ffmpegDir.FullName "bin/ffmpeg.exe") -Destination lib/win/ffmpeg.exe -Force
102+
return $true
103+
} else {
104+
Stop-Job -Job $extractJob
105+
Remove-Job -Job $extractJob -Force
106+
return $false
107+
}
108+
} else {
109+
Stop-Job -Job $job
110+
Remove-Job -Job $job -Force
111+
return $false
112+
}
113+
} finally {
114+
# Cleanup temp directory
115+
if (Test-Path $tempDir) {
116+
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
117+
}
118+
}
119+
}
82120
83-
# Cleanup temp directory
84-
Remove-Item -Recurse -Force $tempDir
121+
# Try first attempt
122+
Write-Host "Attempting to download ffmpeg (attempt 1)..."
123+
if (Install-Ffmpeg -TimeoutSeconds 60) {
124+
Write-Host "ffmpeg installed successfully on first attempt"
125+
} else {
126+
Write-Host "First attempt failed or timed out, retrying..."
127+
# Clean up any stale temp directories (Install-Ffmpeg cleans up its own temp dir in finally block)
128+
Get-ChildItem -Path $env:TEMP -Directory -Filter "ffmpeg-temp-*" -ErrorAction SilentlyContinue |
129+
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
130+
131+
# Retry
132+
Write-Host "Attempting to download ffmpeg (attempt 2)..."
133+
if (Install-Ffmpeg -TimeoutSeconds 60) {
134+
Write-Host "ffmpeg installed successfully on second attempt"
135+
} else {
136+
Write-Host "ffmpeg installation failed after 2 attempts"
137+
exit 1
138+
}
139+
}
85140
86141
# Verify
87142
lib/win/ffmpeg.exe -version
@@ -171,28 +226,7 @@ jobs:
171226
}
172227
173228
- name: Download ffmpeg for macOS
174-
run: |
175-
echo "Downloading ffmpeg for macOS"
176-
177-
# Create temp directory for extraction
178-
TEMP_DIR=$(mktemp -d)
179-
cd "$TEMP_DIR"
180-
181-
# Download ffmpeg static build for macOS
182-
wget -q "https://evermeet.cx/ffmpeg/getrelease/ffmpeg/zip" -O ffmpeg.zip
183-
unzip -q ffmpeg.zip
184-
185-
# Move binary to lib/mac
186-
chmod +x ffmpeg
187-
mv ffmpeg "$GITHUB_WORKSPACE/lib/mac/ffmpeg"
188-
189-
# Cleanup temp directory - change permissions first to ensure deletion succeeds
190-
cd "$GITHUB_WORKSPACE"
191-
chmod -R u+w "$TEMP_DIR" || true
192-
rm -rf "$TEMP_DIR"
193-
194-
# Verify
195-
lib/mac/ffmpeg -version
229+
run: .github/scripts/install-ffmpeg-macos.sh lib/mac
196230

197231
- name: Build macOS executable with PyInstaller
198232
run: |

setup_e2e_environment.sh

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,25 @@ print_success "tttool installed successfully"
138138
print_step "Step 4: Installing ffmpeg"
139139
if ! command -v ffmpeg &> /dev/null; then
140140
echo "=> Installing ffmpeg..." >> "$INSTALL_LOG"
141-
sudo apt-get install -y ffmpeg >> "$INSTALL_LOG" 2>&1
141+
# Try with 60 second timeout
142+
if timeout 60 sudo apt-get install -y ffmpeg >> "$INSTALL_LOG" 2>&1; then
143+
print_success "ffmpeg installed on first attempt"
144+
else
145+
echo "=> First attempt failed or timed out, retrying..." >> "$INSTALL_LOG"
146+
echo "Retrying ffmpeg installation (timeout or failure on first attempt)..."
147+
# Retry with 60 second timeout
148+
if timeout 60 sudo apt-get install -y ffmpeg >> "$INSTALL_LOG" 2>&1; then
149+
print_success "ffmpeg installed on second attempt"
150+
else
151+
print_error "ffmpeg installation failed after 2 attempts"
152+
echo "ffmpeg installation failed after 2 attempts" >> "$INSTALL_LOG"
153+
exit 1
154+
fi
155+
fi
156+
else
157+
print_success "ffmpeg already installed"
142158
fi
143159
ffmpeg -version | head -n1
144-
print_success "ffmpeg installed"
145160

146161
print_step "Step 5: Installing Python dependencies"
147162
PIP_LOG="/tmp/pip_install.log"

0 commit comments

Comments
 (0)