스탠드업을 없애자
어제의 Linear 이슈와 GitHub 커밋을 읽습니다. 스탠드업 업데이트를 포맷합니다. Slack에 게시합니다.
1단계: 설정 확인
필수 환경 변수가 설정되었는지 확인합니다:
echo "LINEAR_API_KEY: ${LINEAR_API_KEY:+set}"
echo "SLACK_WEBHOOK_URL: ${SLACK_WEBHOOK_URL:+set}"
echo "GITHUB_REPO: ${GITHUB_REPO:-not set}"
echo "GITHUB_USERNAME: ${GITHUB_USERNAME:-not set}"
LINEAR_API_KEY가 없으면: 중단합니다. 사용자에게 다음과 같이 알립니다: "LINEAR_API_KEY가 필요합니다. Linear → 설정 → API → Personal API keys에서 가져와 .env 파일에 추가하세요."
SLACK_WEBHOOK_URL이 없으면: 중단합니다. 사용자에게 다음과 같이 알립니다: "SLACK_WEBHOOK_URL이 필요합니다. api.slack.com/apps → Your App → Incoming Webhooks에서 Incoming Webhook을 생성하여 .env 파일에 추가하세요."
GITHUB_REPO가 없으면: 계속 진행합니다. GitHub 커밋은 건너뜁니다. 이 점을 사용자에게 알립니다.
2단계: Linear 활동 가져오기
어제 날짜를 ISO 8601 형식(예: 2026-04-09T00:00:00.000Z)으로 계산합니다.
현재 사용자 ID 가져오기:
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: Bearer $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "query { viewer { id name email } }"}'
응답에서 id 필드를 추출합니다. LINEAR_USER_ID로 저장합니다.
나에게 할당되고 어제 이후 업데이트된 이슈 가져오기:
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: Bearer $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "query($since: DateTime!, $userId: ID!) { issues(first: 50, filter: { assignee: { id: { eq: $userId } } updatedAt: { gte: $since } }) { edges { node { identifier title state { name } url completedAt updatedAt createdAt } } } }",
"variables": {"since": "YESTERDAY_ISO", "userId": "LINEAR_USER_ID"}
}'
이슈 분류:
completedAt이 null이 아님 → 완료state.name이 "In Progress", "Started", 또는 "In Review" → 진행 중state.name이 "Cancelled" → 건너뜀state.name이 "Todo" 또는 "Backlog" → 건너뜀(작업하지 않음)
이슈가 0개인 경우: "어제 Linear 활동이 없습니다."라고 기록합니다.
3단계: GitHub 커밋 가져오기
GITHUB_REPO가 설정되지 않은 경우 이 단계를 조용히 건너뜁니다.
GITHUB_REPO가 설정된 경우:
gh api "repos/$GITHUB_REPO/commits?author=${GITHUB_USERNAME:-$(gh api user --jq .login)}&since=YESTERDAY_ISO&per_page=30" \
--jq '[.[] | {message: .commit.message, url: .html_url}]'
커밋 처리:
- 각 커밋 메시지의 첫 번째 줄(첫 번째 줄바꿈 앞까지)을 추출합니다.
- 병합 커밋 건너뛰기: "Merge"로 시작하는 메시지는 제거합니다.
- 메시지 텍스트로 중복 제거합니다.
GITHUB_REPO가 설정되었지만 커밋이 0개 반환된 경우: "어제 커밋이 없습니다."라고 기록합니다.
4단계: 스탠드업 포맷팅
작성 전에 references/standup-format.md를 전체 읽습니다.
다음 정확한 구조로 스탠드업을 생성합니다:
**완료**
- [ENG-123] 완료된 이슈 제목
- fix: 커밋 메시지
**진행 중**
- [ENG-124] 진행 중인 이슈 제목
**차단**
차단 없음.
standup-format.md의 규칙:
- 1인칭 대명사("나", "저희") 사용 금지
- 완료 항목은 과거형, 진행 중 항목은 현재 진행형
- 각 Linear 항목은
[IDENTIFIER] 제목형식 사용 - 각 GitHub 커밋은 커밋 메시지의 첫 번째 줄 사용
- 완료 항목이 없으면 "완료" 아래에 "완료된 항목 없음." 작성
- 진행 중 항목이 없으면 "진행 중" 아래에 "진행 중인 항목 없음." 작성
- 차단 항목이 없으면 "차단 없음." 작성
- 총 200단어 미만
5단계: Slack에 게시 또는 출력
포맷된 스탠드업을 사용자에게 제시합니다.
"이 내용을 Slack에 게시할까요, 아니면 출력만 할까요?"라고 묻습니다.
게시 확인 시:
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*스탠드업 — DATE_HERE*\n\n*완료*\nITEMS\n\n*진행 중*\nITEMS\n\n*차단*\nITEMS"
}
}
]
}'
커밋 메시지나 이슈 제목의 특수 문자로 인한 셸 따옴표 문제를 피하기 위해 임시 파일 또는 heredoc을 사용하여 본문을 전달합니다:
cat > /tmp/standup-payload.json << 'ENDJSON'
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "STANDUP_CONTENT_HERE"
}
}
]
}
ENDJSON
curl -s -X POST "$SLACK_WEBHOOK_URL" -H "Content-Type: application/json" -d @/tmp/standup-payload.json
게시 후: "스탠드업이 게시되었습니다."
"출력만" 선택 시: 복사하여 붙여넣을 수 있도록 코드 블록 안에 스탠드업을 출력합니다.