/ .github / workflows / ui-ci.yml
ui-ci.yml
  1  name: "CI (UI)"
  2  
  3  on:
  4    workflow_dispatch:
  5    push:
  6      branches:
  7        - "main"
  8  
  9  permissions:
 10    contents: write
 11    packages: write
 12    id-token: write
 13    pull-requests: write
 14    actions: read
 15    statuses: write
 16    checks: write
 17    repository-projects: read
 18  
 19  jobs:
 20    check-paths:
 21      name: "Check if UI files changed"
 22      runs-on: ubuntu-latest
 23      outputs:
 24        should-run: ${{ steps.filter.outputs.ui }}
 25      steps:
 26        - name: Checkout code
 27          uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
 28  
 29        - name: Check for UI changes
 30          uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
 31          id: filter
 32          with:
 33            filters: |
 34              ui:
 35                - 'client/webui/frontend/**'
 36  
 37    ui-build-and-test:
 38      name: "Build and Test UI"
 39      needs: check-paths
 40      if: needs.check-paths.outputs.should-run == 'true'
 41      runs-on: ubuntu-latest
 42      defaults:
 43        run:
 44          working-directory: client/webui/frontend
 45      steps:
 46        - name: Checkout code
 47          uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
 48          with:
 49            fetch-depth: 0
 50  
 51        - name: Setup Node.js
 52          uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
 53          with:
 54            node-version: "25.5.0"
 55            cache: "npm"
 56            cache-dependency-path: client/webui/frontend/package-lock.json
 57            registry-url: https://npm.pkg.github.com/
 58            scope: "@SolaceLabs"
 59  
 60        - name: Configure npm for install
 61          run: |
 62            echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > .npmrc
 63            echo "@SolaceLabs:registry=https://npm.pkg.github.com/" >> .npmrc
 64            echo "legacy-peer-deps=true" >> .npmrc
 65  
 66        - name: Install dependencies
 67          run: npm ci
 68          env:
 69            NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 70  
 71        - name: Restore Playwright Browser From Cache
 72          id: restore-playwright-cache
 73          uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
 74          with:
 75            path: ~/.cache/ms-playwright
 76            key: playwright-${{ runner.os }}-${{ hashFiles('client/webui/frontend/package-lock.json') }}
 77  
 78        - name: Install Playwright browsers
 79          if: steps.restore-playwright-cache.outputs.cache-hit != 'true'
 80          run: ./node_modules/.bin/playwright install chromium --with-deps
 81  
 82        - name: Save Playwright cache
 83          if: steps.restore-playwright-cache.outputs.cache-hit != 'true'
 84          uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
 85          with:
 86            path: ~/.cache/ms-playwright
 87            key: playwright-${{ runner.os }}-${{ hashFiles('client/webui/frontend/package-lock.json') }}
 88  
 89        - name: Run lint
 90          run: npm run lint
 91  
 92        - name: Run Storybook Tests with Coverage
 93          run: npm run ci:storybook:coverage
 94          env:
 95            # Workaround for Node.js 25 Web Storage API breaking jsdom tests
 96            # See: https://github.com/vitest-dev/vitest/issues/8757
 97            NODE_OPTIONS: "--no-webstorage"
 98  
 99        - name: Upload UI Coverage Artifact
100          uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
101          with:
102            name: ui-coverage-standalone
103            path: client/webui/frontend/coverage/
104            retention-days: 1
105  
106        - name: Build UI package
107          run: npm run build-package
108  
109    ui-ci-status:
110      name: "UI CI Status"
111      runs-on: ubuntu-latest
112      needs: [check-paths, ui-build-and-test]
113      if: always()
114      steps:
115        - name: Check build status
116          run: |
117            if [[ "${{ needs.check-paths.outputs.should-run }}" == "false" ]]; then
118              echo "UI files not changed, skipping UI build and tests"
119              exit 0
120            elif [[ "${{ needs.ui-build-and-test.result }}" == "success" ]]; then
121              echo "UI build/tests passed"
122              exit 0
123            else
124              echo "UI build/tests failed"
125              exit 1
126            fi
127  
128    bump-version:
129      needs: [check-paths, ui-build-and-test]
130      name: "Bump UI Version"
131      runs-on: ubuntu-latest
132      if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch && needs.check-paths.outputs.should-run == 'true'
133      outputs:
134        new-tag: ${{ steps.bump.outputs.newTag }}
135      defaults:
136        run:
137          working-directory: client/webui/frontend
138      steps:
139        - name: "Checkout source code"
140          uses: "actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd" # v5.0.1
141          with:
142            ref: ${{ github.ref }}
143            token: ${{ secrets.GITHUB_TOKEN }}
144            fetch-depth: 0
145  
146        - name: "Current package.json"
147          run: cat ./package.json
148  
149        - name: Setup Node.js
150          uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
151          with:
152            node-version: "25.5.0"
153  
154        - name: "Automated Version Bump"
155          id: bump
156          uses: "phips28/gh-action-bump-version@71473b25295fe3907df2ff87cce295a0dce1b20b" # master
157          with:
158            minor-wording: "feat,minor"
159            major-wording: "BREAKING CHANGE,major"
160            patch-wording: "fix,patch,docs,style,refactor,perf,test,build,ci,chore,revert"
161            tag-prefix: "ui-v"
162            commit-message: "ci(ui): bump version to {{version}} [skip ci]"
163            skip-push: "true"
164            default: "patch" # default to patch bump if no bumps included in commit messages
165            bump-policy: "ignore" # always bump regardless of whether bumps included in commit messages
166          env:
167            PACKAGEJSON_DIR: client/webui/frontend
168            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
169  
170        - name: "Updated package.json"
171          run: cat ./package.json
172  
173        - name: "Extract version from tag"
174          id: extract-version
175          run: |
176            if [ -n "${{ steps.bump.outputs.newTag }}" ]; then
177              TAG="${{ steps.bump.outputs.newTag }}"
178              VERSION="${TAG#ui-v}"
179              echo "version=$VERSION" >> $GITHUB_OUTPUT
180              echo "Extracted version: $VERSION from tag: $TAG"
181            else
182              echo "No new tag created"
183              echo "version=" >> $GITHUB_OUTPUT
184            fi
185  
186        - name: Set up SSH agent
187          if: steps.bump.outputs.newTag != ''
188          uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
189          with:
190            ssh-private-key: ${{ secrets.COMMIT_KEY }}
191  
192        - name: Push new version and tag
193          if: steps.bump.outputs.newTag != ''
194          run: |
195            git config user.name "github-actions[bot]"
196            git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
197            git remote set-url origin git@github.com:${{ github.repository }}.git
198            git push origin main
199            git push origin ${{ steps.bump.outputs.newTag }}
200  
201    release-ui:
202      needs: bump-version
203      name: "Release UI Package"
204      if: needs.bump-version.outputs.new-tag != ''
205      uses: ./.github/workflows/ui-release.yml
206      with:
207        tag: ${{ needs.bump-version.outputs.new-tag }}
208      secrets: inherit