Skip to content

Commit

Permalink
Merge branch 'main' into 1495-implement-image-upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaehyeon1020 committed May 27, 2024
2 parents 209c2f9 + f046795 commit 5f22f91
Show file tree
Hide file tree
Showing 36 changed files with 1,262 additions and 152 deletions.
93 changes: 79 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,108 @@ on:
types: [opened, edited, synchronize, reopened]

jobs:
build:
name: Build
build-backend:
name: Build Backend
runs-on: ubuntu-latest

strategy:
matrix:
target: [frontend, backend, backend-admin]
target: [client, admin]

steps:
- uses: actions/checkout@v4

- name: Check if source code has changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
shared: &shared
- 'apps/backend/libs/**'
- 'apps/backend/prisma/**'
- 'apps/backend/*.json'
- 'pnpm-lock.yaml'
client:
- *shared
- 'apps/backend/apps/client/**'
admin:
- *shared
- 'apps/backend/apps/admin/**'
- uses: ./.github/actions/setup-pnpm
if: ${{ steps.filter.outputs[matrix.target] == 'true' }}

- name: Generate Prisma Client
if: ${{ matrix.target == 'backend' || matrix.target == 'backend-admin' }}
if: ${{ steps.filter.outputs[matrix.target] == 'true' }}
run: pnpm --filter="@codedang/backend" exec prisma generate

- name: Build
if: ${{ steps.filter.outputs[matrix.target] == 'true' }}
run: pnpm --filter="@codedang/backend" build ${{ matrix.target }}

build-frontend:
name: Build Frontend
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Check if source code has changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
frontend:
- 'apps/frontend/**'
- 'pnpm-lock.yaml'
- uses: ./.github/actions/setup-pnpm
if: steps.filter.outputs.frontend == 'true'

- name: Setup Next.js build cache
if: ${{ matrix.target == 'frontend' }}
uses: actions/cache@v4
if: steps.filter.outputs.frontend == 'true'
with:
path: apps/frontend/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml') }}-
- name: Load Next.js environment
if: ${{ matrix.target == 'frontend' }}
if: steps.filter.outputs.frontend == 'true'
run: |
echo "NEXT_PUBLIC_BASEURL=https://stage.codedang.com/api" >> apps/frontend/.env
echo "NEXT_PUBLIC_GQL_BASEURL=https://stage.codedang.com/graphql" >> apps/frontend/.env
echo "NEXT_URL=https://stage.codedang.com" >> apps/frontend/.env
- name: Build (backend admin)
if: ${{ matrix.target == 'backend-admin' }}
run: pnpm --filter="@codedang/backend" build admin
- name: Build
if: ${{ matrix.target != 'backend-admin' }}
run: pnpm --filter="apps/${{ matrix.target }}" build
if: steps.filter.outputs.frontend == 'true'
run: pnpm --filter="@codedang/frontend" build

typecheck:
name: Typecheck
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Check if source code has changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'apps/backend/**'
- uses: ./.github/actions/setup-pnpm
if: steps.filter.outputs.backend == 'true'

- name: Generate Prisma Client
if: steps.filter.outputs.backend == 'true'
run: pnpm --filter="@codedang/backend" exec prisma generate

- name: Check types (backend) # For spec files
if: steps.filter.outputs.backend == 'true'
run: pnpm --filter="@codedang/backend" exec tsc --noEmit

# Typecheck is not performed for frontend intentionally.
Expand Down Expand Up @@ -98,8 +149,8 @@ jobs:
- name: Lint (Node.js)
run: pnpm lint

test:
name: Test
test-backend:
name: Test Backend
runs-on: ubuntu-latest

env:
Expand All @@ -118,9 +169,21 @@ jobs:

steps:
- uses: actions/checkout@v4

- name: Check if source code has changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'apps/backend/**'
- 'pnpm-lock.yaml'
- uses: ./.github/actions/setup-pnpm
if: steps.filter.outputs.backend == 'true'

- name: Check Prisma Migration
if: steps.filter.outputs.backend == 'true'
run: |
pnpm --filter="@codedang/backend" exec prisma migrate diff \
--from-migrations ./prisma/migrations \
Expand All @@ -131,7 +194,9 @@ jobs:
"Please run 'pnpm prisma migrate dev' locally and commit the changes." && exit 1)
- name: Migrate Prisma
if: steps.filter.outputs.backend == 'true'
run: pnpm --filter="@codedang/backend" exec prisma migrate reset --force

- name: Test
run: pnpm -r test
if: steps.filter.outputs.backend == 'true'
run: pnpm --filter="@codedang/backend" test
22 changes: 10 additions & 12 deletions apps/backend/apps/client/src/contest/contest.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ describe('ContestService', () => {
groupId,
user01Id
)
expect(contests).to.have.lengthOf(takeNum)
expect(contests.data).to.have.lengthOf(takeNum)
})

