Skip to content

Commit

Permalink
Merge pull request #349 from Ludo-SMP/feat/SP-668-setup-lighthouse-ci
Browse files Browse the repository at this point in the history
SP-668 페이지별 성능 측정 tool(LightHouse) 자동화 환경 구축
  • Loading branch information
SungHyun627 authored Aug 20, 2024
2 parents 10ada59 + 43e629f commit 64b50b4
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 2 deletions.
11 changes: 9 additions & 2 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', 'prettier', 'plugin:storybook/recommended'],
env: { browser: true, es2020: true, node: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
'prettier',
'plugin:storybook/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
Expand All @@ -14,5 +20,6 @@ module.exports = {
'react/jsx-key': 'off',
// 디버그 허용
'no-debugger': 'off',
'@typescript-eslint/no-var-requires': 'off',
},
};
166 changes: 166 additions & 0 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
name: Run lighthouse CI When Push on PR to Dev Branch
on:
pull_request:
branches:
- dev
types: [synchronize, opened]

permissions:
contents: read
pull-requests: write

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

- name: Use Node.js 20.10.0
uses: actions/setup-node@v4
with:
node-version-file: .node-version

- name: Install dependencies
run: |
yarn install --immutable --immutable-cache --check-cache
- name: Add host "local.ludo.study"
run: sudo echo "127.0.0.1 local.ludo.study" | sudo tee -a /etc/hosts

