Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
824c327
Update assignment-6-ci.yml
JunilHwang Jul 23, 2024
108bd59
Update pull_request_template.md
JunilHwang Jul 23, 2024
41dcf59
chore: assignment-6 ci 변경
JunilHwang Jul 23, 2024
534b890
6주차 과제 풀이 - basic
yoosion030 Jul 23, 2024
1dc3c61
feat: 랜덤 리뷰어 등록
yoosion030 Jul 23, 2024
2f513af
feat: 테스트 코드 스크립트 수정
yoosion030 Jul 23, 2024
afda6b0
feat: package.json 업데이트
yoosion030 Jul 23, 2024
e81f348
feat: 의존성 설치 방식 변경
yoosion030 Jul 23, 2024
b4e4c7f
feat: lighthouse 의존성 설치 방식 변경
yoosion030 Jul 23, 2024
018fd31
feat: lighthouse 의존성 설치 방식 변경
yoosion030 Jul 23, 2024
58a66aa
fix: 린트 에러 해결
yoosion030 Jul 23, 2024
9f10dbd
feat: 테스트 커버리지 scripts js 코드로 분리
yoosion030 Jul 24, 2024
4b4cac0
feat: 린트 scripts js 코드로 분리
yoosion030 Jul 24, 2024
6827dd3
feat: lighthouse scripts js 코드로 분리
yoosion030 Jul 24, 2024
0e06432
fix: lighthouse scripts 내부에서 fs에 접근할 수 없는 문제 해결
yoosion030 Jul 24, 2024
91852f5
feat: review scripts js 코드로 분리
yoosion030 Jul 24, 2024
76ad4ea
fix: 잘못 접근하고 있던 review.js 파일 주소 수정
yoosion030 Jul 24, 2024
1b54377
refactor: lighthouse score 계산 로직 개선
yoosion030 Jul 24, 2024
5b88f80
refactor: step 구분 없이 try catch로 에러 처리 하도록 개선
yoosion030 Jul 24, 2024
305c9e4
feat: 린트 에러 발생
yoosion030 Jul 24, 2024
dd929a1
fix: 에러가 발생하여도 Report를 할 수 있도록 해결
yoosion030 Jul 24, 2024
74e7ad5
refactor: pnpm install step 분리 및 cache 추가
yoosion030 Jul 24, 2024
3355f11
feat: composite setup action 생성
yoosion030 Jul 24, 2024
7dae143
feat: 린트 에러 해결
yoosion030 Jul 25, 2024
50211ce
fix: comment 리뷰어와 assign 리뷰어가 다른 이슈 해결
yoosion030 Jul 25, 2024
6123772
Merge remote-tracking branch 'upstream/yoosion-assignment-6' into fea…
yoosion030 Jul 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/actions/setup-node-dependencies/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Setup Node.js and Dependencies
description: Sets up Node.js, pnpm, and installs dependencies

runs:
using: "composite"
steps:
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 8
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"

- name: Get pnpm cache directory path
run: echo "dir=$(pnpm store path)" >> $GITHUB_ENV
shell: bash

