MQTT Explorer uses GitHub Actions for continuous integration and testing. The pipeline tests both Electron (desktop) and browser modes.
This workflow runs on pull requests to master, beta, and release branches.
This workflow builds and publishes a Docker image for the browser mode.
Triggers:
- Push to
master,beta, orreleasebranches (when relevant files change) - Schedule: Runs every two weeks (1st and 15th of each month at 2:00 AM UTC)
- Manual trigger via workflow_dispatch
Platforms:
- linux/amd64 (x86-64)
- linux/arm64 (Raspberry Pi 3/4/5, Apple Silicon)
- linux/arm/v7 (Raspberry Pi 2/3)
Image Registry: GitHub Container Registry (ghcr.io/thomasnordquist/mqtt-explorer)
Tags:
latest- Latest build from master branchmaster- Latest build from masterbeta- Latest build from beta branchrelease- Latest build from release branch<branch>-<sha>- Specific commit builds
Steps:
- Build Docker image with multi-stage build
- Test basic startup with test credentials
- Test health check
- Verify HTTP response
- Test data directory creation
- Check Docker image size
- Setup Node.js 24 for browser tests
- Install dependencies for browser tests
- Install Playwright browsers (
npx playwright install --with-deps chromium) - Start container for browser tests
- Run browser test suite with Playwright
- Push image to GitHub Container Registry
- Generate build attestation for supply chain security
Image Features:
- Multi-stage build for minimal size
- Alpine Linux base with Node.js 24 (~200MB final image)
- Multi-platform support (amd64, arm64, arm/v7)
- Non-root user (UID 1001)
- Health check endpoint
- Proper signal handling with dumb-init
- Persistent data volume at
/app/data
This workflow runs on pull requests to master, beta, and release branches.
Tests the traditional Electron desktop application:
- Environment: Custom Docker container (
ghcr.io/thomasnordquist/mqtt-explorer-ui-tests:latest)- Based on Node.js 24
- Includes Xvfb for headless display
- Includes FFmpeg for video recording
- Includes Mosquitto MQTT broker
- Playwright browsers pre-installed with system dependencies
- Steps:
- Install dependencies with frozen lockfile
- Build the Electron application
- Run unit tests (app + backend)
- Run UI tests with video recording
- Upload test video to S3 with 90-day expiration tag
- Post demo video to PR as comment
- Display test results in GitHub summary
Artifacts:
- UI test video (GIF format) uploaded to S3 using AWS CLI
- Video is tagged with
expiration=90daysfor automatic lifecycle deletion - Video is posted to the PR thread as an embedded image
- Videos expire after 90 days via S3 lifecycle policy
Tests the new browser/server mode:
- Environment: Ubuntu latest with Node.js 24
- MQTT Broker: Mosquitto v2 on port 1883
- Started detached with
-dflag - Anonymous connections allowed
- No persistence
- Started detached with
- Steps:
- Install and start Mosquitto in detached mode
- Setup Node.js 24
- Install dependencies
- Install Playwright browsers (
npx playwright install --with-deps chromium) - Build browser mode (
yarn build:server) - Run unit tests (app + backend)
- Start server in background with test credentials
- Wait for server to be ready
- Run browser smoke tests
- Clean up server process
Environment Variables:
MQTT_EXPLORER_USERNAME=testMQTT_EXPLORER_PASSWORD=test123PORT=3000
The following npm scripts are used in CI/CD:
# Unit tests
yarn test # Run all tests (app + backend)
yarn test:app # Frontend tests only
yarn test:backend # Backend tests only
# Build
yarn build # Build Electron mode
yarn build:server # Build browser mode
# UI Tests (Electron only)
yarn ui-test # Run UI tests with video recordingAdd tests to the test job. UI tests should be added to the test suite that yarn ui-test runs.
Browser-specific tests should:
- Use the pre-configured Mosquitto service
- Connect to
mqtt://mosquitto:1883 - Test server endpoints at
http://localhost:3000
Example:
- name: Browser Integration Test
run: |
# Test MQTT connection through server
curl -X POST http://localhost:3000/api/test# Build the image locally (for your platform)
docker build -f Dockerfile.browser -t mqtt-explorer:local .
# Build for specific platform (e.g., Raspberry Pi)
docker buildx build --platform linux/arm64 -f Dockerfile.browser -t mqtt-explorer:local-arm64 .
# Run the container
docker run -d \
-p 3000:3000 \
-e MQTT_EXPLORER_USERNAME=test \
-e MQTT_EXPLORER_PASSWORD=test123 \
mqtt-explorer:local
# Test the server
curl http://localhost:3000
# Check logs
docker logs <container-id>
# Stop and remove
docker stop <container-id>
docker rm <container-id>See DOCKER.md for complete documentation.
yarn build
yarn test
yarn ui-test# Start Mosquitto in Docker
docker run -d -p 1883:1883 eclipse-mosquitto:2
# Build and test
yarn build:server
yarn test
# Start server
MQTT_EXPLORER_USERNAME=test MQTT_EXPLORER_PASSWORD=test123 yarn start:server
# Run manual tests
curl http://localhost:3000The repository includes a devcontainer configuration that automatically sets up:
- Node.js 20
- MQTT broker (Mosquitto)
- All development dependencies
- Port forwarding for development
See .devcontainer/README.md for details.
Demo videos uploaded from PRs are tagged with expiration=90days and require an S3 lifecycle policy to automatically delete them after 90 days.
Important: The video.mp4 file in the gh-pages branch is NOT tagged and will NOT expire.
- Create a file named
s3-lifecycle-pr-videos.json:
{
"Rules": [
{
"ID": "ExpirePRDemoVideosAfter90Days",
"Status": "Enabled",
"Filter": {
"Tag": {
"Key": "expiration",
"Value": "90days"
}
},
"Expiration": {
"Days": 90
}
}
]
}- Apply the policy to your S3 bucket:
aws s3api put-bucket-lifecycle-configuration \
--bucket YOUR_BUCKET_NAME \
--lifecycle-configuration file://s3-lifecycle-pr-videos.json- Verify the policy:
aws s3api get-bucket-lifecycle-configuration --bucket YOUR_BUCKET_NAME- PR demo videos: Uploaded with filename pattern
pr-{number}-{timestamp}.gifand tagged with:expiration=90days- Used by lifecycle policy for automatic deletionSource=github-actions- Identifies source of uploadType=pr-demo-video- Categorizes the object type
- S3 lifecycle rule: Automatically deletes objects tagged with
expiration=90daysafter 90 days - Upload mechanism: AWS CLI v2 is installed directly, authentication is configured via
aws-actions/configure-aws-credentials@v4GitHub Action, thenaws s3api put-objectis used with object tagging support - gh-pages video:
video.mp4in gh-pages branch is served from GitHub Pages, not S3, so it persists indefinitely
The workflow requires the following secrets/variables:
vars.AWS_KEY_ID- AWS access key ID (requiress3:PutObjectands3:PutObjectTaggingpermissions)secrets.AWS_SECRET_ACCESS_KEY- AWS secret access keyvars.AWS_BUCKET- S3 bucket name- AWS region:
eu-central-1(hardcoded in workflow)
The S3 bucket must have:
- Bucket policy for public read access: Since ACLs are disabled (BucketOwnerEnforced), a bucket policy must grant public read access to uploaded objects
- Object tagging enabled
- Lifecycle policy configured as described above
Example S3 Bucket Policy for Public Read Access:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}
]
}The workflow uses AWS CLI v2 installed directly and aws-actions/configure-aws-credentials@v4 action for secure credential management.
- Server won't start: Check if port 3000 is already in use
- MQTT connection fails: Ensure Mosquitto service is healthy
- Timeout errors: Increase timeout in "Wait for Server" step
- UI tests timeout: Check if the Docker container has display access
- Build fails: Verify all dependencies are in yarn.lock
- Add Playwright browser installation to workflows (browser tests can now use Playwright)
- Add E2E browser tests with Playwright
- Test WebSocket connections in browser mode
- Add performance benchmarks
- Test with different MQTT broker versions
- Add security scanning for browser mode