apisix-dev

SKILL.md

APISIX Development Environment Setup

This skill guides you through setting up the APISIX testing environment and running tests using TEST::NGINX.

Environment Requirements

Ubuntu Only

IMPORTANT: Direct test execution is only supported on Ubuntu.

Before proceeding, check the operating system:

uname -a && cat /etc/os-release 2>/dev/null | head -5

If NOT Ubuntu:

  1. Option A: Use Ubuntu Environment

    • Start an Ubuntu VM, container, or WSL2
    • Run commands there and paste error logs back for analysis
  2. Option B: Use DevContainers (VSCode)

If Ubuntu: Proceed with the setup below.

Quick Start (Ubuntu)

Step 1: Clone Repository with Submodules

git clone --recurse-submodules https://github.com/apache/apisix.git
cd apisix

If already cloned without submodules:

git submodule update --init --recursive

Step 2: Install Dependencies Using CI Scripts

APISIX provides CI scripts that handle all dependency installation. Use these scripts to ensure consistency with the official CI environment.

Reference the CI workflow: https://github.com/apache/apisix/blob/master/.github/workflows/build.yml

Key CI Scripts:

  • ci/common.sh - Common utilities and dependency functions
  • ci/linux_openresty_runner.sh - Main runner script
  • ci/linux_openresty_common_runner.sh - Installation functions (before_install, do_install)

Run the installation:

# Source the CI scripts and run installation
cd apisix

# Set required environment variables
export OPENRESTY_VERSION=default
export SERVER_NAME=linux_openresty

# Source and run the CI installation functions
. ./ci/common.sh
. ./ci/linux_openresty_common_runner.sh

# Run before_install (installs system dependencies, Test::Nginx)
before_install

# Run do_install (installs OpenResty, Lua deps, test-nginx, etc.)
do_install

What the CI scripts install:

  • System packages (cpanminus, build-essential, libssl-dev, etc.)
  • Test::Nginx via cpanm
  • OpenResty with correct version
  • Lua dependencies (make deps)
  • test-nginx from openresty/test-nginx
  • Additional tools (grpcurl, Node.js, etc.)

Note: etcd runs in Docker container, not installed locally.

Step 3: Verify Installation

# Verify OpenResty
openresty -v

# Verify test-nginx exists
ls test-nginx/

Note: If you encounter issues with the CI scripts, check the latest build.yml for any changes to the installation process. The CI scripts are the source of truth for the test environment setup.

Environment Variables

Set these environment variables before running tests:

export OPENRESTY_PREFIX="/usr/local/openresty"
export PATH=$OPENRESTY_PREFIX/nginx/sbin:$OPENRESTY_PREFIX/luajit/bin:$OPENRESTY_PREFIX/bin:$PATH

# Optional - adjust based on your setup
export OPENRESTY_VERSION=default
export SERVER_NAME=linux_openresty

Verify the setup:

which openresty
openresty -v
which etcd
etcd --version

Running Tests

Basic Test Execution

Tests use the prove command with TEST::NGINX. Run from the APISIX repository root:

# Run a single test file
FLUSH_ETCD=1 prove -I./test-nginx/lib -I./ t/path/to/test.t

# Example: Run a specific test
FLUSH_ETCD=1 prove -I./test-nginx/lib -I./ t/plugin/limit-count.t

Test Command Options

Option Description
FLUSH_ETCD=1 Flush etcd before running tests (recommended)
-I./test-nginx/lib Include test-nginx library path
-I./ Include current directory
-v Verbose output
-r Recurse into directories

Run Multiple Tests

# Run all tests in a directory
FLUSH_ETCD=1 prove -I./test-nginx/lib -I./ -r t/plugin/

# Run tests matching a pattern
FLUSH_ETCD=1 prove -I./test-nginx/lib -I./ t/plugin/limit-*.t

Start Required Services

Before running tests, start the CI environment using Docker:

# Start all required services (etcd, etc.) via Docker
make ci-env-up project_compose_ci=ci/pod/docker-compose.common.yml

This starts the necessary containers including etcd. No manual etcd installation is required.

To stop the services:

make ci-env-down

Lint Before Committing

IMPORTANT: Always lint test files before committing.

# Lint all code (source + tests)
make lint

# Or run individual lint scripts
./utils/check-lua-code-style.sh      # Lint source code
./utils/check-test-code-style.sh     # Lint test files

The make lint target:

  1. Requires utils target (downloads linting utilities)
  2. Runs check-lua-code-style.sh for source code
  3. Runs check-test-code-style.sh for test files

Reference: https://github.com/apache/apisix/blob/master/Makefile#L171-L178

Skippable Steps (Initial Setup)

For initial testing, you can skip these steps from the CI workflow:

  1. WASM-related steps - Only needed for WASM plugin tests
  2. Start some services - Only needed for specific integration tests
  3. Build XDS Library - Only needed for xDS-related tests
  4. Build WASM Core - Only needed for WASM tests
  5. Dubbo backend - Only needed for Dubbo plugin tests

