Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 13 additions & 1 deletion .github/ISSUE_TEMPLATE/issue_form.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,19 @@ body:
attributes:
label: '🎟️ 상위 작업 (Ticket Number)'
description: '상위 작업의 Ticket Number를 기입해주세요'
placeholder: 'PRJ-00'
placeholder: 'THIP2025-00'
validations:
required: true

- type: dropdown
id: branchType
attributes:
label: '브랜치 타입'
options:
- feature
- bugfix
- hotfix
- refactor
validations:
required: true

Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/close-jira-issue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Close Jira issue
on:
issues:
types:
- closed

jobs:
close-issue:
name: Close Jira issue
runs-on: ubuntu-latest

steps:
- name: Login to Jira
uses: atlassian/gajira-login@v3
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}

- name: Extract Jira issue key from GitHub issue title
id: extract-key
run: |
ISSUE_TITLE="${{ github.event.issue.title }}"
CLEANED_TITLE=$(echo "$ISSUE_TITLE" | tr -d '[]')
echo "🧼 Cleaned title: $CLEANED_TITLE"

Comment on lines +23 to +26
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

보안: 인라인 스크립트에서 GitHub 이벤트 변수 직접 사용 금지

현재 스크립트에서 ${{ github.event.issue.title }}를 직접 삽입해 입력값을 처리하고 있어 코드 인젝션 위험이 있습니다.
환경 변수로 전달하도록 아래 예시와 같이 리팩토링을 권장합니다:

- run: |
-   ISSUE_TITLE="${{ github.event.issue.title }}"
-   CLEANED_TITLE=$(echo "$ISSUE_TITLE" | tr -d '[]')
+ env:
+   ISSUE_TITLE: ${{ github.event.issue.title }}
+ run: |
+   CLEANED_TITLE=$(echo "$ISSUE_TITLE" | tr -d '[]')
📝 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
ISSUE_TITLE="${{ github.event.issue.title }}"
CLEANED_TITLE=$(echo "$ISSUE_TITLE" | tr -d '[]')
echo "🧼 Cleaned title: $CLEANED_TITLE"
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
CLEANED_TITLE=$(echo "$ISSUE_TITLE" | tr -d '[]')
echo "🧼 Cleaned title: $CLEANED_TITLE"
🤖 Prompt for AI Agents
In .github/workflows/close-jira-issue.yml around lines 23 to 26, avoid directly
using the GitHub event variable `${{ github.event.issue.title }}` inside the
inline script to prevent code injection risks. Instead, pass the issue title as
an environment variable to the script step, then reference that environment
variable within the script. Refactor the workflow to set ISSUE_TITLE as an env
variable and use it safely inside the script without direct interpolation.

JIRA_KEY=$(echo "$CLEANED_TITLE" | grep -oE '[A-Z0-9]+-[0-9]+')

if [ -z "$JIRA_KEY" ]; then
echo "❌ JIRA key could not be extracted. Exiting."
exit 1
fi

echo "✅ Extracted JIRA_KEY=$JIRA_KEY"
echo "JIRA_KEY=$JIRA_KEY" >> $GITHUB_ENV

- name: Transition Jira issue to Done
uses: atlassian/gajira-transition@v3
with:
issue: ${{ env.JIRA_KEY }}
transition: 완료
25 changes: 14 additions & 11 deletions .github/workflows/create-jira-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
uses: stefanbuck/github-issue-praser@v3
id: issue-parser
with:
template-path: .github/ISSUE_TEMPLATE/issue-form.yml
template-path: .github/ISSUE_TEMPLATE/issue_form.yml

- name: Log Issue Parser
run: |
Expand All @@ -47,7 +47,7 @@ jobs:
id: create
uses: atlassian/gajira-create@v3
with:
project: SKP
project: THIP2025
issuetype: Task
summary: '${{ github.event.issue.title }}'
description: '${{ steps.md2jira.outputs.output-text }}'
Expand All @@ -66,20 +66,23 @@ jobs:
with:
ref: develop

- name: Create branch with Ticket number
run: |
ISSUE_NUMBER="${{ steps.create.outputs.issue }}"
ISSUE_TITLE="${{ steps.issue-parser.outputs.issueparser_branch}}"
BRANCH_NAME="${ISSUE_NUMBER}-$(echo ${ISSUE_TITLE} | sed 's/ /-/g')"
git checkout -b "${BRANCH_NAME}"
git push origin "${BRANCH_NAME}"

# - name: Create branch with Ticket number
# run: |
# BRANCH_TYPE="${{ steps.issue-parser.outputs.issueparser_branchType }}"
# ISSUE_TITLE="${{ steps.issue-parser.outputs.issueparser_branch }}"
# BRANCH_NAME="${BRANCH_TYPE}/$(echo ${ISSUE_TITLE} | sed 's/ /-/g')"
# git checkout -b "${BRANCH_NAME}"
# git push origin "${BRANCH_NAME}"
# ISSUE_NUMBER="${{ steps.create.outputs.issue }}"
- name: Update issue title

uses: actions-cool/issues-helper@v3
with:
actions: 'update-issue'
token: ${{ secrets.GITHUB_TOKEN }}
title: '[${{ steps.create.outputs.issue }}] ${{ github.event.issue.title }}'
title: '${{ github.event.issue.title }}'

# [${{ steps.create.outputs.issue }}]

- name: Add comment with Jira issue link
uses: actions-cool/issues-helper@v3
Expand Down
42 changes: 0 additions & 42 deletions src/App.css

This file was deleted.

31 changes: 7 additions & 24 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,14 @@
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';

function App() {
const [count, setCount] = useState(0);
import Router from './pages';
import { Global } from '@emotion/react';
import { globalStyles } from './styles/global/global';

const App = () => {
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount(count => count + 1)}>count is {count}</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">Click on the Vite and React logos to learn more</p>
<Global styles={globalStyles} />
<Router />
</>
);
}
};

export default App;
3 changes: 3 additions & 0 deletions src/assets/leftArrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/assets/react.svg

This file was deleted.

68 changes: 0 additions & 68 deletions src/index.css

This file was deleted.

1 change: 1 addition & 0 deletions src/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import './reset.css';
2 changes: 1 addition & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import './main.css';
import App from './App.tsx';

createRoot(document.getElementById('root')!).render(
Expand Down
25 changes: 25 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
createBrowserRouter,
createRoutesFromElements,
Route,
RouterProvider,
} from 'react-router-dom';
import Signup from './signup/Signup';
import SignupGenre from './signup/SignupGenre';
import SignupNickname from './signup/SignupNickname';

const Router = () => {
const router = createBrowserRouter(
createRoutesFromElements(
<>
<Route path="signup" element={<Signup />}>
<Route index element={<SignupNickname />} />
<Route path="genre" element={<SignupGenre />} />
</Route>
</>,
Comment on lines +14 to +19
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

불필요한 Fragment 제거

정적 분석 도구가 지적한 대로, 단일 자식 요소만 포함하는 Fragment는 불필요합니다.

다음과 같이 수정하세요:

-      <>
-        <Route path="signup" element={<Signup />}>
-          <Route index element={<SignupNickname />} />
-          <Route path="genre" element={<SignupGenre />} />
-        </Route>
-      </>,
+      <Route path="signup" element={<Signup />}>
+        <Route index element={<SignupNickname />} />
+        <Route path="genre" element={<SignupGenre />} />
+      </Route>,
📝 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
<>
<Route path="signup" element={<Signup />}>
<Route index element={<SignupNickname />} />
<Route path="genre" element={<SignupGenre />} />
</Route>
</>,
<Route path="signup" element={<Signup />}>
<Route index element={<SignupNickname />} />
<Route path="genre" element={<SignupGenre />} />
</Route>,
🧰 Tools
🪛 Biome (1.9.4)

[error] 14-19: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🤖 Prompt for AI Agents
In src/pages/index.tsx around lines 14 to 19, remove the unnecessary React
Fragment wrapping the single Route element, as it only contains one child.
Replace the fragment with just the Route component directly to simplify the JSX
structure.

),
);
return <RouterProvider router={router} />;
};

export default Router;
69 changes: 69 additions & 0 deletions src/pages/signup/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import styled from '@emotion/styled';

const HeaderWrapper = styled.div`
background-color: #121212;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
max-width: 768px;
margin: 0 auto;
padding: 16px 20px;

.title {
color: #fefefe;
font-size: 22px;
font-style: normal;
font-weight: 700;
}

.next {
width: 49px;
height: 28px;
padding: 4px 12px;
align-items: center;
border-radius: 20px;
background: #888;

color: #fefefe;
text-align: center;
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 20px;
}
`;

const InnerHeader = styled.div`
width: 100%;
height: 56px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
`;

type HeaderProps = {
title: string;
leftIcon?: React.ReactNode;
rightButton?: React.ReactNode;
onLeftClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
onRightClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
};

const Header = ({ leftIcon, title, rightButton, onLeftClick, onRightClick }: HeaderProps) => (
<HeaderWrapper>
<InnerHeader>
<div onClick={onLeftClick} style={{ cursor: onLeftClick ? 'pointer' : 'default' }}>
{leftIcon}
</div>
<div className="title">{title}</div>
<div onClick={onRightClick} style={{ cursor: onRightClick ? 'pointer' : 'default' }}>
{rightButton}
</div>
</InnerHeader>
</HeaderWrapper>
);

export default Header;
Loading