- Introduce new unit test targets for Workspace and Sandbox V2 integration in the Makefile, ensuring comprehensive testing of the new features. - Update CI workflows to support MongoDB service for Sandbox V2 tests and improve Docker image handling. - Implement Workspace as a first-class entity, allowing for persistent storage decoupled from container lifecycles. - Enhance the Box struct to manage workspace IDs and update related methods for improved functionality. - Refactor tests to accommodate new Workspace features, ensuring robust testing of the integration. These changes significantly improve the testing framework and functionality of the Sandbox V2, enhancing the overall architecture and user experience.
2115 lines
63 KiB
YAML
2115 lines
63 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 + K8s proxy)
|
||
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 \
|
||
--network k3d-tai-test \
|
||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||
-p 8080:8080 -p 9100:9100 -p 2375:2375 -p 6080:6080 -p 6443:6443 \
|
||
-e TAI_K8S_UPSTREAM="tcp://${K3D_IP}:6443" \
|
||
yaoapp/tai:latest
|
||
|
||
TAI_HTTP_READY=false
|
||
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"
|
||
TAI_HTTP_READY=true
|
||
break
|
||
fi
|
||
echo "Waiting for Tai HTTP... ($i)"
|
||
sleep 1
|
||
done
|
||
if [ "$TAI_HTTP_READY" != "true" ]; then
|
||
echo "::error::Tai HTTP failed to become ready within 30s"
|
||
docker logs tai 2>&1 || true
|
||
docker inspect tai --format='{{.State.Status}} exit={{.State.ExitCode}}' || true
|
||
exit 1
|
||
fi
|
||
|
||
TAI_GRPC_READY=false
|
||
for i in $(seq 1 15); do
|
||
if nc -z 127.0.0.1 9100 2>/dev/null; then
|
||
echo "Tai gRPC is ready"
|
||
TAI_GRPC_READY=true
|
||
break
|
||
fi
|
||
echo "Waiting for Tai gRPC... ($i)"
|
||
sleep 1
|
||
done
|
||
if [ "$TAI_GRPC_READY" != "true" ]; then
|
||
echo "::error::Tai gRPC failed to become ready within 15s"
|
||
docker logs tai 2>&1 || true
|
||
exit 1
|
||
fi
|
||
|
||
- 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_K8S_HOST: "127.0.0.1"
|
||
TAI_TEST_K8S_PORT: "6443"
|
||
TAI_TEST_GRPC_PORT: "9100"
|
||
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!'
|
||
});
|