Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat/#131] 태그 기능 추가, main.yml 원복 #132

Merged
merged 1 commit into from
Dec 17, 2024
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
96 changes: 29 additions & 67 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ on:
branches:
- develop
jobs:
build-and-deploy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macos-latest]

outputs:
build_outcome: ${{ steps.build_app.outcome }}
deploy_outcome: ${{ steps.deploy_web.outcome }}

build:
runs-on: ubuntu-20.04
steps:
- name: Checkout source code
uses: actions/checkout@v3
Expand All @@ -23,73 +15,44 @@ jobs:
- name: Get commit message and author
id: get_commit_info
run: |
echo "message=$(git log --format=%s -n 1)" >> $GITHUB_OUTPUT
echo "author=$(git log --format=%an -n 1)" >> $GITHUB_OUTPUT
echo "author_username=$(git log --format=%ae -n 1 | cut -d@ -f1)" >> $GITHUB_OUTPUT
echo "::set-output name=message::$(git log --format=%s -n 1)"
echo "::set-output name=author::$(git log --format=%an -n 1)"
echo "::set-output name=author_username::$(git log --format=%ae -n 1 | cut -d@ -f1)"

- name: Install dependencies
run: yarn install

# 웹 빌드 및 S3 업로드 (macOS 환경에서만)
- name: Build Web App
id: build_web
if: matrix.os == 'macos-latest'
- name: Generate build
id: build
env:
VITE_API_BASE_URL: ${{ secrets.VITE_API_BASE_URL }}
VITE_OAUTH_KAKAO_REST_API_KEY: ${{ secrets.VITE_OAUTH_KAKAO_REST_API_KEY }}
VITE_OAUTH_KAKAO_CLIENT_SECRET_CODE: ${{ secrets.VITE_OAUTH_KAKAO_CLIENT_SECRET_CODE }}
VITE_OAUTH_KAKAO_REDIRECT_URI: ${{ secrets.VITE_OAUTH_KAKAO_REDIRECT_URI }}
VITE_DMG_DOWNLOAD_URL: ${{ secrets.VITE_DMG_DOWNLOAD_URL }}
VITE_EXE_DOWNLOAD_URL: ${{ secrets.VITE_EXE_DOWNLOAD_URL }}
run: |
echo "Building web app..."
yarn build
run: yarn build
continue-on-error: true

- name: Upload Web App to AWS S3
id: deploy_web
if: matrix.os == 'macos-latest'
- name: Deploy to S3
id: deploy
if: steps.build.outcome == 'success'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
echo "Deploying web build to S3..."
aws s3 sync dist/web s3://alignlab-client --delete --region ap-northeast-2

# Electron 빌드 및 GitHub Releases로 Publish
- name: Build and Publish Electron App
id: build_app
env:
VITE_API_BASE_URL: ${{ secrets.VITE_API_BASE_URL }}
VITE_OAUTH_KAKAO_REST_API_KEY: ${{ secrets.VITE_OAUTH_KAKAO_REST_API_KEY }}
VITE_OAUTH_KAKAO_CLIENT_SECRET_CODE: ${{ secrets.VITE_OAUTH_KAKAO_CLIENT_SECRET_CODE }}
VITE_OAUTH_KAKAO_REDIRECT_URI: ${{ secrets.VITE_OAUTH_KAKAO_REDIRECT_URI }}
VITE_DMG_DOWNLOAD_URL: ${{ secrets.VITE_DMG_DOWNLOAD_URL }}
VITE_EXE_DOWNLOAD_URL: ${{ secrets.VITE_EXE_DOWNLOAD_URL }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: yarn electron:publish
aws s3 sync --region ap-northeast-2 dist/web s3://alignlab-client --delete
continue-on-error: true

# CloudFront 캐시 무효화
invalidate-cache:
runs-on: ubuntu-20.04
needs: [build-and-deploy]
if: success()
steps:
- name: Invalidate CloudFront Cache
if: steps.deploy.outcome == 'success'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }}
run: |
echo "Invalidating CloudFront cache..."
aws cloudfront create-invalidation --region ap-northeast-2 --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"

# Discord 알림 - 성공
notify-success:
runs-on: ubuntu-20.04
needs: [build-and-deploy, invalidate-cache]
if: success()
steps:
- name: Discord notification - Success
if: steps.deploy.outcome == 'success'
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_DEPLOY_WEBHOOK }}
DISCORD_USERNAME: GitHub
Expand All @@ -98,28 +61,27 @@ jobs:
with:
args: |
🎉 배포가 성공적으로 완료되었습니다!
다운로드 링크: https://github.com/${{ github.repository }}/releases/latest
웹 앱 링크: https://alignlab.site
브랜치: develop
커밋: ${{ needs.build-and-deploy.outputs.message }}
작성자: ${{ needs.build-and-deploy.outputs.author }}
커밋: ${{ steps.get_commit_info.outputs.message }}
작성자: ${{ steps.get_commit_info.outputs.author }}

