This commit is contained in:
Dmitry 2025-11-27 20:30:52 +03:00
parent 093936cf4a
commit 941b59ba8e
9 changed files with 424 additions and 312 deletions

View file

@ -426,6 +426,8 @@ jobs:
- name: Fix Permissions and Reload Nginx
run: |
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
echo "🔧 Setting correct permissions for web files..."
chown -R www-data:www-data /var/www/mnemo_cards
@ -434,17 +436,32 @@ jobs:
# 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:"
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:"
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"
else
echo "❌ Forgejo (port 3000): NOT reachable before reload!"
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"
else
echo "❌ Backend (port 8081): NOT reachable before reload!"
@ -452,17 +469,17 @@ jobs:
echo "🌐 Testing site accessibility before reload:"
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"
else
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
done
echo "🔄 Reloading nginx to serve new web app..."
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 "🚀 Executing nginx reload..."
sudo systemctl reload nginx
@ -483,40 +500,97 @@ jobs:
echo "⏳ Waiting for services to stabilize after reload..."
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
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
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
echo "📊 Checking service statuses after nginx reload..."
# 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"
# Check loaded configuration
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
echo "❌ nginx: not running"
sudo systemctl status nginx --no-pager || true
echo "❌ nginx: not running or status check timed out"
timeout 15 sudo systemctl status nginx --no-pager || echo "Could not get nginx status"
fi
# 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"
else
echo "❌ backend: not running"
sudo systemctl status mnemo_cards_server --no-pager || true
echo "❌ backend: not running or status check timed out"
timeout 15 sudo systemctl status mnemo_cards_server --no-pager || echo "Could not get backend status"
# Try to start it if it's stopped
echo "🚀 Attempting to start backend..."
sudo systemctl start mnemo_cards_server || true
sleep 2
if sudo systemctl is-active --quiet mnemo_cards_server; then
echo "✅ backend: started successfully"
if timeout 30 sudo systemctl start mnemo_cards_server; then
sleep 3
if timeout 30 sudo systemctl is-active --quiet mnemo_cards_server; then
echo "✅ backend: started successfully"
else
echo "❌ backend: failed to start"
fi
else
echo "❌ backend start command timed out"
fi
fi
@ -559,35 +633,43 @@ jobs:
# Check network connectivity to upstream services
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"
else
echo "⚠️ Forgejo (port 3000): not reachable"
echo "⚠️ Forgejo (port 3000): not reachable or check timed out"
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"
else
echo "⚠️ Backend (port 8081): not reachable"
echo "⚠️ Backend (port 8081): not reachable or check timed out"
fi
# Wait a bit more before testing sites
sleep 3
# Test site accessibility with retries
# Test site accessibility with retries and timeouts
echo "🌐 Testing site accessibility..."
for site in "https://mnemo-cards.online/" "https://code.mnemo-cards.online/" "https://vscode.mnemo-cards.online/"; 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)"
break
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
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
echo "⏳ $site attempt $attempt failed, retrying..."
sleep 2
echo "⏳ $site attempt $attempt failed, retrying in 3 seconds..."
sleep 3
fi
fi
done
@ -599,6 +681,7 @@ jobs:
sudo nginx -t || true
exit 1
fi
' || echo "Step timed out after 20 minutes"
ENDSSH
final-verification:

View file

@ -1 +0,0 @@
{"format-version":[1,0,0],"native-assets":{}}

View file

@ -38,6 +38,6 @@ _flutter.buildConfig = {"engineRevision":"d3d45dcf251823c1769909cd43698d126db38d
_flutter.loader.load({
serviceWorkerSettings: {
serviceWorkerVersion: "1447658096"
serviceWorkerVersion: "1977728131"
}
});

View file

@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {"flutter_bootstrap.js": "d27e18c64dd0c621145dfce18b96c0a5",
const RESOURCES = {"flutter_bootstrap.js": "0dabf8154ea9f84b34d53a38f6c13480",
"version.json": "28542ad255b8c0abed0b83ec843a2417",
"index.html": "bea65743d155de5b43dd38c2a02fa14d",
"/": "bea65743d155de5b43dd38c2a02fa14d",
"main.dart.js": "efd61556cfb88ace9d0e42213140da3c",
"main.dart.js": "3dc6e8335d2ee3822f44330f6c3e7b62",
"flutter.js": "888483df48293866f9f41d3d9274a779",
"mnemo_cards/fonts/Nunito-VariableFont_wght.ttf": "ea0ad4c72a135f9a43ec7bb83f2469aa",
"favicon.png": "5dcef449791fa27946b3d35ad8803796",

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,8 @@
/// - JSON API response format
/// - API versioning via URL prefix
class ApiConfigV2 {
/// App version from pubspec.yaml
static const String appVersion = '1.0.0';
/// Base URL for API v2
/// All v2 endpoints are prefixed with /api/v2
static String get baseUrl {

View file

@ -851,6 +851,15 @@ class _AuthPageState extends State<AuthPage> {
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,
),
],
),

View file

@ -306,5 +306,19 @@ void main() {
// This is tested by ensuring the code compiles without deprecation warnings
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);
});
});
}