Add TCP keepalive options for database connections (#4748) #2312
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 Examples | |
| on: | |
| push: | |
| branches: ['main'] | |
| # pull_request: | |
| # paths: ['examples/*/**'] | |
| concurrency: | |
| group: ${{ github.event_name == 'push' && 'prod-deploy-group' || format('examples-pr-{0}', github.event.number) }} | |
| jobs: | |
| example-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.create-example-matrix.outputs.matrix }} | |
| has_examples: ${{ steps.create-example-matrix.outputs.has_examples }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Create example matrix | |
| id: create-example-matrix | |
| env: | |
| BASE_SHA: ${{ github.event.before }} | |
| run: node scripts/ci/example-matrix.mjs changed-deployable | |
| deploy: | |
| name: Deploy ${{ matrix.example.name }} | |
| environment: ${{ github.event_name == 'push' && 'Production' || 'Pull request' }} | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| needs: example-matrix | |
| if: ${{ needs.example-matrix.outputs.has_examples == 'true' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.example-matrix.outputs.matrix) }} | |
| outputs: | |
| yjs: ${{ steps.deploy.outputs.yjs }} | |
| linearlite-read-only: ${{ steps.deploy.outputs.linearlite-read-only }} | |
| write-patterns: ${{ steps.deploy.outputs.write-patterns }} | |
| nextjs: ${{ steps.deploy.outputs.nextjs }} | |
| todo-app: ${{ steps.deploy.outputs.todo-app }} | |
| proxy-auth: ${{ steps.deploy.outputs.proxy-auth }} | |
| phoenix-liveview: ${{ steps.deploy.outputs.phoenix-liveview }} | |
| tanstack: ${{ steps.deploy.outputs.tanstack }} | |
| remix: ${{ steps.deploy.outputs.remix }} | |
| react: ${{ steps.deploy.outputs.react }} | |
| burn: ${{ steps.deploy.outputs.burn }} | |
| tanstack-db-web-starter: ${{ steps.deploy.outputs.tanstack-db-web-starter }} | |
| env: | |
| DEPLOY_ENV: ${{ github.event_name == 'push' && 'production' || format('pr-{0}', github.event.number) }} | |
| PULUMI_LOG_LEVEL: debug | |
| SST_DEBUG: '1' | |
| SHARED_INFRA_VPC_ID: ${{ vars.SHARED_INFRA_VPC_ID }} | |
| SHARED_INFRA_CLUSTER_ARN: ${{ vars.SHARED_INFRA_CLUSTER_ARN }} | |
| SHARED_EXAMPLES_DATABASE_URI: ${{ secrets.SHARED_EXAMPLES_DATABASE_URI }} | |
| SHARED_EXAMPLES_POOLED_DATABASE_URI: ${{ secrets.SHARED_EXAMPLES_POOLED_DATABASE_URI }} | |
| SHARED_EXAMPLES_SOURCE_ID: ${{ vars.SHARED_EXAMPLES_SOURCE_ID }} | |
| SHARED_EXAMPLES_SOURCE_SECRET: ${{ secrets.SHARED_EXAMPLES_SOURCE_SECRET }} | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_DEFAULT_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_DEFAULT_ACCOUNT_ID }} | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| NEON_API_KEY: ${{ secrets.NEON_API_KEY }} | |
| NEON_PROJECT_ID: ${{ secrets.NEON_PROJECT_ID }} | |
| ELECTRIC_API: ${{ secrets.ELECTRIC_API }} | |
| ELECTRIC_ADMIN_API: ${{ secrets.ELECTRIC_ADMIN_API }} | |
| ELECTRIC_TEAM_ID: ${{ secrets.ELECTRIC_TEAM_ID }} | |
| ELECTRIC_ADMIN_API_AUTH_TOKEN: ${{ secrets.ELECTRIC_ADMIN_API_AUTH_TOKEN }} | |
| SECRET_KEY_BASE: ${{ secrets.LIVEVIEW_EXAMPLE_SECRET_KEY_BASE }} | |
| ANTHROPIC_KEY: ${{ secrets.ANTHROPIC_KEY }} | |
| QUICKSTART_DATABASE_URI: ${{ secrets.QUICKSTART_DATABASE_URI }} | |
| QUICKSTART_POOLED_DATABASE_URI: ${{ secrets.QUICKSTART_POOLED_DATABASE_URI }} | |
| QUICKSTART_SOURCE_ID: ${{ vars.QUICKSTART_SOURCE_ID }} | |
| QUICKSTART_SOURCE_SECRET: ${{ secrets.QUICKSTART_SOURCE_SECRET }} | |
| BETTER_AUTH_SECRET: ${{ secrets.BETTER_AUTH_SECRET }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version-file: '.tool-versions' | |
| cache: 'pnpm' | |
| - name: Install dependencies | |
| run: | | |
| if [ -f "${{ matrix.example.path }}/package.json" ]; then | |
| pnpm --filter "$(jq -r .name "${{ matrix.example.path }}/package.json")..." --filter @electric-examples/shared --filter @electric-sql/client --filter @electric-sql/experimental --filter @electric-sql/react install --frozen-lockfile | |
| else | |
| pnpm install --frozen-lockfile | |
| fi | |
| - name: Cache SST state | |
| uses: actions/cache@v4 | |
| with: | |
| path: .sst | |
| key: sst-cache-${{ matrix.example.name }}-${{ runner.os }} | |
| restore-keys: | | |
| sst-cache-${{ matrix.example.name }}-${{ runner.os }} | |
| - name: Deploy | |
| id: deploy | |
| working-directory: ./${{ matrix.example.path }} | |
| run: | | |
| pnpm --filter @electric-sql/client --filter @electric-sql/experimental --filter @electric-sql/react run build | |
| pnpm sst deploy --stage ${{ env.DEPLOY_ENV }} | |
| if [ -f ".sst/outputs.json" ]; then | |
| website=$(jq -r '.website' .sst/outputs.json) | |
| echo "${{ matrix.example.name }}=$website" >> $GITHUB_OUTPUT | |
| echo "website=$website" >> $GITHUB_OUTPUT | |
| else | |
| echo "sst outputs file not found. Exiting." | |
| exit 123 | |
| fi | |
| - name: Test deployed example | |
| if: ${{ matrix.example.deploy_test_folder != '' }} | |
| uses: ./.github/actions/test-example | |
| with: | |
| test_folder: ${{ matrix.example.deploy_test_folder }} | |
| example_url: ${{ steps.deploy.outputs.website }} | |
| comment: | |
| if: github.event_name == 'pull_request' && needs.example-matrix.outputs.has_examples == 'true' | |
| needs: [example-matrix, deploy] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Create PR comment with deployment URLs | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| // Get the matrix of examples that were deployed | |
| const matrix = JSON.parse(${{ toJSON(needs.example-matrix.outputs.matrix) }}) | |
| const urls = { | |
| yjs: "${{ needs.deploy.outputs.yjs }}", | |
| "linearlite-read-only": "${{ needs.deploy.outputs.linearlite-read-only }}", | |
| "write-patterns": "${{ needs.deploy.outputs.write-patterns }}", | |
| nextjs: "${{ needs.deploy.outputs.nextjs }}", | |
| "todo-app": "${{ needs.deploy.outputs.todo-app }}", | |
| "proxy-auth": "${{ needs.deploy.outputs.proxy-auth }}", | |
| "phoenix-liveview": "${{ needs.deploy.outputs.phoenix-liveview }}", | |
| "tanstack": "${{ needs.deploy.outputs.tanstack }}", | |
| "remix": "${{ needs.deploy.outputs.remix }}", | |
| "react": "${{ needs.deploy.outputs.react }}", | |
| "tanstack-db-web-starter": "${{ needs.deploy.outputs.tanstack-db-web-starter }}" | |
| } | |
| // Create deployments array only for examples that were deployed | |
| const deployments = matrix.example.map(example => ({ | |
| name: example.name, | |
| url: urls[example.name] | |
| })) | |
| const commentBody = [ | |
| "## Examples", | |
| ...deployments.map(d => `- ${d.name}: ${d.url || '*deploy failed*'}`), | |
| ].join('\n') | |
| const prNumber = context.issue.number | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }) | |
| const existingComment = comments.find(comment => comment.user.login ==='github-actions[bot]' && comment.body.startsWith("## Examples")) | |
| if (existingComment) { | |
| // Update the existing comment | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existingComment.id, | |
| body: commentBody, | |
| }) | |
| } else { | |
| // Create a new comment if none exists | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: commentBody, | |
| }) | |
| } |