# Copyright (c) Abstract Machines # SPDX-License-Identifier: Apache-2.0 name: Property Based Tests on: push: branches: - main paths: - ".github/workflows/api-tests.yaml" - "api/**" - "internal/atom/**" - "channels/api/http/**" - "clients/api/http/**" - "domains/api/http/**" - "groups/api/http/**" - "journal/api/**" - "users/api/**" - "bootstrap/api/**" - "certs/api/http/**" - "readers/api/http/**" - "re/**" - "alarms/**" - "reports/**" - "apidocs/openapi/**" pull_request: branches: - main paths: - ".github/workflows/api-tests.yaml" - "api/**" - "internal/atom/**" - "channels/api/http/**" - "clients/api/http/**" - "domains/api/http/**" - "groups/api/http/**" - "journal/api/**" - "users/api/**" - "bootstrap/api/**" - "certs/api/http/**" - "readers/api/http/**" - "re/**" - "alarms/**" - "reports/**" - "apidocs/openapi/**" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: ATOM_LOGIN_URL: http://localhost/auth/login USER_IDENTITY: admin USER_SECRET: 12345678 DOMAIN_NAME: demo-test USERS_URL: http://localhost DOMAIN_URL: http://localhost CLIENTS_URL: http://localhost CHANNELS_URL: http://localhost GROUPS_URL: http://localhost JOURNAL_URL: http://localhost:9021 BOOTSTRAP_URL: http://localhost:9013 CERTS_URL: http://localhost:9019 READERS_URL: http://localhost:9011 RE_URL: http://localhost:9008 ALARMS_URL: http://localhost:8050 REPORTS_URL: http://localhost:9017 jobs: api-test: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v7 with: fetch-depth: 0 - name: Install Go uses: actions/setup-go@v7 with: go-version-file: go.mod cache-dependency-path: "go.sum" - name: Check for changes in specific paths uses: dorny/paths-filter@v4 id: changes with: filters: | workflow: - ".github/workflows/api-tests.yaml" journal: - "apidocs/openapi/journal.yaml" - "journal/api/**" domains: - "apidocs/openapi/domains.yaml" - "internal/atom/**" - "domains/api/http/**" clients: - "apidocs/openapi/clients.yaml" - "internal/atom/**" - "clients/api/http/**" channels: - "apidocs/openapi/channels.yaml" - "internal/atom/**" - "channels/api/http/**" groups: - "apidocs/openapi/groups.yaml" - "internal/atom/**" - "groups/api/http/**" users: - "apidocs/openapi/users.yaml" - "internal/atom/**" - "users/api/**" bootstrap: - "apidocs/openapi/bootstrap.yaml" - "bootstrap/api/**" certs: - "apidocs/openapi/certs.yaml" - "certs/api/http/**" readers: - "apidocs/openapi/readers.yaml" - "readers/api/http/**" re: - "apidocs/openapi/rules.yaml" - "re/**" - "cmd/re/**" - "internal/atom/**" alarms: - "apidocs/openapi/alarms.yaml" - "alarms/**" - "cmd/alarms/**" - "internal/atom/**" reports: - "apidocs/openapi/reports.yaml" - "reports/**" - "cmd/reports/**" - "internal/atom/**" - name: Build images run: make all -j $(nproc) && make dockers_dev -j $(nproc) - name: Provision Atom service tokens run: make provision_atom_tokens - name: Start containers run: make run_latest_ci up args="-d" && make run_addons up args="-d" - name: Wait for services to be ready run: | echo "Waiting for services to start..." sleep 15 # Check if services are responding for i in {1..30}; do if curl -f -s http://localhost/health > /dev/null 2>&1; then echo "Services are ready!" exit 0 fi echo "Waiting for services... ($i/30)" sleep 2 done echo "Services failed to become ready" >&2 docker compose -f docker/docker-compose.yaml -f docker/docker-compose-ci.yaml --env-file docker/.env --env-file docker/.env.tokens -p "${USER_REPO:-absmach_magistrala}" ps || true docker logs --tail 100 magistrala-nginx || true docker logs --tail 100 magistrala-atom || true docker logs --tail 100 magistrala-atom-bootstrap || true exit 1 - name: Set access token run: | export USER_TOKEN=$(curl -fsS -X POST "$ATOM_LOGIN_URL" -H "Content-Type: application/json" -d "{\"identifier\":\"$USER_IDENTITY\",\"secret\":\"$USER_SECRET\",\"kind\":\"password\"}" | jq -er .token) echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV - name: Run Users API tests if: (steps.changes.outputs.users == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('users/api/**') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/users.yaml base-url: ${{ env.USERS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --exclude-operation-id=requestPasswordReset --phases=examples' coverage-artifact-name: schema-coverage-users coverage-pr-comment: false - name: Run Groups API tests if: (steps.changes.outputs.groups == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('groups/api/http/**') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/groups.yaml base-url: ${{ env.GROUPS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-groups coverage-pr-comment: false - name: Run Clients API tests if: (steps.changes.outputs.clients == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('clients/api/http/**') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/clients.yaml base-url: ${{ env.CLIENTS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-clients coverage-pr-comment: false - name: Run Channels API tests if: (steps.changes.outputs.channels == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('channels/api/http/**') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/channels.yaml base-url: ${{ env.CHANNELS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-channels coverage-pr-comment: false - name: Run Domains API tests if: (steps.changes.outputs.domains == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('domains/api/http/**') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/domains.yaml base-url: ${{ env.DOMAIN_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-domains coverage-pr-comment: false - name: Run Journal API tests if: steps.changes.outputs.journal == 'true' || steps.changes.outputs.workflow == 'true' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/journal.yaml base-url: ${{ env.JOURNAL_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-journal coverage-pr-comment: false - name: Run Bootstrap API tests if: (steps.changes.outputs.bootstrap == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('bootstrap/api/**') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/bootstrap.yaml base-url: ${{ env.BOOTSTRAP_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-bootstrap coverage-pr-comment: false - name: Run Certs API tests if: (steps.changes.outputs.certs == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('docker/addons/certs/docker-compose.yaml') != '' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/certs.yaml base-url: ${{ env.CERTS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-certs coverage-pr-comment: false - name: Run Readers API tests if: steps.changes.outputs.readers == 'true' || steps.changes.outputs.workflow == 'true' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/readers.yaml base-url: ${{ env.READERS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-readers coverage-pr-comment: false - name: Run Rules Engine API tests if: steps.changes.outputs.re == 'true' || steps.changes.outputs.workflow == 'true' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/rules.yaml base-url: ${{ env.RE_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-rules coverage-pr-comment: false - name: Run Alarms API tests if: steps.changes.outputs.alarms == 'true' || steps.changes.outputs.workflow == 'true' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/alarms.yaml base-url: ${{ env.ALARMS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-alarms coverage-pr-comment: false - name: Run Reports API tests if: steps.changes.outputs.reports == 'true' || steps.changes.outputs.workflow == 'true' uses: schemathesis/action@v3.0.0 with: schema: apidocs/openapi/reports.yaml base-url: ${{ env.REPORTS_URL }} checks: all args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples' coverage-artifact-name: schema-coverage-reports coverage-pr-comment: false - name: Stop containers if: always() run: make run_latest_ci down args="-v" && make run_addons down args="-v"