Skip to content

Merge pull request #29 from boris91/chore/header-controls-keys-naming #21

Merge pull request #29 from boris91/chore/header-controls-keys-naming

Merge pull request #29 from boris91/chore/header-controls-keys-naming #21

Workflow file for this run

name: MDK UI CI
on:
push:
branches: [main]
paths:
- "ui-client/**"
- ".github/workflows/ui.yaml"
pull_request:
branches: [main]
types: [opened, reopened, synchronize]
paths:
- "ui-client/**"
- ".github/workflows/ui.yaml"
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: "lts/*"
PNPM_VERSION: "10.5.0"
UI_DIR: ui-client
jobs:
dependency-review:
name: Dependency Review
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Dependency Review
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
with:
fail-on-severity: moderate
vulnerability-check: true
license-check: true
comment-summary-in-pr: always
ui-setup:
name: UI Setup Dependencies
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: ${{ env.UI_DIR }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup runtime
uses: ./.github/actions/setup-runtime
with:
node_version: ${{ env.NODE_VERSION }}
package_manager: pnpm
pnpm_version: ${{ env.PNPM_VERSION }}
cache_dependency_path: ${{ env.UI_DIR }}/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
ui-lint:
name: UI Lint
runs-on: ubuntu-latest
needs: [ui-setup]
permissions:
contents: read
defaults:
run:
working-directory: ${{ env.UI_DIR }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup runtime
uses: ./.github/actions/setup-runtime
with:
node_version: ${{ env.NODE_VERSION }}
package_manager: pnpm
pnpm_version: ${{ env.PNPM_VERSION }}
cache_dependency_path: ${{ env.UI_DIR }}/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm run lint
ui-typecheck:
name: UI Typecheck
runs-on: ubuntu-latest
needs: [ui-setup]
permissions:
contents: read
defaults:
run:
working-directory: ${{ env.UI_DIR }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup runtime
uses: ./.github/actions/setup-runtime
with:
node_version: ${{ env.NODE_VERSION }}
package_manager: pnpm
pnpm_version: ${{ env.PNPM_VERSION }}
cache_dependency_path: ${{ env.UI_DIR }}/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Typecheck
run: pnpm run typecheck
ui-test:
name: UI Test
runs-on: ubuntu-latest
needs: [ui-setup]
permissions:
contents: read
defaults:
run:
working-directory: ${{ env.UI_DIR }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup runtime
uses: ./.github/actions/setup-runtime
with:
node_version: ${{ env.NODE_VERSION }}
package_manager: pnpm
pnpm_version: ${{ env.PNPM_VERSION }}
cache_dependency_path: ${{ env.UI_DIR }}/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Format check
continue-on-error: true
run: pnpm run format
- name: Test with coverage
id: run-tests
run: pnpm run test:coverage || pnpm test
- name: Coverage summary
if: always()
shell: bash
run: |
set -euo pipefail
TEST_OUTCOME="${{ steps.run-tests.outcome }}"
mapfile -t COVERAGE_JSON_FILES < <(find . -type f -path '*/coverage/coverage-final.json')
mapfile -t LCOV_FILES < <(find . -type f -path '*/coverage/lcov.info')
if [ ${#COVERAGE_JSON_FILES[@]} -gt 0 ]; then
rm -rf .nyc_output
mkdir -p .nyc_output
i=0
for file in "${COVERAGE_JSON_FILES[@]}"; do
cp "$file" ".nyc_output/out-$i.json"
i=$((i + 1))
done
npx --yes nyc merge .nyc_output coverage-merged.json >/dev/null
cp coverage-merged.json .nyc_output/out.json
NYC_REPORT="$(npx --yes nyc report --reporter=text-summary 2>&1)"
echo "$NYC_REPORT"
STMT=$(echo "$NYC_REPORT" | sed -n 's/^Statements[^:]*: *\([0-9.]*\)%.*/\1/p')
BRANCH=$(echo "$NYC_REPORT" | sed -n 's/^Branches[^:]*: *\([0-9.]*\)%.*/\1/p')
FN=$(echo "$NYC_REPORT" | sed -n 's/^Functions[^:]*: *\([0-9.]*\)%.*/\1/p')
LINES=$(echo "$NYC_REPORT" | sed -n 's/^Lines[^:]*: *\([0-9.]*\)%.*/\1/p')
[ -z "$STMT" ] && STMT="—"; [ -z "$BRANCH" ] && BRANCH="—"; [ -z "$FN" ] && FN="—"; [ -z "$LINES" ] && LINES="—"
SRC="coverage-final.json"
elif [ ${#LCOV_FILES[@]} -gt 0 ]; then
LF=$(awk -F: '/^LF:/ {sum+=$2} END {print sum+0}' "${LCOV_FILES[@]}")
LH=$(awk -F: '/^LH:/ {sum+=$2} END {print sum+0}' "${LCOV_FILES[@]}")
FNF=$(awk -F: '/^FNF:/ {sum+=$2} END {print sum+0}' "${LCOV_FILES[@]}")
FNH=$(awk -F: '/^FNH:/ {sum+=$2} END {print sum+0}' "${LCOV_FILES[@]}")
BRF=$(awk -F: '/^BRF:/ {sum+=$2} END {print sum+0}' "${LCOV_FILES[@]}")
BRH=$(awk -F: '/^BRH:/ {sum+=$2} END {print sum+0}' "${LCOV_FILES[@]}")
LINES=$(awk -v h="$LH" -v f="$LF" 'BEGIN { if (f==0) print "0.00"; else printf "%.2f", (h/f)*100 }')
STMT="$LINES"
FN=$(awk -v h="$FNH" -v f="$FNF" 'BEGIN { if (f==0) print "0.00"; else printf "%.2f", (h/f)*100 }')
BRANCH=$(awk -v h="$BRH" -v f="$BRF" 'BEGIN { if (f==0) print "0.00"; else printf "%.2f", (h/f)*100 }')
SRC="lcov.info"
else
STMT="—"; BRANCH="—"; FN="—"; LINES="—"; SRC="none"
fi
[ "$TEST_OUTCOME" = "success" ] && ICON="✅ PASS" || ICON="❌ FAIL"
{
echo "## UI Coverage Summary"
echo ""
echo "| Scope | Status | Statements | Branches | Functions | Lines | Source | Gate |"
echo "|---|---|---:|---:|---:|---:|---|---|"
echo "| UI | ${ICON} | ${STMT}% | ${BRANCH}% | ${FN}% | ${LINES}% | ${SRC} | Vitest thresholds |"
} >> "$GITHUB_STEP_SUMMARY"
[ "$TEST_OUTCOME" = "success" ] || exit 1
ui-build:
name: UI Build
runs-on: ubuntu-latest
needs: [ui-setup]
permissions:
contents: read
defaults:
run:
working-directory: ${{ env.UI_DIR }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Setup runtime
uses: ./.github/actions/setup-runtime
with:
node_version: ${{ env.NODE_VERSION }}
package_manager: pnpm
pnpm_version: ${{ env.PNPM_VERSION }}
cache_dependency_path: ${{ env.UI_DIR }}/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Security audit
run: |
set +e
pnpm audit --audit-level=moderate 2>&1
MODERATE_EXIT=$?
pnpm audit --audit-level=high 2>&1
HIGH_EXIT=$?
set -e
[ $MODERATE_EXIT -eq 0 ] && MODERATE_STATUS="PASS" || MODERATE_STATUS="WARN"
[ $HIGH_EXIT -eq 0 ] && HIGH_STATUS="PASS" || HIGH_STATUS="WARN"
{
echo "## UI Security Audit Summary"
echo ""
echo "| Scope | Moderate Audit | High Audit | Gate |"
echo "|---|---|---|---|"
echo "| UI | ${MODERATE_STATUS} | ${HIGH_STATUS} | High/Critical blocking |"
} >> "$GITHUB_STEP_SUMMARY"
if [ $MODERATE_EXIT -ne 0 ]; then
echo "::error::pnpm audit reported moderate-level issues"
fi
if [ $HIGH_EXIT -ne 0 ]; then
echo "::error::pnpm audit reported high-level issues"
fi
[ $HIGH_EXIT -eq 0 ]
- name: Build
run: pnpm run build
- name: Bundle size report
continue-on-error: true
run: |
echo "## UI Bundle Size Report" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
pnpm run size -- --markdown 2>&1 | tee -a "$GITHUB_STEP_SUMMARY"