name: CI / Integration on: workflow_call: inputs: database: type: boolean default: false release: type: boolean default: false network_frameworks: type: string default: '[]' full: type: boolean default: false permissions: contents: read jobs: database-timezone: name: MySQL and PostgreSQL time contracts if: inputs.database runs-on: ubuntu-latest timeout-minutes: 20 env: TZ: America/New_York PYTHONUTF8: '1' defaults: run: working-directory: ruoyi-fastapi-backend services: mysql: image: mysql:8.0 env: MYSQL_ROOT_PASSWORD: timezone_test TZ: Asia/Shanghai ports: ['3306:3306'] options: >- --health-cmd="mysqladmin ping -h localhost -ptimezone_test" --health-interval=10s --health-timeout=5s --health-retries=12 postgres: image: postgres:14 env: POSTGRES_PASSWORD: timezone_test TZ: America/New_York PGTZ: America/New_York ports: ['5432:5432'] options: >- --health-cmd="pg_isready -U postgres" --health-interval=10s --health-timeout=5s --health-retries=12 steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: python-version: '3.12' cache: pip cache-dependency-path: ruoyi-fastapi-backend/requirements*.txt - run: python -m pip install -r requirements.txt -r requirements-pg.txt -r requirements-test.txt - name: Configure isolated database verification run: | mkdir -p target/ci/timezone python - <<'PY' import json from pathlib import Path for dialect, port, username, database in [('mysql', 3306, 'root', 'mysql'), ('postgresql', 5432, 'postgres', 'postgres')]: source = dict(db_type=dialect, db_host='127.0.0.1', db_port=port, db_username=username, db_password='timezone_test', db_database=database) Path(f'target/ci/timezone/{dialect}.json').write_text(json.dumps(source)) PY - name: Verify drivers, CRUD and scheduler persistence run: | python -m scripts.verify_timezone_database --config target/ci/timezone/mysql.json --report target/ci/timezone/mysql-report.json python -m scripts.verify_timezone_database --config target/ci/timezone/postgresql.json --report target/ci/timezone/postgresql-report.json - uses: actions/upload-artifact@v6 if: always() with: name: integration-database-timezones path: ruoyi-fastapi-backend/target/ci/timezone/*-report.json retention-days: 7 task-bundle: name: Task plugin bundle if: inputs.release runs-on: ubuntu-latest timeout-minutes: 10 defaults: run: working-directory: ruoyi-fastapi-backend/plugins/examples/python/task_demo/web steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v6 with: node-version: '22' cache: npm cache-dependency-path: ruoyi-fastapi-backend/plugins/examples/python/task_demo/web/package.json - run: npm install --no-audit --no-fund --package-lock=false - run: npm test - run: npm run build - uses: actions/upload-artifact@v6 with: name: integration-task-bundle path: ruoyi-fastapi-backend/plugins/examples/python/task_demo/web/dist/ if-no-files-found: error retention-days: 1 release: name: Plugin maintenance / Python ${{ matrix.python }} needs: task-bundle if: inputs.release runs-on: ubuntu-latest timeout-minutes: 30 strategy: fail-fast: false matrix: python: ${{ fromJSON(inputs.full && '["3.10","3.11","3.12","3.13"]' || '["3.12"]') }} defaults: run: working-directory: ruoyi-fastapi-backend services: mysql: image: mysql:8.0 env: MYSQL_ROOT_PASSWORD: ci-only-mysql ports: ['3306:3306'] options: >- --health-cmd="mysqladmin ping -h localhost -pci-only-mysql" --health-interval=10s --health-timeout=5s --health-retries=12 postgres: image: postgres:14 env: POSTGRES_PASSWORD: ci-only-postgres ports: ['5432:5432'] options: >- --health-cmd="pg_isready -U postgres" --health-interval=10s --health-timeout=5s --health-retries=12 redis: image: redis:6.2 ports: ['6379:6379'] options: >- --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=12 env: RUOYI_PLUGIN_IT_ALLOW: '1' RUOYI_IT_MYSQL_PASSWORD: ci-only-mysql RUOYI_IT_PG_PASSWORD: ci-only-postgres RUOYI_IT_REDIS_PASSWORD: '' PYTHONUTF8: '1' _TYPER_FORCE_DISABLE_TERMINAL: '1' steps: - uses: actions/checkout@v5 - uses: actions/download-artifact@v6 with: name: integration-task-bundle path: ruoyi-fastapi-backend/plugins/examples/python/task_demo/web/dist - uses: actions/setup-python@v6 with: python-version: ${{ matrix.python }} cache: pip cache-dependency-path: ruoyi-fastapi-backend/requirements*.txt - run: python -m pip install -r requirements.txt -r requirements-pg.txt - name: Verify MySQL and PostgreSQL maintenance releases shell: bash run: | mkdir -p target/ci/release python scripts/plugin_release_integration.py --engine mysql 2>&1 | tee target/ci/release/mysql.log python scripts/plugin_release_integration.py --engine postgresql 2>&1 | tee target/ci/release/postgresql.log - uses: actions/upload-artifact@v6 if: always() with: name: integration-release-${{ matrix.python }} path: ruoyi-fastapi-backend/target/ci/release/ retention-days: 7 network: name: ${{ matrix.framework }} proxy and plugin sessions if: inputs.network_frameworks != '[]' runs-on: ubuntu-latest timeout-minutes: 20 strategy: fail-fast: false matrix: framework: ${{ fromJSON(inputs.network_frameworks) }} defaults: run: working-directory: ruoyi-fastapi-backend env: RUOYI_PLUGIN_NETWORK_SMOKE: '1' RUOYI_PLUGIN_FRONTEND_FRAMEWORK: ${{ matrix.framework }} NODE_OPTIONS: ${{ matrix.framework == 'vue2' && '--openssl-legacy-provider' || '' }} DB_SOURCES: '{"primary":{"db_type":"mysql","db_host":"127.0.0.1","db_port":3306,"db_username":"network-smoke","db_password":"network-smoke","db_database":"network-smoke"}}' JWT_SECRET_KEY: isolated-plugin-network-smoke-ci-only steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: python-version: '3.12' cache: pip cache-dependency-path: ruoyi-fastapi-backend/requirements*.txt - uses: actions/setup-node@v6 with: node-version: '22' cache: npm cache-dependency-path: ruoyi-fastapi-frontend/${{ matrix.framework }}/web/package.json - run: python -m pip install -r requirements.txt -r requirements-test.txt playwright==1.62.0 - run: python -m playwright install --with-deps chromium - run: npm --prefix ../ruoyi-fastapi-frontend/${{ matrix.framework }}/web install --no-audit --no-fund --package-lock=false - name: Verify HTTPS proxy, iframe sessions and long connections run: python -m pytest tests/plugins/integration/test_network_smoke.py -m browser --strict-markers -v --junitxml=target/plugin-network-smoke/${{ matrix.framework }}/results.xml - run: python ../.github/scripts/check_test_report.py target/plugin-network-smoke/${{ matrix.framework }}/results.xml - uses: actions/upload-artifact@v6 if: always() with: name: integration-network-${{ matrix.framework }} path: ruoyi-fastapi-backend/target/plugin-network-smoke/${{ matrix.framework }}/ retention-days: 7