extra-test-suite · master
Docs · CI integration

GitHub Action

The reusable GitHub Composite Action. Inputs, version pinning, and how it pairs with uanetstandard-test-suite in a typical CI matrix.

The repo is a GitHub Composite Action. One step brings both servers up on the runner.

Minimal example

text .github/workflows/test.yml
name: Integration tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: php-opcua/[email protected]

      - run: vendor/bin/pest --group=integration

When the uses: step finishes, all three ports are open:

  • opc.tcp://localhost:24840open62541-nm
  • opc.tcp://localhost:24841open62541-all-security
  • opc.tcp://localhost:24842open62541-historizing

Inputs

Input Default Effect
image-tag latest Image tag for every service in compose. v1.1.0, latest, …
startup-timeout 30 Seconds to wait for each service's TCP port

No outputs. The endpoint URLs are part of the suite's versioned contract24840, 24841, and 24842 are stable. Your test code hardcodes them.

What it does internally

The action runs three things:

  1. docker compose pull (with the CI override)
  2. docker compose up -d
  3. Polls nc -z localhost <port> for each service until success or startup-timeout seconds elapse

On failure, it dumps docker compose logs to the runner output and exits non-zero.

Version pinning

Form Recommendation
@v1.1.0 Recommended. Reproducible.
@master Tracks tip — may break
@<sha> Maximum reproducibility (rare)

Pin both uses: and the inner image-tag if you want a double-locked version:

text double-pin
- uses: php-opcua/[email protected]
  with:
    image-tag: v1.1.0

The action's published v1.1.0 is the same set of files as the GHCR image's v1.1.0. Both pinning to the same tag is the common pattern.

Paired with uanetstandard-test-suite

The two suites are designed to be used side by side:

text full CI matrix
jobs:
  integration:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Main suite: 10 classic servers on 4840-4849, SKS on 4851, PubSub on UDP 14850
      - uses: php-opcua/[email protected]

      # Extras: 3 open62541 servers on 24840-24842
      - uses: php-opcua/[email protected]

      - run: vendor/bin/pest --group=integration

12 OPC UA servers on the runner, no port conflicts. Tests target whichever endpoint they need.

Selecting a subset

The action has no services: input — it always brings up both. To start only one, skip the composite action entirely and call docker compose directly against a clone of the repo:

text single-service via direct compose
- run: |
    git clone --depth 1 --branch v1.1.0 \
      https://github.com/php-opcua/extra-test-suite.git /tmp/extras
    docker compose -f /tmp/extras/docker-compose.yml \
                   -f /tmp/extras/docker-compose.ci.yml \
                   up -d open62541-nm

In practice, both services are cheap (~120 MB combined). The overhead of pulling just one isn't worth the complexity.

Real-world example

php-opcua/opcua-client uses this pattern in its integration job — same uses: step, then vendor/bin/pest with a group filter that picks up NodeManagement tests:

text opcua-client.github/workflows/tests.yml
- uses: php-opcua/[email protected]
- uses: php-opcua/[email protected]
- run: vendor/bin/pest --group=integration

NodeManagement tests target :24840; all other integration tests target the main suite's ports.

Resource cost on GitHub runners

Standard ubuntu-latest runners have 2-4 vCPU and 7-16 GB RAM. Both this suite and uanetstandard-test-suite running together use ~700 MB RAM — comfortable.

Common failures

Symptom Cause / fix
Step times out startup-timeout too low. Increase to 60.
Image pull fails GHCR rate-limited or image-tag doesn't exist
nc not found Older runner image — should be on ubuntu-22.04+
Port already in use Another job is sharing the runner (rare)