feat(ka): consolidate canonical runtime #791
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy | |
| on: | |
| push: | |
| branches: [ main ] | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| deploy_production: | |
| description: "Run production deployment steps" | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: read | |
| packages: write | |
| jobs: | |
| build-and-test: | |
| name: Build and Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Set up Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '24' | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --require-hashes -r requirements.lock | |
| - name: Install Node dependencies | |
| run: | | |
| cd frontend | |
| npm ci | |
| - name: Run deterministic startup precheck gate | |
| run: | | |
| python scripts/runtime_precheck.py --strict --skip-ports --allow-env-from-process --json-report reports/runtime_precheck_report_deploy.json | |
| env: | |
| FLASK_ENV: "testing" | |
| SESSION_SECRET: "ci-session-secret" | |
| DATABASE_URL: "sqlite:///:memory:" | |
| OPENAI_API_KEY: "mock-key-for-ci" | |
| - name: Build frontend | |
| run: | | |
| cd frontend | |
| npm run build | |
| - name: Run smoke bootstrap check | |
| run: | | |
| python scripts/test_smoke.py | |
| - name: Validate docs references | |
| run: | | |
| python scripts/verify_docs_references.py | |
| - name: Validate SQLite/Postgres schema parity | |
| run: | | |
| python scripts/validate_schema_parity.py --report reports/schema_parity_report_deploy.json | |
| - name: Run tests | |
| run: | | |
| python -m pytest tests/ -v --no-cov | |
| env: | |
| PYTHONPATH: "." | |
| DATABASE_URL: "sqlite:///:memory:" | |
| OPENAI_API_KEY: "mock-key-for-ci" | |
| FLASK_ENV: "testing" | |
| SESSION_SECRET: "ci-session-secret" | |
| SECRET_KEY: "ci-test-secret-key" | |
| JWT_SECRET_KEY: "ci-test-jwt-secret" | |
| - name: Run phase 3 integrity + crash controls regression | |
| run: | | |
| python -m pytest -q --no-cov tests/unit/test_phase3_integrity_crash_controls.py | |
| env: | |
| PYTHONPATH: "." | |
| DATABASE_URL: "sqlite:///:memory:" | |
| OPENAI_API_KEY: "mock-key-for-ci" | |
| FLASK_ENV: "testing" | |
| SESSION_SECRET: "ci-session-secret" | |
| SECRET_KEY: "ci-test-secret-key" | |
| - name: Verify installer artifact integrity | |
| run: | | |
| python scripts/verify_installer_integrity.py --report reports/installer_integrity_report_deploy.json | |
| - name: Check crash reporting configuration | |
| id: crash-reporting-config | |
| env: | |
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
| run: | | |
| if [ -n "$SENTRY_DSN" ]; then | |
| echo "configured=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "configured=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Verify crash reporting provider pipeline (optional) | |
| if: steps.crash-reporting-config.outputs.configured == 'true' | |
| env: | |
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
| FLASK_ENV: "production" | |
| APP_VERSION: "deploy-pipeline" | |
| run: | | |
| python scripts/send_sentry_test_event.py --message "DataLogicEngine deploy crash-reporting probe" --tag source=deploy --tag workflow=deploy | |
| docker-build: | |
| name: Build Docker Images | |
| runs-on: ubuntu-latest | |
| needs: build-and-test | |
| if: | | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | |
| github.event_name == 'workflow_dispatch' | |
| env: | |
| REGISTRY_IMAGE: ghcr.io/${{ github.repository_owner }}/datalogicengine | |
| GHCR_PUSH_ENABLED: ${{ secrets.GHCR_PAT != '' }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 | |
| - name: Log in to Container Registry | |
| if: env.GHCR_PUSH_ENABLED == 'true' | |
| uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GHCR_PAT }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 | |
| with: | |
| images: ${{ env.REGISTRY_IMAGE }} | |
| tags: | | |
| type=ref,event=branch | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=sha | |
| - name: Build Docker image (push when GHCR_PAT is set) | |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 | |
| with: | |
| context: . | |
| file: Dockerfile.cloud | |
| push: ${{ env.GHCR_PUSH_ENABLED == 'true' }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| deploy-config: | |
| name: Deployment Config Gate | |
| runs-on: ubuntu-latest | |
| needs: docker-build | |
| if: github.event_name == 'workflow_dispatch' && inputs.deploy_production == true | |
| outputs: | |
| healthcheck_configured: ${{ steps.validate.outputs.healthcheck_configured }} | |
| steps: | |
| - name: Validate deployment variables | |
| id: validate | |
| env: | |
| DEPLOY_COMMAND: ${{ vars.DEPLOY_COMMAND }} | |
| HEALTHCHECK_URL: ${{ vars.PRODUCTION_HEALTHCHECK_URL }} | |
| run: | | |
| if [ -z "$DEPLOY_COMMAND" ]; then | |
| echo "::error::Missing repository variable DEPLOY_COMMAND." | |
| echo "::error::Set it in Settings > Secrets and variables > Actions > Variables." | |
| exit 1 | |
| fi | |
| if [ -z "$HEALTHCHECK_URL" ]; then | |
| echo "::warning::PRODUCTION_HEALTHCHECK_URL is not configured; health check will be skipped." | |
| echo "healthcheck_configured=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "healthcheck_configured=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| deploy-production: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: deploy-config | |
| if: github.event_name == 'workflow_dispatch' && inputs.deploy_production == true | |
| environment: | |
| name: production | |
| url: https://datalogicengine.com | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Deploy to production | |
| env: | |
| DEPLOY_COMMAND: ${{ vars.DEPLOY_COMMAND }} | |
| run: | | |
| bash -lc "$DEPLOY_COMMAND" | |
| - name: Production health check | |
| if: needs.deploy-config.outputs.healthcheck_configured == 'true' | |
| env: | |
| HEALTHCHECK_URL: ${{ vars.PRODUCTION_HEALTHCHECK_URL }} | |
| run: | | |
| curl --fail --silent --show-error --retry 5 --retry-delay 5 --retry-connrefused "$HEALTHCHECK_URL" | |
| - name: Notify deployment status | |
| if: always() | |
| run: | | |
| echo "Send notification about deployment status" | |
| echo "Status: ${{ job.status }}" |