mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
219 lines
12 KiB
YAML
219 lines
12 KiB
YAML
name: Полные бенчмарки производительности
|
|
|
|
on:
|
|
# Every main promotion is a stable-release candidate and must have an
|
|
# exact-SHA full comparison before stable assets are published.
|
|
push:
|
|
branches:
|
|
- main
|
|
paths-ignore:
|
|
- ".github/workflows/**"
|
|
- "docs/**"
|
|
schedule:
|
|
- cron: "0 4 * * 1"
|
|
workflow_dispatch:
|
|
inputs:
|
|
comparison_ref:
|
|
description: "Optional baseline tag, branch or SHA; empty uses the candidate parent"
|
|
required: false
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: full-performance-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
performance:
|
|
name: Бенчмарки рендера и геометрии
|
|
# Every profile keeps base and candidate sequential on one hosted runner.
|
|
# Independent profile pairs run in parallel: cross-profile timing is never
|
|
# compared, while serialising all profile pairs cannot fit the job timeout.
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 60
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
profile:
|
|
- large-house
|
|
- isometric
|
|
- isometric-stage3
|
|
- plan-snap
|
|
- interaction
|
|
- blend
|
|
- overlay
|
|
- space-default
|
|
- space-glow
|
|
steps:
|
|
- name: Check out candidate
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
path: candidate
|
|
fetch-depth: 2
|
|
|
|
- name: Resolve comparison SHA
|
|
id: base
|
|
working-directory: candidate
|
|
env:
|
|
EVENT_NAME: ${{ github.event_name }}
|
|
PUSH_BEFORE_SHA: ${{ github.event.before }}
|
|
MANUAL_BASE: ${{ inputs.comparison_ref }}
|
|
# #587: кандидат стабильного релиза судится о предыдущий стабильный
|
|
# тег, а не о прошлую вершину main. Признак кандидата — трейлер
|
|
# `Release:` в сообщении head-коммита, поэтому оно едет в скрипт.
|
|
HEAD_MESSAGE: ${{ github.event.head_commit.message }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [ "$(git rev-parse --is-shallow-repository)" = "true" ]; then
|
|
git fetch --force --tags --prune --unshallow origin
|
|
else
|
|
git fetch --force --tags --prune origin
|
|
fi
|
|
# Решение целиком в скрипте: его отрицательные случаи проверяются
|
|
# фикстурами, а shell-развилку прогнать тестом нельзя (#556, #587).
|
|
node scripts/performance-baseline.mjs
|
|
|
|
- name: Check out base SHA
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
ref: ${{ steps.base.outputs.sha }}
|
|
path: baseline
|
|
|
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
with:
|
|
node-version: 22
|
|
cache: npm
|
|
cache-dependency-path: |
|
|
candidate/package-lock.json
|
|
baseline/package-lock.json
|
|
|
|
- name: Install candidate and baseline dependencies
|
|
run: npm ci --prefix candidate && npm ci --prefix baseline
|
|
|
|
# То же, что в validate.yml: кэш браузеров, apt не трогаем (#206).
|
|
- name: Кэш браузеров Playwright
|
|
id: pw
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-${{ runner.os }}-${{ hashFiles('candidate/package-lock.json') }}
|
|
- name: Install pinned Chromium
|
|
if: steps.pw.outputs.cache-hit != 'true'
|
|
working-directory: candidate
|
|
run: npx playwright install chromium
|
|
|
|
- name: Build both exact source trees
|
|
run: |
|
|
npm --prefix candidate run build
|
|
(cd candidate && node scripts/bundle-sync.mjs)
|
|
npm --prefix baseline run build
|
|
if [ -f baseline/scripts/bundle-sync.mjs ]; then
|
|
(cd baseline && node scripts/bundle-sync.mjs)
|
|
else
|
|
echo "::notice::The comparison base predates bundle-sync.mjs; materializing its freshly built bundle with the legacy copy path."
|
|
mkdir -p baseline/custom_components/houseplan/frontend baseline/demo/srv/assets
|
|
cp baseline/dist/houseplan-card.js baseline/custom_components/houseplan/frontend/houseplan-card.js
|
|
cp baseline/dist/houseplan-card.js baseline/demo/srv/assets/houseplan-card.js
|
|
fi
|
|
|
|
- name: Capture base and candidate profile
|
|
working-directory: candidate
|
|
env:
|
|
PROFILE: ${{ matrix.profile }}
|
|
run: |
|
|
mkdir -p ../artifacts/performance
|
|
case "$PROFILE" in
|
|
large-house)
|
|
npm run benchmark:large-house -- --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/baseline.json
|
|
npm run benchmark:large-house -- --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/candidate.json
|
|
;;
|
|
isometric)
|
|
npm run benchmark:large-house-isometric -- --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/isometric-baseline.json
|
|
npm run benchmark:large-house-isometric -- --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/isometric-candidate.json
|
|
;;
|
|
isometric-stage3)
|
|
npm run benchmark:isometric-stage3-dense -- --allow-stage2-base --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/isometric-stage3-baseline.json
|
|
npm run benchmark:isometric-stage3-dense -- --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/isometric-stage3-candidate.json
|
|
;;
|
|
plan-snap)
|
|
npm run benchmark:large-house-plan-snap -- --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/plan-snap-baseline.json
|
|
npm run benchmark:large-house-plan-snap -- --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/plan-snap-candidate.json
|
|
;;
|
|
interaction)
|
|
npm run benchmark:large-house-interaction -- --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/interaction-baseline.json
|
|
npm run benchmark:large-house-interaction -- --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/interaction-candidate.json
|
|
;;
|
|
blend)
|
|
npm run benchmark:glow -- --profile=large-light-blend-v1 --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/blend-baseline.json
|
|
npm run benchmark:glow -- --profile=large-light-blend-v1 --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/blend-candidate.json
|
|
;;
|
|
overlay)
|
|
npm run benchmark:glow -- --profile=large-house-glow-overlay-v1 --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/overlay-baseline.json
|
|
npm run benchmark:glow -- --profile=large-house-glow-overlay-v1 --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/overlay-candidate.json
|
|
if ! grep -q "glow_enabled" ../baseline/src/logic.ts; then
|
|
echo "Base predates independent Glow; bootstrap relative overlay baseline, keep absolute gate"
|
|
cp ../artifacts/performance/overlay-candidate.json ../artifacts/performance/overlay-baseline.json
|
|
fi
|
|
;;
|
|
space-default)
|
|
npm run benchmark:glow -- --profile=large-space-card-default-v1 --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/space-default-baseline.json
|
|
npm run benchmark:glow -- --profile=large-space-card-default-v1 --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/space-default-candidate.json
|
|
;;
|
|
space-glow)
|
|
npm run benchmark:glow -- --profile=large-space-card-glow-v1 --target-root=../baseline --samples=7 --warmups=1 --output=../artifacts/performance/space-glow-baseline.json
|
|
npm run benchmark:glow -- --profile=large-space-card-glow-v1 --target-root=. --samples=7 --warmups=1 --output=../artifacts/performance/space-glow-candidate.json
|
|
if ! grep -q "light_pools" ../baseline/src/space-card.ts; then
|
|
echo "Base predates opt-in static Glow; bootstrap relative baseline, keep absolute gate"
|
|
cp ../artifacts/performance/space-glow-candidate.json ../artifacts/performance/space-glow-baseline.json
|
|
fi
|
|
;;
|
|
*)
|
|
echo "::error::Unknown performance profile: $PROFILE"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
- name: Enforce relative and absolute performance budget
|
|
working-directory: candidate
|
|
env:
|
|
PROFILE: ${{ matrix.profile }}
|
|
run: |
|
|
case "$PROFILE" in
|
|
large-house)
|
|
npm run benchmark:compare -- --baseline=../artifacts/performance/baseline.json --candidate=../artifacts/performance/candidate.json --output=../artifacts/performance/comparison.json
|
|
;;
|
|
isometric)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-house-isometric.json --baseline=../artifacts/performance/isometric-baseline.json --candidate=../artifacts/performance/isometric-candidate.json --baseline-sha="$(git -C ../baseline rev-parse HEAD)" --candidate-sha="$(git rev-parse HEAD)" --output=../artifacts/performance/isometric-comparison.json
|
|
;;
|
|
isometric-stage3)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-isometric-stage3-dense.json --baseline=../artifacts/performance/isometric-stage3-baseline.json --candidate=../artifacts/performance/isometric-stage3-candidate.json --baseline-sha="$(git -C ../baseline rev-parse HEAD)" --candidate-sha="$(git rev-parse HEAD)" --output=../artifacts/performance/isometric-stage3-comparison.json
|
|
;;
|
|
plan-snap)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-house-plan-snap.json --baseline=../artifacts/performance/plan-snap-baseline.json --candidate=../artifacts/performance/plan-snap-candidate.json --output=../artifacts/performance/plan-snap-comparison.json
|
|
;;
|
|
interaction)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-house-interaction.json --baseline=../artifacts/performance/interaction-baseline.json --candidate=../artifacts/performance/interaction-candidate.json --output=../artifacts/performance/interaction-comparison.json
|
|
;;
|
|
blend)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-light-blend.json --baseline=../artifacts/performance/blend-baseline.json --candidate=../artifacts/performance/blend-candidate.json --output=../artifacts/performance/blend-comparison.json
|
|
;;
|
|
overlay)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-house-glow-overlay.json --baseline=../artifacts/performance/overlay-baseline.json --candidate=../artifacts/performance/overlay-candidate.json --output=../artifacts/performance/overlay-comparison.json
|
|
;;
|
|
space-default)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-space-card-default.json --baseline=../artifacts/performance/space-default-baseline.json --candidate=../artifacts/performance/space-default-candidate.json --output=../artifacts/performance/space-default-comparison.json
|
|
;;
|
|
space-glow)
|
|
npm run benchmark:compare -- --budgets=demo/performance/budgets-large-space-card-glow.json --baseline=../artifacts/performance/space-glow-baseline.json --candidate=../artifacts/performance/space-glow-candidate.json --output=../artifacts/performance/space-glow-comparison.json
|
|
;;
|
|
esac
|
|
|
|
- name: Upload full performance report
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: full-performance-${{ matrix.profile }}
|
|
path: artifacts/performance
|