Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8895e09
menu-bar-longstick-bug-fix (#560)
banchan01 Jan 27, 2026
61af4b6
#562 menu bar style 태그 클래스 수정 (#563)
banchan01 Jan 27, 2026
22f2977
Merge branch 'main' into develop
banchan01 Jan 28, 2026
e877095
#559 CI 파이프라인에서 Kustomization 이미지 태그 변경 (#565)
Boksam Jan 31, 2026
4328065
add service-architecture-docs
banchan01 Feb 5, 2026
0b03474
edit service-architecture-docs
banchan01 Feb 5, 2026
d7bafc3
add service-architecture image
banchan01 Feb 5, 2026
792425c
edit service-architecture-docs
banchan01 Feb 5, 2026
52dc5a3
update format in service-architecture
banchan01 Feb 5, 2026
f052236
update style in service-architecture
banchan01 Feb 5, 2026
3098af7
update format in service-architecture
banchan01 Feb 5, 2026
a7890e1
update format in service-architecture
banchan01 Feb 5, 2026
d656aaf
#566 Grafana 대시보드 구축 (#567)
Boksam Feb 9, 2026
037ac3a
#569 공지사항 더보기 고정 게시물 디자인 적용 (#570)
wlsgur11 Feb 10, 2026
3c81fd9
ci: Update dev image tags to 037ac3a4cbe1d68fb46ea6b696686e10acb72ce6…
github-actions[bot] Feb 10, 2026
caaf8cc
fix: 공지사항 텍스트 클릭 시 목록으로 라우팅되는 문제 해결 (#572)
taekoong Feb 11, 2026
df274ba
ci: Update dev image tags to caaf8cc596132e355ce3f05350e13fca751b50d5…
github-actions[bot] Feb 11, 2026
99ea533
#579 Formatter applying (#580)
banchan01 Feb 18, 2026
49a29d9
ci: Update dev image tags to 99ea533d3c60cc21847c3f77bf6110f0a74bc278…
github-actions[bot] Feb 18, 2026
6e9bfee
#573 커뮤니티 게시글 '목록' 버튼 추가를 통한 탐색 편의성 개선 (#575)
wlsgur11 Feb 19, 2026
eb26fae
ci: Update dev image tags to 6e9bfee470d7308a165a2f13aad7f2b0e07931df…
github-actions[bot] Feb 19, 2026
f89a617
랭킹 페이지 페이지네이션 오류 수정 (#578)
wlsgur11 Feb 19, 2026
ffa34bf
ci: Update dev image tags to f89a6176260d00fdba0b540bb5e9a7343dbe498f…
github-actions[bot] Feb 19, 2026
35dae58
#574 공지사항 상세 페이지 내 목록 기능 추가 (#576)
taekoong Feb 23, 2026
abb5586
ci: Update dev image tags to 35dae587c7ba957bce3ebb46320424cdc7dd1ab3…
github-actions[bot] Feb 23, 2026
64caf67
#582 Code Place Hub 쿠버네티스 마이그레이션 (#583)
Boksam Feb 24, 2026
94dca1c
#556 redesign overall problem-creation-page UI (#585)
banchan01 Mar 3, 2026
31d11d2
ci: Update dev image tags to 94dca1c65a792828c8d0fad29cd0768245f8ff47…
github-actions[bot] Mar 3, 2026
81a4f95
#584 rename center name to AI융합교육원 (#586)
banchan01 Mar 3, 2026
b1f05fa
ci: Update dev image tags to 81a4f95b34b6804fc05181e0e059540b48e6fb2e…
github-actions[bot] Mar 3, 2026
1dc6efc
#589 Fix problem code editor (#590)
banchan01 Mar 10, 2026
088f544
ci: Update dev image tags to 241ae801ba075540d0d74f63b74647fcaf3d2674…
github-actions[bot] Mar 10, 2026
0f3d0ec
#587 문제 풀이/커뮤니티 페이지 드롭다운 필터 UI 정렬 오류 (#588)
taekoong Mar 10, 2026
26c261b
ci: Update dev image tags to 4164dbd483739243a19b4240a328236f63249a14…
github-actions[bot] Mar 10, 2026
c8e042c
Merge branch 'main' into release-2.0.2
banchan01 Mar 10, 2026
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
86 changes: 80 additions & 6 deletions .github/workflows/ci2develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- "deployment/**"
- "scripts/**"
- ".github/**"
- "kubernetes/**"
branches: [develop]
workflow_dispatch:

Expand Down Expand Up @@ -53,9 +54,7 @@ jobs:
context: ./backend
file: ./backend/Dockerfile
push: true
tags: |
${{ secrets.HARBOR_REGISTRY }}/code-place-dev/backend:${{ github.sha }}-dev
${{ secrets.HARBOR_REGISTRY }}/code-place-dev/backend:latest
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-dev/backend:${{ github.sha }}-dev

ci-frontend-dev:
needs: [detect-changes-by-component]
Expand All @@ -81,9 +80,84 @@ jobs:
context: ./frontend
file: ./frontend/Dockerfile
push: true
tags: |
${{ secrets.HARBOR_REGISTRY }}/code-place-dev/frontend:${{ github.sha }}-dev
${{ secrets.HARBOR_REGISTRY }}/code-place-dev/frontend:latest
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-dev/frontend:${{ github.sha }}-dev
build-args: |
SERVER_NAME=${{ secrets.DEV_SERVER_NAME }}
APP_VERSION=${{ github.sha }}-dev

ci-hub-auth-dev:
needs: [detect-changes-by-component]
if: ${{ needs.detect-changes-by-component.outputs.hub-auth == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1

- name: Login to Harbor
uses: docker/login-action@v1
with:
registry: ${{ secrets.HARBOR_REGISTRY }}
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}

- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: ./hub/auth_server
file: ./hub/auth_server/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-dev/hub-auth:${{ github.sha }}-dev

update-dev-manifest:
needs: [ci-backend-dev, ci-frontend-dev, ci-hub-auth-dev]
if: |
always() &&
(needs.ci-backend-dev.result == 'success' || needs.ci-frontend-dev.result == 'success' || needs.ci-hub-auth-dev.result == 'success')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
token: ${{ secrets.ACTION_TOKEN }}
fetch-depth: 0

# NOTE: 기존에 kustomize를 사용하였지만 포멧 문제로 yq로 변경 (junwoo)
# images.[] .name 에 맞는 항목의 newTag 값을 github.sha-dev로 변경
- name: Update Backend Image Tag
if: needs.ci-backend-dev.result == 'success'
uses: mikefarah/yq@master
with:
cmd: yq -i '(.images[] | select(.name == "backend").newTag) = "${{ github.sha }}-dev"' kubernetes/overlays/dev/kustomization.yaml

- name: Update Frontend Image Tag
if: needs.ci-frontend-dev.result == 'success'
uses: mikefarah/yq@master
with:
cmd: yq -i '(.images[] | select(.name == "frontend").newTag) = "${{ github.sha }}-dev"' kubernetes/overlays/dev/kustomization.yaml

- name: Update Hub Auth Image Tag
if: needs.ci-hub-auth-dev.result == 'success'
uses: mikefarah/yq@master
with:
cmd: yq -i '(.images[] | select(.name == "hub-auth").newTag) = "${{ github.sha }}-dev"' kubernetes/overlays/dev/kustomization.yaml

- name: Commit and push changes
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add kubernetes/overlays/dev/kustomization.yaml

# 변경사항이 없으면 종료
if git diff-index --quiet HEAD; then
echo "No changes to commit"
exit 0
fi

# 충돌 방지를 위해 최신 develop 브랜치로 rebase 후 push
# [skip ci] 태그를 커밋 메시지에 추가하여 추가 CI 실행을 방지
git commit -m "ci: Update dev image tags to ${{ github.sha }} [skip ci]"
git pull --rebase origin ${{ github.ref_name }}
git push origin ${{ github.ref_name }}
69 changes: 57 additions & 12 deletions .github/workflows/ci2production-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
paths-ignore:
- "deployment/**"
- "scripts/**"
- "kubernetes/**"
branches: [main]
workflow_dispatch:

Expand Down Expand Up @@ -81,9 +82,7 @@ jobs:
context: ./backend
file: ./backend/Dockerfile
push: true
tags: |
${{ secrets.HARBOR_REGISTRY }}/code-place-prod/backend:${{ github.sha }}-prod
${{ secrets.HARBOR_REGISTRY }}/code-place-prod/backend:latest
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-prod/backend:${{ github.sha }}-prod

ci-frontend:
needs: [detect-changes-by-component]
Expand All @@ -109,9 +108,7 @@ jobs:
context: ./frontend
file: ./frontend/Dockerfile
push: true
tags: |
${{ secrets.HARBOR_REGISTRY }}/code-place-prod/frontend:${{ github.sha }}-prod
${{ secrets.HARBOR_REGISTRY }}/code-place-prod/frontend:latest
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-prod/frontend:${{ github.sha }}-prod
build-args: |
SERVER_NAME=${{ secrets.PROD_SERVER_NAME }}
APP_VERSION=${{ github.sha }}
Expand Down Expand Up @@ -140,17 +137,65 @@ jobs:
context: ./hub/auth_server
file: ./hub/auth_server/Dockerfile
push: true
tags: |
${{ secrets.HARBOR_REGISTRY }}/code-place-hub/auth-server:${{ github.sha }}
${{ secrets.HARBOR_REGISTRY }}/code-place-hub/auth-server:latest
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-prod/hub-auth:${{ github.sha }}-prod

update-prod-manifest:
needs: [check-release-branch, ci-backend, ci-frontend, ci-hub-auth]
if: |
always() &&
needs.check-release-branch.outputs.is_release == 'true' &&
(needs.ci-frontend.result == 'success' || needs.ci-backend.result == 'success' || needs.ci-hub-auth.result == 'success')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
token: ${{ secrets.ACTION_TOKEN }}
fetch-depth: 0

# NOTE: 기존에 kustomize를 사용하였지만 포멧 문제로 yq로 변경 (junwoo)
# images.[] .name 에 맞는 항목의 newTag 값을 github.sha 로 변경
- name: Update Backend Image Tag
if: needs.ci-backend.result == 'success'
uses: mikefarah/yq@master
with:
cmd: yq -i '(.images[] | select(.name == "backend").newTag) = "${{ github.sha }}-prod"' kubernetes/overlays/prod/kustomization.yaml

- name: Update Frontend Image Tag
if: needs.ci-frontend.result == 'success'
uses: mikefarah/yq@master
with:
cmd: yq -i '(.images[] | select(.name == "frontend").newTag) = "${{ github.sha }}-prod"' kubernetes/overlays/prod/kustomization.yaml

- name: Update Hub Auth Image Tag
if: needs.ci-hub-auth.result == 'success'
uses: mikefarah/yq@master
with:
cmd: yq -i '(.images[] | select(.name == "hub-auth").newTag) = "${{ github.sha }}-prod"' kubernetes/overlays/prod/kustomization.yaml

- name: Commit and push changes
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add kubernetes/overlays/prod/kustomization.yaml

# 변경사항이 없으면 종료
if git diff-index --quiet HEAD; then
echo "No changes to commit"
exit 0
fi

# [skip ci] 태그를 커밋 메시지에 추가하여 추가 CI 실행을 방지
git commit -m "ci: Update prod image tags to ${{ github.sha }} [skip ci]"
git pull --rebase origin main
git push origin main

create-release:
needs: [check-release-branch, ci-frontend, ci-backend]
needs: [check-release-branch, update-prod-manifest]
if: |
always() &&
needs.check-release-branch.outputs.is_release == 'true' &&
(needs.ci-frontend.result == 'success' || needs.ci-frontend.result == 'skipped') &&
(needs.ci-backend.result == 'success' || needs.ci-backend.result == 'skipped')
(needs.update-prod-manifest.result == 'success' || needs.update-prod-manifest.result == 'skipped')
runs-on: ubuntu-latest
steps:
- name: Checkout Code
Expand Down
5 changes: 4 additions & 1 deletion .style.yapf
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[style]
based_on_style = google
based_on_style = yapf
column_limit = 120
spaces_before_comment = 4
split_before_logical_operator = true
indent_width = 4
28 changes: 13 additions & 15 deletions backend/account/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ class Migration(migrations.Migration):
name='UserScore',
fields=[
('user',
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
serialize=False,
to='account.user')),
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False,
to='account.user')),
('yesterday_score', models.IntegerField(default=0)),
('total_score', models.IntegerField(default=0)),
('fluctuation', models.IntegerField(default=0)),
Expand All @@ -77,10 +76,9 @@ class Migration(migrations.Migration):
name='UserSolved',
fields=[
('user',
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
serialize=False,
to='account.user')),
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False,
to='account.user')),
('math_solved', models.BigIntegerField(default=0)),
('implementation_solved', models.BigIntegerField(default=0)),
('datastructure_solved', models.BigIntegerField(default=0)),
Expand All @@ -105,13 +103,13 @@ class Migration(migrations.Migration):
('oi_problems_status', models.JSONField(default=dict)),
('real_name', models.TextField(null=True)),
('student_id',
models.CharField(max_length=9,
null=True,
validators=[
django.core.validators.RegexValidator(code='invalid_student_id',
message='학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.',
regex='^\\d{6,9}$')
])),
models.CharField(
max_length=9,
null=True,
validators=[
django.core.validators.RegexValidator(
code='invalid_student_id', message='학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.', regex='^\\d{6,9}$')
])),
('avatar', models.TextField(default='/public/avatar/default.png')),
('blog', models.URLField(null=True)),
('mood', models.TextField(null=True)),
Expand Down
23 changes: 11 additions & 12 deletions backend/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ class Meta:

