diff --git a/.github/ISSUE_TEMPLATE/issue-form.yml b/.github/ISSUE_TEMPLATE/issue-form.yml new file mode 100644 index 00000000..08679b6d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue-form.yml @@ -0,0 +1,55 @@ +name: '이슈 생성' +description: 'Repo에 이슈를 생성하며, 생성된 이슈는 Jira와 연동됩니다.' +labels: [feat] +title: '이슈 이름을 작성해주세요' +body: + - type: input + id: parentKey + attributes: + label: '🎟️ 상위 작업 (Ticket Number)' + description: '상위 작업의 Ticket Number를 기입해주세요' + placeholder: 'PRJ-00' + validations: + required: true + + - type: dropdown + id: branchType + attributes: + label: '📂 브랜치 타입 (Branch Type)' + description: '브랜치 타입을 선택해주세요' + options: + - feature + - style + - fix + - refactor + - docs + - chore + validations: + required: true + + - type: input + id: branch + attributes: + label: '🌳 브랜치명 (Branch)' + description: '영어로 브랜치명을 작성해주세요' + validations: + required: true + + - type: input + id: description + attributes: + label: '📝 상세 내용(Description)' + description: '이슈에 대해서 간략히 설명해주세요' + validations: + required: true + + - type: textarea + id: tasks + attributes: + label: '✅ 체크리스트(Tasks)' + description: '해당 이슈에 대해 필요한 작업목록을 작성해주세요' + value: | + - [ ] Task1 + - [ ] Task2 + validations: + required: true \ No newline at end of file diff --git a/.github/workflows/close-jira-issue.yml b/.github/workflows/close-jira-issue.yml new file mode 100644 index 00000000..39a831f6 --- /dev/null +++ b/.github/workflows/close-jira-issue.yml @@ -0,0 +1,35 @@ +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 }}" + # 알파벳/숫자/하이픈만 허용하여 필터링 + SAFE_TITLE=$(echo "$ISSUE_TITLE" | tr -cd '[:alnum:]- ') + # 패턴 미매칭 시에도 스크립트가 종료되지 않도록 처리 + JIRA_KEY=$(echo "$SAFE_TITLE" | grep -oE '[A-Z]+-[0-9]+' || true) + echo "JIRA_KEY=$JIRA_KEY" >> $GITHUB_ENV + + - name: Close Jira issue + if: env.JIRA_KEY != '' + uses: atlassian/gajira-transition@v3 + with: + issue: ${{ env.JIRA_KEY }} + transition: 완료 \ No newline at end of file diff --git a/.github/workflows/create-jira-issue.yml b/.github/workflows/create-jira-issue.yml new file mode 100644 index 00000000..b906d439 --- /dev/null +++ b/.github/workflows/create-jira-issue.yml @@ -0,0 +1,97 @@ +name: Create Jira issue +on: + issues: + types: + - opened + +permissions: + contents: write + issues: write + +jobs: + create-issue: + name: Create Jira issue + runs-on: ubuntu-latest + steps: + - name: Login + 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: Checkout main code + uses: actions/checkout@v4 + with: + ref: main + + - name: Issue Parser + uses: stefanbuck/github-issue-parser@v3 + id: issue-parser + with: + template-path: .github/ISSUE_TEMPLATE/issue-form.yml + + - name: Log Issue Parser + run: | + echo '${{ steps.issue-parser.outputs.issueparser_parentKey }}' + echo '${{ steps.issue-parser.outputs.__ticket_number }}' + echo '${{ steps.issue-parser.outputs.jsonString }}' + + - name: Convert markdown to Jira Syntax + uses: peter-evans/jira2md@v1 + id: md2jira + with: + input-text: | + ### Github Issue Link + - ${{ github.event.issue.html_url }} + + ${{ github.event.issue.body }} + mode: md2jira + + - name: Create Issue + id: create + uses: atlassian/gajira-create@v3 + with: + project: FZ + issuetype: Task + summary: '${{ github.event.issue.title }}' + description: '${{ steps.md2jira.outputs.output-text }}' + fields: | + { + "parent": { + "key": "${{ steps.issue-parser.outputs.issueparser_parentKey }}" + } + } + + - name: Log created issue + run: echo "Jira Issue ${{ steps.issue-parser.outputs.issueparser_parentKey }}/${{ steps.create.outputs.issue }} was created" + + - name: Checkout develop code + uses: actions/checkout@v4 + with: + ref: develop + + - name: Create branch with Ticket number and type + run: | + ISSUE_NUMBER="${{ steps.create.outputs.issue }}" + BRANCH_TYPE="${{ steps.issue-parser.outputs.issueparser_branchType }}" + ISSUE_TITLE="${{ steps.issue-parser.outputs.issueparser_branch }}" + SLUG_TITLE=$(echo "${ISSUE_TITLE}" | sed 's/ /-/g' | tr '[:upper:]' '[:lower:]') + BRANCH_NAME="${BRANCH_TYPE}/${ISSUE_NUMBER}-${SLUG_TITLE}" + git checkout -b "${BRANCH_NAME}" + git push origin "${BRANCH_NAME}" + + - 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 }}' + + - name: Add comment with Jira issue link + uses: actions-cool/issues-helper@v3 + with: + actions: 'create-comment' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: 'Jira Issue Created: [${{ steps.create.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create.outputs.issue }})' diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 00000000..f325f862 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,164 @@ +name: Fanzip Server CI/CD with Docker + +on: + push: + branches: ['develop'] # main 브랜치에 push할 때 실행 + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + # Spring Legacy Build (WAR) + - name: Make gradlew executable + run: chmod +x ./gradlew + + - name: Spring Legacy Build + run: ./gradlew clean build -x test + + # Docker Image Build + - name: Docker Image Build + run: docker build -t ekhanz/fanzip-server . + + # DockerHub Login + - name: Docker Hub Login + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # Docker Hub push + - name: Docker Hub Push + run: docker push ekhanz/fanzip-server + + # GET GitHub IP + - name: Get GitHub IP + id: ip + uses: haythem/public-ip@v1.2 + + # Configure AWS Credentials + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ap-northeast-2 + + - name: Add GitHub IP to AWS + run: | + echo "Using Security Group ID: ${{ secrets.AWS_SG_ID }}" + echo "Current AWS Account:" + aws sts get-caller-identity + echo "Available Security Groups:" + aws ec2 describe-security-groups --query 'SecurityGroups[*].[GroupId,GroupName]' --output table + aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32 + + # Deploy to EC2 with environment variables + - name: Deploy to EC2 + uses: appleboy/ssh-action@v0.1.7 + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USERNAME }} + key: ${{ secrets.EC2_PRIVATE_KEY }} + port: ${{ secrets.EC2_SSH_PORT }} + timeout: 120s + script: | + # 현재 위치 확인 + echo "=== 현재 디렉토리 ===" + pwd + ls -la + + # 환경변수 파일 생성 + echo "=== .env 파일 생성 ===" + cat > .env << 'EOF' + JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} + DB_URL=${{ secrets.DB_URL }} + DB_USERNAME=${{ secrets.DB_USERNAME }} + DB_PASSWORD=${{ secrets.DB_PASSWORD }} + KAKAO_CLIENT_ID=${{ secrets.KAKAO_CLIENT_ID }} + KAKAO_REDIRECT_URI=${{ secrets.KAKAO_REDIRECT_URI }} + TOSS_PAYMENTS_CLIENT_KEY=${{ secrets.TOSS_PAYMENTS_CLIENT_KEY }} + TOSS_PAYMENTS_SECRET_KEY=${{ secrets.TOSS_PAYMENTS_SECRET_KEY }} + FIREBASE_CREDENTIALS_PATH=${{ secrets.FIREBASE_CREDENTIALS_PATH }} + FIREBASE_PROJECT_ID=${{ secrets.FIREBASE_PROJECT_ID }} + FIREBASE_CREDENTIALS_JSON=${{ secrets.FIREBASE_CREDENTIALS_JSON }} + aws.access-key=${{ secrets.AWS_ACCESS_KEY_ID }} + aws.secret-key=${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws.region=ap-northeast-2 + EOF + + # .env 파일 생성 확인 + echo "=== .env 파일 확인 ===" + ls -la .env + head -3 .env + + # Docker Compose 파일 생성 + echo "=== docker-compose.yml 파일 생성 ===" + cat > docker-compose.yml << 'EOF' + version: '3.8' + services: + redis: + image: redis:7-alpine + container_name: fanzip-redis + ports: + - "6379:6379" + volumes: + - redis_data:/data + restart: unless-stopped + command: redis-server --appendonly yes + + app: + image: ekhanz/fanzip-server + container_name: fanzip-server + ports: + - "8080:8080" + depends_on: + - redis + env_file: + - .env + environment: + - REDIS_HOST=redis + - REDIS_PORT=6379 + restart: unless-stopped + + volumes: + redis_data: + EOF + + # docker-compose.yml 파일 생성 확인 + echo "=== docker-compose.yml 파일 확인 ===" + ls -la docker-compose.yml + echo "=== docker-compose.yml 내용 확인 ===" + cat docker-compose.yml + + # 기존 컨테이너들 정리 + sudo docker stop fanzip-redis fanzip-server || true + sudo docker rm fanzip-redis fanzip-server || true + sudo docker-compose down || true + + # 최신 이미지 다운로드 + sudo docker pull ekhanz/fanzip-server + + # Docker Compose로 서비스 시작 + sudo docker-compose up -d + + # 컨테이너 상태 확인 + sudo docker ps + + # 환경변수 확인 (보안상 일부만) + echo "=== 환경변수 확인 ===" + sudo docker exec fanzip-server env | grep -E "FIREBASE_PROJECT_ID|DB_URL" | head -2 + + # Remove GitHub IP from Security Group + - name: Remove IP FROM security group + run: | + aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32 diff --git a/.gitignore b/.gitignore index ae118677..acc76a64 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ build/ !**/src/test/**/build/ ### IntelliJ IDEA ### +.idea .idea/modules.xml .idea/jarRepositories.xml .idea/compiler.xml @@ -42,4 +43,15 @@ bin/ .DS_Store ### 환경 변수 ### -.env \ No newline at end of file +.env + +# workspace.xml 로컬 설정 파일 +.idea/workspace.xml + +### 설정 파일 ### +src/main/resources/application.yml +.claude/settings.local.json + + +### firebase 설정 파일 +src/main/resources/firebase/service-account.json \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index ce1c62c7..f2c1963c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -5,6 +5,7 @@