Layer5 Cloud Tests #310
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Layer5 Cloud Tests | |
| on: | |
| workflow_call: | |
| inputs: | |
| pr_commit_sha: | |
| description: "Git commit SHA to checkout for testing" | |
| required: true | |
| type: string | |
| pr_number: | |
| description: "PR number for comment updates (empty for push events)" | |
| default: "" | |
| required: false | |
| type: string | |
| run_integration_tests: | |
| description: "Whether to run integration tests" | |
| default: false | |
| required: false | |
| type: boolean | |
| node_version: | |
| description: "Node.js version for UI tests" | |
| required: false | |
| default: '20.x' | |
| type: string | |
| secrets: | |
| GH_ACCESS_TOKEN: | |
| required: true | |
| workflow_dispatch: | |
| inputs: | |
| pr_commit_sha: | |
| description: "Git commit SHA to checkout for testing" | |
| required: true | |
| type: string | |
| pr_number: | |
| description: "PR number for comment updates (leave empty for master/qa runs)" | |
| required: false | |
| default: "" | |
| run_integration_tests: | |
| description: "Whether to run integration tests" | |
| required: false | |
| default: false | |
| type: boolean | |
| node_version: | |
| description: "Node.js version for UI tests" | |
| required: false | |
| default: '20.x' | |
| type: string | |
| jobs: | |
| server-tests: | |
| name: Server Tests | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| steps: | |
| - name: Checkout for composite action | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| sparse-checkout: | | |
| .github/actions/cloud-comment | |
| sparse-checkout-cone-mode: false | |
| - name: Comment starting | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: "Starting Cloud Server tests ([takes approximately 8 min end-to-end](https://github.com/layer5labs/meshery-extensions-packages/actions/runs/${{ github.run_id }}))..." | |
| append: false | |
| recreate: true | |
| #------------------------------------------ | |
| - name: Checkout Cloud code | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: layer5io/meshery-cloud | |
| ref: ${{ inputs.pr_number != '' && format('refs/pull/{0}/head', inputs.pr_number) || inputs.pr_commit_sha }} | |
| token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| fetch-depth: 1 | |
| path: meshery-cloud | |
| - name: Comment checkout success | |
| if: success() | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":heavy_check_mark: Checked out meshery-cloud repo." | |
| - name: Comment checkout failure | |
| if: failure() | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":x: Failed to clone meshery-cloud repo." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Setup Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: "1.25" | |
| check-latest: true | |
| cache: true | |
| - name: Download dependencies | |
| working-directory: meshery-cloud | |
| run: | | |
| go mod download | |
| go mod verify | |
| - name: Comment Go setup success | |
| if: success() | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":heavy_check_mark: Setup Golang environment. Running unit tests... (takes approximately 3 min)" | |
| - name: Comment Go setup failure | |
| if: failure() | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":x: Failed to setup Golang environment." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Run unit tests | |
| id: unit-tests | |
| continue-on-error: true | |
| working-directory: meshery-cloud | |
| run: make server-tests-unit | |
| - name: Comment unit tests success | |
| if: steps.unit-tests.outcome == 'success' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":heavy_check_mark: Unit tests passed. Running integration tests..." | |
| - name: Comment unit tests failure | |
| if: steps.unit-tests.outcome == 'failure' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":x: Unit tests failed. Running integration tests..." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Run integration tests | |
| id: integration-tests | |
| continue-on-error: true | |
| if: ${{ inputs.run_integration_tests }} | |
| working-directory: meshery-cloud | |
| run: make ENVIRONMENT=staging server-tests-integration | |
| - name: Comment integration tests success | |
| if: steps.integration-tests.outcome == 'success' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":heavy_check_mark: Golang integration tests passed." | |
| - name: Comment integration tests failure | |
| if: steps.integration-tests.outcome == 'failure' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":x: Golang integration tests failed." | |
| - name: Comment integration tests skipped | |
| if: steps.integration-tests.outcome == 'skipped' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":fast_forward: Integration tests skipped (not requested)." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: server-test-results | |
| path: meshery-cloud/allure-results/ | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| # Publish server test results (pass or fail) to qa.meshery.io. PR runs | |
| # route under pr-reports/<N>/ so they stay out of the master dashboard. | |
| # The sync is intentionally ungated on test outcome — failing runs must | |
| # land so the dashboard reflects every CI run. | |
| - name: Checkout QA | |
| if: ${{ !cancelled() }} | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: meshery-extensions/qa | |
| path: qa | |
| token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| - name: Sync server test results to qa | |
| if: ${{ !cancelled() }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${{ inputs.pr_number }}" ]; then | |
| BASE="qa/pr-reports/${{ inputs.pr_number }}" | |
| else | |
| BASE="qa" | |
| fi | |
| SERVER_DEST="$BASE/meshery-server-results" | |
| rm -rf "$SERVER_DEST" | |
| mkdir -p "$SERVER_DEST" | |
| for dir in \ | |
| meshery-cloud/allure-results \ | |
| meshery-cloud/server/*/allure-results; do | |
| [ -d "$dir" ] || continue | |
| cp -R "$dir/." "$SERVER_DEST/" 2>/dev/null || true | |
| done | |
| echo "meshery-server-results: $(find "$SERVER_DEST" -type f | wc -l) file(s)" | |
| - name: Commit & push server results to qa | |
| if: ${{ !cancelled() }} | |
| uses: stefanzweifel/git-auto-commit-action@v7 | |
| with: | |
| commit_message: "[Cloud] Sync server test results - ${GITHUB_SHA}" | |
| commit_options: --signoff | |
| repository: qa | |
| file_pattern: ${{ inputs.pr_number != '' && format('pr-reports/{0}', inputs.pr_number) || 'meshery-server-results' }} | |
| commit_user_name: meshery-ci | |
| commit_user_email: ci@meshery.io | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| - name: Comment QA sync success | |
| if: ${{ success() && !cancelled() }} | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":heavy_check_mark: Synced server test results to QA dashboard." | |
| - name: Comment QA sync failure | |
| if: ${{ failure() }} | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":x: Failed to sync server test results to QA dashboard." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Comment final success | |
| if: ${{ steps.unit-tests.outcome == 'success' && (steps.integration-tests.outcome == 'success' || steps.integration-tests.outcome == 'skipped') }} | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":white_check_mark: All Layer5 Cloud Server tests completed successfully." | |
| - name: Comment final failure | |
| if: ${{ steps.unit-tests.outcome == 'failure' || steps.integration-tests.outcome == 'failure' }} | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-tests | |
| message: ":x: Layer5 Cloud Server tests completed with failures. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})." | |
| - name: Fail if any tests failed | |
| if: ${{ steps.unit-tests.outcome == 'failure' || steps.integration-tests.outcome == 'failure' }} | |
| run: | | |
| echo "::error::Test failures detected" | |
| [ "${{ steps.unit-tests.outcome }}" = "failure" ] && echo " - Unit tests failed" | |
| [ "${{ steps.integration-tests.outcome }}" = "failure" ] && echo " - Integration tests failed" | |
| exit 1 | |
| #------------------------------------------ | |
| ui-tests: | |
| name: UI Tests | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| steps: | |
| - name: Checkout for composite action | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| sparse-checkout: | | |
| .github/actions/cloud-comment | |
| sparse-checkout-cone-mode: false | |
| - name: Comment starting | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: "Starting Cloud UI tests ([workflow run](https://github.com/layer5labs/meshery-extensions-packages/actions/runs/${{ github.run_id }}))..." | |
| append: false | |
| recreate: true | |
| #------------------------------------------ | |
| - name: Checkout Cloud code | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: layer5io/meshery-cloud | |
| ref: ${{ inputs.pr_number != '' && format('refs/pull/{0}/head', inputs.pr_number) || inputs.pr_commit_sha }} | |
| token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| fetch-depth: 1 | |
| path: meshery-cloud | |
| - name: Comment checkout success | |
| if: success() | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":heavy_check_mark: Checked out meshery-cloud repo." | |
| - name: Comment checkout failure | |
| if: failure() | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":x: Failed to clone meshery-cloud repo." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Setup Node.js | |
| id: setup-node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ inputs.node_version }} | |
| cache: "npm" | |
| cache-dependency-path: meshery-cloud/ui/package-lock.json | |
| - name: Comment Node setup success | |
| if: steps.setup-node.outcome == 'success' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":heavy_check_mark: Setup Node.js. Installing dependencies..." | |
| - name: Comment Node setup failure | |
| if: steps.setup-node.outcome == 'failure' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":x: Failed to setup Node.js." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Install UI dependencies | |
| id: install-deps | |
| working-directory: meshery-cloud | |
| run: make ui-setup | |
| - name: Comment deps success | |
| if: steps.install-deps.outcome == 'success' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":heavy_check_mark: Installed UI dependencies. Running UI tests..." | |
| - name: Comment deps failure | |
| if: steps.install-deps.outcome == 'failure' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":x: Failed to install UI dependencies." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| - name: Run UI tests | |
| id: ui-tests | |
| working-directory: meshery-cloud | |
| run: make ui-tests | |
| - name: Upload UI test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ui-test-results | |
| path: meshery-cloud/ui/coverage/ | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| - name: Comment UI tests success | |
| if: steps.ui-tests.outcome == 'success' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":white_check_mark: All Cloud UI tests passed." | |
| - name: Comment UI tests failure | |
| if: steps.ui-tests.outcome == 'failure' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-ui-tests | |
| message: ":x: Cloud UI tests failed. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})." | |
| #------------------------------------------ | |
| #------------------------------------------ | |
| # Publish UI (Jest) results to qa.meshery.io. Runs on pass or fail. | |
| # Until meshery-cloud wires an allure-jest reporter into the ui target, | |
| # meshery-cloud/ui/allure-results will be empty and this step no-ops. | |
| - name: Checkout QA | |
| if: ${{ !cancelled() }} | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: meshery-extensions/qa | |
| path: qa | |
| token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| - name: Sync UI test results to qa | |
| if: ${{ !cancelled() }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${{ inputs.pr_number }}" ]; then | |
| BASE="qa/pr-reports/${{ inputs.pr_number }}" | |
| else | |
| BASE="qa" | |
| fi | |
| UI_DEST="$BASE/remote-provider-results" | |
| mkdir -p "$UI_DEST" | |
| for dir in meshery-cloud/ui/allure-results; do | |
| [ -d "$dir" ] || continue | |
| cp -R "$dir/." "$UI_DEST/" 2>/dev/null || true | |
| done | |
| echo "remote-provider-results (UI): $(find "$UI_DEST" -type f | wc -l) file(s)" | |
| - name: Commit & push UI results to qa | |
| if: ${{ !cancelled() }} | |
| uses: stefanzweifel/git-auto-commit-action@v7 | |
| with: | |
| commit_message: "[Cloud] Sync UI test results - ${GITHUB_SHA}" | |
| commit_options: --signoff | |
| repository: qa | |
| file_pattern: ${{ inputs.pr_number != '' && format('pr-reports/{0}', inputs.pr_number) || 'remote-provider-results' }} | |
| commit_user_name: meshery-ci | |
| commit_user_email: ci@meshery.io | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| #------------------------------------------ | |
| e2e-tests: | |
| name: Playwright e2e | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| steps: | |
| - name: Checkout for composite action | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| sparse-checkout: | | |
| .github/actions/cloud-comment | |
| sparse-checkout-cone-mode: false | |
| - name: Comment starting | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-e2e-tests | |
| message: "Starting Cloud Playwright e2e ([workflow run](https://github.com/layer5labs/meshery-extensions-packages/actions/runs/${{ github.run_id }}))..." | |
| append: false | |
| recreate: true | |
| - name: Checkout Cloud code | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: layer5io/meshery-cloud | |
| ref: ${{ inputs.pr_number != '' && format('refs/pull/{0}/head', inputs.pr_number) || inputs.pr_commit_sha }} | |
| token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| fetch-depth: 1 | |
| path: meshery-cloud | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ inputs.node_version }} | |
| cache: 'npm' | |
| cache-dependency-path: meshery-cloud/ui/package-lock.json | |
| - name: Install Cloud UI dependencies | |
| working-directory: meshery-cloud | |
| run: make ui-setup | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ hashFiles('meshery-cloud/ui/package-lock.json') }} | |
| - name: Install Playwright browsers | |
| working-directory: meshery-cloud/ui | |
| run: npx playwright install --with-deps | |
| # ALLURE_RESULTS_DIR routes allure-playwright (when wired in | |
| # meshery-cloud) to a path the sync-to-qa step collects. Until that | |
| # reporter is added, the directory stays empty and sync no-ops. | |
| # Step timeout is set below the job timeout so a hung test fails | |
| # with room left for the QA sync + gating step to run. Current | |
| # observed e2e runtime is ~22 min; 25 min gives a small buffer. | |
| - name: Run Cloud UI e2e tests | |
| id: e2e | |
| timeout-minutes: 25 | |
| continue-on-error: true | |
| working-directory: meshery-cloud/ui | |
| env: | |
| ALLURE_RESULTS_DIR: ${{ github.workspace }}/meshery-cloud/ui/allure-results | |
| run: npm run e2e | |
| - name: Comment e2e success | |
| if: steps.e2e.outcome == 'success' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-e2e-tests | |
| message: ":white_check_mark: Cloud Playwright e2e tests passed." | |
| - name: Comment e2e failure | |
| if: steps.e2e.outcome == 'failure' | |
| uses: ./.github/actions/cloud-comment | |
| with: | |
| id: cloud-e2e-tests | |
| message: ":x: Cloud Playwright e2e tests failed. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})." | |
| - name: Upload e2e test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-test-results | |
| path: meshery-cloud/ui/allure-results/ | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| #------------------------------------------ | |
| # Publish Playwright e2e results to qa.meshery.io. Runs on pass or | |
| # fail. PR runs route under pr-reports/<N>/. | |
| - name: Checkout QA | |
| if: ${{ !cancelled() }} | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: meshery-extensions/qa | |
| path: qa | |
| token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| # Clear the destination before copying so removed/renamed result | |
| # files don't linger as stale entries on the QA dashboard. Safe in | |
| # this job because no other parallel job writes to the same subtree | |
| # within this run (the ui-tests Jest sync is currently a no-op). | |
| - name: Sync e2e results to qa | |
| if: ${{ !cancelled() }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${{ inputs.pr_number }}" ]; then | |
| BASE="qa/pr-reports/${{ inputs.pr_number }}" | |
| else | |
| BASE="qa" | |
| fi | |
| E2E_DEST="$BASE/remote-provider-results" | |
| rm -rf "$E2E_DEST" | |
| mkdir -p "$E2E_DEST" | |
| for dir in meshery-cloud/ui/allure-results; do | |
| [ -d "$dir" ] || continue | |
| cp -R "$dir/." "$E2E_DEST/" 2>/dev/null || true | |
| done | |
| echo "remote-provider-results (e2e): $(find "$E2E_DEST" -type f | wc -l) file(s)" | |
| - name: Commit & push e2e results to qa | |
| if: ${{ !cancelled() }} | |
| uses: stefanzweifel/git-auto-commit-action@v7 | |
| with: | |
| commit_message: "[Cloud] Sync e2e results - ${GITHUB_SHA}" | |
| commit_options: --signoff | |
| repository: qa | |
| file_pattern: ${{ inputs.pr_number != '' && format('pr-reports/{0}', inputs.pr_number) || 'remote-provider-results' }} | |
| commit_user_name: meshery-ci | |
| commit_user_email: ci@meshery.io | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| # Gate after the sync so failing e2e results still publish to QA | |
| # while the job correctly surfaces as failed in PR checks. | |
| - name: Fail job if e2e failed | |
| if: steps.e2e.outcome == 'failure' | |
| run: | | |
| echo "::error::Playwright e2e tests failed" | |
| exit 1 | |
| #------------------------------------------ |