def get_default_field_score():
return {
"0": 0, # "Math"
"1": 0, # "Implementation"
"2": 0, # "Datastructure"
"3": 0, # "Search"
"4": 0, # "Sorting"
"0": 0, # "Math"
"1": 0, # "Implementation"
"2": 0, # "Datastructure"
"3": 0, # "Search"
"4": 0, # "Sorting"
}


Expand Down Expand Up @@ -121,13 +121,12 @@ class UserProfile(models.Model):
oi_problems_status = JSONField(default=dict)

real_name = models.TextField(null=True)
student_id = models.CharField(max_length=9,
null=True,
validators=[
RegexValidator(regex=r'^\d{6,9}$',
message='학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.',
code='invalid_student_id'),
])
student_id = models.CharField(
max_length=9,
null=True,
validators=[
RegexValidator(regex=r'^\d{6,9}$', message='학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.', code='invalid_student_id'),
])
avatar = models.TextField(default=f"{settings.AVATAR_URI_PREFIX}/default.png")
blog = models.URLField(null=True)
mood = models.TextField(null=True)
Expand Down
54 changes: 27 additions & 27 deletions backend/account/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ class UserRegisterSerializer(serializers.Serializer):
username = serializers.CharField(min_length=3, max_length=8)
real_name = serializers.CharField(max_length=13)
email = serializers.EmailField(max_length=64)
password = serializers.RegexField(regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8,
error_messages={'invalid': '비밀번호는 8글자 이상이어야 하며, 영문, 숫자, 특수문자를 모두 포함해야 합니다.'})
student_id = serializers.RegexField(regex=r'^\d{6,9}$',
min_length=6,
max_length=9,
error_messages={'invalid': '학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.'})
password = serializers.RegexField(
regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8,
error_messages={'invalid': '비밀번호는 8글자 이상이어야 하며, 영문, 숫자, 특수문자를 모두 포함해야 합니다.'})
student_id = serializers.RegexField(
regex=r'^\d{6,9}$', min_length=6, max_length=9, error_messages={'invalid': '학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.'})
collegeId = serializers.IntegerField()
departmentId = serializers.IntegerField()


