Skip to content

Commit

Permalink
[#605] Google LightHouse CI 추가 (#606)
Browse files Browse the repository at this point in the history
* setting: LightHouse CI 파일 작성

* fix: name에 - 프리픽스 추가

* chore: syntaxError 수정

* chore: 자잘한 수정

* fix: syntax 수정

* fix: 설치 버전 수정

* chore: actions/checkout 옵션 추가

* fix: 워크플로 동작 조건 수정

* fix: fetch-depth 옵션 제거

* fix: env 설정

* chore: 타이틀 name 수정

* feat: lighthouse 성능 측정 url 수정 및 추가

* fix lighthouserc.js collect 옵션 수정

* fix: http 환경에서 테스트하도록 변경

* fix: https 환경으로 테스트

* fix: startServerCommand 수정

* fix: http 테스트

* fix: url localhost로 변경

* feat: 성능측정 점수 PR 코멘트 자동화 기능 추가

* fix: lighthouserc.js에 upload 옵션 수정

* chore: lighthouse.yml 수정

* fix: lighthouse.yml 수정

* fix: 빌드에러 수정

* fix: forEach에 index 레퍼런스 추가

* fix: 점수 지표 PR Comment 워크플로 재작성

* fix: 상단의 let comments 제거

* fix: 파일 수정

* fix: await 지시문 삭제

* fix: 파일 수정

* fix: PR comment 방식 변경

* fix: PR Comment 방식 변경

* fix: PR Comment 관련 코드 수정

* fix: 워크플로우 동작 branch 설정

* refactor: script 분리 테스트

* setting: @actions/core 설치

* fix: 워크플로우에 @actions/core 적용

* feat: 워크플로우에 @actions/core 패키지 설치 옵션 추가

* fix: @actions/core 디펜던시 제거

* fix: github action 트리거 조건 수정

* fix: pr comment 작성 및 수정 방식 교체

* chore: 워크플로우 시작 조건 변경 및 lighthouse 동작 횟수 변경

* chore: 주석 수정 및 제거

* fix: @actions/core 디펜던시 추가

* fix: comment 방식 수정

* fix: LightHouse 워크플로우 동작 조건 롤백
  • Loading branch information
hanyugeon authored Jun 2, 2024
1 parent 46a6db6 commit 5af75fd
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 0 deletions.
101 changes: 101 additions & 0 deletions .github/actions/get-score-comments/action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
const core = require('@actions/core');

try {
// 점수 지표 파일 정보
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('./lhci_reports/manifest.json'));
const totalReports = results.length;

// LightHouse 점수 지표
const averageScores = {
performance: 0,
accessibility: 0,
'best-practices': 0,
seo: 0,
pwa: 0,
};
const auditSummaries = {
'first-contentful-paint': 0,
'largest-contentful-paint': 0,
interactive: 0,
'total-blocking-time': 0,
'cumulative-layout-shift': 0,
};

// 점수 평균
results.forEach(result => {
const { summary } = result;

for (const key in averageScores) {
averageScores[key] += summary[key];
}

const details = JSON.parse(fs.readFileSync(result.jsonPath));
[
'first-contentful-paint',
'largest-contentful-paint',
'interactive',
'total-blocking-time',
'cumulative-layout-shift',
].forEach(auditName => {
if (details.audits[auditName]) {
const auditDetails = details.audits[auditName];
auditSummaries[auditName] += parseFloat(auditDetails.displayValue) || 0;
}
});
});

// 점수 색상 표시
const formatScore = res => (res >= 90 ? '🟢' : res >= 70 ? '🟠' : '🔴');

// 상세 지표 점수 색상 표시
const detailScore = (value, metric) => {
switch (metric) {
case 'first-contentful-paint':
return value <= 1.8 ? '🟢' : value <= 3 ? '🟠' : '🔴';
case 'largest-contentful-paint':
return value <= 2.5 ? '🟢' : value <= 4 ? '🟠' : '🔴';
case 'interactive':
return value <= 3.8 ? '🟢' : value <= 7.3 ? '🟠' : '🔴';
case 'total-blocking-time':
return value <= 300 ? '🟢' : value <= 600 ? '🟠' : '🔴';
case 'cumulative-layout-shift':
return value <= 0.1 ? '🟢' : value <= 0.25 ? '🟠' : '🔴';
default:
return '🔴'; // Default to red if metric is unknown
}
};

// comments 파싱
let comments =
'⚡️ Lighthouse Average Scores Across Reports:\n| Category | Score |\n| --- | --- |\n';
Object.keys(averageScores).forEach(key => {
const avgScore = Math.round((averageScores[key] / totalReports) * 100);
comments += `| ${formatScore(avgScore)} ${key.replace(
/-/g,
' '
)} | ${avgScore} |\n`;
});

comments +=
'\n⚡️ Average Details Across All Reports:\n| Category | Score |\n| --- | --- |\n';
Object.keys(auditSummaries).forEach(auditName => {
const average = auditSummaries[auditName] / totalReports;
const formattedName = auditName.replace(/-/g, ' ');
const colorCode = detailScore(average, auditName);
const unit =
auditName === 'total-blocking-time'
? 'ms'
: auditName === 'cumulative-layout-shift'
? ''
: 's';
comments += `| ${colorCode} ${formattedName} | ${average.toFixed(
1
)}${unit} |\n`;
});

// comments 내보내기
core.setOutput('comments', comments);
} catch (error) {
console.error(error);
}
10 changes: 10 additions & 0 deletions .github/actions/get-score-comments/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: 'get-score-comments'
description: 'Get Score Comments'

