-
-
Notifications
You must be signed in to change notification settings - Fork 397
Add Docker build for browser mode with optimized 3-stage build, multi-platform support, comprehensive UI testing, one-click deployment, enterprise SSO integration, and biweekly CI pipeline #934
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
78e3628
c8bd78d
319bc4c
2b5cd99
67e345b
a7742fc
625d5ed
f822cdc
3d28977
785cc42
b2a40c8
13beb04
4695488
10ab0ca
aeaf2a7
8fbbd7d
9439885
e7e3913
d91f948
d190b67
8ae915d
8944539
8beb173
fa9d04a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # Git | ||
| .git | ||
| .gitignore | ||
| .github | ||
|
|
||
| # Dependencies | ||
| node_modules | ||
| app/node_modules | ||
| backend/node_modules | ||
|
|
||
| # Build artifacts | ||
| build | ||
| dist | ||
| app/dist | ||
|
|
||
| # Testing | ||
| coverage | ||
| .nyc_output | ||
| test-screenshot-*.png | ||
| ui-test.mp4 | ||
| ui-test.gif | ||
|
|
||
| # Development | ||
| .vscode | ||
| .devcontainer | ||
| *.log | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
|
|
||
| # OS | ||
| .DS_Store | ||
| Thumbs.db | ||
|
|
||
| # IDE | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
| .idea | ||
|
|
||
| # Documentation | ||
| *.md | ||
| !Readme.md | ||
| LICENSE.md | ||
|
|
||
| # CI/CD files | ||
| .releaserc | ||
| appveyor.yml | ||
|
|
||
| # Misc | ||
| res | ||
| scripts | ||
| docker | ||
| icon.xcf | ||
| greenkeeper.json | ||
| prettier.config.js | ||
| .prettierignore | ||
| .eslintrc.json | ||
| .cspell.json | ||
| tslint.json | ||
| mcp.json | ||
|
|
||
| # Data directory (will be created in container) | ||
| data |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,219 @@ | ||
| name: Docker Browser Build | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - master | ||
| - release | ||
| - beta | ||
| paths: | ||
| - 'Dockerfile.browser' | ||
| - 'src/server.ts' | ||
| - 'src/AuthManager.ts' | ||
| - 'app/**' | ||
| - 'backend/**' | ||
| - 'package.json' | ||
| - 'yarn.lock' | ||
| - '.github/workflows/docker-browser.yml' | ||
| - 'tsconfig.json' | ||
| - 'events/**' | ||
| schedule: | ||
| # Run every two weeks (1st and 15th of each month) at 2:00 AM UTC | ||
| - cron: '0 2 1,15 * *' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| build-and-test: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
|
thomasnordquist marked this conversation as resolved.
|
||
| id-token: write | ||
|
|
||
| services: | ||
| # MQTT broker for testing | ||
| mosquitto: | ||
| image: eclipse-mosquitto:2 | ||
| ports: | ||
| - 1883:1883 | ||
| options: >- | ||
| --health-cmd "mosquitto_sub -t '$SYS/#' -C 1" | ||
| --health-interval 10s | ||
| --health-timeout 5s | ||
| --health-retries 5 | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
|
Check warning on line 50 in .github/workflows/docker-browser.yml
|
||
|
|
||
| - name: Log in to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
|
Check warning on line 53 in .github/workflows/docker-browser.yml
|
||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Extract metadata (tags, labels) for Docker | ||
| id: meta | ||
| uses: docker/metadata-action@v5 | ||
|
Check warning on line 61 in .github/workflows/docker-browser.yml
|
||
| with: | ||
| images: ghcr.io/${{ github.repository }} | ||
| tags: | | ||
| type=ref,event=branch | ||
| type=sha,prefix={{branch}}- | ||
| type=raw,value=latest,enable={{is_default_branch}} | ||
|
|
||
| - name: Build Docker image | ||
| uses: docker/build-push-action@v5 | ||
|
Check warning on line 70 in .github/workflows/docker-browser.yml
|
||
| with: | ||
| context: . | ||
| file: ./Dockerfile.browser | ||
| platforms: linux/amd64 | ||
| push: false | ||
| load: true | ||
| tags: mqtt-explorer:test | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
|
|
||
| - name: Test Docker image - Basic startup | ||
| run: | | ||
| # Start container with test credentials | ||
| docker run -d \ | ||
| --name mqtt-explorer-test \ | ||
| -p 3000:3000 \ | ||
| -e MQTT_EXPLORER_USERNAME=test \ | ||
| -e MQTT_EXPLORER_PASSWORD=test123 \ | ||
| -e PORT=3000 \ | ||
| mqtt-explorer:test | ||
|
|
||
| # Wait for server to be ready (max 60 seconds) | ||
| echo "Waiting for server to start..." | ||
| for i in {1..60}; do | ||
| if curl -f http://localhost:3000 > /dev/null 2>&1; then | ||
| echo "Server started successfully after $i seconds" | ||
| break | ||
| fi | ||
| if [ $i -eq 60 ]; then | ||
| echo "Server failed to start within 60 seconds" | ||
| docker logs mqtt-explorer-test | ||
| exit 1 | ||
| fi | ||
| sleep 1 | ||
| done | ||
|
|
||
| - name: Test Docker image - Health check | ||
| run: | | ||
| # Wait for health check to pass | ||
| echo "Waiting for health check to pass..." | ||
| for i in {1..30}; do | ||
| health=$(docker inspect --format='{{.State.Health.Status}}' mqtt-explorer-test) | ||
| if [ "$health" = "healthy" ]; then | ||
| echo "Container is healthy" | ||
| break | ||
| fi | ||
| if [ $i -eq 30 ]; then | ||
| echo "Health check failed" | ||
| docker logs mqtt-explorer-test | ||
| exit 1 | ||
| fi | ||
| sleep 2 | ||
| done | ||
|
|
||
| - name: Test Docker image - Verify response | ||
| run: | | ||
| # Test that the server responds with HTML | ||
| response=$(curl -s http://localhost:3000) | ||
| if echo "$response" | grep -q "MQTT Explorer"; then | ||
| echo "Server is serving the application correctly" | ||
| else | ||
| echo "Server response does not contain expected content" | ||
| echo "Response: $response" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Test Docker image - Verify data persistence | ||
| run: | | ||
| # Check that data directory was created | ||
| docker exec mqtt-explorer-test sh -c '[ -d /app/data ] && echo "Data directory exists"' | ||
|
|
||
| - name: Clean up test container | ||
| if: always() | ||
| run: | | ||
| docker stop mqtt-explorer-test || true | ||
| docker rm mqtt-explorer-test || true | ||
|
|
||
| - name: Check Docker image size | ||
| run: | | ||
| echo "### Docker Image Size" >> $GITHUB_STEP_SUMMARY | ||
| docker images mqtt-explorer:test --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" >> $GITHUB_STEP_SUMMARY | ||
|
|
||
| # Get size in bytes for detailed reporting | ||
| SIZE_BYTES=$(docker inspect mqtt-explorer:test --format='{{.Size}}') | ||
| SIZE_MB=$((SIZE_BYTES / 1024 / 1024)) | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "**Image size**: ${SIZE_MB} MB (${SIZE_BYTES} bytes)" >> $GITHUB_STEP_SUMMARY | ||
| echo "Image size: ${SIZE_MB} MB" | ||
|
|
||
| - name: Setup Node.js for browser tests | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '24' | ||
| cache: 'yarn' | ||
|
|
||
| - name: Install dependencies for browser tests | ||
| run: yarn install --frozen-lockfile | ||
|
|
||
| - name: Start Docker container for browser tests | ||
| run: | | ||
| docker run -d \ | ||
| --name mqtt-explorer-browser-test \ | ||
| --network host \ | ||
| -e MQTT_EXPLORER_USERNAME=test \ | ||
| -e MQTT_EXPLORER_PASSWORD=test123 \ | ||
| -e PORT=3000 \ | ||
| mqtt-explorer:test | ||
|
|
||
| # Wait for server to be ready | ||
| echo "Waiting for Docker container to be ready..." | ||
| timeout 60 bash -c 'until curl -f http://localhost:3000; do sleep 1; done' | ||
| echo "Docker container is ready" | ||
|
|
||
| - name: Run browser test suite | ||
| run: | | ||
| yarn test:browser | ||
| env: | ||
| MQTT_EXPLORER_USERNAME: test | ||
| MQTT_EXPLORER_PASSWORD: test123 | ||
| BROWSER_MODE_URL: http://localhost:3000 | ||
| MQTT_BROKER_HOST: localhost | ||
| MQTT_BROKER_PORT: 1883 | ||
|
|
||
| - name: Clean up browser test container | ||
| if: always() | ||
| run: | | ||
| docker logs mqtt-explorer-browser-test || true | ||
| docker stop mqtt-explorer-browser-test || true | ||
| docker rm mqtt-explorer-browser-test || true | ||
|
|
||
| - name: Build and push Docker image | ||
| id: build | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| file: ./Dockerfile.browser | ||
| platforms: linux/amd64,linux/arm64,linux/arm/v7 | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
|
|
||
| - name: Generate artifact attestation | ||
| uses: actions/attest-build-provenance@v1 | ||
| with: | ||
| subject-name: ghcr.io/${{ github.repository }} | ||
| subject-digest: ${{ steps.build.outputs.digest }} | ||
| push-to-registry: true | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow paths do not include
tsconfig.jsonandevents/**, but both are copied in the Dockerfile and can affect the build output. Changes to TypeScript configuration or event definitions should trigger a Docker rebuild. Add these paths to ensure the Docker image is rebuilt when these critical files change.