- name: Cache pnpm dependencies
id: pnpm-cache
uses: actions/cache@v4
with:
path: ${{ env.dir }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-

- name: Install dependencies
run: pnpm install --prefer-frozen-lockfile
shell: bash
85 changes: 6 additions & 79 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,11 @@
## 체크포인트

### 코드 작성 체크포인트
### PR 올리기 전에 확인사항

- 가독성
- [ ] 변수와 함수의 이름이 용도와 기능을 명확히 나타내는가?
- [ ] 중복되는 로직을 별도의 함수로 추출했는가?
- [ ] 중첩된 if 문을 피하고 조건문을 단순화했는가?
- [ ] 매직 넘버와 반복되는 문자열을 상수로 정의했는가?
- [ ] 데이터 처리에 reduce, filter, map 등의 고차 함수를 사용했는가?
- [ ] 일관된 코딩 스타일, 적절한 들여쓰기, 논리적인 함수 배치로 가독성을 향상시켰는가?
- 단일 책임 원칙
- [ ] 함수/훅이 하나의 명확한 목적만을 가지고 있는가?
- [ ] 함수/훅의 이름이 그 목적을 명확하게 나타내는가?
- 순수 함수
- [ ] 동일한 입력에 대해 항상 동일한 출력을 반환하는가?
- [ ] 외부 상태를 변경하지 않는가?
- [ ] 입력 데이터를 직접 수정하지 않고 새로운 데이터를 반환하는가?
- 합성 가능성
- [ ] 함수/훅을 다른 함수/훅과 쉽게 조합할 수 있는가?
- 관심사 분리
- [ ] 비즈니스 로직과 UI 로직이 적절히 분리되어 있는가?
- DRY (Don't Repeat Yourself) 원칙
- [ ] 이 함수/훅이 중복 코드를 제거하는 데 도움이 되는가?
- 테스트 용이성
- [ ] 함수/훅에 대한 단위 테스트를 쉽게 작성할 수 있는가?
(input에 대한 output을 정의하기 수월한가)
1. head barnch와 sync를 맞춰주세요.

### advanced 과제 체크포인트
```bash
$ git pull https://github.com/hanghae-plus/front_2nd.git main
```

- [ ] advanced.test.ts에 있는 시나리오 테스트를 모두 통과한다.
- [ ] 3개 이상의 custom hook을 통해서 리팩토링을 진행했고, 해당 hook에 대한 테스트 코드가 작성되었다.
- [ ] 3개 이상의 순수함수를 통해서 리팩토링을 진행했고, 해당 함수에 대한 테스트 코드가 작성되었다.


## 고민했던 부분과 새롭게 알게 된 점
<!-- 과제를 해결하면서 어려웠던 점이나 고민했던 부분, 그리고 새롭게 학습한 내용을 적어주세요. -->

### 고민했던 부분
-
-

### 새롭게 알게 된 점
-
-

## 해결하지 못한 문제
<!-- 현재 해결하지 못한 문제나 향후 개선이 필요한 부분을 작성해주세요. -->
-
-

## 리뷰 요청 사항
<!-- 특별히 피드백을 받고 싶은 부분이나 의견을 구하고 싶은 부분을 적어주세요. -->
-
-

## 자기 평가
<!-- 이번 과제를 통해 얻은 성장 포인트와 다음에 개선하고 싶은 부분을 작성해주세요. -->

### 성장 포인트
<!-- 이번 PR 작업 중 있었던 긍정적 시도와 변화를 최소 3가지 정도 적어주세요 -->
1.
2.
3.

### 개선하고 싶은 부분
-
-

## 인사이트

현재 작성된 코드가 요구사항에 잘 대응할 수 있는지 자체적으로 점검해보세요. **내가 작성한 코드가 좋은 코드인지 판단해볼 수 있습니다.**

1. start:advanced로 실행하면 초기 데이터를 localStorage에서 불러오고, 추가하고, 수정하고, 삭제할 수 있다.
2. start:api-mock로 실행하면 초기 데이터를 API를 통해서 불러오고, 추가하고, 수정하고, 삭제할 수 있다.
- API는 [msw](https://mswjs.io/)로 만든다.
3. 회원 등급별 할인 기능
- 관리자는 회원 등급을 추가할 수 있다.
- 회원 등급에 따른 할인율이 존재한다.
- 예시) 일반: 3%, 실버: 5%, 골드: 7%, VIP: 10%,
- 장바구니 페이지에서 현재 회원 등급을 임의로 선택할 수 있다.
- 회원 등급에 따라 총 구매 가격에 할인율이 적용되어야 한다.

이 외에도 다양한 요구사항이 추가될 수 있습니다.
2. base branch를 `hanghae-plus:main`이 아니라 `hanghae-plus:<본안아이디>` 로 수정해주세요 확인해주세요.
83 changes: 83 additions & 0 deletions .github/scripts/lighthouse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
const formatScore = (score) => Math.round(score * 100);
const getScoreEmoji = (score) =>
score >= 90 ? "🟢" : score >= 50 ? "🟠" : "🔴";

const createMarkdownTable = (headers, rows) => {
return [
`| ${headers.join(" | ")} |`,
`| ${headers.map(() => "---").join(" | ")} |`,
...rows.map((row) => `| ${row.join(" | ")} |`),
].join("\n");
};

const createLighthouseComment = (summary, audits) => {
const formattedSummary = Object.fromEntries(
Object.entries(summary).map(([key, value]) => [key, formatScore(value)])
);

const summaryTable = createMarkdownTable(
["Category", "Score"],
Object.entries(formattedSummary).map(([key, value]) => [
`${getScoreEmoji(value)} ${key.charAt(0).toUpperCase() + key.slice(1)}`,
value,
])
);

const detailRows = [
"first-contentful-paint",
"largest-contentful-paint",
"total-blocking-time",
"cumulative-layout-shift",
"speed-index",
].map((metric) => {
const score = formatScore(audits[metric].score * 100);
return [
`${getScoreEmoji(score)} ${metric
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ")}`,
audits[metric].displayValue,
];
});

const detailTable = createMarkdownTable(["Category", "Score"], detailRows);

return `
⚡️ Lighthouse report!
${summaryTable}

📊 Lighthouse Detail
${detailTable}
`.trim();
};

const reportLighthouseSuccess = async ({ github, context, results, fs }) => {
const comments = results
.map((result) => {
const { summary, jsonPath } = result;
const { audits } = JSON.parse(fs.readFileSync(jsonPath));
return createLighthouseComment(summary, audits);
})
.join("\n\n");

await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comments,
});
};

