diff --git a/.github/workflows/stress.yml b/.github/workflows/stress.yml new file mode 100644 index 000000000..6ba3f96a2 --- /dev/null +++ b/.github/workflows/stress.yml @@ -0,0 +1,63 @@ +name: stress +on: + schedule: + - cron: "* * * * *" + workflow_dispatch: + inputs: + repeat_count: + description: "Number of times to repeat each test" + required: false + default: "100" + parallel_workers: + description: "Number of parallel workers (-n auto or specific number)" + required: false + default: "auto" + +jobs: + stress-test: + name: ${{ matrix.project }} stress test (python-${{ matrix.python-version }}, nats-server-${{ matrix.nats-server-version }}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + python-version: ["3.11", "3.12", "3.13"] + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + nats-server-version: ["latest"] + project: ["nats-server"] + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: "stable" + + - name: Install NATS Server + run: | + go install github.com/nats-io/nats-server/v2@${{ matrix.nats-server-version }} + shell: bash + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Install uv + uses: astral-sh/setup-uv@v6 + + - name: Install dependencies + run: uv sync --dev + working-directory: ${{ matrix.project }} + + - name: Run stress tests for ${{ matrix.project }} + run: uv run pytest -v -n ${{ github.event.inputs.parallel_workers || 'auto' }} --count=${{ github.event.inputs.repeat_count || '100' }} + working-directory: ${{ matrix.project }} + + - name: Upload failure artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: stress-test-failures-${{ matrix.os }}-py${{ matrix.python-version }} + path: ${{ matrix.project }}/.pytest_cache/ + retention-days: 7 diff --git a/pyproject.toml b/pyproject.toml index e750ccb79..1ae170727 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,7 @@ dev-dependencies = [ "pytest-asyncio>=0.21.0", "pytest-cov>=7.0.0", "pytest-xdist>=3.0.0", + "pytest-repeat>=0.9.0", "ty>=0.0.0a6", "ruff>=0.1.0", "codespell>=2.2.0", diff --git a/uv.lock b/uv.lock index c60fcdfc4..310899ffa 100644 --- a/uv.lock +++ b/uv.lock @@ -19,6 +19,7 @@ dev = [ { name = "pytest", specifier = ">=7.0.0" }, { name = "pytest-asyncio", specifier = ">=0.21.0" }, { name = "pytest-cov", specifier = ">=7.0.0" }, + { name = "pytest-repeat", specifier = ">=0.9.0" }, { name = "pytest-xdist", specifier = ">=3.0.0" }, { name = "ruff", specifier = ">=0.1.0" }, { name = "ty", specifier = ">=0.0.0a6" }, @@ -721,6 +722,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, ] +[[package]] +name = "pytest-repeat" +version = "0.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/d4/69e9dbb9b8266df0b157c72be32083403c412990af15c7c15f7a3fd1b142/pytest_repeat-0.9.4.tar.gz", hash = "sha256:d92ac14dfaa6ffcfe6917e5d16f0c9bc82380c135b03c2a5f412d2637f224485", size = 6488, upload-time = "2025-04-07T14:59:53.077Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/d4/8b706b81b07b43081bd68a2c0359fe895b74bf664b20aca8005d2bb3be71/pytest_repeat-0.9.4-py3-none-any.whl", hash = "sha256:c1738b4e412a6f3b3b9e0b8b29fcd7a423e50f87381ad9307ef6f5a8601139f3", size = 4180, upload-time = "2025-04-07T14:59:51.492Z" }, +] + [[package]] name = "pytest-xdist" version = "3.8.0"