deploy
This commit is contained in:
parent
093936cf4a
commit
941b59ba8e
9 changed files with 424 additions and 312 deletions
|
|
@ -426,6 +426,8 @@ jobs:
|
||||||
- name: Fix Permissions and Reload Nginx
|
- name: Fix Permissions and Reload Nginx
|
||||||
run: |
|
run: |
|
||||||
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
||||||
|
# Set a global timeout for the entire step (20 minutes max)
|
||||||
|
timeout 1200 bash -c '
|
||||||
set -e
|
set -e
|
||||||
echo "🔧 Setting correct permissions for web files..."
|
echo "🔧 Setting correct permissions for web files..."
|
||||||
chown -R www-data:www-data /var/www/mnemo_cards
|
chown -R www-data:www-data /var/www/mnemo_cards
|
||||||
|
|
@ -434,17 +436,32 @@ jobs:
|
||||||
|
|
||||||
# Pre-reload diagnostics
|
# Pre-reload diagnostics
|
||||||
echo "🔍 Pre-reload diagnostics..."
|
echo "🔍 Pre-reload diagnostics..."
|
||||||
|
|
||||||
|
# Check running processes BEFORE reload
|
||||||
|
echo "📊 Processes BEFORE reload:"
|
||||||
|
echo "Forgejo processes:"
|
||||||
|
pgrep -f forgejo || echo "No forgejo processes"
|
||||||
|
echo "Backend processes:"
|
||||||
|
pgrep -f mnemo_cards_server || echo "No backend processes"
|
||||||
|
echo "Nginx processes:"
|
||||||
|
pgrep -f nginx || echo "No nginx processes"
|
||||||
|
|
||||||
echo "📊 Current nginx status:"
|
echo "📊 Current nginx status:"
|
||||||
sudo systemctl status nginx --no-pager || true
|
sudo systemctl status nginx --no-pager || true
|
||||||
|
|
||||||
|
# Check system load and memory
|
||||||
|
echo "📊 System BEFORE reload:"
|
||||||
|
uptime || true
|
||||||
|
free -h || true
|
||||||
|
|
||||||
echo "🌐 Testing upstream connectivity before reload:"
|
echo "🌐 Testing upstream connectivity before reload:"
|
||||||
if nc -z 127.0.0.1 3000 2>/dev/null; then
|
if timeout 10 nc -z 127.0.0.1 3000 2>/dev/null; then
|
||||||
echo "✅ Forgejo (port 3000): reachable"
|
echo "✅ Forgejo (port 3000): reachable"
|
||||||
else
|
else
|
||||||
echo "❌ Forgejo (port 3000): NOT reachable before reload!"
|
echo "❌ Forgejo (port 3000): NOT reachable before reload!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if nc -z 127.0.0.1 8081 2>/dev/null; then
|
if timeout 10 nc -z 127.0.0.1 8081 2>/dev/null; then
|
||||||
echo "✅ Backend (port 8081): reachable"
|
echo "✅ Backend (port 8081): reachable"
|
||||||
else
|
else
|
||||||
echo "❌ Backend (port 8081): NOT reachable before reload!"
|
echo "❌ Backend (port 8081): NOT reachable before reload!"
|
||||||
|
|
@ -452,17 +469,17 @@ jobs:
|
||||||
|
|
||||||
echo "🌐 Testing site accessibility before reload:"
|
echo "🌐 Testing site accessibility before reload:"
|
||||||
for site in "https://mnemo-cards.online/" "https://code.mnemo-cards.online/" "https://vscode.mnemo-cards.online/"; do
|
for site in "https://mnemo-cards.online/" "https://code.mnemo-cards.online/" "https://vscode.mnemo-cards.online/"; do
|
||||||
if curl -I --max-time 5 "$site" 2>/dev/null | grep -q "200\|301\|302"; then
|
if timeout 15 curl -I --max-time 10 "$site" 2>/dev/null | grep -q "200\|301\|302"; then
|
||||||
echo "✅ $site accessible before reload"
|
echo "✅ $site accessible before reload"
|
||||||
else
|
else
|
||||||
echo "⚠️ $site not accessible before reload"
|
echo "⚠️ $site not accessible before reload"
|
||||||
curl -I --max-time 5 "$site" || true
|
timeout 10 curl -I --max-time 5 "$site" || echo "Pre-reload check failed"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "🔄 Reloading nginx to serve new web app..."
|
echo "🔄 Reloading nginx to serve new web app..."
|
||||||
echo "📋 Current nginx configuration test:"
|
echo "📋 Current nginx configuration test:"
|
||||||
if sudo nginx -t 2>&1; then
|
if timeout 30 sudo nginx -t 2>&1; then
|
||||||
echo "✅ nginx configuration is valid"
|
echo "✅ nginx configuration is valid"
|
||||||
echo "🚀 Executing nginx reload..."
|
echo "🚀 Executing nginx reload..."
|
||||||
sudo systemctl reload nginx
|
sudo systemctl reload nginx
|
||||||
|
|
@ -483,40 +500,97 @@ jobs:
|
||||||
echo "⏳ Waiting for services to stabilize after reload..."
|
echo "⏳ Waiting for services to stabilize after reload..."
|
||||||
sleep 5
|
sleep 5
|
||||||
|
|
||||||
|
# IMMEDIATE upstream check after reload
|
||||||
|
echo "🔍 IMMEDIATE upstream check after reload (0 seconds wait):"
|
||||||
|
if timeout 5 nc -z 127.0.0.1 3000 2>/dev/null; then
|
||||||
|
echo "✅ Forgejo (port 3000): reachable immediately after reload"
|
||||||
|
else
|
||||||
|
echo "❌ CRITICAL: Forgejo (port 3000): NOT reachable immediately after reload!"
|
||||||
|
echo "🔍 Checking forgejo process:"
|
||||||
|
pgrep -f forgejo || echo "No forgejo process found"
|
||||||
|
ps aux | grep forgejo | grep -v grep || echo "No forgejo in ps"
|
||||||
|
echo "🔍 Checking forgejo service status:"
|
||||||
|
timeout 10 sudo systemctl status forgejo --no-pager || echo "Could not get forgejo status"
|
||||||
|
echo "🔍 Checking if port 3000 is bound:"
|
||||||
|
ss -tlnp | grep :3000 || echo "Port 3000 not bound"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if timeout 5 nc -z 127.0.0.1 8081 2>/dev/null; then
|
||||||
|
echo "✅ Backend (port 8081): reachable immediately after reload"
|
||||||
|
else
|
||||||
|
echo "❌ CRITICAL: Backend (port 8081): NOT reachable immediately after reload!"
|
||||||
|
echo "🔍 Checking backend process:"
|
||||||
|
pgrep -f mnemo_cards_server || echo "No backend process found"
|
||||||
|
ps aux | grep mnemo_cards_server | grep -v grep || echo "No backend in ps"
|
||||||
|
echo "🔍 Checking backend service status:"
|
||||||
|
timeout 10 sudo systemctl status mnemo_cards_server --no-pager || echo "Could not get backend status"
|
||||||
|
echo "🔍 Checking if port 8081 is bound:"
|
||||||
|
ss -tlnp | grep :8081 || echo "Port 8081 not bound"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for OOM killer activity
|
||||||
|
echo "🚨 Checking for OOM killer activity:"
|
||||||
|
timeout 10 sudo dmesg | grep -i "oom\|kill" | tail -5 || echo "No OOM killer activity detected"
|
||||||
|
|
||||||
|
# Check systemd logs for service events around reload time
|
||||||
|
echo "📋 Checking systemd journal for recent service events:"
|
||||||
|
timeout 10 sudo journalctl --since "5 minutes ago" --no-pager -u nginx -u mnemo_cards_server --grep "(start|stop|reload|fail)" | tail -10 || echo "No recent systemd events"
|
||||||
|
|
||||||
# Check nginx logs for errors after reload
|
# Check nginx logs for errors after reload
|
||||||
echo "📋 Checking nginx error logs after reload:"
|
echo "📋 Checking nginx error logs after reload:"
|
||||||
sudo tail -20 /var/log/nginx/error.log || true
|
timeout 10 sudo tail -30 /var/log/nginx/error.log | grep -E "(connect|upstream|error)" | tail -10 || echo "No recent upstream errors in nginx logs"
|
||||||
|
|
||||||
|
# Check running processes AFTER reload
|
||||||
|
echo "📊 Processes AFTER reload:"
|
||||||
|
echo "Forgejo processes:"
|
||||||
|
pgrep -f forgejo || echo "No forgejo processes"
|
||||||
|
echo "Backend processes:"
|
||||||
|
pgrep -f mnemo_cards_server || echo "No backend processes"
|
||||||
|
echo "Nginx processes:"
|
||||||
|
pgrep -f nginx || echo "No nginx processes"
|
||||||
|
|
||||||
|
# Check system load and memory after reload
|
||||||
|
echo "📊 System AFTER reload:"
|
||||||
|
uptime || true
|
||||||
|
free -h || true
|
||||||
|
|
||||||
# Check nginx status again
|
# Check nginx status again
|
||||||
echo "📊 Nginx status after reload:"
|
echo "📊 Nginx status after reload:"
|
||||||
sudo systemctl status nginx --no-pager || true
|
timeout 15 sudo systemctl status nginx --no-pager || echo "Could not get nginx status"
|
||||||
|
|
||||||
# Check all services status
|
# Check all services status
|
||||||
echo "📊 Checking service statuses after nginx reload..."
|
echo "📊 Checking service statuses after nginx reload..."
|
||||||
|
|
||||||
# Check nginx
|
# Check nginx
|
||||||
if sudo systemctl is-active --quiet nginx; then
|
echo "🔍 Checking nginx status..."
|
||||||
|
if timeout 30 sudo systemctl is-active --quiet nginx; then
|
||||||
echo "✅ nginx: running"
|
echo "✅ nginx: running"
|
||||||
# Check loaded configuration
|
# Check loaded configuration
|
||||||
echo "📋 Loaded nginx sites:"
|
echo "📋 Loaded nginx sites:"
|
||||||
ls -la /etc/nginx/sites-enabled/ || true
|
timeout 10 ls -la /etc/nginx/sites-enabled/ || echo "Could not list sites"
|
||||||
else
|
else
|
||||||
echo "❌ nginx: not running"
|
echo "❌ nginx: not running or status check timed out"
|
||||||
sudo systemctl status nginx --no-pager || true
|
timeout 15 sudo systemctl status nginx --no-pager || echo "Could not get nginx status"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check backend
|
# Check backend
|
||||||
if sudo systemctl is-active --quiet mnemo_cards_server; then
|
echo "🔍 Checking backend status..."
|
||||||
|
if timeout 30 sudo systemctl is-active --quiet mnemo_cards_server; then
|
||||||
echo "✅ backend: running"
|
echo "✅ backend: running"
|
||||||
else
|
else
|
||||||
echo "❌ backend: not running"
|
echo "❌ backend: not running or status check timed out"
|
||||||
sudo systemctl status mnemo_cards_server --no-pager || true
|
timeout 15 sudo systemctl status mnemo_cards_server --no-pager || echo "Could not get backend status"
|
||||||
# Try to start it if it's stopped
|
# Try to start it if it's stopped
|
||||||
echo "🚀 Attempting to start backend..."
|
echo "🚀 Attempting to start backend..."
|
||||||
sudo systemctl start mnemo_cards_server || true
|
if timeout 30 sudo systemctl start mnemo_cards_server; then
|
||||||
sleep 2
|
sleep 3
|
||||||
if sudo systemctl is-active --quiet mnemo_cards_server; then
|
if timeout 30 sudo systemctl is-active --quiet mnemo_cards_server; then
|
||||||
echo "✅ backend: started successfully"
|
echo "✅ backend: started successfully"
|
||||||
|
else
|
||||||
|
echo "❌ backend: failed to start"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "❌ backend start command timed out"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -559,35 +633,43 @@ jobs:
|
||||||
|
|
||||||
# Check network connectivity to upstream services
|
# Check network connectivity to upstream services
|
||||||
echo "🌐 Checking upstream connectivity..."
|
echo "🌐 Checking upstream connectivity..."
|
||||||
if nc -z 127.0.0.1 3000 2>/dev/null; then
|
if timeout 10 nc -z 127.0.0.1 3000 2>/dev/null; then
|
||||||
echo "✅ Forgejo (port 3000): reachable"
|
echo "✅ Forgejo (port 3000): reachable"
|
||||||
else
|
else
|
||||||
echo "⚠️ Forgejo (port 3000): not reachable"
|
echo "⚠️ Forgejo (port 3000): not reachable or check timed out"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if nc -z 127.0.0.1 8081 2>/dev/null; then
|
if timeout 10 nc -z 127.0.0.1 8081 2>/dev/null; then
|
||||||
echo "✅ Backend (port 8081): reachable"
|
echo "✅ Backend (port 8081): reachable"
|
||||||
else
|
else
|
||||||
echo "⚠️ Backend (port 8081): not reachable"
|
echo "⚠️ Backend (port 8081): not reachable or check timed out"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Wait a bit more before testing sites
|
# Wait a bit more before testing sites
|
||||||
sleep 3
|
sleep 3
|
||||||
|
|
||||||
# Test site accessibility with retries
|
# Test site accessibility with retries and timeouts
|
||||||
echo "🌐 Testing site accessibility..."
|
echo "🌐 Testing site accessibility..."
|
||||||
for site in "https://mnemo-cards.online/" "https://code.mnemo-cards.online/" "https://vscode.mnemo-cards.online/"; do
|
for site in "https://mnemo-cards.online/" "https://code.mnemo-cards.online/" "https://vscode.mnemo-cards.online/"; do
|
||||||
for attempt in {1..3}; do
|
for attempt in {1..3}; do
|
||||||
if curl -I --max-time 10 "$site" 2>/dev/null | grep -q "200\|301\|302"; then
|
echo "🔍 Testing $site (attempt $attempt)..."
|
||||||
|
if timeout 15 curl -I --max-time 10 "$site" 2>/dev/null | grep -q "200\|301\|302"; then
|
||||||
echo "✅ $site accessible (attempt $attempt)"
|
echo "✅ $site accessible (attempt $attempt)"
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
|
CURL_EXIT=$?
|
||||||
|
if [ $CURL_EXIT -eq 124 ]; then
|
||||||
|
echo "⏰ Timeout testing $site (attempt $attempt)"
|
||||||
|
else
|
||||||
|
echo "❌ $site returned error (attempt $attempt)"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $attempt -eq 3 ]; then
|
if [ $attempt -eq 3 ]; then
|
||||||
echo "❌ $site not accessible after 3 attempts"
|
echo "❌ $site not accessible after 3 attempts"
|
||||||
curl -I --max-time 5 "$site" || true
|
timeout 10 curl -I --max-time 5 "$site" || echo "Final check also failed"
|
||||||
else
|
else
|
||||||
echo "⏳ $site attempt $attempt failed, retrying..."
|
echo "⏳ $site attempt $attempt failed, retrying in 3 seconds..."
|
||||||
sleep 2
|
sleep 3
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
@ -599,6 +681,7 @@ jobs:
|
||||||
sudo nginx -t || true
|
sudo nginx -t || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
' || echo "Step timed out after 20 minutes"
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
final-verification:
|
final-verification:
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{"format-version":[1,0,0],"native-assets":{}}
|
|
||||||
Binary file not shown.
|
|
@ -38,6 +38,6 @@ _flutter.buildConfig = {"engineRevision":"d3d45dcf251823c1769909cd43698d126db38d
|
||||||
|
|
||||||
_flutter.loader.load({
|
_flutter.loader.load({
|
||||||
serviceWorkerSettings: {
|
serviceWorkerSettings: {
|
||||||
serviceWorkerVersion: "1447658096"
|
serviceWorkerVersion: "1977728131"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
|
||||||
const TEMP = 'flutter-temp-cache';
|
const TEMP = 'flutter-temp-cache';
|
||||||
const CACHE_NAME = 'flutter-app-cache';
|
const CACHE_NAME = 'flutter-app-cache';
|
||||||
|
|
||||||
const RESOURCES = {"flutter_bootstrap.js": "d27e18c64dd0c621145dfce18b96c0a5",
|
const RESOURCES = {"flutter_bootstrap.js": "0dabf8154ea9f84b34d53a38f6c13480",
|
||||||
"version.json": "28542ad255b8c0abed0b83ec843a2417",
|
"version.json": "28542ad255b8c0abed0b83ec843a2417",
|
||||||
"index.html": "bea65743d155de5b43dd38c2a02fa14d",
|
"index.html": "bea65743d155de5b43dd38c2a02fa14d",
|
||||||
"/": "bea65743d155de5b43dd38c2a02fa14d",
|
"/": "bea65743d155de5b43dd38c2a02fa14d",
|
||||||
"main.dart.js": "efd61556cfb88ace9d0e42213140da3c",
|
"main.dart.js": "3dc6e8335d2ee3822f44330f6c3e7b62",
|
||||||
"flutter.js": "888483df48293866f9f41d3d9274a779",
|
"flutter.js": "888483df48293866f9f41d3d9274a779",
|
||||||
"mnemo_cards/fonts/Nunito-VariableFont_wght.ttf": "ea0ad4c72a135f9a43ec7bb83f2469aa",
|
"mnemo_cards/fonts/Nunito-VariableFont_wght.ttf": "ea0ad4c72a135f9a43ec7bb83f2469aa",
|
||||||
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
|
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -7,6 +7,8 @@
|
||||||
/// - JSON API response format
|
/// - JSON API response format
|
||||||
/// - API versioning via URL prefix
|
/// - API versioning via URL prefix
|
||||||
class ApiConfigV2 {
|
class ApiConfigV2 {
|
||||||
|
/// App version from pubspec.yaml
|
||||||
|
static const String appVersion = '1.0.0';
|
||||||
/// Base URL for API v2
|
/// Base URL for API v2
|
||||||
/// All v2 endpoints are prefixed with /api/v2
|
/// All v2 endpoints are prefixed with /api/v2
|
||||||
static String get baseUrl {
|
static String get baseUrl {
|
||||||
|
|
|
||||||
|
|
@ -851,6 +851,15 @@ class _AuthPageState extends State<AuthPage> {
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Version ${ApiConfigV2.appVersion}',
|
||||||
|
style: theme.textTheme.bodySmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -306,5 +306,19 @@ void main() {
|
||||||
// This is tested by ensuring the code compiles without deprecation warnings
|
// This is tested by ensuring the code compiles without deprecation warnings
|
||||||
expect(find.byType(Container), findsWidgets);
|
expect(find.byType(Container), findsWidgets);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('displays app version at bottom of auth page', (tester) async {
|
||||||
|
await tester.pumpWidget(createTestWidget(const AuthPage()));
|
||||||
|
|
||||||
|
// Verify version text is displayed
|
||||||
|
expect(find.text('Version 1.0.0'), findsOneWidget);
|
||||||
|
|
||||||
|
// Verify version text uses proper styling
|
||||||
|
final versionFinder = find.text('Version 1.0.0');
|
||||||
|
final versionWidget = tester.widget<Text>(versionFinder);
|
||||||
|
expect(versionWidget.style?.fontWeight, FontWeight.w500);
|
||||||
|
expect(versionWidget.style?.color, isNotNull);
|
||||||
|
expect(versionWidget.textAlign, TextAlign.center);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue