Skip to content
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8ca9236
Refactor: rewrites 설정 추가하여 PR preview URL 리다이렉트 수정
miraclee1226 Jan 27, 2025
0fca04b
Fix: handleNavigationActions props 수정
miraclee1226 Jan 27, 2025
92b2804
Test: 프리뷰 테스트
miraclee1226 Jan 27, 2025
aa4c967
Feat: PR 이벤트 타입 추가로 미리보기 URL 갱신
miraclee1226 Jan 28, 2025
f4ea8be
Fix: 프리뷰 빌드 경로 수정
miraclee1226 Jan 28, 2025
b0796aa
Chore: next.config.mjs의 basePath, rewrites 제거
miraclee1226 Jan 28, 2025
5b10ac4
Feat: 프리뷰 url과 일반 url에 따른 라우팅 분기 처리
miraclee1226 Jan 28, 2025
0a83fd6
Refactor: RegExp match 메서드를 exec로 변경
miraclee1226 Jan 28, 2025
f439c73
Feat: GNB 페이지 이동 시 PR 번호 유지되도록 수정
miraclee1226 Jan 28, 2025
ca3beba
Feat: PR 프리뷰 URL 형식을 쿼리 파라미터 방식으로 변경
miraclee1226 Jan 28, 2025
d435300
Fix: 빌드 에러 해결
miraclee1226 Jan 28, 2025
d45510e
Feat: PR 프리뷰 빌드에 assetPrefix 설정 추가
miraclee1226 Jan 28, 2025
43ad171
Test: 빌드 로그 테스트
miraclee1226 Jan 28, 2025
6e318b4
Test: 빌드 로그 테스트
miraclee1226 Jan 28, 2025
6e350e4
Test: 빌드 테스트트
miraclee1226 Jan 29, 2025
6d2e1fb
Test: AuthGuard 확인 과정 삭제
miraclee1226 Jan 29, 2025
d73435d
Test: out 경로수정
miraclee1226 Jan 29, 2025
b2ba199
Test: PR의 변경사항이 제대로 체크아웃되었는지 확인
miraclee1226 Jan 29, 2025
c837759
Test: 변경사항 확인
miraclee1226 Jan 29, 2025
c2efbcc
Test: 빌드 결과물 확인
miraclee1226 Jan 29, 2025
e66b216
Test: 생성된 chuck 파일 확인
miraclee1226 Jan 29, 2025
ff0c850
Test: app 디렉토리의 chunk 파일들과 dashboard 페이지의 chunk 내용 확인
miraclee1226 Jan 29, 2025
72c08c6
Test: dashboard 파일 내용 확인
miraclee1226 Jan 29, 2025
bfec3f3
Test: DashboardSection 파일 내용 확인
miraclee1226 Jan 29, 2025
c75f041
Test: Next.js 캐시 지우고 빌드 시도
miraclee1226 Jan 29, 2025
32924bd
Test: PR 코드가 workflow에서 사용되는지 확인
miraclee1226 Jan 29, 2025
f59e72d
Test: next.config.mjs 확인
miraclee1226 Jan 29, 2025
b6cf743
Test: 경로 변경
miraclee1226 Jan 29, 2025
6b70eed
Test: GITHUB_EVENT_NAME과 GITHUB_EVENT_NUMBER를 .env.production.local 파…
miraclee1226 Jan 29, 2025
6d428e0
Feat: actions/checkout@v4 액션에 ref 옵션을 추가하여 PR 브랜치의 코드를 체크아웃하도록 변경
miraclee1226 Jan 30, 2025
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
26 changes: 24 additions & 2 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ permissions:
on:
pull_request:
branches: [develop]
types: [opened, synchronize, reopened]

jobs:
preview:
Expand Down Expand Up @@ -35,8 +36,25 @@ jobs:
env:
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}

- name: Check AuthGuard content
run: |
echo "AuthGuard content:"
cat apps/web/app/components/auth/AuthGuard.tsx

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

보안: AuthGuard 내용 노출 위험이 있습니다.

AuthGuard.tsx 파일의 내용을 로그에 출력하는 것은 인증 로직이 노출될 수 있어 보안상 위험합니다. 디버깅이 필요한 경우 파일 존재 여부만 확인하거나, 민감하지 않은 정보만 선택적으로 출력하는 것이 좋습니다.

다음과 같이 수정하는 것을 제안합니다:

-      - name: Check AuthGuard content
-        run: |
-          echo "AuthGuard content:"
-          cat apps/web/app/components/auth/AuthGuard.tsx
+      - name: Verify AuthGuard file
+        run: |
+          echo "Checking if AuthGuard exists..."
+          test -f apps/web/app/components/auth/AuthGuard.tsx && echo "AuthGuard file exists"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Check AuthGuard content
run: |
echo "AuthGuard content:"
cat apps/web/app/components/auth/AuthGuard.tsx
- name: Verify AuthGuard file
run: |
echo "Checking if AuthGuard exists..."
test -f apps/web/app/components/auth/AuthGuard.tsx && echo "AuthGuard file exists"

- name: Build
run: pnpm -filter=web build
run: |
echo "Current branch: ${{ github.head_ref }}"
echo "PR number: ${{ github.event.pull_request.number }}"
echo "Event name: ${{ github.event_name }}"
pnpm -filter=web build
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
Comment on lines +43 to +49
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

환경 변수 처리 방식의 보안 강화가 필요합니다.

GitHub Actions의 컨텍스트 변수를 직접 사용하는 것은 보안상 위험할 수 있습니다.

다음과 같이 수정하는 것을 권장합니다:

        run: |
-          echo "GITHUB_EVENT_NAME=${{ github.event_name }}" >> apps/web/.env.production.local
-          echo "GITHUB_EVENT_NUMBER=${{ github.event.pull_request.number }}" >> apps/web/.env.production.local
+          echo "GITHUB_EVENT_NAME=$GITHUB_EVENT_NAME" >> apps/web/.env.production.local
+          echo "GITHUB_EVENT_NUMBER=$GITHUB_EVENT_NUMBER" >> apps/web/.env.production.local
          pnpm -filter=web build
        env:
          GITHUB_EVENT_NAME: ${{ github.event_name }}
          GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
run: |
echo "GITHUB_EVENT_NAME=${{ github.event_name }}" >> apps/web/.env.production.local
echo "GITHUB_EVENT_NUMBER=${{ github.event.pull_request.number }}" >> apps/web/.env.production.local
pnpm -filter=web build
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
run: |
echo "GITHUB_EVENT_NAME=$GITHUB_EVENT_NAME" >> apps/web/.env.production.local
echo "GITHUB_EVENT_NUMBER=$GITHUB_EVENT_NUMBER" >> apps/web/.env.production.local
pnpm -filter=web build
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}


Comment on lines +45 to +50
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

보안: github.head_ref 사용 방식을 개선해야 합니다.

GitHub Actions 보안 가이드라인에 따르면, github.head_ref와 같은 신뢰할 수 없는 입력값을 직접 스크립트에서 사용하는 것은 위험할 수 있습니다.

다음과 같이 환경 변수를 통해 전달하도록 수정하는 것을 제안합니다:

       - name: Build
         run: |
-          echo "Current branch: ${{ github.head_ref }}"
+          echo "Current branch: $GITHUB_HEAD_REF"
           echo "PR number: ${{ github.event.pull_request.number }}"
           echo "Event name: ${{ github.event_name }}"
           pnpm -filter=web build
         env:
+          GITHUB_HEAD_REF: ${{ github.head_ref }}
           GITHUB_EVENT_NAME: ${{ github.event_name }}
           GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
run: |
echo "Current branch: ${{ github.head_ref }}"
echo "PR number: ${{ github.event.pull_request.number }}"
echo "Event name: ${{ github.event_name }}"
pnpm -filter=web build
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
run: |
echo "Current branch: $GITHUB_HEAD_REF"
echo "PR number: ${{ github.event.pull_request.number }}"
echo "Event name: ${{ github.event_name }}"
pnpm -filter=web build
env:
GITHUB_HEAD_REF: ${{ github.head_ref }}
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
🧰 Tools
🪛 actionlint (1.7.4)

45-45: "github.head_ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions for more details

(expression)

- name: Check build output
run: |
echo "Checking index.html content:"
cat out/index.html
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

보안: index.html 내용 노출 제한이 필요합니다.

빌드 결과물인 index.html 파일의 전체 내용을 로그에 출력하는 것은 민감한 정보가 노출될 수 있어 보안상 위험합니다.

다음과 같이 수정하는 것을 제안합니다:

       - name: Check build output
         run: |
-          echo "Checking index.html content:"
-          cat out/index.html
+          echo "Verifying build output..."
+          test -f out/index.html && echo "✓ index.html exists"
+          echo "File size: $(stat -f%z out/index.html) bytes"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Check build output
run: |
echo "Checking index.html content:"
cat out/index.html
- name: Check build output
run: |
echo "Verifying build output..."
test -f out/index.html && echo "✓ index.html exists"
echo "File size: $(stat -f%z out/index.html) bytes"


- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
Expand All @@ -46,7 +64,11 @@ jobs:
aws-region: ${{ secrets.AWS_REGION }}

- name: Deploy to S3 with PR-specific prefix
run: aws s3 sync ./${{ secrets.BUILD_DIRECTORY }} s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --delete
run: |
echo "Syncing files to S3..."
aws s3 sync ${{ secrets.BUILD_DIRECTORY }} s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --delete
echo "Files uploaded to S3:"
aws s3 ls s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --recursive
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

보안: S3 파일 목록 노출 제한이 필요합니다.

S3에 업로드된 모든 파일 목록을 로그에 출력하는 것은 민감한 정보가 노출될 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

       - name: Deploy to S3 with PR-specific prefix
         run: |
           echo "Syncing files to S3..."
           aws s3 sync ${{ secrets.BUILD_DIRECTORY }} s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --delete
-          echo "Files uploaded to S3:"
-          aws s3 ls s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --recursive
+          echo "Deployment summary:"
+          aws s3 ls s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --recursive --summarize | grep "Total Objects:"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
run: |
echo "Syncing files to S3..."
aws s3 sync ${{ secrets.BUILD_DIRECTORY }} s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --delete
echo "Files uploaded to S3:"
aws s3 ls s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --recursive
run: |
echo "Syncing files to S3..."
aws s3 sync ${{ secrets.BUILD_DIRECTORY }} s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --delete
echo "Deployment summary:"
aws s3 ls s3://${{ secrets.AWS_S3_BUCKET_NAME }}/pr-${{ github.event.pull_request.number }} --recursive --summarize | grep "Total Objects:"


- name: CloudFront Invalidate Cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} --paths "/pr-${{ github.event.pull_request.number }}/*"
Expand Down
5 changes: 4 additions & 1 deletion apps/mobile/app/(route)/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
import { parseMessage } from "@/utils/parseMessage";

export default function DashboardScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();

const requestOnMessage = (e: WebViewMessageEvent) => {
handleNavigationActions(e);
const { type, data } = parseMessage(e);

handleNavigationActions({ type, data });
};

return <WebView className="flex-1" source={{ uri: `${baseUrl}${ROUTES.DASHBOARD}` }} onMessage={requestOnMessage} />;
Expand Down
5 changes: 4 additions & 1 deletion apps/mobile/app/(route)/meetings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
import { parseMessage } from "@/utils/parseMessage";

export default function MeetingsScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();

const requestOnMessage = (e: WebViewMessageEvent) => {
handleNavigationActions(e);
const { type, data } = parseMessage(e);

handleNavigationActions({ type, data });
};

return <WebView className="flex-1" source={{ uri: `${baseUrl}${ROUTES.MEETINGS}` }} onMessage={requestOnMessage} />;
Expand Down
5 changes: 4 additions & 1 deletion apps/mobile/app/(route)/seats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
import { parseMessage } from "@/utils/parseMessage";

export default function SeatsScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();

const requestOnMessage = (e: WebViewMessageEvent) => {
handleNavigationActions(e);
const { type, data } = parseMessage(e);

handleNavigationActions({ type, data });
};

return <WebView className="flex-1" source={{ uri: `${baseUrl}${ROUTES.SEATS}` }} onMessage={requestOnMessage} />;
Expand Down
6 changes: 5 additions & 1 deletion apps/mobile/app/(route)/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
import { parseMessage } from "@/utils/parseMessage";

export default function SettingsScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();

const requestOnMessage = (e: WebViewMessageEvent) => {
handleNavigationActions(e);
const { type, data } = parseMessage(e);

handleNavigationActions({ type, data });
};