# Discord 알림 - 실패
notify-failure:
runs-on: ubuntu-20.04
needs: [build-and-deploy]
if: failure()
steps:
- name: Discord notification - Failure
if: steps.build.outcome == 'failure' || steps.deploy.outcome == 'failure'
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_DEPLOY_WEBHOOK }}
DISCORD_USERNAME: GitHub
DISCORD_AVATAR: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
uses: Ilshidur/action-discord@master
with:
args: |
❌ ${{ needs.build-and-deploy.outputs.build_outcome == 'failure' && '빌드 중' || '배포 중' }} 오류가 발생했습니다.
❌ ${{ steps.build.outcome == 'failure' && '빌드 중' || '배포 중' }} 오류가 발생했습니다.
브랜치: develop
커밋: ${{ needs.build-and-deploy.outputs.message }}
커밋: ${{ steps.get_commit_info.outputs.message }}
작성자: <@${{ secrets.DISCORD_ID_1 }}>
실패한 워크플로우: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
${{ needs.build-and-deploy.outputs.build_outcome == 'failure' && '빌드 오류 메시지:' || '' }}
${{ needs.build-and-deploy.outputs.build_outcome == 'failure' && needs.build-and-deploy.steps.build_app.outputs.stderr || '' }}
${{ steps.build.outcome == 'failure' && '빌드 오류 메시지:' || '' }}
${{ steps.build.outcome == 'failure' && steps.build.outputs.stderr || '' }}

- name: Check deploy result
if: steps.build.outcome == 'failure' || steps.deploy.outcome == 'failure'
run: exit 1
15 changes: 15 additions & 0 deletions src/api/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface group {
userCapacity?: number
hasJoined?: boolean
ranks?: groupUserRank[]
tagNames?: string[]
}

export interface groupUserRank {
Expand All @@ -41,6 +42,7 @@ export interface groupsReq {
page: number
size: number
sort: sort
keyword: string
}

export interface groupsRes {
Expand Down Expand Up @@ -70,6 +72,10 @@ export interface MyGroupData {
userCount: number
userCapacity: number
ownerNickname: string
ownerUid: number
isHidden: boolean
joinCode?: string
tagNames: string[]
}

export const getGroups = async (groupsReq: groupsReq): Promise<groupsRes> => {
Expand Down Expand Up @@ -128,6 +134,15 @@ export const createGroup = async (group: group): Promise<group> => {
}
}

export const modifyGroup = async (group: group): Promise<group> => {
try {
const res = await axiosInstance.put(`groups/${group.id}`, { ...group })
return res.data.data
} catch (e) {
throw e
}
}

export const getGroupScores = async (groupdId: string | number): Promise<{ data: GroupUserRankData }> => {
try {
const res = await axiosInstance.get(`/group-scores?groupId=${groupdId}`)
Expand Down
11 changes: 11 additions & 0 deletions src/assets/icons/crew-edit-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/assets/icons/crew-search-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 40 additions & 11 deletions src/components/Crew/CrewItem.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
import { group } from "@/api"
import PrivateCrewIcon from "@assets/icons/crew-private-icon.svg?react"
import CrewUserIcon from "@assets/icons/crew-user-icon.svg?react"
import { ReactElement } from "react"
import { ReactElement, useCallback } from "react"

interface CrewItemProps {
group: group
keyword: string
onClickDetail: () => void
}

// 키워드 강조 함수
const highlightKeyword = (text: string | undefined, keyword: string): React.ReactNode => {
if (!text) return null
if (!keyword) return text
const parts = text.split(new RegExp(`(${keyword})`, "gi"))
return parts.map((part, index) =>
part.toLowerCase() === keyword.toLowerCase() ? (
<span key={index} className="text-[#1A75FF]">
{part}
</span>
) : (
part
)
)
}

const CrewItem = (props: CrewItemProps): ReactElement => {
const { group, onClickDetail } = props
const { group, keyword, onClickDetail } = props

const createTags = useCallback(
(tags: string[] | undefined): React.ReactElement[] | null => {
if (!tags || tags.length === 0) return null
return tags.map((tag) => <div key={`${group.id}-tag-${tag}`}>{highlightKeyword(`#${tag}`, keyword)}</div>)
},
[group.id, keyword]
)

return (
<div
Expand All @@ -19,15 +44,19 @@ const CrewItem = (props: CrewItemProps): ReactElement => {
}}
className="flex w-full items-center gap-[24px] bg-white px-[24px] py-[11px] text-[14px] font-semibold leading-[32px]"
>
{/* crew name */}
<div className="flex items-center gap-[6px]">
{group.isHidden && <PrivateCrewIcon />}
<div>{group.name}</div>
</div>
{/* crew user cnt */}
<div className="flex flex-grow items-center gap-[6px]">
<CrewUserIcon />
<div>{`${group.userCount}/${group.userCapacity}명`}</div>
<div className="flex flex-grow items-center gap-[24px]">
{/* crew name */}
<div className="flex items-center gap-[6px]">
{group.isHidden && <PrivateCrewIcon />}
<div>{highlightKeyword(group.name, keyword)}</div>
</div>
{/* crew user cnt */}
<div className="flex items-center gap-[6px]">
<CrewUserIcon />
<div>{`${group.userCount}/${group.userCapacity}명`}</div>
</div>
{/* crew tags */}
{keyword && <div className="flex gap-2.5 text-zinc-400">{createTags(group?.tagNames)}</div>}
</div>
{/* detail button */}
<button
Expand Down
Loading
Loading