gitea, notion webhook
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
4.0 KiB

4 months ago
# slack-notifier
Gitea webhook · Notion webhook 알림을 받아 **담당자에게 Slack 개인 DM**으로 보내는 중계 서버.
- 담당자 매핑: 이메일 자동 매칭(Gitea/Notion 이메일 → Slack `users.lookupByEmail`) + **수동 매핑 보강**(관리 페이지)
- 스택: **Go + Gin** (저사양 환경 대응, 단일 정적 바이너리), 관리 UI는 html/template + HTMX
```
[Gitea] ──webhook──┐
├─▶ slack-notifier ─▶ (매핑 해석) ─▶ users.lookupByEmail ─▶ chat.postMessage(DM)
[Notion] ─webhook──┘ (서명검증) 자동+수동 이메일→Slack ID
```
## 빠른 시작 (로컬)
Go는 [mise](https://mise.jdx.dev)로 관리합니다 (`mise use go@1.26`).
```bash
cd slack-notifier
cp .env.example .env # 값 채우기
go run . # 기본 :8000
```
- 헬스체크: `curl localhost:8000/health`
- 관리 페이지: 브라우저로 `http://localhost:8000/admin/mappings`
- 테스트: `go test ./...`
- 빌드: `go build -o slack-notifier .`
Docker:
```bash
docker compose up --build # distroless 기반 경량 이미지
```
## 엔드포인트
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | `/health` | 헬스체크 |
| POST | `/webhooks/gitea` | Gitea webhook 수신 |
| POST | `/webhooks/notion` | Notion webhook 수신 (+ 최초 검증 핸드셰이크) |
| GET | `/admin/mappings` | 유저 매핑 관리 페이지 |
| POST | `/admin/mappings` | 매핑 추가 (HTMX) |
| DELETE | `/admin/mappings/:source` | 매핑 삭제 (HTMX) |
## 담당자 매핑
1. **자동(이메일)**: Gitea/Notion 이벤트의 이메일을 그대로 Slack에서 조회.
2. **수동(오버라이드)**: `/admin/mappings`에서 `소스(이메일 또는 로그인) → Slack 이메일`을 등록.
시스템 간 이메일이 다르거나 자동 조회가 안 될 때 보강. `data/mappings.json`에 저장됨.
3. 그래도 못 찾으면 `DEFAULT_SLACK_CHANNEL`로 fallback(설정 시), 없으면 skip.
## Slack 앱 준비
1. https://api.slack.com/apps 에서 앱 생성 → **Bot Token Scopes**: `chat:write`, `users:read.email`, `im:write`
2. 워크스페이스에 설치 후 **Bot User OAuth Token**(`xoxb-...`)을 `SLACK_BOT_TOKEN`에 설정
## Gitea 설정
저장소/조직 → Settings → Webhooks → Add Webhook (Gitea)
- **Target URL**: `https://<배포주소>/webhooks/gitea`
- **Secret**: `GITEA_WEBHOOK_SECRET`와 동일하게 입력 (HMAC-SHA256 서명 검증)
처리하는 이벤트 → 담당자:
| 이벤트 | 알림 대상 |
|--------|-----------|
| PR `assigned` / `opened` / `reopened` | 담당자(assignees) |
| PR `review_requested` | 리뷰어 |
| PR `closed`(merged) | PR 작성자 |
| PR review 등록 | PR 작성자 |
| 이슈 `assigned` | 담당자 |
| 이슈/PR 댓글 | 담당자 + 작성자 (댓글 단 본인 제외) |
> 그 외 이벤트(예: push)는 기본 무시. 필요하면 `internal/gitea/gitea.go`에 핸들러를 추가하세요.
## Notion 설정
1. **Integration** 생성 → `NOTION_API_TOKEN` 설정, 대상 DB/페이지에 integration 연결(공유)
2. Notion **Webhook subscription** 생성 → endpoint `https://<배포주소>/webhooks/notion`
3. 최초 구독 시 Notion이 `verification_token`을 POST → 서버 로그에 출력됨 → `NOTION_VERIFICATION_TOKEN`에 넣고 재시작
4. 알림 대상은 페이지의 **People 속성들**(`NOTION_ASSIGNEE_PROPERTY`, 콤마 구분, 기본 `담당자,처리자,참조인원`)에서 읽어 이메일로 매핑. 여러 속성의 인원을 합쳐(중복 제거) 모두에게 발송. 본문/댓글에서 **@멘션된 사람**도 수신자에 추가됨(작성자 본인 제외).
4 months ago
## 저사양 배포 메모
- 단일 정적 바이너리(distroless 이미지 ~10MB대), idle 메모리 수십 MB 수준.
- 메모리가 빠듯하면 `GOMEMLIMIT=200MiB` 등으로 상한을 줄 수 있음(README/`.env.example` 참고).
- webhook 수신을 위해 외부 접근 가능한 HTTPS 엔드포인트 필요. 로컬 테스트는 `ngrok http 8000` 같은 터널 사용.