Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions .github/workflows/nightly-jupiter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Nightly Jupiter Trading Pairs Test

on:
schedule:
# Run daily at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch: # Allow manual triggering
inputs:
min_success_rate:
description: 'Minimum success rate percentage (default: 80)'
required: false
default: '80'

env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always

jobs:
nightly-test:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-

- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-git-

- name: Cache target directory
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-target-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-target-

- name: Install Surfpool (optional)
run: |
# Install surfpool from source
git clone https://github.com/txtx/surfpool.git /tmp/surfpool
cd /tmp/surfpool
cargo xtask install || echo "Surfpool installation skipped"

- name: Run nightly tests
env:
HELIUS_API_KEY: ${{ secrets.HELIUS_API_KEY }}
SURFPOOL_ENABLED: ${{ secrets.SURFPOOL_ENABLED || '0' }}
MIN_SUCCESS_RATE: ${{ github.event.inputs.min_success_rate || '80' }}
RUST_LOG: info
working-directory: src
run: |
cargo test -p solana_test_utils --test nightly_jupiter -- --ignored --nocapture

- name: Upload test reports
if: always()
uses: actions/upload-artifact@v4
with:
name: nightly-test-reports-${{ github.run_number }}
path: |
src/solana_test_utils/reports/nightly/*.json
src/solana_test_utils/reports/nightly/*.md
retention-days: 30

- name: Read latest report
if: always()
id: report
run: |
if [ -f src/solana_test_utils/reports/nightly/latest.md ]; then
echo "report_exists=true" >> $GITHUB_OUTPUT
# Read first 1000 chars of report for summary
head -c 1000 src/solana_test_utils/reports/nightly/latest.md > /tmp/report_summary.txt
else
echo "report_exists=false" >> $GITHUB_OUTPUT
fi

- name: Comment on commit (if report exists)
if: always() && steps.report.outputs.report_exists == 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const reportPath = 'src/solana_test_utils/reports/nightly/latest.md';

if (fs.existsSync(reportPath)) {
const report = fs.readFileSync(reportPath, 'utf8');

// Post as workflow summary
await core.summary
.addHeading('Jupiter Nightly Test Report')
.addRaw(report)
.write();
}

- name: Notify on failure
if: failure()
uses: actions/github-script@v7
with:
script: |
const issue_number = context.issue.number;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: 1, // Adjust to your notification issue number
body: '❌ Nightly Jupiter test failed. Check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.'
});

- name: Post to Slack (optional)
if: failure() && secrets.SLACK_WEBHOOK_URL != ''
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "❌ Jupiter nightly tests failed",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Jupiter Nightly Test Failed*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
1 change: 1 addition & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"Config":"7206b539fe0c38605adb937a59631055fcebf9e9e450d5a855a8d91890fe57bb.json","RepoTags":["docker.io/library/parser_app:latest"],"Layers":["62dcf5452ea5243894c4559f455c0dbe564a35116422c0784a700c719aeb018b.tar","3a9981d4d037340a18f87b0afe182f94f0078bfcf39bd5904aa25d6f813e4eb5.tar","b93e49931ed6f6f9e0c142c7be9525be4ba4f796cb97ae05662e4144830b6135.tar"]}]
Binary file added parser_app.tar
Binary file not shown.
Binary file added parser_host.tar
Binary file not shown.
1 change: 1 addition & 0 deletions repositories
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"docker.io/library/parser_app":{"latest":"9e481a93f6b00c347eb07ab51de5e62354ae58668f533e92876eec88ffe7b9a7"}}
101 changes: 101 additions & 0 deletions scripts/start-parser.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/bin/sh
set -e

# Default values
PARSER_HOST="${PARSER_HOST:-0.0.0.0}"
PARSER_PORT="${PARSER_PORT:-44020}"
PARSER_METRICS_PORT="${PARSER_METRICS_PORT:-44021}"
PARSER_OUTER_SOCKET_PATH="${PARSER_OUTER_SOCKET_PATH:-/tmp/outer_parser.sock}"
PARSER_INNER_SOCKET_PATH="${PARSER_INNER_SOCKET_PATH:-/tmp/inner_parser.sock}"
EPHEMERAL_FILE="${EPHEMERAL_FILE:-${ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || echo .)}/src/integration/fixtures/ephemeral.secret}"
GATEWAY_PORT="${GATEWAY_PORT:-8080}"

# Binary locations (use cargo run in dev, direct binaries in container)
PARSER_APP_BIN="${PARSER_APP_BIN:-cargo run --bin parser_app --}"
SIMULATOR_ENCLAVE_BIN="${SIMULATOR_ENCLAVE_BIN:-cargo run --bin simulator_enclave --}"
PARSER_HOST_BIN="${PARSER_HOST_BIN:-cargo run --bin parser_host --}"
GATEWAY_BIN="${GATEWAY_BIN:-/usr/local/bin/gateway}"

# Timeout for waiting (in seconds)
TIMEOUT="${TIMEOUT:-30}"

# Clean up any existing sockets
rm -f "${PARSER_OUTER_SOCKET_PATH}" "${PARSER_INNER_SOCKET_PATH}"

# Trap to clean up background processes on exit
cleanup() {
echo "Shutting down..."
[ -n "$APP_PID" ] && kill $APP_PID 2>/dev/null || true
[ -n "$ENCLAVE_PID" ] && kill $ENCLAVE_PID 2>/dev/null || true
[ -n "$GATEWAY_PID" ] && kill $GATEWAY_PID 2>/dev/null || true
rm -f "${PARSER_OUTER_SOCKET_PATH}" "${PARSER_INNER_SOCKET_PATH}"
}
trap cleanup EXIT INT TERM

# Function to wait for a socket to exist
wait_for_socket() {
local socket_path="$1"
local component_name="$2"
local elapsed=0

echo "Waiting for ${component_name} socket at ${socket_path}..."
while [ ! -S "${socket_path}" ]; do
if [ $elapsed -ge $TIMEOUT ]; then
echo "ERROR: Timeout waiting for ${component_name} socket"
return 1
fi
sleep 0.1
elapsed=$((elapsed + 1))
done
echo "${component_name} socket ready"
}

# Start parser_app in background
echo "Starting parser_app..."
$PARSER_APP_BIN \
--usock "${PARSER_INNER_SOCKET_PATH}" \
--ephemeral-file "${EPHEMERAL_FILE}" &
APP_PID=$!

# Wait for parser_app socket to be created
wait_for_socket "${PARSER_INNER_SOCKET_PATH}" "parser_app"

# Start simulator_enclave in background
echo "Starting simulator_enclave..."
$SIMULATOR_ENCLAVE_BIN \
"${PARSER_OUTER_SOCKET_PATH}" \
"${PARSER_INNER_SOCKET_PATH}" &
ENCLAVE_PID=$!

# Wait for simulator_enclave socket to be created
wait_for_socket "${PARSER_OUTER_SOCKET_PATH}" "simulator_enclave"

# Start parser_host in background
echo "Starting parser_host on ${PARSER_HOST}:${PARSER_PORT}..."
$PARSER_HOST_BIN \
--host-ip "${PARSER_HOST}" \
--host-port "${PARSER_PORT}" \
--metrics \
--metrics-port "${PARSER_METRICS_PORT}" \
--usock "${PARSER_OUTER_SOCKET_PATH}" &
PARSER_HOST_PID=$!

# Wait a moment for parser_host to start
sleep 2

# Start grpc-gateway if binary exists
if [ -x "${GATEWAY_BIN}" ]; then
echo "Starting grpc-gateway on port ${GATEWAY_PORT}..."
$GATEWAY_BIN \
--grpc-server-endpoint "localhost:${PARSER_PORT}" \
--http-port "${GATEWAY_PORT}" &
GATEWAY_PID=$!
echo "Gateway ready at http://localhost:${GATEWAY_PORT}"
fi

echo "Parser is ready to accept requests"
echo " gRPC: ${PARSER_HOST}:${PARSER_PORT}"
echo " REST: http://localhost:${GATEWAY_PORT}/visualsign/api/v1/parse"

# Wait for parser_host process
wait $PARSER_HOST_PID
Loading
Loading