const reportLighthouseFailure = async ({ github, context }) => {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "빌드가 실패하여 Lighthouse 결과를 측정할 수 없습니다.",
});
};

module.exports = {
reportLighthouseSuccess,
reportLighthouseFailure,
};
26 changes: 26 additions & 0 deletions .github/scripts/lint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const reportLintSuccess = async ({ context, github }) => {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Lint 성공 🎉`,
});
};

const reportLintFailure = async ({ eslintReport, context, github }) => {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `
## ESLint Results

${eslintReport}
`,
});
};

module.exports = {
reportLintSuccess,
reportLintFailure,
};
49 changes: 49 additions & 0 deletions .github/scripts/review.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const getRandomReviewer = () => {
const reviewers = ["yoosion030", "dhp94d", "lydiahjchung", "callipenguin"];
const randomReviewer =
reviewers[Math.floor(Math.random() * reviewers.length)];

return randomReviewer;
};

const commentReviewer = async ({ github, context, reviewer }) => {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `@${reviewer}, 리뷰를 부탁드립니다.`,
});
};

const assignReviewer = async ({ github, context, reviewer }) => {
const currentReviewers = await github.rest.pulls.listRequestedReviewers({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});

if (currentReviewers.data.users.length > 0) {
const reviewersToRemove = currentReviewers.data.users.map(
(user) => user.login
);
await github.rest.pulls.removeRequestedReviewers({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
reviewers: reviewersToRemove,
});
}

await github.rest.pulls.requestReviewers({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
reviewers: [reviewer],
});
};

module.exports = {
commentReviewer,
assignReviewer,
getRandomReviewer,
};
37 changes: 37 additions & 0 deletions .github/scripts/test-coverage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const reportTestSuccess = async ({ totalCoverage, github, context }) => {
const coverageComment = `
## 테스트 성공 ✅
### 커버리지 결과

- 라인 커버리지: ${totalCoverage.lines.pct}%
- 브랜치 커버리지: ${totalCoverage.branches.pct}%
- 함수 커버리지: ${totalCoverage.functions.pct}%
- 구문 커버리지: ${totalCoverage.statements.pct}%
`;

await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: coverageComment,
});
};

const reportTestFailure = async ({ github, context }) => {
const coverageComment = `
## 테스트 실패 ❌

테스트 코드를 확인해주세요.
`;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: coverageComment,
});
};

module.exports = {
reportTestSuccess,
reportTestFailure,
};
Loading