ci: integrate frontend and backend tests with organization-related test suites #3810
Workflow file for this run
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: Test Frontend | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - release/** | |
| pull_request: | |
| branches: | |
| - main | |
| - release/** | |
| workflow_dispatch: | |
| defaults: | |
| run: | |
| shell: bash | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: pr-checks-${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| name: Build | Front-end | |
| runs-on: transaction-tools-linux-medium | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout Code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 | |
| with: | |
| node-version: 22.12.0 | |
| cache: 'npm' | |
| cache-dependency-path: | | |
| front-end/pnpm-lock.yaml | |
| - name: Install pnpm | |
| run: npm install -g pnpm@9.15.3 | |
| - name: Install front-end Dependencies | |
| run: pnpm install --frozen-lockfile | |
| working-directory: front-end | |
| - name: Build Linux executable | |
| run: pnpm run build:linux | |
| working-directory: front-end | |
| - name: Cache Build Artifacts | |
| uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 | |
| with: | |
| path: front-end/release/linux-unpacked | |
| key: build-artifacts-${{ github.sha }} | |
| test: | |
| name: Automation | ${{ matrix.test-suite.name }} | |
| runs-on: transaction-tools-linux-medium | |
| needs: build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| test-suite: | |
| - name: Organization | |
| command: OrganizationGroupTests | |
| soloRequired: true | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout Code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 | |
| with: | |
| node-version: 22.12.0 | |
| cache: 'npm' | |
| cache-dependency-path: | | |
| automation/pnpm-lock.yaml | |
| - name: Install pnpm | |
| run: npm install -g pnpm@9.15.3 | |
| - name: Install Docker Compose Plugin | |
| run: | | |
| sudo curl -fLo /usr/local/lib/docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-linux-x86_64 | |
| sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose | |
| # Provide legacy docker-compose command for scripts that use hyphenated syntax. | |
| sudo ln -sf /usr/local/lib/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose | |
| - name: Install Automation Dependencies | |
| run: pnpm install --frozen-lockfile | |
| working-directory: automation | |
| - name: Deploy Back-end | |
| working-directory: back-end | |
| run: | | |
| set -euo pipefail | |
| # Install mkcert for generating a locally-trusted TLS certificate. | |
| # libnss3-tools provides certutil, required by mkcert -install on Linux. | |
| sudo apt-get update -q | |
| sudo apt-get install -y --no-install-recommends libnss3-tools | |
| curl -fsSL https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64 \ | |
| -o /tmp/mkcert | |
| sudo install -m755 /tmp/mkcert /usr/local/bin/mkcert | |
| # Install the local CA so the cert is trusted by Chromium/Electron. | |
| mkcert -install | |
| # Create cert directory and generate TLS certificates for localhost. | |
| mkdir -p cert | |
| mkcert -key-file cert/key.pem -cert-file cert/cert.pem localhost | |
| # Copy .env files from examples for all back-end packages. | |
| for dir in . apps/api apps/chain apps/notifications typeorm scripts; do | |
| cp "${dir}/example.env" "${dir}/.env" | |
| done | |
| # Align frontend version compatibility constraints with the built app. | |
| FE_VERSION="$(node -p "require('../front-end/package.json').version")" | |
| sed -i "s/^LATEST_SUPPORTED_FRONTEND_VERSION=.*/LATEST_SUPPORTED_FRONTEND_VERSION=${FE_VERSION}/" apps/api/.env | |
| sed -i "s/^MINIMUM_SUPPORTED_FRONTEND_VERSION=.*/MINIMUM_SUPPORTED_FRONTEND_VERSION=${FE_VERSION}/" apps/api/.env | |
| sed -i "s/^MINIMUM_SUPPORTED_FRONTEND_VERSION=.*/MINIMUM_SUPPORTED_FRONTEND_VERSION=${FE_VERSION}/" apps/notifications/.env | |
| # Notifications service requires EMAIL_API_SECURE to be a boolean. | |
| sed -i 's/^EMAIL_API_SECURE=.*/EMAIL_API_SECURE=false/' apps/notifications/.env | |
| # Install back-end dependencies (required because the dev docker-compose | |
| # mounts .:/usr/src/app, overwriting the container's node_modules). | |
| SKIP_NOTICE_GEN=true pnpm install | |
| export COMPOSE_PARALLEL_LIMIT=4 | |
| # Ensure Docker daemon is reachable before deploying. | |
| # Do not restart dockerd here; restarting is disruptive on shared/self-hosted runners. | |
| if ! docker info &>/dev/null; then | |
| echo "Docker daemon is not reachable; attempting to start it..." | |
| sudo service docker start || true | |
| sudo systemctl start docker || true | |
| fi | |
| for i in $(seq 1 15); do | |
| if docker info &>/dev/null; then | |
| break | |
| fi | |
| if [ "${i}" -eq 15 ]; then | |
| echo "Docker daemon is unavailable after startup attempts" >&2 | |
| ls -l /var/run/docker.sock || true | |
| sudo ls -l /var/run/docker.sock || true | |
| ps -ef | grep -E 'dockerd|containerd' | grep -v grep || true | |
| exit 1 | |
| fi | |
| sleep 2 | |
| done | |
| # Start all services from back-end/docker-compose.yaml. | |
| # Retries handle flaky Docker Hub pulls on self-hosted runners. | |
| for attempt in $(seq 1 5); do | |
| if docker-compose up -d; then | |
| break | |
| fi | |
| if [ "${attempt}" -eq 5 ]; then | |
| echo "docker compose up failed after 5 attempts" >&2 | |
| docker-compose ps || true | |
| docker-compose logs --tail=200 || true | |
| exit 1 | |
| fi | |
| echo "Attempt ${attempt} failed; retrying in 15s..." | |
| sleep 15 | |
| done | |
| # Wait for the API to become ready. | |
| # The API serves HTTPS when NODE_ENV=development and cert files are present. | |
| MAX_ATTEMPTS=60 | |
| for attempt in $(seq 1 "${MAX_ATTEMPTS}"); do | |
| code="$(curl -k -s -o /dev/null -w '%{http_code}' https://localhost:3001/ 2>/dev/null || echo '000')" | |
| if [[ "${code}" == "200" || "${code}" == "426" ]]; then | |
| echo "Back-end is ready (attempt ${attempt})" | |
| break | |
| fi | |
| if (( attempt % 10 == 0 )); then | |
| echo "Waiting for back-end... attempt ${attempt}/${MAX_ATTEMPTS} (HTTP ${code})" | |
| docker-compose ps | |
| docker-compose logs --tail=50 api || true | |
| fi | |
| if [ "${attempt}" -eq "${MAX_ATTEMPTS}" ]; then | |
| echo "Back-end did not become ready in time" >&2 | |
| docker-compose ps || true | |
| docker-compose logs --tail=300 || true | |
| exit 1 | |
| fi | |
| sleep 5 | |
| done | |
| docker-compose ps | |
| - name: Test API connectivity | |
| run: | | |
| set -euo pipefail | |
| code="$(curl -k -sS -o /dev/null -w '%{http_code}' https://localhost:3001/ || echo '000')" | |
| echo "API connectivity check returned HTTP ${code}" | |
| if [[ "${code}" != "200" && "${code}" != "426" ]]; then | |
| echo "Unexpected HTTP status from API: ${code}" >&2 | |
| exit 1 | |
| fi | |
| - name: Setup Kind | |
| if: ${{ matrix.test-suite.soloRequired }} | |
| uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0 | |
| with: | |
| install_only: true | |
| node_image: kindest/node:v1.31.4@sha256:2cb39f7295fe7eafee0842b1052a599a4fb0f8bcf3f83d96c7f4864c357c6c30 | |
| version: v0.26.0 | |
| kubectl_version: v1.31.4 | |
| verbosity: 3 | |
| wait: 120s | |
| - name: Install Solo CLI | |
| if: ${{ matrix.test-suite.soloRequired }} | |
| run: | | |
| set -euo pipefail | |
| npm install -g @hashgraph/solo | |
| solo --version | |
| kind --version | |
| - name: Deploy Solo | |
| if: ${{ matrix.test-suite.soloRequired }} | |
| id: solo_deploy | |
| env: | |
| SOLO_CLUSTER_NAME: solo | |
| SOLO_NAMESPACE: solo | |
| SOLO_CLUSTER_SETUP_NAMESPACE: solo-cluster | |
| SOLO_DEPLOYMENT: solo-deployment | |
| run: | | |
| set -euo pipefail | |
| kind create cluster -n "${SOLO_CLUSTER_NAME}" | |
| solo one-shot single deploy | tee solo-deploy.log | |
| - name: Check port forwarding | |
| if: ${{ matrix.test-suite.soloRequired }} | |
| run: | | |
| set -euo pipefail | |
| ps -ef | grep port-forward || true | |
| curl -fsS http://localhost:8080/api/v1/network/nodes | |
| curl -fsS http://localhost:8081/api/v1/network/nodes | |
| - name: Restore Build Artifacts | |
| uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 | |
| with: | |
| fail-on-cache-miss: true | |
| path: front-end/release/linux-unpacked | |
| key: build-artifacts-${{ github.sha }} | |
| - name: Install xvfb | |
| run: sudo apt-get update && sudo apt-get install -y xvfb | |
| - name: Install Runtime Shared Libraries | |
| run: sudo apt-get install --no-install-recommends -y xorg openbox libnss3 libasound2 libatk-adaptor libgtk-3-0 | |
| - name: Run Automation | |
| env: | |
| EXECUTABLE_PATH: ../front-end/release/linux-unpacked/hedera-transaction-tool | |
| PRIVATE_KEY: ${{ secrets.SOLO_PRIVATE_KEY }} | |
| OPERATOR_KEY: ${{ secrets.OPERATOR_KEY }} | |
| ENVIRONMENT: LOCALNET | |
| ORGANIZATION_URL: https://localhost:3001 | |
| POSTGRES_HOST: localhost | |
| POSTGRES_PORT: 5432 | |
| POSTGRES_DATABASE: postgres | |
| POSTGRES_USERNAME: postgres | |
| POSTGRES_PASSWORD: postgres | |
| run: xvfb-run -a npx playwright test tests/${{ matrix.test-suite.command }} | |
| working-directory: automation | |
| - name: Upload Playwright Report | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report-${{ matrix.test-suite.name }} | |
| path: | | |
| automation/playwright-report | |
| automation/test-results | |
| if-no-files-found: warn | |
| retention-days: 3 | |
| - name: Show Back-end Logs | |
| if: ${{ failure() }} | |
| run: docker-compose logs --tail=300 | |
| working-directory: back-end | |
| - name: Stop Back-end Services | |
| if: ${{ always() }} | |
| run: docker-compose down --remove-orphans || true | |
| working-directory: back-end | |
| unit-test: | |
| name: Unit Tests | ${{ matrix.test-suite.name }} | |
| runs-on: transaction-tools-linux-medium | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| test-suite: | |
| - name: Main Process | |
| command: main:coverage | |
| - name: Renderer Process | |
| command: renderer | |
| - name: Shared | |
| command: shared | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout Code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 | |
| with: | |
| node-version: 22.12.0 | |
| cache: 'npm' | |
| cache-dependency-path: | | |
| front-end/pnpm-lock.yaml | |
| - name: Install pnpm | |
| run: npm install -g pnpm@9.15.3 | |
| - name: Install front-end Dependencies | |
| run: pnpm install --frozen-lockfile | |
| working-directory: front-end | |
| - name: Run Unit Tests | |
| run: pnpm run test:${{ matrix.test-suite.command }} | |
| working-directory: front-end | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@5c47607acb93fed5485fdbf7232e8a31425f672a # v5.0.2 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} |