class UserChangePasswordSerializer(serializers.Serializer):
old_password = serializers.CharField()
new_password = serializers.RegexField(regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8,
error_messages={'invalid': '비밀번호는 8글자 이상이어야 하며, 영문, 숫자, 특수문자를 모두 포함해야 합니다.'})
new_password = serializers.RegexField(
regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8,
error_messages={'invalid': '비밀번호는 8글자 이상이어야 하며, 영문, 숫자, 특수문자를 모두 포함해야 합니다.'})


class GenerateUserSerializer(serializers.Serializer):
Expand Down Expand Up @@ -130,25 +130,25 @@ class EditUserSerializer(serializers.Serializer):
id = serializers.IntegerField()
username = serializers.CharField(min_length=3, max_length=8)
real_name = serializers.CharField(max_length=13)
password = serializers.RegexField(allow_null=True,
allow_blank=True,
regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8,
error_messages={'invalid': '비밀번호는 8글자 이상이어야 하며, 영문, 숫자, 특수문자를 모두 포함해야 합니다.'})
password = serializers.RegexField(
allow_null=True,
allow_blank=True,
regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8,
error_messages={'invalid': '비밀번호는 8글자 이상이어야 하며, 영문, 숫자, 특수문자를 모두 포함해야 합니다.'})
# email = serializers.EmailField(max_length=64)
admin_type = serializers.ChoiceField(choices=(AdminType.REGULAR_USER, AdminType.ADMIN, AdminType.SUPER_ADMIN))
problem_permission = serializers.ChoiceField(choices=(ProblemPermission.NONE, ProblemPermission.OWN,
ProblemPermission.ALL))
problem_permission = serializers.ChoiceField(
choices=(ProblemPermission.NONE, ProblemPermission.OWN, ProblemPermission.ALL))
college = serializers.IntegerField(allow_null=True)
department = serializers.IntegerField(allow_null=True)
student_id = serializers.CharField(max_length=9,
allow_null=True,
allow_blank=True,
validators=[
RegexValidator(regex=r'^\d{6,9}$',
message='학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.',
code='invalid_student_id'),
])
student_id = serializers.CharField(
max_length=9,
allow_null=True,
allow_blank=True,
validators=[
RegexValidator(regex=r'^\d{6,9}$', message='학번은 6자리 이상 9자리 이하의 숫자만 입력 가능합니다.', code='invalid_student_id'),
])
open_api = serializers.BooleanField()
two_factor_auth = serializers.BooleanField()
is_disabled = serializers.BooleanField()
Expand All @@ -161,8 +161,8 @@ class ApplyResetPasswordSerializer(serializers.Serializer):

class ResetPasswordSerializer(serializers.Serializer):
token = serializers.CharField()
password = serializers.RegexField(regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$',
min_length=8)
password = serializers.RegexField(
regex=r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$', min_length=8)
captcha = serializers.CharField()


Expand Down
Loading