Skip to content

deploy

deploy #5968

Workflow file for this run

name: CI
on:
merge_group:
pull_request:
push:
branches: [main, dev]
workflow_dispatch:
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
jobs:
# set yarn cache
cache-deps:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Environment
uses: ./.github/actions/setup-env
with:
build-nextjs: true
env:
YARN_ENABLE_HARDENED_MODE: 0
- name: Show github refs
run: |
echo github.ref=${{ github.ref }}
echo github.head_ref=${{ github.head_ref }}
unit-tests:
name: Unit Tests
runs-on: self-hosted
needs: [cache-deps]
env:
ANVIL_MAINNET_FORK_URL: ${{ secrets.CI_ANVIL_MAINNET_FORK_URL }}
ANVIL_BASE_FORK_URL: ${{ secrets.CI_ANVIL_BASE_FORK_URL }}
FOUNDRY_BASE_SEPOLIA_RPC_URL: ${{ secrets.CI_FOUNDRY_BASE_SEPOLIA_RPC_URL }}
YARN_ENABLE_HARDENED_MODE: 0
steps:
- name: Install Tilt
id: tilt
shell: bash
run: |
cd /tmp
curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
- name: Add hosts to /etc/hosts
run: |
sudo su
if grep -q "host.docker.internal" /etc/hosts; then
echo "Hosts file already contains host.docker.internal"
else
echo "127.0.0.1 host.docker.internal" | sudo tee -a /etc/hosts
fi
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Brew Bundle
id: brew-bundle
run: |
brew bundle
brew cleanup
- name: Setup Environment
uses: ./.github/actions/setup-env
env:
YARN_ENABLE_HARDENED_MODE: 0
with:
yarn-install: false
- name: Load Next.js Build Cache
uses: actions/download-artifact@v4
with:
name: nextjs-build
path: ${{ github.workspace }}/apps/next/.next
# - name: Snaplet Login
# shell: bash
# run: bunx snaplet auth login ${{ secrets.CI_SNAPLET_AUTH_TOKEN }}
- name: Tilt CI
id: tilt-ci
shell: bash
run: tilt ci unit-tests --timeout=10m
- name: Lint
run: yarn lint
- name: Tilt Down
# always run tilt down if tilt ci started
if: always() && steps.tilt-ci.outcome != 'skipped'
shell: bash
run: tilt down
# @todo anvil fixtures cause dirty repo, but only in github actions 😢
- name: All Changes Committed
shell: bash
run: git diff # --exit-code
playwright-tests:
name: Playwright Tests
runs-on: self-hosted
needs: [cache-deps]
env:
ANVIL_MAINNET_FORK_URL: ${{ secrets.CI_ANVIL_MAINNET_FORK_URL }}
ANVIL_BASE_FORK_URL: ${{ secrets.CI_ANVIL_BASE_FORK_URL }}
YARN_ENABLE_HARDENED_MODE: 0
# for writing PR comments
permissions:
pull-requests: write
timeout-minutes: 40
steps:
- name: Install Tilt
id: tilt
shell: bash
run: |
cd /tmp
curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
- name: Add hosts to /etc/hosts
run: |
sudo su
if grep -q "host.docker.internal" /etc/hosts; then
echo "Hosts file already contains host.docker.internal"
else
echo "127.0.0.1 host.docker.internal" | sudo tee -a /etc/hosts
fi
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Brew Bundle
id: brew-bundle
run: |
brew bundle
brew cleanup
- name: Setup Environment
uses: ./.github/actions/setup-env
env:
YARN_ENABLE_HARDENED_MODE: 0
- name: Load Next.js Build Cache
uses: actions/download-artifact@v4
with:
name: nextjs-build
path: ${{ github.workspace }}/apps/next/.next
# - name: Snaplet Login
# shell: bash
# run: bunx snaplet auth login ${{ secrets.CI_SNAPLET_AUTH_TOKEN }}
- name: Install Playwright Dependencies
run: yarn playwright playwright install --with-deps
# @todo anvil fixtures cause dirty repo, but only in github actions 😢
# - name: All Changes Committed
# shell: bash
# run: git diff --exit-code
# this is on purpose so we get github annotations
- name: Build Next.js
shell: bash
run: |
tilt ci yarn:install # install and setup env
yarn web:docker:build # build nextjs docker image
- name: Playwright Tests
id: playwright
shell: bash
run: |
# set debug logs if runner.debug is set
# if [ "${{runner.debug}}" == "1" ]; then
# export DEBUG="test:*,app:*,api:*,next:*"
# fi
export DEBUG="api:*,app:*,test:*,-test:fixtures:snaplet:*"
nohup tilt up playwright:deps &
tilt_pid=$!
echo "Tilt process started with PID: $tilt_pid"
echo waiting for tilt to be ready
for i in {1..10}; do
curl -s http://localhost:10350 > /dev/null && break || echo "Attempt $i failed, trying again..."
sleep 1
done
sleep 1
echo tilt is ready
max_attempts=60
wait_timeout=7
for ((i=1; i<=max_attempts; i++)); do
echo "Attempt $i: Waiting for tilt with timeout ${wait_timeout}s"
# Check if the Tilt process is still running
if ! ps -p $tilt_pid > /dev/null; then
echo "Tilt process (PID: $tilt_pid) is no longer running, exiting"
exit 1
fi
# Check if any targets are in error
has_errors=$(tilt dump engine | jq '
.ManifestTargets
| to_entries
| map(
select(
.value.State.RuntimeState.Status == "error" or
(.value.State.BuildHistory | length > 0 and .[0].Error != null)
)
)
| length > 0
')
if [ "$has_errors" = "true" ]; then
echo "There are targets in error status:"
tilt dump engine | jq '
.ManifestTargets
| to_entries
| map(
select(
.value.State.RuntimeState.Status == "error" or
(.value.State.BuildHistory | length > 0 and .[0].Error != null)
)
)
| map(.key)
'
exit 1
fi
if tilt wait --timeout "${wait_timeout}s" --for=condition=Ready "uiresource/playwright:deps"; then
echo "Tilt is ready"
break
else
echo "Tilt not ready, retrying..."
if [ "${{runner.debug}}" == "1" ]; then
tilt dump engine | jq '
.ManifestTargets
| to_entries
| map({key: (.value.State.RuntimeState.Status // "in_progress"), value: .key})
| group_by(.key)
| map({key: .[0].key, value: map(.value)})
| from_entries
'
fi
fi
if ((i == max_attempts)); then
echo "Reached maximum attempts, exiting"
exit 1
fi
done
yarn playwright test
- name: Playwright Markdown Report
if: always() && steps.playwright.outcome != 'skipped'
id: playwright-md-report
shell: bash
run: |
echo "Markdown report:"
echo "------------------"
bun run packages/playwright/bin/report-markdown.ts > playwright-report.md
cat playwright-report.md
echo "------------------"
echo "Markdown report end"
- uses: mshick/add-pr-comment@v2
if: always() && steps.playwright.outcome != 'skipped'
with:
message-id: playwright-report
refresh-message-position: true
message-path: |
playwright-report.md
- name: Tilt Down
# always run tilt down if tilt ci started
if: always() && steps.playwright.outcome != 'skipped'
shell: bash
run: tilt down
- name: Playwright Report
uses: actions/upload-artifact@v4
if: always() && steps.playwright.outcome == 'failure'
with:
name: playwright-report
path: packages/playwright/playwright-report/
retention-days: 30
- name: Playwright Test Results
uses: actions/upload-artifact@v4
if: always() && steps.playwright.outcome == 'failure'
with:
name: playwright-test-results
path: packages/playwright/test-results/
retention-days: 30
vercel-deploy-preview:
# **always** skip if on dev and main since it will be deployed with another workflow
if: ${{ github.ref != 'refs/heads/dev' && github.ref != 'refs/heads/main' && github.head_ref != 'dev' && github.head_ref != 'main' }}
runs-on: ubuntu-latest
needs: [cache-deps]
permissions:
pull-requests: write
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Environment
uses: ./.github/actions/setup-env
with:
yarn-install: false
env:
YARN_ENABLE_HARDENED_MODE: 0
- name: Load Next.js Build Cache
uses: actions/download-artifact@v4
with:
name: nextjs-build
path: ${{ github.workspace }}/apps/next/.next
- name: Extract branch name
id: extract-branch
uses: ./.github/actions/extract-branch
- name: Set Public Hostname
id: public-hostname
run: echo "public-hostname=sendapp-${{steps.extract-branch.outputs.branch}}-0xsend.vercel.app" >> $GITHUB_OUTPUT
- name: Vercel Deploy Preview with Supabase Branch
if: github.base_ref == 'dev'
id: vercel-deploy-with-branch
uses: ./.github/actions/vercel-deploy
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
public-hostname: ${{ steps.public-hostname.outputs.public-hostname }}
deploy-preview-extra-args: >-
-e SUPABASE_DB_URL="${{ secrets.STAGING_SUPABASE_DB_URL }}"
-e SUPABASE_JWT_SECRET="${{ secrets.STAGING_SUPABASE_JWT_SECRET }}"
-e SUPABASE_SERVICE_ROLE="${{ secrets.STAGING_SUPABASE_SERVICE_ROLE }}"
-e NEXT_PUBLIC_SUPABASE_URL="https://${{ secrets.STAGING_SUPABASE_PROJECT_ID }}.supabase.co"
-e NEXT_PUBLIC_SUPABASE_PROJECT_ID="${{ secrets.STAGING_SUPABASE_PROJECT_ID }}"
-e NEXT_PUBLIC_SUPABASE_GRAPHQL_URL="https://${{ secrets.STAGING_SUPABASE_PROJECT_ID }}.supabase.co/graphql"
-e NEXT_PUBLIC_BASE_CHAIN_ID="84532"
-e NEXT_PUBLIC_MAINNET_CHAIN_ID="11155111"
-e NEXT_PUBLIC_BASE_RPC_URL="${{ secrets.BASE_SEPOLIA_RPC_URL }}"
-e NEXT_PUBLIC_MAINNET_RPC_URL="https://ethereum-sepolia-rpc.publicnode.com"
-e NEXT_PUBLIC_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InVncXRvdWxleGh2YWhldnN5c3VxIiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTMwOTE5MzUsImV4cCI6MjAwODY2NzkzNX0.RL8W-jw2rsDhimYl8KklF2B9bNTPQ-Kj5zZA0XlufUA"
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_GIT_COMMIT_SHA: ${{ github.sha }}
VERCEL_GIT_COMMIT_REF: ${{ github.head_ref }}
VERCEL_GIT_PULL_REQUEST_ID: ${{ github.event.pull_request.number }}
SUPABASE_DB_URL: ${{ secrets.STAGING_SUPABASE_DB_URL }}
SUPABASE_JWT_SECRET: ${{ secrets.STAGING_SUPABASE_JWT_SECRET }}
SUPABASE_SERVICE_ROLE: ${{ secrets.STAGING_SUPABASE_SERVICE_ROLE }}
NEXT_PUBLIC_SUPABASE_URL: https://${{ secrets.STAGING_SUPABASE_PROJECT_ID }}.supabase.co
NEXT_PUBLIC_SUPABASE_PROJECT_ID: ${{ secrets.STAGING_SUPABASE_PROJECT_ID }}
NEXT_PUBLIC_SUPABASE_GRAPHQL_URL: https://${{ secrets.STAGING_SUPABASE_PROJECT_ID }}.supabase.co/graphql
NEXT_PUBLIC_BASE_CHAIN_ID: 84532
NEXT_PUBLIC_MAINNET_CHAIN_ID: 11155111
NEXT_PUBLIC_BASE_RPC_URL: ${{ secrets.BASE_SEPOLIA_RPC_URL }}
NEXT_PUBLIC_MAINNET_RPC_URL: https://ethereum-sepolia-rpc.publicnode.com
NEXT_PUBLIC_SUPABASE_ANON_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InVncXRvdWxleGh2YWhldnN5c3VxIiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTMwOTE5MzUsImV4cCI6MjAwODY2NzkzNX0.RL8W-jw2rsDhimYl8KklF2B9bNTPQ-Kj5zZA0XlufUA
- name: Vercel Deploy Preview
if: github.base_ref != 'dev'
id: vercel-deploy-preview
uses: ./.github/actions/vercel-deploy
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
public-hostname: ${{ steps.public-hostname.outputs.public-hostname }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_GIT_COMMIT_SHA: ${{ github.sha }}
VERCEL_GIT_COMMIT_REF: ${{ github.head_ref }}
VERCEL_GIT_PULL_REQUEST_ID: ${{ github.event.pull_request.number }}
- uses: mshick/add-pr-comment@v2
if: github.base_ref == 'dev'
with:
message-id: vercel-preview-url
refresh-message-position: true
message: |
Vercel Unique URL: [${{ steps.vercel-deploy-with-branch.outputs.deployment-url }}](${{ steps.vercel-deploy-with-branch.outputs.deployment-url }})
Vercel Preview URL: [${{ steps.public-hostname.outputs.public-hostname }}](https://${{ steps.public-hostname.outputs.public-hostname }}/)
Last Commit: ${{ github.event.pull_request.head.sha }}
- uses: mshick/add-pr-comment@v2
if: github.base_ref != 'dev'
with:
message-id: vercel-preview-url
refresh-message-position: true
message: |
Vercel Unique URL: [${{ steps.vercel-deploy-preview.outputs.deployment-url }}](${{ steps.vercel-deploy-preview.outputs.deployment-url }})
Vercel Preview URL: [${{ steps.public-hostname.outputs.public-hostname }}](https://${{ steps.public-hostname.outputs.public-hostname }}/)
Last Commit: ${{ github.event.pull_request.head.sha }}