outputs:
comments:
description: 'Comments that Parsed Scores'

runs:
using: 'node16'
main: 'action.js'
55 changes: 55 additions & 0 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: LightHouse CI

on:
pull_request:
branches:
- main

jobs:
lhci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Use Node.js 18
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'yarn'

- name: Install packages
run: yarn install && yarn global add @lhci/[email protected] && yarn add @actions/core

- name: Set .env
run: echo "${{ vars.DEVELOPMENT_ENV }}" > .env.local

- name: Build
run: yarn build

- name: Run Lighthouse CI
run: lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}

- name: Get Score Comments
id: get-score-comments
uses: ./.github/actions/get-score-comments

- name: Find Comment
if: github.event_name == 'pull_request'
uses: peter-evans/find-comment@v2
id: find_comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: ⚡️ Lighthouse Average Scores Across Reports

- name: Create or update comment
if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@v2
with:
comment-id: ${{ steps.find_comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: ${{ steps.get-score-comments.outputs.comments }}
edit-mode: replace
20 changes: 20 additions & 0 deletions lighthouserc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
ci: {
collect: {
startServerCommand: 'yarn next start',
startServerReadyPattern: 'ready on',
url: [
'http://localhost:3000/bookarchive',
'http://localhost:3000/book/search',
'http://localhost:3000/group',
'http://localhost:3000/profile/me',
],
numberOfRuns: 2,
},
upload: {
target: 'filesystem',
outputDir: './lhci_reports',
reportFilenamePattern: '%%PATHNAME%%-%%DATETIME%%-report.%%EXTENSION%%',
},
},
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"postinstall": "patch-package"
},
"dependencies": {
"@actions/core": "^1.10.1",
"@chakra-ui/icons": "^2.0.17",
"@chakra-ui/react": "^2.4.9",
"@emotion/react": "^11.10.5",
Expand Down
38 changes: 38 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
# yarn lockfile v1


"@actions/core@^1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.1.tgz#61108e7ac40acae95ee36da074fa5850ca4ced8a"
integrity sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==
dependencies:
"@actions/http-client" "^2.0.1"
uuid "^8.3.2"

"@actions/http-client@^2.0.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.1.tgz#ed3fe7a5a6d317ac1d39886b0bb999ded229bb38"
integrity sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==
dependencies:
tunnel "^0.0.6"
undici "^5.25.4"

"@alloc/quick-lru@^5.2.0":
version "5.2.0"
resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz"
Expand Down Expand Up @@ -2998,6 +3014,11 @@
resolved "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz"
integrity sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==

"@fastify/busboy@^2.0.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d"
integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==

"@headlessui/react@^1.7.15":
version "1.7.15"
resolved "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz"
Expand Down Expand Up @@ -12173,6 +12194,11 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"

tunnel@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==

tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz"
Expand Down Expand Up @@ -12257,6 +12283,13 @@ unbox-primitive@^1.0.2:
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"

undici@^5.25.4:
version "5.28.4"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068"
integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==
dependencies:
"@fastify/busboy" "^2.0.0"

unfetch@^4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz"
Expand Down Expand Up @@ -12433,6 +12466,11 @@ uuid@^3.3.2:
resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==

uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==

uuid@^9.0.0:
version "9.0.0"
resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz"
Expand Down

0 comments on commit 5af75fd

Please sign in to comment.