APISIX Deployment Modes

Reference: https://apisix.apache.org/docs/apisix/deployment-modes/

APISIX supports three deployment modes:

Mode Description Config Provider
traditional Data plane + control plane together etcd only
decoupled Separate data/control planes etcd only
standalone Data plane with local file config yaml or json

Using YAML Config Provider

CRITICAL: Only data_plane role supports config_provider: yaml.

CORRECT configuration (in conf/config.yaml):

deployment:
  role: data_plane
  role_data_plane:
    config_provider: yaml

INCORRECT - This does NOT work:

# DO NOT USE - traditional role does not support yaml config provider
deployment:
  role: traditional
  role_traditional:
    config_provider: yaml

Symptoms of incorrect configuration:

  1. config.yaml gets overwritten when running apisix start/reload/init
  2. Content configured in apisix.yaml has no effect

YAML Configuration File

When using config_provider: yaml:

  • Rules are stored in conf/apisix.yaml
  • File must end with #END marker for APISIX to load it
  • APISIX checks for changes every second and hot-reloads

Example conf/apisix.yaml:

routes:
  - uri: /hello
    upstream:
      nodes:
        '127.0.0.1:8080': 1
      type: roundrobin
#END

CI Reference

IMPORTANT: Always check the official CI workflow for the latest installation process. The CI scripts are maintained by the APISIX team and are the source of truth.

Official CI workflow: https://github.com/apache/apisix/blob/master/.github/workflows/build.yml

Key CI scripts in the repository:

Script Purpose
ci/common.sh Common utilities, dependency functions, tool installation
ci/linux_openresty_runner.sh Main Linux runner (sources common_runner)
ci/linux_openresty_common_runner.sh before_install(), do_install(), script() functions

CI Functions:

  • before_install() - Installs system dependencies, Test::Nginx
  • do_install() - Installs OpenResty, etcd, Lua deps, test-nginx, grpcurl, etc.
  • script() - Runs the actual test suite

When something doesn't work: Check if the CI scripts have been updated. The build.yml and CI scripts evolve with the project.

Troubleshooting

Test Fails with "nginx: command not found"

Ensure OpenResty is in PATH:

export PATH=/usr/local/openresty/nginx/sbin:$PATH
which nginx

etcd Connection Failed

Ensure the CI environment is running:

# Start CI services (includes etcd)
make ci-env-up project_compose_ci=ci/pod/docker-compose.common.yml

# Check if containers are running
docker ps | grep etcd

Permission Denied Errors

Some tests require sudo:

sudo -E FLUSH_ETCD=1 prove -I./test-nginx/lib -I./ t/path/to/test.t

Missing Lua Dependencies

Reinstall dependencies:

make deps

Submodule Issues

Re-initialize submodules:

git submodule update --init --recursive

TEST::NGINX Basics

APISIX tests are written using TEST::NGINX, a Perl-based testing framework.

Reference Existing Tests First

IMPORTANT: When writing new tests, always reference similar existing tests in the APISIX repository first.

Test directory: https://github.com/apache/apisix/tree/master/t

Directory Test Type
t/plugin/ Plugin tests (limit-count, key-auth, cors, etc.)
t/admin/ Admin API tests
t/core/ Core functionality tests
t/node/ Node/upstream tests
t/router/ Router tests
t/stream/ Stream proxy tests
t/discovery/ Service discovery tests
t/xrpc/ xRPC protocol tests

How to find similar tests:

# Search for tests related to a plugin
ls t/plugin/ | grep -i <keyword>

# Search for specific patterns in test files
grep -r "your_pattern" t/

# Example: Find tests using key-auth
grep -r "key-auth" t/plugin/

Why reference existing tests:

  1. Follow established patterns and conventions
  2. Understand how to set up test fixtures
  3. Learn correct assertion methods
  4. Avoid reinventing test utilities

Test File Structure

use t::APISIX 'no_plan';

repeat_each(1);
no_long_string();
no_root_location();

run_tests;

__DATA__

=== TEST 1: test description
--- config
location /t {
    content_by_lua_block {
        -- test code here
    }
}
--- request
GET /t
--- response_body
expected response
--- no_error_log
[error]

Common Test Sections

Section Description
--- config Nginx configuration
--- request HTTP request to send
--- response_body Expected response body
--- error_code Expected HTTP status code
--- no_error_log Patterns that should NOT appear in error log
--- error_log Patterns that SHOULD appear in error log

Non-Ubuntu Environment Workflow

If you're not on Ubuntu:

  1. Start Ubuntu environment (VM, container, WSL2)
  2. Run commands there
  3. If errors occur: Copy the complete error log
  4. Paste to AI for analysis: The AI can help diagnose issues without direct execution

Example error sharing format:

Command: FLUSH_ETCD=1 prove -I./test-nginx/lib -I./ t/plugin/limit-count.t
Error:
[paste complete error output here]
Weekly Installs
5
Installed on
claude-code4
windsurf3
opencode3
codex3
gemini-cli3
trae2