Skip to content
Merged
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
197 changes: 197 additions & 0 deletions .github/workflows/wrapup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
name: Wrapup 📦

on:
schedule:
# 매주 일요일 오전 10시 (KST 기준, UTC로는 일요일 1시)
- cron: "0 1 * * 0"
workflow_dispatch:
inputs:
date:
description: "마무리할 주차에 속한 날짜 (비워두면 어제, KST 기준)"
required: false
type: string
default: ""
exclude_prs:
description: 'PR numbers to exclude (comma-separated, e.g., "1972,1973")'
required: false
type: string
default: ""
skip_release:
description: "릴리즈 생성 건너뛰기"
required: false
type: boolean
default: false

jobs:
wrapup:
name: Wrap Up the Week 📦
runs-on: ubuntu-latest
permissions:
contents: write # 릴리즈 생성

steps:
- name: Resolve target week
id: week
env:
DATE_INPUT: ${{ inputs.date }}
run: |
date="${DATE_INPUT:-$(TZ=Asia/Seoul date -d yesterday +%F)}"
echo "🗓️ 대상 날짜: $date"

response=$(curl -sS -X POST "https://github.dalestudy.com/resolve-iteration" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg date "$date" '{date: $date}')")

echo "$response" | jq '.'

if [ "$(echo "$response" | jq -r '.success // false')" != "true" ]; then
echo "::error::주차 조회에 실패했습니다"
exit 1
fi

found=$(echo "$response" | jq -r '.found')
echo "found=$found" >> $GITHUB_OUTPUT

if [ "$found" != "true" ]; then
{
echo "## 📦 마무리할 주차가 없습니다"
echo ""
echo "\`$date\`이(가) 어느 주차에도 속하지 않습니다. 기수 사이 휴식기입니다."
} >> $GITHUB_STEP_SUMMARY
exit 0
fi

cohort=$(echo "$response" | jq -r '.cohort')
week=$(echo "$response" | jq -r '.week')

{
echo "week_label=$(echo "$response" | jq -r '.week_label')"
echo "tag=v${cohort}.${week}.0"
echo "period=$(echo "$response" | jq -r '"\(.start_date) ~ \(.end_date)"')"
} >> $GITHUB_OUTPUT

- name: Build exclude list
id: excludes
if: steps.week.outputs.found == 'true'
env:
EXCLUDE_PRS: ${{ inputs.exclude_prs }}
run: |
if [ -z "$EXCLUDE_PRS" ]; then
echo "json=[]" >> $GITHUB_OUTPUT
exit 0
fi

if ! echo "$EXCLUDE_PRS" | grep -qE '^[0-9]+(,[0-9]+)*$'; then
echo "::error::exclude_prs 형식이 잘못되었습니다: $EXCLUDE_PRS"
exit 1
fi

echo "json=[$EXCLUDE_PRS]" >> $GITHUB_OUTPUT

- name: Approve PRs
id: approve
if: steps.week.outputs.found == 'true'
env:
WEEK_LABEL: ${{ steps.week.outputs.week_label }}
EXCLUDES: ${{ steps.excludes.outputs.json }}
REPO_NAME: ${{ github.event.repository.name }}
run: |
echo "👍 ${WEEK_LABEL} PR 승인 중..."

response=$(curl -sS -X POST "https://github.dalestudy.com/approve-prs" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg repo "$REPO_NAME" --arg week "$WEEK_LABEL" \
--argjson excludes "$EXCLUDES" \
'{repo_name: $repo, week: $week, excludes: $excludes}')")

echo "$response" | jq '.'
echo "response=$(echo "$response" | jq -c '.')" >> $GITHUB_OUTPUT

if [ "$(echo "$response" | jq -r '.success // false')" != "true" ]; then
echo "::error::승인 요청에 실패했습니다"
exit 1
fi

- name: Merge PRs
id: merge
if: steps.week.outputs.found == 'true'
env:
WEEK_LABEL: ${{ steps.week.outputs.week_label }}
EXCLUDES: ${{ steps.excludes.outputs.json }}
REPO_NAME: ${{ github.event.repository.name }}
run: |
echo "🚀 ${WEEK_LABEL} PR 병합 중..."

response=$(curl -sS -X POST "https://github.dalestudy.com/merge-prs" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg repo "$REPO_NAME" --arg week "$WEEK_LABEL" \
--argjson excludes "$EXCLUDES" \
'{repo_name: $repo, week: $week, merge_method: "squash", excludes: $excludes}')")

echo "$response" | jq '.'
echo "response=$(echo "$response" | jq -c '.')" >> $GITHUB_OUTPUT

if [ "$(echo "$response" | jq -r '.success // false')" != "true" ]; then
echo "::error::병합 요청에 실패했습니다"
exit 1
fi

- name: Create release
id: release
if: steps.week.outputs.found == 'true' && inputs.skip_release != true
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
TAG: ${{ steps.week.outputs.tag }}
run: |
if gh release view "$TAG" --repo "$REPO" > /dev/null 2>&1; then
echo "⏭️ ${TAG} 릴리즈가 이미 있어 건너뜁니다"
exit 0
fi

echo "🏷️ ${TAG} 릴리즈 생성 중..."
gh release create "$TAG" --repo "$REPO" \
--target main --title "$TAG" --generate-notes

- name: Summary
if: steps.week.outputs.found == 'true'
env:
WEEK_LABEL: ${{ steps.week.outputs.week_label }}
PERIOD: ${{ steps.week.outputs.period }}
TAG: ${{ steps.week.outputs.tag }}
APPROVE_RESPONSE: ${{ steps.approve.outputs.response }}
MERGE_RESPONSE: ${{ steps.merge.outputs.response }}
REPO: ${{ github.repository }}
run: |
# 자동 처리 대상이 아닌 PR은 미해결로 세지 않는다
normal_skip='.reason == "draft PR"'
unresolved_filter=".results[]? | select(.merged != true) | select($normal_skip | not)"

approved=$(echo "$APPROVE_RESPONSE" | jq -r '.approved')
merged=$(echo "$MERGE_RESPONSE" | jq -r '.merged')
matched=$(echo "$MERGE_RESPONSE" | jq -r '.week_matched')
solving=$(echo "$MERGE_RESPONSE" | jq -r '.solving_excluded')

{
echo "## 📦 ${WEEK_LABEL} 마무리"
echo ""
echo "- 🗓️ 기간: ${PERIOD}"
echo "- 📋 대상 PR: **${matched}**개 (Solving 제외 ${solving}개)"
echo "- 👍 승인: **${approved}**개"
echo "- 🚀 병합: **${merged}**개"
echo "- 🏷️ 릴리즈: [${TAG}](https://github.com/${REPO}/releases/tag/${TAG})"
} >> $GITHUB_STEP_SUMMARY

unresolved=$(echo "$MERGE_RESPONSE" | jq "[$unresolved_filter] | length")

if [ "$unresolved" -gt 0 ]; then
{
echo ""
echo "### ⚠️ 병합되지 않은 PR"
echo ""
echo "$MERGE_RESPONSE" | jq -r "$unresolved_filter | \"- #\(.pr) \(.title) — \(.reason // .error // \"unknown\")\""
} >> $GITHUB_STEP_SUMMARY

echo "::error::병합되지 않은 PR ${unresolved}건 — 직접 확인이 필요합니다"
exit 1
fi
Loading