Skip to content
42 changes: 34 additions & 8 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,18 @@ jobs:
- 3.12.0
- 3.13.0
- 3.14.1
env:
BACKEND_APISIX_VERSION: ${{ matrix.version }}
BACKEND_APISIX_IMAGE: ${{ matrix.version }}-debian
- dev
steps:
- name: Determine APISIX image tag
run: |
if [ "${{ matrix.version }}" = "dev" ]; then
echo "BACKEND_APISIX_VERSION=999.999.999" >> $GITHUB_ENV
echo "BACKEND_APISIX_IMAGE=dev" >> $GITHUB_ENV
else
echo "BACKEND_APISIX_VERSION=${{ matrix.version }}" >> $GITHUB_ENV
echo "BACKEND_APISIX_IMAGE=${{ matrix.version }}-debian" >> $GITHUB_ENV
Comment thread
jarvis9443 marked this conversation as resolved.
Outdated
fi

- uses: actions/checkout@v4

# Setup backend environment
Expand Down Expand Up @@ -117,14 +125,32 @@ jobs:
if: contains(github.event.pull_request.labels.*.name, 'test/api7') || github.event_name == 'push'
Comment thread
jarvis9443 marked this conversation as resolved.
strategy:
matrix:
version: [3.5.5, 3.6.1, 3.7.8, 3.8.22, 3.9.2]
env:
BACKEND_API7_VERSION: ${{ matrix.version }}
BACKEND_API7_DOWNLOAD_URL: https://run.api7.ai/api7-ee/api7-ee-v${{ matrix.version }}.tar.gz
BACKEND_API7_LICENSE: ${{ secrets.BACKEND_API7_LICENSE }}
version: [3.5.5, 3.6.1, 3.7.8, 3.8.22, 3.9.2, dev]
Comment thread
jarvis9443 marked this conversation as resolved.
Outdated
steps:
- name: Determine API7 image and license
run: |
if [ "${{ matrix.version }}" = "dev" ]; then
echo "BACKEND_API7_VERSION=999.999.999" >> $GITHUB_ENV
echo "API7_DASHBOARD_IMAGE=ghcr.io/api7/api7-ee-3-integrated" >> $GITHUB_ENV
echo "API7_IMAGE_TAG=dev" >> $GITHUB_ENV
echo "BACKEND_API7_LICENSE=${{ secrets.BACKEND_API7_DEV_LICENSE }}" >> $GITHUB_ENV
else
echo "BACKEND_API7_VERSION=${{ matrix.version }}" >> $GITHUB_ENV
echo "API7_DASHBOARD_IMAGE=api7/api7-ee-3-integrated" >> $GITHUB_ENV
echo "API7_IMAGE_TAG=v${{ matrix.version }}" >> $GITHUB_ENV
echo "BACKEND_API7_LICENSE=${{ secrets.BACKEND_API7_LICENSE }}" >> $GITHUB_ENV
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- uses: actions/checkout@v4

- name: Login to GHCR
if: matrix.version == 'dev'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

# Build and test ADC CLI
- uses: actions/setup-node@v4
with:
Expand Down
25 changes: 25 additions & 0 deletions libs/backend-api7/e2e/assets/dashboard-conf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
server:
listen:
disable: true
host: "0.0.0.0"
port: 7080
tls:
disable: false
host: "0.0.0.0"
port: 7443
status:
disable: false
host: "0.0.0.0"
port: 7081
cron_spec: "@every 1s"
Comment thread
jarvis9443 marked this conversation as resolved.
Outdated
log:
level: warn
output: stderr
access_log: stdout
database:
dsn: "postgres://api7ee:changeme@postgresql:5432/api7ee"
max_open_conns: 30
session_options_config:
same_site: "lax"
secure: false
max_age: 86400
Comment thread
jarvis9443 marked this conversation as resolved.
Outdated
29 changes: 29 additions & 0 deletions libs/backend-api7/e2e/assets/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
postgresql:
image: bitnami/postgresql:14
environment:
POSTGRESQL_USERNAME: api7ee
POSTGRESQL_PASSWORD: changeme
POSTGRESQL_DATABASE: api7ee
healthcheck:
test: ["CMD", "pg_isready", "-U", "api7ee", "-d", "api7ee"]
interval: 5s
retries: 10
networks:
api7:

dashboard:
image: ${API7_DASHBOARD_IMAGE:-api7/api7-ee-3-integrated}:${API7_IMAGE_TAG:-dev}
depends_on:
postgresql:
condition: service_healthy
volumes:
- ./dashboard-conf.yaml:/app/conf/config.yaml:ro
ports:
- "7443:7443"
Comment thread
jarvis9443 marked this conversation as resolved.
networks:
api7:

networks:
api7:
driver: bridge
101 changes: 60 additions & 41 deletions libs/backend-api7/e2e/support/global-setup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from 'axios';
import { spawn, spawnSync } from 'node:child_process';
import { spawnSync } from 'node:child_process';
import { randomUUID } from 'node:crypto';
import { readFileSync, writeFileSync } from 'node:fs';
import { resolve as pathResolve } from 'node:path';
import { Agent } from 'node:https';
import * as semver from 'semver';

Expand Down Expand Up @@ -31,49 +31,58 @@ httpClient.interceptors.request.use(
(error) => Promise.reject(error),
);

const setupAPI7 = async () => {
return new Promise<void>((resolve, reject) => {
const download = spawnSync(
'sh',
[
'-c',
`curl -O ${process.env.BACKEND_API7_DOWNLOAD_URL} && tar xf api7-ee-*.tar.gz`,
],
{ cwd: `/tmp` },
);

console.log('stdout: ' + download.stdout.toString('utf-8'));
console.log('stderr: ' + download.stderr.toString('utf-8'));

const dockerComposePath = `/tmp/api7-ee/docker-compose.yaml`;
const dockerCompose = readFileSync(dockerComposePath, 'utf-8').replaceAll(
': bitnami/',
': bitnamilegacy/',
);
writeFileSync(dockerComposePath, dockerCompose, 'utf-8');

const setup = spawn('sh', ['-c', `cd api7-ee && bash run.sh start`], {
cwd: `/tmp`,
});

console.log('\nSetup API7 Instance\n');
const assetsDir = pathResolve(__dirname, '../../e2e/assets');

const waitForDashboard = async (
maxRetries = 60,
intervalMs = 2000,
): Promise<void> => {
console.log('Waiting for Dashboard to be ready...');
for (let i = 0; i < maxRetries; i++) {
try {
await httpClient.get('/api/status', { timeout: 2000 });
console.log('Dashboard is ready');
return;
} catch {
// Also try login endpoint as a fallback health check
try {
await httpClient.post(
'/api/login',
{ username: '', password: '' },
{ timeout: 2000, validateStatus: () => true },
);
console.log('Dashboard is ready');
return;
} catch {
// not ready yet
}
}
await new Promise((r) => setTimeout(r, intervalMs));
}
throw new Error(
`Dashboard not ready after ${maxRetries * intervalMs / 1000}s`,
);
};

setup.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
const setupAPI7 = async () => {
const pullPolicy =
process.env.API7_IMAGE_TAG === 'dev' ? '--pull always' : '';

setup.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
console.log('\nSetup API7 Instance via Docker Compose\n');
const result = spawnSync(
'sh',
['-c', `docker compose ${pullPolicy} up -d`],
{
cwd: assetsDir,
stdio: 'inherit',
},
);

setup.on('exit', function (code) {
if (code)
reject(`child process exited with non-zero code: ${code?.toString()}`);
if (result.status !== 0)
throw new Error(`docker compose up failed with code ${result.status}`);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

console.log('Successful deployment');
resolve();
});
});
console.log('Docker Compose started');
await waitForDashboard();
};

const initUser = async (
Expand Down Expand Up @@ -181,4 +190,14 @@ export default async () => {
process.env.GATEWAY_GROUP = 'adc';
process.env.BACKEND_API7_VERSION = '0.0.0'; */
// ONLY FOR LOCAL TEST //

// Return teardown function to clean up Docker Compose
return async () => {
if (process.env['SKIP_API7_SETUP'] === 'true') return;
console.log('Tearing down API7 via Docker Compose');
spawnSync('sh', ['-c', 'docker compose down -v'], {
cwd: assetsDir,
stdio: 'inherit',
});
};
};
3 changes: 2 additions & 1 deletion libs/backend-api7/e2e/support/global-teardown.ts
Comment thread
jarvis9443 marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Teardown is handled by the globalSetup return function in global-setup.ts
export default async () => {
//TODO
// no-op
};
Loading