- Rename and enhance the Docker instance startup steps for Tai in CI workflows, improving clarity and readiness checks for both HTTP and gRPC services. - Update health check logic to ensure accurate reporting of service readiness, including specific error messages for failures. - Modify environment variable configurations to streamline the setup for K8s and Docker instances, ensuring consistent port usage across tests. These changes improve the reliability and clarity of the CI processes for the Tai service, enhancing overall testing and deployment workflows.
2129 lines
64 KiB
YAML
2129 lines
64 KiB
YAML
name: PR Unit Test
|
||
|
||
# read-write repo token
|
||
# access to secrets
|
||
on:
|
||
workflow_run:
|
||
workflows: ["Receive PR"]
|
||
types:
|
||
- completed
|
||
env:
|
||
YAO_DEV: ${{ github.WORKSPACE }}
|
||
YAO_ENV: development
|
||
YAO_ROOT: ${{ github.WORKSPACE }}/../app
|
||
YAO_HOST: 0.0.0.0
|
||
YAO_PORT: 5099
|
||
YAO_SESSION: "memory"
|
||
YAO_LOG: "./logs/application.log"
|
||
YAO_LOG_MODE: "TEXT"
|
||
YAO_JWT_SECRET: "bLp@bi!oqo-2U+hoTRUG"
|
||
YAO_DB_AESKEY: "ZLX=T&f6refeCh-ro*r@"
|
||
OSS_TEST_ID: ${{ secrets.OSS_TEST_ID}}
|
||
OSS_TEST_SECRET: ${{ secrets.OSS_TEST_SECRET}}
|
||
ROOT_PLUGIN: ${{ github.WORKSPACE }}/../../../data/gou-unit/plugins
|
||
|
||
MYSQL_TEST_HOST: "127.0.0.1"
|
||
MYSQL_TEST_PORT: "3308"
|
||
MYSQL_TEST_USER: test
|
||
MYSQL_TEST_PASS: "123456"
|
||
|
||
SQLITE_DB: "./app/db/yao.db"
|
||
|
||
REDIS_TEST_HOST: "127.0.0.1"
|
||
REDIS_TEST_PORT: "6379"
|
||
REDIS_TEST_DB: "2"
|
||
|
||
MONGO_TEST_HOST: "127.0.0.1"
|
||
MONGO_TEST_PORT: "27017"
|
||
MONGO_TEST_USER: "root"
|
||
MONGO_TEST_PASS: "123456"
|
||
|
||
OPENAI_TEST_KEY: ${{ secrets.OPENAI_TEST_KEY }}
|
||
TEST_MOAPI_SECRET: ${{ secrets.OPENAI_TEST_KEY }}
|
||
OPENAI_API_KEY: ${{ secrets.OPENAI_TEST_KEY }}
|
||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||
TEST_MOAPI_MIRROR: https://api.openai.com
|
||
|
||
# DeepSeek API Configuration
|
||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
||
DEEPSEEK_API_PROXY: ${{ secrets.DEEPSEEK_API_PROXY }}
|
||
DEEPSEEK_MODELS_R1: ${{ secrets.DEEPSEEK_MODELS_R1 }}
|
||
DEEPSEEK_MODELS_V3: ${{ secrets.DEEPSEEK_MODELS_V3 }}
|
||
DEEPSEEK_MODELS_V3_1: ${{ secrets.DEEPSEEK_MODELS_V3_1 }}
|
||
|
||
# Search API Configuration
|
||
TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }}
|
||
SERPAPI_API_KEY: ${{ secrets.SERPAPI_API_KEY }}
|
||
SERPER_API_KEY: ${{ secrets.SERPER_API_KEY }}
|
||
|
||
# Claude API Configuration
|
||
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
|
||
CLAUDE_PROXY: ${{ secrets.CLAUDE_PROXY }}
|
||
CLAUDE_API_HOST: ${{ secrets.CLAUDE_API_HOST }}
|
||
CLAUDE_SONNET_4: ${{ secrets.CLAUDE_SONNET_4 }}
|
||
CLAUDE_SONNET_4_THINKING: ${{ secrets.CLAUDE_SONNET_4_THINKING }}
|
||
|
||
# Moonshot / Kimi API Configuration
|
||
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
|
||
MOONSHOT_PROXY: "https://api.moonshot.cn"
|
||
KIMI_CODE_API_KEY: ${{ secrets.KIMI_CODE_API_KEY }}
|
||
KIMI_CODE_PROXY: "https://api.kimi.com/coding"
|
||
|
||
TAB_NAME: "::PET ADMIN"
|
||
PAGE_SIZE: "20"
|
||
PAGE_LINK: "https://yaoapps.com"
|
||
PAGE_ICON: "icon-trash"
|
||
|
||
DEMO_APP: ${{ github.WORKSPACE }}/../app
|
||
|
||
# Application Setting
|
||
|
||
## Path
|
||
YAO_EXTENSION_ROOT: ${{ github.WORKSPACE }}/../extension
|
||
YAO_TEST_APPLICATION: ${{ github.WORKSPACE }}/../app
|
||
YAO_SUI_TEST_APPLICATION: ${{ github.WORKSPACE }}/../yao-startup-webapp
|
||
|
||
## Runtime
|
||
YAO_RUNTIME_MIN: 3
|
||
YAO_RUNTIME_MAX: 6
|
||
YAO_RUNTIME_HEAP_LIMIT: 1500000000
|
||
YAO_RUNTIME_HEAP_RELEASE: 10000000
|
||
YAO_RUNTIME_HEAP_AVAILABLE: 550000000
|
||
YAO_RUNTIME_PRECOMPILE: true
|
||
|
||
# Neo4j
|
||
NEO4J_TEST_URL: "neo4j://localhost:7687"
|
||
NEO4J_TEST_USER: "neo4j"
|
||
NEO4J_TEST_PASS: "Yao2026Neo4j"
|
||
|
||
# Qdrant
|
||
QDRANT_TEST_HOST: "127.0.0.1"
|
||
QDRANT_TEST_PORT: "6334"
|
||
|
||
# S3
|
||
S3_API: ${{ secrets.S3_API }}
|
||
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
|
||
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
|
||
S3_BUCKET: ${{ secrets.S3_BUCKET }}
|
||
S3_PUBLIC_URL: ${{ secrets.S3_PUBLIC_URL }}
|
||
|
||
# === Openapi Signin Configs ===
|
||
SIGNIN_CLIENT_ID: "kiCeR88kDwHBDuNHvN51cZgmpp3tmF6Z"
|
||
|
||
## Google
|
||
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
|
||
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
|
||
|
||
## Microsoft
|
||
MICROSOFT_CLIENT_ID: ${{ secrets.MICROSOFT_CLIENT_ID }}
|
||
MICROSOFT_CLIENT_SECRET: ${{ secrets.MICROSOFT_CLIENT_SECRET }}
|
||
|
||
## Apple
|
||
APPLE_SERVICE_ID: ${{ secrets.APPLE_SERVICE_ID }}
|
||
APPLE_PRIVATE_KEY_PATH: "apple/signin_client_secret_key.p8"
|
||
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
|
||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||
|
||
## Github
|
||
GITHUBUSER_CLIENT_ID: ${{ secrets.GITHUBUSER_CLIENT_ID }}
|
||
GITHUBUSER_CLIENT_SECRET: ${{ secrets.GITHUBUSER_CLIENT_SECRET }}
|
||
|
||
## Cloudflare Turnstile
|
||
CLOUDFLARE_TURNSTILE_SITEKEY: ${{ secrets.CLOUDFLARE_TURNSTILE_SITEKEY }}
|
||
CLOUDFLARE_TURNSTILE_SECRET: ${{ secrets.CLOUDFLARE_TURNSTILE_SECRET }}
|
||
|
||
# === Messaging Services ===
|
||
## Mailgun
|
||
MAILGUN_DOMAIN: ${{ secrets.MAILGUN_DOMAIN }}
|
||
MAILGUN_API_KEY: ${{ secrets.MAILGUN_API_KEY }}
|
||
MAILGUN_FROM: "Yaobots Tests <unit-test@mailgun.yaobots.com>"
|
||
|
||
## SMTP Server( Mailgun )
|
||
SMTP_HOST: "smtp.mailgun.org"
|
||
SMTP_PORT: "465"
|
||
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
|
||
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
|
||
SMTP_FROM: "Yaobots SMTP Tests <unit-test@mailgun.yaobots.com>"
|
||
|
||
## SMTP Server( Gmail )
|
||
RELIABLE_SMTP_HOST: "smtp.gmail.com"
|
||
RELIABLE_SMTP_PORT: "465"
|
||
RELIABLE_SMTP_USERNAME: ${{ secrets.RELIABLE_SMTP_USERNAME }}
|
||
RELIABLE_SMTP_PASSWORD: ${{ secrets.RELIABLE_SMTP_PASSWORD }}
|
||
RELIABLE_SMTP_FROM: "Yaobots Gmail Tests <shadow.iqka@gmail.com>"
|
||
|
||
## IMAP Server (Gmail)
|
||
RELIABLE_IMAP_HOST: "imap.gmail.com"
|
||
RELIABLE_IMAP_PORT: "993"
|
||
RELIABLE_IMAP_USERNAME: ${{ secrets.RELIABLE_SMTP_USERNAME }}
|
||
RELIABLE_IMAP_PASSWORD: ${{ secrets.RELIABLE_SMTP_PASSWORD }}
|
||
RELIABLE_IMAP_MAILBOX: "INBOX"
|
||
|
||
## Twilio
|
||
TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
|
||
TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
|
||
TWILIO_API_SID: ${{ secrets.TWILIO_API_SID }}
|
||
TWILIO_API_KEY: ${{ secrets.TWILIO_API_KEY }}
|
||
TWILIO_SENDGRID_API_SID: ${{ secrets.TWILIO_SENDGRID_API_SID }}
|
||
TWILIO_SENDGRID_API_KEY: ${{ secrets.TWILIO_SENDGRID_API_KEY }}
|
||
TWILIO_FROM_PHONE: "+17035701412"
|
||
TWILIO_FROM_EMAIL: "unit-test@sendgrid.yaobots.com"
|
||
TWILIO_TEST_PHONE: ${{ secrets.TWILIO_TEST_PHONE }}
|
||
|
||
jobs:
|
||
# =============================================================================
|
||
# KB Tests (kb) - Run once with SQLite (requires Qdrant, Neo4j, FastEmbed)
|
||
# =============================================================================
|
||
KBTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
qdrant:
|
||
image: qdrant/qdrant:latest
|
||
ports:
|
||
- 6333:6333
|
||
- 6334:6334
|
||
|
||
fastembed:
|
||
image: yaoapp/fastembed:latest-amd64
|
||
env:
|
||
FASTEMBED_PASSWORD: Yao@2026
|
||
ports:
|
||
- 6001:8000
|
||
|
||
neo4j:
|
||
image: neo4j:latest
|
||
ports:
|
||
- "7687:7687"
|
||
env:
|
||
NEO4J_AUTH: neo4j/Yao2026Neo4j
|
||
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 KB Tests (kb) running with SQLite...'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Apple Private Key
|
||
run: |
|
||
mkdir -p ../app/openapi/certs/apple
|
||
echo "${{ secrets.APPLE_PRIVATE_KEY_USER }}" > ../app/openapi/certs/apple/signin_client_secret_key.p8
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Run KB Tests (kb)
|
||
run: make unit-test-kb
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
|
||
- name: "Comment on PR - KB Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ KB Tests (kb) passed!'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Agent Tests (agent, aigc) - Run once with SQLite
|
||
# =============================================================================
|
||
AgentTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
qdrant:
|
||
image: qdrant/qdrant:latest
|
||
ports:
|
||
- 6333:6333
|
||
- 6334:6334
|
||
|
||
fastembed:
|
||
image: yaoapp/fastembed:latest-amd64
|
||
env:
|
||
FASTEMBED_PASSWORD: Yao@2026
|
||
ports:
|
||
- 6001:8000
|
||
|
||
neo4j:
|
||
image: neo4j:latest
|
||
ports:
|
||
- "7687:7687"
|
||
env:
|
||
NEO4J_AUTH: neo4j/Yao2026Neo4j
|
||
|
||
mcp-everything:
|
||
image: yaoapp/mcp-everything:latest
|
||
ports:
|
||
- "3021:3021"
|
||
- "3022:3022"
|
||
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 Agent Tests (agent, aigc) running with SQLite...'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Apple Private Key
|
||
run: |
|
||
mkdir -p ../app/openapi/certs/apple
|
||
echo "${{ secrets.APPLE_PRIVATE_KEY_USER }}" > ../app/openapi/certs/apple/signin_client_secret_key.p8
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Install pdftoppm, mutool, imagemagick
|
||
run: |
|
||
sudo apt update
|
||
sudo apt install -y poppler-utils mupdf-tools imagemagick
|
||
|
||
- name: Test pdftoppm, mutool, imagemagick
|
||
run: |
|
||
pdftoppm -v
|
||
mutool -v
|
||
convert -version
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Pull Sandbox Test Images
|
||
run: |
|
||
docker pull alpine:latest
|
||
docker pull yaoapp/sandbox-base:latest || true
|
||
docker pull yaoapp/sandbox-claude:latest || true
|
||
|
||
- name: Run Agent Tests (agent, aigc)
|
||
env:
|
||
YAO_SANDBOX_WORKSPACE: ${{ runner.temp }}/sandbox/workspace
|
||
YAO_SANDBOX_IPC: ${{ runner.temp }}/sandbox/ipc
|
||
run: |
|
||
export YAO_SANDBOX_CONTAINER_USER="$(id -u):$(id -g)"
|
||
make unit-test-agent
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
|
||
- name: "Comment on PR - Agent Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ Agent Tests (agent, aigc) passed!'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Robot Tests (all agent/robot/... packages) - Unit + E2E with real LLM calls
|
||
# =============================================================================
|
||
RobotTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
mcp-everything:
|
||
image: yaoapp/mcp-everything:latest
|
||
ports:
|
||
- "3021:3021"
|
||
- "3022:3022"
|
||
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 Robot Tests (Unit + E2E) running with SQLite...'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Run Robot Tests (Unit + E2E)
|
||
run: make unit-test-robot
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
|
||
- name: "Comment on PR - Robot Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ Robot Tests (Unit + E2E) passed!'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Sandbox Tests (requires Docker) - Run with Docker-in-Docker
|
||
# =============================================================================
|
||
SandboxTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 Sandbox Tests running with Docker...'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Pull Sandbox Test Images
|
||
run: |
|
||
docker pull alpine:latest
|
||
docker pull yaoapp/sandbox-base:latest || true
|
||
docker pull yaoapp/sandbox-claude:latest || true
|
||
|
||
- name: Run Sandbox Tests
|
||
env:
|
||
YAO_SANDBOX_WORKSPACE: ${{ runner.temp }}/sandbox/workspace
|
||
YAO_SANDBOX_IPC: ${{ runner.temp }}/sandbox/ipc
|
||
run: |
|
||
# Use runner's UID:GID to avoid permission issues
|
||
export YAO_SANDBOX_CONTAINER_USER="$(id -u):$(id -g)"
|
||
make unit-test-sandbox
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
|
||
- name: "Comment on PR - Sandbox Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ Sandbox Tests passed!'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Sandbox V2 Tests (tai + sandbox/v2 + workspace, Docker + K8s via k3d)
|
||
# =============================================================================
|
||
SandboxV2Test:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 Sandbox V2 Tests running (tai + sandbox-v2 + workspace)...'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Apple Private Key
|
||
run: |
|
||
mkdir -p ../app/openapi/certs/apple
|
||
echo "${{ secrets.APPLE_PRIVATE_KEY_USER }}" > ../app/openapi/certs/apple/signin_client_secret_key.p8
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Pull Test Images
|
||
run: |
|
||
docker pull yaoapp/sandbox-v2-test:latest || true
|
||
docker pull yaoapp/tai:latest
|
||
docker pull alpine:latest
|
||
|
||
- name: Install k3d
|
||
run: curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
|
||
|
||
- name: Create k3d cluster
|
||
run: |
|
||
k3d cluster create tai-test --no-lb --wait --api-port 16443
|
||
kubectl wait --for=condition=Ready node --all --timeout=60s
|
||
k3d image import alpine:latest -c tai-test
|
||
|
||
- name: Start Tai Docker instance
|
||
run: |
|
||
docker run -d --name tai-docker \
|
||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||
-p 8080:8080 -p 9100:9100 -p 2375:2375 -p 6080:6080 \
|
||
yaoapp/tai:latest
|
||
|
||
for i in $(seq 1 30); do
|
||
if curl -sf http://127.0.0.1:8080/healthz > /dev/null 2>&1; then
|
||
echo "Tai Docker HTTP ready"; break
|
||
fi
|
||
echo "Waiting for Tai Docker HTTP... ($i)"; sleep 1
|
||
done
|
||
curl -sf http://127.0.0.1:8080/healthz > /dev/null 2>&1 || {
|
||
echo "::error::Tai Docker HTTP failed"; docker logs tai-docker 2>&1; exit 1
|
||
}
|
||
|
||
for i in $(seq 1 15); do
|
||
if nc -z 127.0.0.1 9100 2>/dev/null; then
|
||
echo "Tai Docker gRPC ready"; break
|
||
fi
|
||
echo "Waiting for Tai Docker gRPC... ($i)"; sleep 1
|
||
done
|
||
nc -z 127.0.0.1 9100 2>/dev/null || {
|
||
echo "::error::Tai Docker gRPC failed"; docker logs tai-docker 2>&1; exit 1
|
||
}
|
||
|
||
- name: Start Tai K8s instance
|
||
run: |
|
||
K3D_IP=$(docker inspect k3d-tai-test-server-0 | jq -r '.[0].NetworkSettings.Networks["k3d-tai-test"].IPAddress')
|
||
echo "k3d server IP: ${K3D_IP}"
|
||
|
||
docker run -d --name tai-k8s \
|
||
--network k3d-tai-test \
|
||
-p 8081:8080 -p 9101:9100 -p 6443:6443 -p 6081:6080 \
|
||
-e TAI_K8S_UPSTREAM="tcp://${K3D_IP}:6443" \
|
||
yaoapp/tai:latest
|
||
|
||
for i in $(seq 1 30); do
|
||
if curl -sf http://127.0.0.1:8081/healthz > /dev/null 2>&1; then
|
||
echo "Tai K8s HTTP ready"; break
|
||
fi
|
||
echo "Waiting for Tai K8s HTTP... ($i)"; sleep 1
|
||
done
|
||
curl -sf http://127.0.0.1:8081/healthz > /dev/null 2>&1 || {
|
||
echo "::error::Tai K8s HTTP failed"; docker logs tai-k8s 2>&1; exit 1
|
||
}
|
||
|
||
for i in $(seq 1 15); do
|
||
if nc -z 127.0.0.1 9101 2>/dev/null; then
|
||
echo "Tai K8s gRPC ready"; break
|
||
fi
|
||
echo "Waiting for Tai K8s gRPC... ($i)"; sleep 1
|
||
done
|
||
nc -z 127.0.0.1 9101 2>/dev/null || {
|
||
echo "::error::Tai K8s gRPC failed"; docker logs tai-k8s 2>&1; exit 1
|
||
}
|
||
|
||
- name: Generate kubeconfig for Tai K8s proxy
|
||
run: |
|
||
k3d kubeconfig get tai-test > /tmp/kubeconfig-k3d.yml
|
||
sed 's|server: .*|server: https://127.0.0.1:6443|' /tmp/kubeconfig-k3d.yml \
|
||
> ${{ runner.temp }}/kubeconfig-tai.yml
|
||
echo "Generated kubeconfig:"
|
||
grep server: ${{ runner.temp }}/kubeconfig-tai.yml
|
||
|
||
- name: Run Sandbox V2 Tests (tai + sandbox-v2 + workspace)
|
||
env:
|
||
TAI_TEST_HOST: "127.0.0.1"
|
||
TAI_TEST_DOCKER: "tcp://127.0.0.1:2375"
|
||
TAI_TEST_GRPC_PORT: "9100"
|
||
TAI_TEST_K8S_HOST: "127.0.0.1"
|
||
TAI_TEST_K8S_PORT: "6443"
|
||
TAI_TEST_K8S_GRPC_PORT: "9101"
|
||
TAI_TEST_KUBECONFIG: "${{ runner.temp }}/kubeconfig-tai.yml"
|
||
TAI_TEST_HOST_IP: "172.17.0.1"
|
||
SANDBOX_TEST_REMOTE_ADDR: "tai://127.0.0.1:9100"
|
||
SANDBOX_TEST_IMAGE: "yaoapp/sandbox-v2-test:latest"
|
||
run: make unit-test-sandbox-v2
|
||
|
||
- name: Codecov Report
|
||
if: always()
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
fail_ci_if_error: false
|
||
|
||
- name: "Comment on PR - Sandbox V2 Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ Sandbox V2 Tests passed (tai + sandbox-v2 + workspace)!'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Benchmark & Memory Leak Tests - Run with MySQL8.0 and SQLite3
|
||
# =============================================================================
|
||
PerfTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
mcp-everything:
|
||
image: yaoapp/mcp-everything:latest
|
||
ports:
|
||
- "3021:3021"
|
||
- "3022:3022"
|
||
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
db: [MySQL8.0, SQLite3]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Install FFmpeg 7.x
|
||
run: |
|
||
wget https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz
|
||
tar -xf ffmpeg-master-latest-linux64-gpl.tar.xz
|
||
sudo cp ffmpeg-master-latest-linux64-gpl/bin/ffmpeg /usr/local/bin/
|
||
sudo cp ffmpeg-master-latest-linux64-gpl/bin/ffprobe /usr/local/bin/
|
||
sudo chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe
|
||
|
||
- name: Test FFmpeg
|
||
run: ffmpeg -version
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ${{ matrix.db }}
|
||
uses: ./.github/actions/setup-db
|
||
with:
|
||
kind: "${{ matrix.db }}"
|
||
db: "xiang"
|
||
user: "xiang"
|
||
password: ${{ secrets.UNIT_PASS }}
|
||
|
||
- name: Setup ENV
|
||
env:
|
||
PASSWORD: ${{ secrets.UNIT_PASS }}
|
||
run: |
|
||
echo "YAO_DB_DRIVER=$DB_DRIVER" >> $GITHUB_ENV
|
||
if [ "$DB_DRIVER" = "mysql" ]; then
|
||
echo "YAO_DB_PRIMARY=$DB_USER:$PASSWORD@$DB_HOST" >> $GITHUB_ENV
|
||
else
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
fi
|
||
|
||
- name: Run Benchmark & Memory Leak Tests
|
||
run: |
|
||
make benchmark
|
||
make memory-leak
|
||
|
||
# =============================================================================
|
||
# Core Tests - Run with DB matrix (MySQL/SQLite/Redis/Mongo combinations)
|
||
# =============================================================================
|
||
CoreTest:
|
||
runs-on: ubuntu-latest
|
||
|
||
services:
|
||
qdrant:
|
||
image: qdrant/qdrant:latest
|
||
ports:
|
||
- 6333:6333 # HTTP API
|
||
- 6334:6334 # gRPC
|
||
|
||
fastembed:
|
||
image: yaoapp/fastembed:latest-amd64
|
||
env:
|
||
FASTEMBED_PASSWORD: Yao@2026
|
||
ports:
|
||
- 6001:8000
|
||
|
||
neo4j:
|
||
image: neo4j:latest
|
||
ports:
|
||
- "7687:7687"
|
||
env:
|
||
NEO4J_AUTH: neo4j/Yao2026Neo4j
|
||
|
||
mcp-everything:
|
||
image: yaoapp/mcp-everything:latest
|
||
ports:
|
||
- "3021:3021"
|
||
- "3022:3022"
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
db: [MySQL8.0, SQLite3]
|
||
redis: [4, 5, 6]
|
||
mongo: ["6.0"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var fs = require('fs');
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: 'Thank you for the PR! The db: ${{ matrix.db }} redis: ${{ matrix.redis }} mongo: ${{ matrix.mongo }} test workflow is running, the results of the run will be commented later.'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file") # Get the directory where the ZIP file is located
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Yao Startup Webapp
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-startup-webapp
|
||
submodules: true
|
||
token: ${{ secrets.YAO_TEST_TOKEN }}
|
||
path: yao-startup-webapp
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Kun, Xun, Gou, V8Go
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
mv yao-startup-webapp ../
|
||
ls -l .
|
||
ls -l ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Apple Private Key
|
||
run: |
|
||
mkdir -p ../app/openapi/certs/apple
|
||
echo "${{ secrets.APPLE_PRIVATE_KEY_USER }}" > ../app/openapi/certs/apple/signin_client_secret_key.p8
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:${{ matrix.redis }}
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Install FFmpeg 7.x
|
||
run: |
|
||
wget https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz
|
||
tar -xf ffmpeg-master-latest-linux64-gpl.tar.xz
|
||
sudo cp ffmpeg-master-latest-linux64-gpl/bin/ffmpeg /usr/local/bin/
|
||
sudo cp ffmpeg-master-latest-linux64-gpl/bin/ffprobe /usr/local/bin/
|
||
sudo chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe
|
||
|
||
- name: Test FFmpeg
|
||
run: ffmpeg -version
|
||
|
||
- name: Install pdftoppm, mutool, imagemagick
|
||
run: |
|
||
sudo apt update
|
||
sudo apt install -y poppler-utils mupdf-tools imagemagick
|
||
|
||
- name: Test pdftoppm, mutool, imagemagick
|
||
run: |
|
||
pdftoppm -v
|
||
mutool -v
|
||
convert -version
|
||
|
||
- name: Start MongoDB
|
||
run: |
|
||
docker run --name mongodb --publish 27017:27017 \
|
||
-e MONGO_INITDB_DATABASE=test \
|
||
-e MONGO_INITDB_ROOT_USERNAME=root \
|
||
-e MONGO_INITDB_ROOT_PASSWORD=123456 \
|
||
--detach mongo:${{ matrix.mongo }}
|
||
# Wait for MongoDB to be ready
|
||
for i in $(seq 1 20); do
|
||
if docker exec mongodb mongosh --quiet --port 27017 --username root --password 123456 --eval "db.serverStatus()" > /dev/null 2>&1; then
|
||
echo "MongoDB is ready"
|
||
break
|
||
fi
|
||
echo "Waiting for MongoDB... ($i)"
|
||
sleep 1
|
||
done
|
||
|
||
- name: Setup MySQL8.0 (connector)
|
||
uses: ./.github/actions/setup-db
|
||
with:
|
||
kind: "MySQL8.0"
|
||
db: "test"
|
||
user: "test"
|
||
password: "123456"
|
||
port: "3308"
|
||
|
||
- name: Setup ${{ matrix.db }}
|
||
uses: ./.github/actions/setup-db
|
||
with:
|
||
kind: "${{ matrix.db }}"
|
||
db: "xiang"
|
||
user: "xiang"
|
||
password: ${{ secrets.UNIT_PASS }}
|
||
|
||
- name: Setup Go Tools
|
||
run: |
|
||
make tools
|
||
|
||
- name: Setup ENV & Host
|
||
env:
|
||
PASSWORD: ${{ secrets.UNIT_PASS }}
|
||
run: |
|
||
sudo echo "127.0.0.1 local.iqka.com" | sudo tee -a /etc/hosts
|
||
echo "YAO_DB_DRIVER=$DB_DRIVER" >> $GITHUB_ENV
|
||
echo "GITHUB_WORKSPACE:\n" && ls -l $GITHUB_WORKSPACE
|
||
|
||
if [ "$DB_DRIVER" = "mysql" ]; then
|
||
echo "YAO_DB_PRIMARY=$DB_USER:$PASSWORD@$DB_HOST" >> $GITHUB_ENV
|
||
elif [ "$DB_DRIVER" = "postgres" ]; then
|
||
echo "YAO_DB_PRIMARY=postgres://$DB_USER:$PASSWORD@$DB_HOST" >> $GITHUB_ENV
|
||
else
|
||
echo "YAO_DB_PRIMARY=$YAO_ROOT/$DB_HOST" >> $GITHUB_ENV
|
||
fi
|
||
|
||
echo ".:\n" && ls -l .
|
||
echo "..:\n" && ls -l ..
|
||
ping -c 1 -t 1 local.iqka.com
|
||
|
||
- name: Test Prepare
|
||
run: |
|
||
make vet
|
||
make fmt-check
|
||
make misspell-check
|
||
|
||
- name: Run Core Tests (exclude AI)
|
||
run: make unit-test-core
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var fs = require('fs');
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✨DONE✨ db: ${{ matrix.db }} redis: ${{ matrix.redis }} mongo: ${{ matrix.mongo }} passed.'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Registry Client SDK Tests (requires Yao Registry Docker service)
|
||
# =============================================================================
|
||
RegistryTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
yao-registry:
|
||
image: yaoapp/registry:latest
|
||
ports:
|
||
- "8080:8080"
|
||
env:
|
||
REGISTRY_INIT_USER: yaoagents
|
||
REGISTRY_INIT_PASS: yaoagents
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 Registry Client SDK Tests running...'
|
||
});
|
||
|
||
- name: Wait for Registry
|
||
run: |
|
||
for i in $(seq 1 15); do
|
||
if curl -sf http://localhost:8080/.well-known/yao-registry > /dev/null 2>&1; then
|
||
echo "Registry is ready"
|
||
break
|
||
fi
|
||
echo "Waiting for registry... ($i)"
|
||
sleep 1
|
||
done
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Run Registry Client Tests
|
||
env:
|
||
YAO_REGISTRY_URL: http://localhost:8080
|
||
YAO_TEST_APPLICATION: ${{ github.workspace }}/../app
|
||
run: make unit-test-registry
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
|
||
- name: "Comment on PR - Registry Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ Registry Client SDK Tests passed!'
|
||
});
|
||
|
||
# =============================================================================
|
||
# Benchmark: Sandbox V2 + Workspace (parallel with SandboxV2Test, non-blocking)
|
||
# =============================================================================
|
||
BenchmarkSandboxV2:
|
||
runs-on: ubuntu-latest
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Apple Private Key
|
||
run: |
|
||
mkdir -p ../app/openapi/certs/apple
|
||
echo "${{ secrets.APPLE_PRIVATE_KEY_USER }}" > ../app/openapi/certs/apple/signin_client_secret_key.p8
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Pull Test Images
|
||
run: |
|
||
docker pull yaoapp/sandbox-v2-test:latest || true
|
||
docker pull yaoapp/tai:latest
|
||
docker pull alpine:latest
|
||
|
||
- name: Start Tai (Docker proxy for benchmarks)
|
||
run: |
|
||
docker run -d --name tai \
|
||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||
-p 8080:8080 -p 9100:9100 -p 2375:2375 -p 6080:6080 \
|
||
yaoapp/tai:latest
|
||
|
||
for i in $(seq 1 30); do
|
||
if curl -sf http://127.0.0.1:8080/healthz > /dev/null 2>&1; then
|
||
echo "Tai HTTP is ready"
|
||
break
|
||
fi
|
||
echo "Waiting for Tai HTTP... ($i)"
|
||
sleep 1
|
||
done
|
||
|
||
for i in $(seq 1 15); do
|
||
if nc -z 127.0.0.1 9100 2>/dev/null; then
|
||
echo "Tai gRPC is ready"
|
||
break
|
||
fi
|
||
echo "Waiting for Tai gRPC... ($i)"
|
||
sleep 1
|
||
done
|
||
|
||
- name: Run Benchmarks
|
||
env:
|
||
TAI_TEST_HOST: "127.0.0.1"
|
||
TAI_TEST_DOCKER: "tcp://127.0.0.1:2375"
|
||
TAI_TEST_GRPC_PORT: "9100"
|
||
TAI_TEST_HOST_IP: "172.17.0.1"
|
||
SANDBOX_TEST_REMOTE_ADDR: "tai://127.0.0.1:9100"
|
||
SANDBOX_TEST_IMAGE: "yaoapp/sandbox-v2-test:latest"
|
||
run: make benchmark-sandbox-v2
|
||
|
||
# =============================================================================
|
||
# gRPC Tests - Run once with SQLite (transport layer, no DB matrix needed)
|
||
# =============================================================================
|
||
GRPCTest:
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
mongodb:
|
||
image: mongo:6.0
|
||
ports:
|
||
- 27017:27017
|
||
env:
|
||
MONGO_INITDB_ROOT_USERNAME: root
|
||
MONGO_INITDB_ROOT_PASSWORD: 123456
|
||
MONGO_INITDB_DATABASE: test
|
||
|
||
strategy:
|
||
matrix:
|
||
go: ["1.25"]
|
||
if: >
|
||
${{ github.event.workflow_run.event == 'pull_request' &&
|
||
github.event.workflow_run.conclusion == 'success' }}
|
||
steps:
|
||
- name: "Download artifact"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
run_id: ${{github.event.workflow_run.id }},
|
||
});
|
||
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||
return artifact.name == "pr"
|
||
})[0];
|
||
var download = await github.rest.actions.downloadArtifact({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
artifact_id: matchArtifact.id,
|
||
archive_format: 'zip',
|
||
});
|
||
var fs = require('fs');
|
||
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
|
||
|
||
- name: "Read NR & SHA"
|
||
run: |
|
||
unzip pr.zip
|
||
cat NR
|
||
cat SHA
|
||
echo HEAD=$(cat SHA) >> $GITHUB_ENV
|
||
echo NR=$(cat NR) >> $GITHUB_ENV
|
||
|
||
- name: "Comment on PR"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '🤖 gRPC Tests running with SQLite...'
|
||
});
|
||
|
||
- name: Checkout Kun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/kun
|
||
path: kun
|
||
|
||
- name: Checkout Xun
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/xun
|
||
path: xun
|
||
|
||
- name: Checkout Gou
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/gou
|
||
path: gou
|
||
|
||
- name: Checkout V8Go
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/v8go
|
||
path: v8go
|
||
|
||
- name: Unzip libv8
|
||
run: |
|
||
files=$(find ./v8go -name "libv8*.zip")
|
||
for file in $files; do
|
||
dir=$(dirname "$file")
|
||
echo "Extracting $file to directory $dir"
|
||
unzip -o -d $dir $file
|
||
rm -rf $dir/__MACOSX
|
||
done
|
||
|
||
- name: Checkout Demo App
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-dev-app
|
||
path: app
|
||
|
||
- name: Checkout Extension
|
||
uses: actions/checkout@v4
|
||
with:
|
||
repository: yaoapp/yao-extensions-dev
|
||
path: extension
|
||
|
||
- name: Move Dependencies
|
||
run: |
|
||
mv kun ../
|
||
mv xun ../
|
||
mv gou ../
|
||
mv v8go ../
|
||
mv app ../
|
||
mv extension ../
|
||
|
||
- name: Checkout pull request HEAD commit
|
||
uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ env.HEAD }}
|
||
|
||
- name: Setup Apple Private Key
|
||
run: |
|
||
mkdir -p ../app/openapi/certs/apple
|
||
echo "${{ secrets.APPLE_PRIVATE_KEY_USER }}" > ../app/openapi/certs/apple/signin_client_secret_key.p8
|
||
|
||
- name: Setup Go ${{ matrix.go }}
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ matrix.go }}
|
||
|
||
- name: Start Redis
|
||
run: docker run --name redis --publish 6379:6379 --detach redis:6
|
||
|
||
- name: Setup Go Tools
|
||
run: make tools
|
||
|
||
- name: Setup ENV (SQLite)
|
||
run: |
|
||
mkdir -p ${{ github.WORKSPACE }}/../app/db
|
||
echo "YAO_DB_DRIVER=sqlite3" >> $GITHUB_ENV
|
||
echo "YAO_DB_PRIMARY=${{ github.WORKSPACE }}/../app/db/yao.db" >> $GITHUB_ENV
|
||
|
||
- name: Run gRPC Tests
|
||
run: make unit-test-grpc
|
||
|
||
- name: Codecov Report
|
||
uses: codecov/codecov-action@v4
|
||
with:
|
||
token: ${{ secrets.CODECOV_TOKEN }}
|
||
|
||
- name: "Comment on PR - gRPC Tests Done"
|
||
uses: actions/github-script@v7
|
||
with:
|
||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||
script: |
|
||
const { NR } = process.env
|
||
var issue_number = NR;
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issue_number,
|
||
body: '✅ gRPC Tests passed!'
|
||
});
|