return <WebView className="flex-1" source={{ uri: `${baseUrl}${ROUTES.SETTINGS}` }} onMessage={requestOnMessage} />;
}
23 changes: 17 additions & 6 deletions apps/web/app/_components/AuthGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useEffect, useState } from "react";
import { PAGE_NAME } from "@ui/src/utils/constants/pageNames";
import { useRouter } from "next/navigation";
import { useRouter, usePathname } from "next/navigation";
import { useAuthStore } from "@/app/store/useAuthStore";
import { createWebViewEventListener } from "../../lib/bridge/createWebViewEventListener";
import { parseWebViewAuthMessage } from "../../lib/bridge/parseWebViewAuthMessage";
Expand All @@ -11,10 +11,10 @@ import SignInForm from "./SignInForm";

export default function AuthGuard(): JSX.Element | null {
const router = useRouter();
const pathname = usePathname();
const [isLoading, setIsLoading] = useState(true);
const { isLoggedIn } = useAuthStore();
const { isIOSWebView, isAndroidWebView } = useDetectWebView();

const webViewEventListener = createWebViewEventListener({ isIOSWebView, isAndroidWebView });

useEffect(() => {
Expand All @@ -23,14 +23,25 @@ export default function AuthGuard(): JSX.Element | null {
}, []);

useEffect(() => {
if (isLoggedIn) {
router.replace(PAGE_NAME.DASHBOARD);
if (!isLoggedIn) {
setIsLoading(false);
return;
}

if (pathname === "/" && typeof window !== "undefined") {
const urlParams = new URLSearchParams(window.location.search);
const prNumber = urlParams.get("pr");

if (prNumber) {
router.replace(`/dashboard?pr=${prNumber}`);
} else {
router.replace(PAGE_NAME.DASHBOARD);
}
}

setIsLoading(false);
}, [isLoggedIn, router]);
}, [isLoggedIn, router, pathname]);

if (isLoading) return null;

return isLoggedIn ? null : <SignInForm />;
}
1 change: 1 addition & 0 deletions apps/web/app/dashboard/_components/DashboardSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default function DashboardSection({ data = [] }: DashboardSectionProps):

return (
<div>
<h1>Preview Test</h1>
<h1 className="mb-16">내 회의</h1>
<hr className="mb-16 border-gray-200/10" />
{upcomingMeetings.length > 0 ? (
Expand Down
20 changes: 17 additions & 3 deletions apps/web/components/Gnb/GnbMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,22 @@ export default function GnbMenu({ isAdmin }: GnbMenuProps): JSX.Element | null {
const { push } = useAppRouter();
const { isWebView } = useDetectWebView();

const getPrNumber = (): string | null => {
if (typeof window === "undefined") return null;

const urlParams = new URLSearchParams(window.location.search);

return urlParams.get("pr");
};

const getUrlWithPR = (path: string): string => {
const prNumber = getPrNumber();

return prNumber ? `${path}?pr=${prNumber}` : path;
};

const handleButtonClick = (path: string): void => {
push(path);
push(getUrlWithPR(path));
};

return (
Expand All @@ -57,7 +71,7 @@ export default function GnbMenu({ isAdmin }: GnbMenuProps): JSX.Element | null {
},
}
: {
href,
href: getUrlWithPR(href),
})}
className={cn("h-full justify-start md:h-40 md:w-full md:px-0 md:py-0", index === 3 && "block md:hidden")}
variant="Text"
Expand All @@ -82,7 +96,7 @@ export default function GnbMenu({ isAdmin }: GnbMenuProps): JSX.Element | null {
{ADMIN_ITEMS.map(({ href, name, icon: Icon }) => {
const isActive = pathname === href;
return (
<Link key={name} href={href} className="hidden md:block">
<Link key={name} href={getUrlWithPR(href)} className="hidden md:block">
<div
className={clsx(
"rounded-10 flex size-full w-48 flex-col items-center md:w-full md:flex-row md:gap-10 md:px-16 md:py-8",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
const isPR = process.env.GITHUB_EVENT_NAME === "pull_request";
const prNumber = process.env.GITHUB_EVENT_NUMBER;

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: "export",
...(isPR && {
assetPrefix: `/pr-${prNumber}`,
}),

images: {
remotePatterns: [
Expand Down
4 changes: 3 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"NEXT_PUBLIC_IOS_API_URL",
"EXPO_PUBLIC_API_URL_ANDROID",
"EXPO_PUBLIC_API_URL_IOS",
"NODE_ENV"
"NODE_ENV",
"GITHUB_EVENT_NAME",
"GITHUB_EVENT_NUMBER"
],
"tasks": {
"build": {
Expand Down