on: pull_request_target: # Use pull_request_target branches: [master, beta, release] jobs: test: runs-on: ubuntu-latest container: image: ghcr.io/thomasnordquist/mqtt-explorer-ui-tests:latest volumes: - ./:/app options: --user root steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Packages run: yarn install --frozen-lockfile - name: Build run: yarn build - name: Test run: yarn test browser-ui-tests: runs-on: ubuntu-latest container: image: ghcr.io/thomasnordquist/mqtt-explorer-ui-tests:latest volumes: - ./:/app options: --user root env: TESTS_MQTT_BROKER_HOST: mosquitto TESTS_MQTT_BROKER_PORT: 1883 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Start mosquitto run: mosquitto -c /etc/mosquitto/conf.d/default.conf -d - name: Install Packages run: yarn install --frozen-lockfile - name: Build Browser Mode run: yarn build:server - name: Run Browser UI Tests timeout-minutes: 10 run: ./scripts/runBrowserTests.sh - name: Upload Test Screenshots if: always() uses: actions/upload-artifact@v4 with: name: browser-test-screenshots path: | test-screenshot-*.png retention-days: 30 demo-video: runs-on: ubuntu-latest container: image: ghcr.io/thomasnordquist/mqtt-explorer-ui-tests:latest volumes: - ./:/app options: --user root env: TESTS_MQTT_BROKER_HOST: localhost TESTS_MQTT_BROKER_PORT: 1883 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Start mosquitto run: mosquitto -c /etc/mosquitto/conf.d/default.conf -d - name: Install Packages run: yarn install --frozen-lockfile - name: Build run: yarn build - name: Generate Demo Video run: yarn ui-test - name: Post-processing run: ./scripts/prepareVideo.sh - name: Generate unique base path id: basepath run: | TIMESTAMP=$(date +%Y%m%d-%H%M%S) BASEPATH="pr-${{ github.event.pull_request.number }}-${TIMESTAMP}" echo "basepath=${BASEPATH}" >> $GITHUB_OUTPUT - name: Install AWS CLI v2 run: | apt-get update && apt-get install -y unzip curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip -q awscliv2.zip ./aws/install rm -rf aws awscliv2.zip - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ vars.AWS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: 'eu-central-1' - name: Upload full video to S3 env: AWS_BUCKET: ${{ vars.AWS_BUCKET }} BASEPATH: ${{ steps.basepath.outputs.basepath }} run: | # Upload GIF aws s3api put-object \ --bucket ${AWS_BUCKET} \ --key artifacts/${BASEPATH}/ui-test.gif \ --body ./ui-test.gif \ --content-type image/gif # Upload MP4 aws s3api put-object \ --bucket ${AWS_BUCKET} \ --key artifacts/${BASEPATH}/ui-test.mp4 \ --body ./ui-test.mp4 \ --content-type video/mp4 - name: Upload video segments to S3 env: AWS_BUCKET: ${{ vars.AWS_BUCKET }} BASEPATH: ${{ steps.basepath.outputs.basepath }} shell: bash run: | # Upload all GIF segment files if they exist shopt -s nullglob # Make glob return empty list if no matches for segment in segment-*.gif; do echo "Uploading $segment..." aws s3api put-object \ --bucket ${AWS_BUCKET} \ --key artifacts/${BASEPATH}/${segment} \ --body ./${segment} \ --content-type image/gif done shopt -u nullglob # Restore default behavior - name: Generate file URLs id: fileurl env: AWS_BUCKET: ${{ vars.AWS_BUCKET }} BASEPATH: ${{ steps.basepath.outputs.basepath }} run: | BASE_URL="https://${AWS_BUCKET}.s3.eu-central-1.amazonaws.com/artifacts/${BASEPATH}" echo "base-url=${BASE_URL}" >> $GITHUB_OUTPUT echo "Uploaded to: ${BASE_URL}" - name: Generate markdown summary id: markdown env: BASE_URL: ${{ steps.fileurl.outputs.base-url }} run: | MARKDOWN=$(node ./scripts/generateMarkdownSummary.js "${BASE_URL}") echo "markdown<> $GITHUB_OUTPUT echo "$MARKDOWN" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Add to workflow summary env: MARKDOWN: ${{ steps.markdown.outputs.markdown }} run: | echo "$MARKDOWN" >> $GITHUB_STEP_SUMMARY - name: Post video to PR uses: actions/github-script@v7 env: MARKDOWN: ${{ steps.markdown.outputs.markdown }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const markdown = process.env.MARKDOWN; github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: markdown }); test-browser: runs-on: ubuntu-latest env: TESTS_MQTT_BROKER_HOST: localhost TESTS_MQTT_BROKER_PORT: 1883 services: mosquitto: image: ghcr.io/thomasnordquist/mqtt-explorer-ui-tests:latest ports: - 1883:1883 entrypoint: /bin/sh args: ["-c", "mosquitto -c /etc/mosquitto/conf.d/default.conf"] options: >- --health-cmd "mosquitto_sub -t '$SYS/#' -C 1" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '24' - name: Install Dependencies run: yarn install --frozen-lockfile - name: Install Playwright Browsers run: npx playwright install --with-deps chromium - name: Build Browser Mode run: yarn build:server - name: Test App run: yarn test:app - name: Test Backend run: yarn test:backend - name: Start Server in Background run: | yarn start:server & echo $! > server.pid env: MQTT_EXPLORER_USERNAME: test MQTT_EXPLORER_PASSWORD: test123 PORT: 3000 - name: Wait for Server run: | timeout 30 bash -c 'until curl -f http://localhost:3000; do sleep 1; done' - name: Browser Smoke Test run: | # Test server is running curl -f http://localhost:3000 || exit 1 echo "Browser mode server is running successfully" - name: Stop Server if: always() run: | if [ -f server.pid ]; then kill $(cat server.pid) || true rm server.pid fi