diff --git a/.forgejo/workflows b/.forgejo/workflows deleted file mode 120000 index df1658a..0000000 --- a/.forgejo/workflows +++ /dev/null @@ -1 +0,0 @@ -../tools/ci \ No newline at end of file diff --git a/.forgejo/workflows/ci-backend.yml b/.forgejo/workflows/ci-backend.yml new file mode 100644 index 0000000..59387fc --- /dev/null +++ b/.forgejo/workflows/ci-backend.yml @@ -0,0 +1,127 @@ +name: Backend CI + +on: + push: + branches: [ main, master ] + paths: + - 'mnemo_cards_backend/**' + - 'mnemo_cards_common/**' + - 'mnemo_cards_common_backend/**' + pull_request: + branches: [ main, master ] + paths: + - 'mnemo_cards_backend/**' + - 'mnemo_cards_common/**' + - 'mnemo_cards_common_backend/**' + +jobs: + test: + runs-on: ubuntu-latest + container: dart:stable + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Dart SDK + uses: dart-lang/setup-dart@v1 + with: + sdk: stable + + - name: Cache pub dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards_backend/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_common_backend/.dart_tool + key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-pub- + + - name: Install common dependencies + run: | + cd mnemo_cards_common + dart pub get + + - name: Install common backend dependencies + run: | + cd mnemo_cards_common_backend + dart pub get + + - name: Install backend dependencies + run: | + cd mnemo_cards_backend + dart pub get + + - name: Run code generation + run: | + cd mnemo_cards_backend + dart run build_runner build --delete-conflicting-outputs + + - name: Run linting + run: | + cd mnemo_cards_backend + dart analyze lib/ + dart format --set-exit-if-changed lib/ + + - name: Run tests + run: | + cd mnemo_cards_backend + dart test --coverage=coverage + dart pub global activate coverage + dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + file: ./mnemo_cards_backend/coverage/lcov.info + flags: backend + name: backend-coverage + + build: + needs: test + runs-on: ubuntu-latest + container: dart:stable + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Dart SDK + uses: dart-lang/setup-dart@v1 + with: + sdk: stable + + - name: Cache pub dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards_backend/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_common_backend/.dart_tool + key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-pub- + + - name: Install dependencies + run: | + cd mnemo_cards_common + dart pub get + cd ../mnemo_cards_common_backend + dart pub get + cd ../mnemo_cards_backend + dart pub get + + - name: Build backend executable + run: | + cd mnemo_cards_backend + dart compile exe lib/main.dart -o server.exe + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: backend-binary + path: mnemo_cards_backend/server.exe diff --git a/.forgejo/workflows/ci-main.yml b/.forgejo/workflows/ci-main.yml new file mode 100644 index 0000000..b4142e5 --- /dev/null +++ b/.forgejo/workflows/ci-main.yml @@ -0,0 +1,29 @@ +name: Main CI Pipeline + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + workflow_dispatch: + +jobs: + code-quality: + uses: ./code-quality.yml + + backend-ci: + needs: code-quality + uses: ./ci-backend.yml + + web-ci: + needs: code-quality + uses: ./ci-web.yml + + mobile-ci: + needs: code-quality + uses: ./ci-mobile.yml + + deploy: + needs: [backend-ci, web-ci, mobile-ci] + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' + uses: ./cd-deploy.yml diff --git a/.forgejo/workflows/ci-mobile.yml b/.forgejo/workflows/ci-mobile.yml new file mode 100644 index 0000000..389d38c --- /dev/null +++ b/.forgejo/workflows/ci-mobile.yml @@ -0,0 +1,216 @@ +name: Mobile App CI + +on: + push: + branches: [ main, master ] + paths: + - 'mnemo_cards/**' + - 'mnemo_cards_common/**' + - 'mnemo_cards_frontend_common/**' + - 'chat/mnemo_cards_chat/**' + - 'games/packages/**' + - 'funny_letters/**' + pull_request: + branches: [ main, master ] + paths: + - 'mnemo_cards/**' + - 'mnemo_cards_common/**' + - 'mnemo_cards_frontend_common/**' + - 'chat/mnemo_cards_chat/**' + - 'games/packages/**' + - 'funny_letters/**' + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.0' + channel: 'stable' + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: Cache Flutter dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_frontend_common/.dart_tool + chat/mnemo_cards_chat/.dart_tool + funny_letters/.dart_tool + key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-flutter- + + - name: Install common dependencies + run: | + cd mnemo_cards_common + flutter pub get + + - name: Install frontend common dependencies + run: | + cd mnemo_cards_frontend_common + flutter pub get + + - name: Install chat dependencies + run: | + cd chat/mnemo_cards_chat + flutter pub get + + - name: Install funny letters dependencies + run: | + cd funny_letters + flutter pub get + + - name: Install mobile app dependencies + run: | + cd mnemo_cards + flutter pub get + + - name: Run code generation + run: | + cd mnemo_cards + flutter pub run build_runner build --delete-conflicting-outputs + + - name: Run linting + run: | + cd mnemo_cards + flutter analyze lib/ + flutter format --set-exit-if-changed lib/ + + - name: Run tests + run: | + cd mnemo_cards + flutter test --coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + file: ./mnemo_cards/coverage/lcov.info + flags: mobile + name: mobile-coverage + + build-android: + needs: test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.0' + channel: 'stable' + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Cache Flutter dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_frontend_common/.dart_tool + chat/mnemo_cards_chat/.dart_tool + funny_letters/.dart_tool + key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-flutter- + + - name: Install dependencies + run: | + cd mnemo_cards_common + flutter pub get + cd ../mnemo_cards_frontend_common + flutter pub get + cd ../chat/mnemo_cards_chat + flutter pub get + cd ../funny_letters + flutter pub get + cd ../mnemo_cards + flutter pub get + + - name: Build Android APK + run: | + cd mnemo_cards + flutter build apk --release + + - name: Upload Android APK + uses: actions/upload-artifact@v4 + with: + name: android-apk + path: mnemo_cards/build/app/outputs/flutter-apk/app-release.apk + + build-ios: + needs: test + runs-on: macos-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.0' + channel: 'stable' + + - name: Cache Flutter dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_frontend_common/.dart_tool + chat/mnemo_cards_chat/.dart_tool + funny_letters/.dart_tool + key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-flutter- + + - name: Install dependencies + run: | + cd mnemo_cards_common + flutter pub get + cd ../mnemo_cards_frontend_common + flutter pub get + cd ../chat/mnemo_cards_chat + flutter pub get + cd ../funny_letters + flutter pub get + cd ../mnemo_cards + flutter pub get + + - name: Build iOS + run: | + cd mnemo_cards + flutter build ios --release --no-codesign + + - name: Upload iOS build + uses: actions/upload-artifact@v4 + with: + name: ios-build + path: mnemo_cards/build/ios/iphoneos/ diff --git a/.forgejo/workflows/ci-web.yml b/.forgejo/workflows/ci-web.yml new file mode 100644 index 0000000..4654e66 --- /dev/null +++ b/.forgejo/workflows/ci-web.yml @@ -0,0 +1,138 @@ +name: Web App CI + +on: + push: + branches: [ main, master ] + paths: + - 'mnemo_cards_web_v2/**' + - 'mnemo_cards_common/**' + - 'mnemo_cards_frontend_common/**' + - 'chat/mnemo_cards_chat/**' + - 'games/packages/**' + pull_request: + branches: [ main, master ] + paths: + - 'mnemo_cards_web_v2/**' + - 'mnemo_cards_common/**' + - 'mnemo_cards_frontend_common/**' + - 'chat/mnemo_cards_chat/**' + - 'games/packages/**' + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.0' + channel: 'stable' + + - name: Cache Flutter dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards_web_v2/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_frontend_common/.dart_tool + chat/mnemo_cards_chat/.dart_tool + key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-flutter- + + - name: Install common dependencies + run: | + cd mnemo_cards_common + flutter pub get + + - name: Install frontend common dependencies + run: | + cd mnemo_cards_frontend_common + flutter pub get + + - name: Install chat dependencies + run: | + cd chat/mnemo_cards_chat + flutter pub get + + - name: Install web app dependencies + run: | + cd mnemo_cards_web_v2 + flutter pub get + + - name: Run code generation + run: | + cd mnemo_cards_web_v2 + flutter pub run build_runner build --delete-conflicting-outputs + + - name: Run linting + run: | + cd mnemo_cards_web_v2 + flutter analyze lib/ + flutter format --set-exit-if-changed lib/ + + - name: Run tests + run: | + cd mnemo_cards_web_v2 + flutter test --coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + file: ./mnemo_cards_web_v2/coverage/lcov.info + flags: web + name: web-coverage + + build: + needs: test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.0' + channel: 'stable' + + - name: Cache Flutter dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + mnemo_cards_web_v2/.dart_tool + mnemo_cards_common/.dart_tool + mnemo_cards_frontend_common/.dart_tool + chat/mnemo_cards_chat/.dart_tool + key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-flutter- + + - name: Install dependencies + run: | + cd mnemo_cards_common + flutter pub get + cd ../mnemo_cards_frontend_common + flutter pub get + cd ../chat/mnemo_cards_chat + flutter pub get + cd ../../mnemo_cards_web_v2 + flutter pub get + + - name: Build web app + run: | + cd mnemo_cards_web_v2 + flutter build web --release --dart-define=API_BASE_URL=https://1592725-cf88967.twc1.net:8081 + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: web-build + path: mnemo_cards_web_v2/build/web/ diff --git a/.forgejo/workflows/code-quality.yml b/.forgejo/workflows/code-quality.yml new file mode 100644 index 0000000..b87173e --- /dev/null +++ b/.forgejo/workflows/code-quality.yml @@ -0,0 +1,77 @@ +name: Code Quality + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + quality-gate: + runs-on: ubuntu-latest + container: dart:stable + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.0' + channel: 'stable' + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + **/.dart_tool + key: ${{ runner.os }}-deps-${{ hashFiles('**/pubspec.lock') }} + + - name: Quick dependency check + run: | + # Быстрая проверка наличия pubspec файлов + if ! find . -name "pubspec.yaml" -type f | grep -q .; then + echo "No pubspec.yaml files found" + exit 1 + fi + + - name: Check for common issues + run: | + # Проверка на наличие TODO/FIXME в коде + if grep -r -i "todo\|fixme\|hack" --include="*.dart" . | grep -v -E "(test|example)"; then + echo "⚠️ Found TODO/FIXME comments in production code" + fi + + # Проверка на потенциальные секреты + if grep -r -i "password\|secret\|key\|token" --include="*.dart" --include="*.yaml" --include="*.json" . | grep -v -E "(example|test|mock|fake|pubspec)"; then + echo "⚠️ Potential secrets found in code" + echo "Please review and ensure no real secrets are committed" + else + echo "✅ No obvious secrets found" + fi + + - name: Quality gate check + run: | + # Проверка что основные проекты существуют + projects=("mnemo_cards_backend" "mnemo_cards_web_v2" "mnemo_cards") + for project in "${projects[@]}"; do + if [ ! -d "$project" ]; then + echo "❌ Project $project not found" + exit 1 + fi + done + + # Проверка что нет критических ошибок в логах + if [ -f ".github/workflows/code-quality.log" ]; then + if grep -i "error\|failed\|exception" .github/workflows/code-quality.log; then + echo "❌ Found critical errors in quality check" + exit 1 + fi + fi + + echo "✅ Quality gate passed" + diff --git a/.forgejo/workflows/deploy.yaml b/.forgejo/workflows/deploy.yaml new file mode 100644 index 0000000..81ddc2a --- /dev/null +++ b/.forgejo/workflows/deploy.yaml @@ -0,0 +1,80 @@ +name: Deploy Mnemo Cards + +on: + workflow_dispatch: + push: + branches: + - master + +jobs: + deploy-backend: + name: Deploy Backend + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts + + - name: Sync Source Code + run: | + # Sync common packages + rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'doc' \ + mnemo_cards_common \ + mnemo_cards_common_backend \ + ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/ + + # Sync backend project + rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'server.exe' \ + mnemo_cards_backend \ + ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/ + + # Sync build script + rsync -avz tools/deploy/backend/server_build.sh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/mnemo_cards_backend/ + ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "chmod +x ~/mnemo_cards_backend/server_build.sh" + + - name: Trigger Remote Build + run: | + ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/mnemo_cards_backend/server_build.sh" + + deploy-web: + name: Deploy Web App + runs-on: ubuntu-latest + needs: deploy-backend + if: always() # Run even if backend fails (optional, but usually good to separate) + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.2' # Adjust version as needed + channel: 'stable' + + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts + + - name: Build Web App + run: | + cd mnemo_cards_web_v2 + flutter pub get + flutter build web --release --dart-define=API_BASE_URL=https://api.memo-cards.online:8444 --dart2js-optimization=O4 + + - name: Deploy Web App + run: | + # Sync build artifacts + rsync -avz --delete build/web/ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/mnemo_cards/ + + - name: Fix Permissions + run: | + ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "chown -R www-data:www-data /var/www/mnemo_cards && chmod -R 755 /var/www/mnemo_cards"