it('should return a contest array which starts with id 9', async () => {
Expand All @@ -228,7 +228,7 @@ describe('ContestService', () => {
groupId,
user01Id
)
expect(contests[0].id).to.equals(9)
expect(contests.data[0].id).to.equals(9)
})

it('a contest should contain following fields', async () => {
Expand All @@ -238,12 +238,12 @@ describe('ContestService', () => {
groupId,
user01Id
)
expect(contests[0]).to.have.property('title')
expect(contests[0]).to.have.property('startTime')
expect(contests[0]).to.have.property('endTime')
expect(contests[0]).to.have.property('participants')
expect(contests[0].group).to.have.property('id')
expect(contests[0].group).to.have.property('groupName')
expect(contests.data[0]).to.have.property('title')
expect(contests.data[0]).to.have.property('startTime')
expect(contests.data[0]).to.have.property('endTime')
expect(contests.data[0]).to.have.property('participants')
expect(contests.data[0].group).to.have.property('id')
expect(contests.data[0].group).to.have.property('groupName')
})

it("shold return contests whose title contains '낮'", async () => {
Expand All @@ -255,7 +255,7 @@ describe('ContestService', () => {
user01Id,
keyword
)
expect(contests.map((contest) => contest.title)).to.deep.equals([
expect(contests.data.map((contest) => contest.title)).to.deep.equals([
'소프트의 낮'
])
})
Expand All @@ -268,9 +268,7 @@ describe('ContestService', () => {
10,
groupId
)
const contestIds = contests.finished
.map((c) => c.id)
.sort((a, b) => a - b)
const contestIds = contests.data.map((c) => c.id).sort((a, b) => a - b)
const finishedContestIds = [6, 7, 8, 9, 10, 11, 12, 13]
expect(contestIds).to.deep.equal(finishedContestIds)
})
Expand Down
34 changes: 32 additions & 2 deletions apps/backend/apps/client/src/contest/contest.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,23 @@ export class ContestService {
orderBy: [{ endTime: 'desc' }, { id: 'desc' }]
})

return this.renameToParticipants(contests)
const total = await this.prisma.contest.count({
where: {
groupId,
endTime: {
lte: now
},
id: {
in: registeredContestIds
},
title: {
contains: search
},
isVisible: true
}
})

return { data: this.renameToParticipants(contests), total }
}

async getFinishedContestsByGroupId(
Expand Down Expand Up @@ -239,7 +255,21 @@ export class ContestService {
select: contestSelectOption,
orderBy: [{ endTime: 'desc' }, { id: 'desc' }]
})
return { finished: this.renameToParticipants(finished) }

const total = await this.prisma.contest.count({
where: {
endTime: {
lte: now
},
groupId,
isVisible: true,
title: {
contains: search
}
}
})

return { data: this.renameToParticipants(finished), total }
}

// TODO: participants 대신 _count.contestRecord 그대로 사용하는 것 고려해보기
Expand Down
35 changes: 19 additions & 16 deletions apps/backend/apps/client/src/group/group.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,25 @@ describe('GroupService', () => {
const cursor = null
const res = await service.getGroups(cursor, take)

expect(res).to.deep.equal([
{
id: 3,
groupName: 'Example Private Group 2',
description:
'This is an example private group just for testing. Check if this group is not shown to users not registered to this group.',
memberNum: 1
},
{
id: 4,
groupName: 'Example Private Group 3',
description:
'This is an example private group just for testing. Check if this group is not shown to users not registered to this group.',
memberNum: 2
}
])
expect(res).to.deep.equal({
data: [
{
id: 3,
groupName: 'Example Private Group 2',
description:
'This is an example private group just for testing. Check if this group is not shown to users not registered to this group.',
memberNum: 1
},
{
id: 4,
groupName: 'Example Private Group 3',
description:
'This is an example private group just for testing. Check if this group is not shown to users not registered to this group.',
memberNum: 2
}
],
total: 4
})
})
})

Expand Down
14 changes: 13 additions & 1 deletion apps/backend/apps/client/src/group/group.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,19 @@ export class GroupService {
}
})

return groups
const total = await this.prisma.group.count({
where: {
NOT: {
id: 1
},
config: {
path: ['showOnList'],
equals: true
}
}
})

return { data: groups, total }
}

async getJoinedGroups(userId: number) {
Expand Down
15 changes: 12 additions & 3 deletions apps/backend/apps/client/src/notice/notice.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const noticeId = 2
const userId = 1
const groupId = 1
const username = 'manager'
const totalNotice = 24

const notice = {
id: noticeId,
Expand Down Expand Up @@ -55,7 +56,8 @@ const db = {
findUnique: stub().resolves(notice),
findUniqueOrThrow: stub().resolves(notice),
findFirst: stub(),
findFirstOrThrow: stub()
findFirstOrThrow: stub(),
count: stub().resolves(24)
},
group: {
findUnique: stub().resolves(group)
Expand Down Expand Up @@ -121,7 +123,10 @@ describe('NoticeService', () => {
take: 3,
groupId: group.id
})
expect(getNoticesByGroupId).to.deep.equal(userNotices)
expect(getNoticesByGroupId).to.deep.equal({
data: userNotices,
total: totalNotice
})
})
})

Expand Down Expand Up @@ -165,7 +170,11 @@ describe('NoticeService', () => {
take: 3,
groupId: group.id
})
expect(getFixedNoticesByGroupId).to.deep.equal(userNotices)

expect(getFixedNoticesByGroupId).to.deep.equal({
data: userNotices,
total: totalNotice
})
})
})

Expand Down
Loading

0 comments on commit 5f22f91

Please sign in to comment.