- name: Build the project
run: |
yarn build
- name: Run Lighthouse CI - Desktop
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
run: |
yarn global add @lhci/cli
lhci collect --config=lighthouserc-desktop.cjs || echo "Fail to Run Lighthouse CI!"
lhci upload --config=lighthouserc-desktop.cjs || echo "Fail to Run Lighthouse CI!"
- name: Run Lighthouse CI - Mobile
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
run: |
lhci collect --config=lighthouserc-mobile.cjs || echo "Fail to Run Lighthouse CI!"
lhci upload --config=lighthouserc-mobile.cjs || echo "Fail to Run Lighthouse CI!"
- name: Format Lighthouse Score
id: format_lighthouse_score
uses: actions/github-script@v7
env:
working-directory: ${{ github.workspace }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const {
LH_MONITORING_PAGE_NAMES,
DEV_ORIGIN_URL,
LH_MONITORING_PAGE_ROUTES,
LH_MIN_SCORES,
} = require('./src/Constants/lighthouse.ts');
const desktopLightHouseResults = JSON.parse(fs.readFileSync('lhci_reports/desktop/manifest.json'));
const mobileLightHouseResults = JSON.parse(fs.readFileSync('lhci_reports/mobile/manifest.json'));
let comments = `### 💡 LightHouse Reports\n\n`;
comments += `#### 🟢 90 ~ 100    🟠 50 ~ 89    🔴 0 ~ 49 \n\n`;
const getFormattingScore = (res) => Math.round(res * 100);
const getScoreColor = (score) => (score >= LH_MIN_SCORES.GREEN ? '🟢' : score >= LH_MIN_SCORES.ORANGE ? '🟠' : '🔴');
const getMonitoringPageName = (url) => {
const route = url.replace(DEV_ORIGIN_URL, '');
for (let pageName of LH_MONITORING_PAGE_NAMES) {
if (route === LH_MONITORING_PAGE_ROUTES[pageName]) return pageName;
}
};
const getFormattingResultByPage = (result) => {
const { url, summary, jsonPath } = result;
const { audits } = JSON.parse(fs.readFileSync(jsonPath));
const { performance, accessibility, 'best-practices': bestPractices, seo } = summary;
const {
'first-contentful-paint': firstContentfulPaint,
'largest-contentful-paint': largestContentfulPaint,
'speed-index': speedIndex,
'total-blocking-time': totalBlockingTime,
'cumulative-layout-shift': cumulativeLayoutShift,
} = audits;
const formattingTable = [
`| Category | Score |`,
`| --- | --- |`,
`| ${getScoreColor(getFormattingScore(performance))} Performance | ${getFormattingScore(performance)} |`,
`| ${getScoreColor(getFormattingScore(accessibility))} Accessibility | ${getFormattingScore(accessibility)} |`,
`| ${getScoreColor(getFormattingScore(bestPractices))} Best practices | ${getFormattingScore(bestPractices)} |`,
`| ${getScoreColor(getFormattingScore(seo))} SEO | ${getFormattingScore(seo)} |`,
`| ${getScoreColor(getFormattingScore(firstContentfulPaint.score))} First Contentful Paint | ${firstContentfulPaint.displayValue} |`,
`| ${getScoreColor(getFormattingScore(largestContentfulPaint.score))} Largest Contentful Paint | ${largestContentfulPaint.displayValue} |`,
`| ${getScoreColor(getFormattingScore(speedIndex.score))} Speed Index | ${speedIndex.displayValue} |`,
`| ${getScoreColor(getFormattingScore(totalBlockingTime.score))} Total Blocking Time | ${totalBlockingTime.displayValue} |`,
`| ${getScoreColor(getFormattingScore(cumulativeLayoutShift.score))} Cumulative Layout Shift | ${cumulativeLayoutShift.displayValue} |`,
`\n`,
].join('\n');
return `<details>\n<summary>${`📄 ${getMonitoringPageName(url)}\n`}</summary>\n\n${formattingTable}\n</details>\n\n`;
};
const getLightHouseFormattingResult = (results, type) => {
let comment = type === 'mobile' ? `#### 📱 Mobile\n` : `#### 🖥 Desktop\n`;
results.forEach((result) => (comment += getFormattingResultByPage(result)));
return comment + '\n';
};
comments += getLightHouseFormattingResult(desktopLightHouseResults, 'desktop');
comments += getLightHouseFormattingResult(mobileLightHouseResults, 'mobile');
core.setOutput('comments', comments)
- name: Comment PR
id: add_pr_comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({ auth: `${{ secrets.GITHUB_TOKEN }}` });
const { payload, repo } = context
const newComment = `${{ steps.format_lighthouse_score.outputs.comments }}`
const { data: prevComments } = await octokit.rest.issues.listComments({
owner: repo.owner,
repo: repo.repo,
issue_number : payload.pull_request.number,
})
const prevReportComment = prevComments.find(comment => comment.body.includes(`### 💡 LightHouse Reports\n\n`));
if (prevReportComment) {
await octokit.rest.issues.updateComment({
owner: repo.owner,
repo: repo.repo,
comment_id: prevReportComment.id,
body: newComment,
});
} else {
await octokit.rest.issues.createComment({
owner: repo.owner,
repo: repo.repo,
issue_number: payload.pull_request.number,
body: newComment,
});
}
26 changes: 26 additions & 0 deletions lighthouserc-desktop.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const {
LH_MONITORING_PAGE_NAMES,
DEV_ORIGIN_URL,
LH_MONITORING_PAGE_ROUTES,
} = require('./src/Constants/lighthouse.ts');

const urls = LH_MONITORING_PAGE_NAMES.map((pageName) => `${DEV_ORIGIN_URL}${LH_MONITORING_PAGE_ROUTES[pageName]}`);

module.exports = {
ci: {
collect: {
startServerCommand: 'yarn start:mac',
url: urls,
numberOfRuns: 1,
settings: {
chromeFlags: '--ignore-certificate-errors',
preset: 'desktop',
},
},
upload: {
target: 'filesystem',
outputDir: './lhci_reports/desktop',
reportFilenamePattern: '%%PATHNAME%%-%%DATETIME%%-desktop-report.%%EXTENSION%%',
},
},
};
25 changes: 25 additions & 0 deletions lighthouserc-mobile.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const {
LH_MONITORING_PAGE_NAMES,
DEV_ORIGIN_URL,
LH_MONITORING_PAGE_ROUTES,
} = require('./src/Constants/lighthouse.ts');

const urls = LH_MONITORING_PAGE_NAMES.map((pageName) => `${DEV_ORIGIN_URL}${LH_MONITORING_PAGE_ROUTES[pageName]}`);

module.exports = {
ci: {
collect: {
startServerCommand: 'yarn start:mac',
url: urls,
numberOfRuns: 1,
settings: {
chromeFlags: '--ignore-certificate-errors',
},
},
upload: {
target: 'filesystem',
outputDir: './lhci_reports/mobile',
reportFilenamePattern: '%%PATHNAME%%-%%DATETIME%%-mobile-report.%%EXTENSION%%',
},
},
};
26 changes: 26 additions & 0 deletions src/Constants/lighthouse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const TEST_RECRUITMENT_ID = 70;
const LH_GREEN_MIN_SCORE = 90;
const LH_ORANGE_MIN_SCORE = 50;

const PAGE_ROUTES = {
MAIN: '/',
AUTH: {
LOGIN: '/login',
},
RECRUITMENT: {
RECRUITMENTS: '/studies',
DETAIL: `/studies/${TEST_RECRUITMENT_ID}/recruitment`,
},
};

module.exports = {
DEV_ORIGIN_URL: `https://local.ludo.study:3000`,
LH_MONITORING_PAGE_NAMES: ['메인', '로그인', '모집공고 모아보기', '모집공고 상세'],
LH_MIN_SCORES: { GREEN: LH_GREEN_MIN_SCORE, ORANGE: LH_ORANGE_MIN_SCORE },
LH_MONITORING_PAGE_ROUTES: {
메인: PAGE_ROUTES.MAIN,
로그인: PAGE_ROUTES.AUTH.LOGIN,
'모집공고 모아보기': PAGE_ROUTES.RECRUITMENT.RECRUITMENTS,
'모집공고 상세': PAGE_ROUTES.RECRUITMENT.DETAIL,
},
};

0 comments on commit 64b50b4

Please sign in to comment.