on: pull_request_target: # Use pull_request_target branches: [master, beta, release] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true 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 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - 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 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: 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 }); demo-video-mobile: runs-on: ubuntu-latest container: image: ghcr.io/thomasnordquist/mqtt-explorer-ui-tests:latest volumes: - ./:/app steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Packages run: yarn install --frozen-lockfile - name: Build Browser Mode run: yarn build:server - name: Generate Mobile Demo Video id: generate_video continue-on-error: true run: ./scripts/uiTestsMobile.sh - name: Post-processing if: always() continue-on-error: true run: ./scripts/prepareVideoMobile.sh - name: Generate unique base path id: basepath run: | TIMESTAMP=$(date +%Y%m%d-%H%M%S) BASEPATH="pr-${{ github.event.pull_request.number }}-mobile-${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 mobile video to S3 if: always() continue-on-error: true env: AWS_BUCKET: ${{ vars.AWS_BUCKET }} BASEPATH: ${{ steps.basepath.outputs.basepath }} run: | # Upload GIF if it exists if [ -f ./ui-test-mobile.gif ]; then aws s3api put-object \ --bucket ${AWS_BUCKET} \ --key artifacts/${BASEPATH}/ui-test-mobile.gif \ --body ./ui-test-mobile.gif \ --content-type image/gif fi # Upload MP4 if it exists if [ -f ./ui-test-mobile.mp4 ]; then aws s3api put-object \ --bucket ${AWS_BUCKET} \ --key artifacts/${BASEPATH}/ui-test-mobile.mp4 \ --body ./ui-test-mobile.mp4 \ --content-type video/mp4 fi - name: Upload mobile video segments to S3 if: always() continue-on-error: true env: AWS_BUCKET: ${{ vars.AWS_BUCKET }} BASEPATH: ${{ steps.basepath.outputs.basepath }} shell: bash run: | # Upload all mobile GIF segment files if they exist shopt -s nullglob # Make glob return empty list if no matches for segment in segment-mobile-*.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 if: always() 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 if: always() id: markdown env: BASE_URL: ${{ steps.fileurl.outputs.base-url }} TEST_STATUS: ${{ steps.generate_video.outcome }} run: | MARKDOWN=$(node ./scripts/generateMarkdownSummaryMobile.js "${BASE_URL}" "${TEST_STATUS}") echo "markdown<> $GITHUB_OUTPUT echo "$MARKDOWN" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Add to workflow summary if: always() env: MARKDOWN: ${{ steps.markdown.outputs.markdown }} run: | echo "$MARKDOWN" >> $GITHUB_STEP_SUMMARY - name: Post mobile video to PR if: always() 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 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install System Dependencies run: | sudo apt-get update sudo apt-get install -y mosquitto mosquitto-clients - 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: Run Browser UI Tests run: ./scripts/runBrowserTests.sh