sdd-tool 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ /**
2
+ * SDD 프로젝트용 commitlint 설정
3
+ *
4
+ * 사용법:
5
+ * 1. 이 파일을 프로젝트 루트에 복사
6
+ * 2. npm install --save-dev @commitlint/cli
7
+ * 3. Git hooks에서 commitlint 실행
8
+ */
9
+
10
+ module.exports = {
11
+ extends: ['@commitlint/config-conventional'],
12
+
13
+ // 스펙 커밋 타입 추가
14
+ rules: {
15
+ 'type-enum': [
16
+ 2,
17
+ 'always',
18
+ [
19
+ // SDD 스펙 타입
20
+ 'spec', // 스펙 신규 생성
21
+ 'spec-update', // 스펙 내용 수정
22
+ 'spec-status', // 스펙 상태 변경
23
+ 'plan', // 구현 계획
24
+ 'tasks', // 작업 분해
25
+ 'constitution', // Constitution 변경
26
+ 'sdd-config', // SDD 설정 변경
27
+
28
+ // Conventional Commits 타입
29
+ 'feat', // 새 기능
30
+ 'fix', // 버그 수정
31
+ 'docs', // 문서 변경
32
+ 'style', // 코드 포맷팅
33
+ 'refactor', // 리팩토링
34
+ 'perf', // 성능 개선
35
+ 'test', // 테스트
36
+ 'build', // 빌드 시스템
37
+ 'ci', // CI 설정
38
+ 'chore', // 기타 작업
39
+ 'revert', // 되돌리기
40
+ ],
41
+ ],
42
+
43
+ // 스코프 형식: 영문 소문자, 하이픈, 슬래시, 쉼표, 별표 허용
44
+ 'scope-case': [2, 'always', 'lower-case'],
45
+ 'scope-empty': [0], // 스코프는 선택사항
46
+
47
+ // 제목 규칙
48
+ 'subject-case': [0], // 케이스 제한 없음 (한글 허용)
49
+ 'subject-empty': [2, 'never'],
50
+ 'subject-max-length': [2, 'always', 50],
51
+
52
+ // 본문 규칙
53
+ 'body-max-line-length': [2, 'always', 72],
54
+
55
+ // 헤더 규칙
56
+ 'header-max-length': [2, 'always', 72],
57
+ },
58
+
59
+ // 에러 메시지 한글화
60
+ prompt: {
61
+ messages: {
62
+ skip: '(엔터로 건너뛰기)',
63
+ max: '최대 %d자',
64
+ min: '최소 %d자',
65
+ emptyWarning: '비어있으면 안 됩니다',
66
+ upperLimitWarning: '글자 수 초과',
67
+ lowerLimitWarning: '글자 수 부족',
68
+ },
69
+ questions: {
70
+ type: {
71
+ description: '커밋 유형을 선택하세요',
72
+ enum: {
73
+ spec: { description: '스펙 신규 생성', title: 'Spec' },
74
+ 'spec-update': { description: '스펙 내용 수정', title: 'Spec Update' },
75
+ 'spec-status': { description: '스펙 상태 변경', title: 'Spec Status' },
76
+ plan: { description: '구현 계획', title: 'Plan' },
77
+ tasks: { description: '작업 분해', title: 'Tasks' },
78
+ constitution: { description: 'Constitution 변경', title: 'Constitution' },
79
+ 'sdd-config': { description: 'SDD 설정 변경', title: 'SDD Config' },
80
+ feat: { description: '새 기능', title: 'Feature' },
81
+ fix: { description: '버그 수정', title: 'Fix' },
82
+ docs: { description: '문서 변경', title: 'Docs' },
83
+ style: { description: '코드 포맷팅', title: 'Style' },
84
+ refactor: { description: '리팩토링', title: 'Refactor' },
85
+ perf: { description: '성능 개선', title: 'Perf' },
86
+ test: { description: '테스트', title: 'Test' },
87
+ build: { description: '빌드 시스템', title: 'Build' },
88
+ ci: { description: 'CI 설정', title: 'CI' },
89
+ chore: { description: '기타 작업', title: 'Chore' },
90
+ revert: { description: '되돌리기', title: 'Revert' },
91
+ },
92
+ },
93
+ scope: {
94
+ description: '스코프를 입력하세요 (예: auth, auth/user-login)',
95
+ },
96
+ subject: {
97
+ description: '간결한 변경 설명을 입력하세요',
98
+ },
99
+ body: {
100
+ description: '상세한 변경 설명을 입력하세요 (선택)',
101
+ },
102
+ isBreaking: {
103
+ description: 'Breaking Change가 있나요?',
104
+ },
105
+ breakingBody: {
106
+ description: 'Breaking Change 상세 내용을 입력하세요',
107
+ },
108
+ breaking: {
109
+ description: 'Breaking Change 요약을 입력하세요',
110
+ },
111
+ isIssueAffected: {
112
+ description: '관련 이슈가 있나요?',
113
+ },
114
+ issuesBody: {
115
+ description: '이슈 참조 (예: Refs: #123)',
116
+ },
117
+ issues: {
118
+ description: '이슈 번호를 입력하세요',
119
+ },
120
+ },
121
+ },
122
+ };
@@ -0,0 +1,194 @@
1
+ # GitHub Branch Protection 설정 가이드
2
+
3
+ SDD 프로젝트에 권장하는 브랜치 보호 규칙입니다.
4
+
5
+ ## 설정 위치
6
+
7
+ Repository → Settings → Branches → Add branch protection rule
8
+
9
+ ---
10
+
11
+ ## main 브랜치 규칙
12
+
13
+ ### Branch name pattern
14
+ ```
15
+ main
16
+ ```
17
+
18
+ ### 권장 설정
19
+
20
+ #### Protect matching branches
21
+
22
+ - [x] **Require a pull request before merging**
23
+ - [x] Require approvals: `2`
24
+ - [x] Dismiss stale pull request approvals when new commits are pushed
25
+ - [x] Require review from Code Owners
26
+ - [ ] Restrict who can dismiss pull request reviews
27
+
28
+ - [x] **Require status checks to pass before merging**
29
+ - [x] Require branches to be up to date before merging
30
+ - Status checks:
31
+ - `sdd-validate`
32
+ - `sdd-lint` (있는 경우)
33
+
34
+ - [x] **Require conversation resolution before merging**
35
+
36
+ - [ ] **Require signed commits** (선택)
37
+
38
+ - [x] **Require linear history** (권장)
39
+
40
+ - [ ] **Require merge queue** (대규모 팀)
41
+
42
+ - [ ] **Require deployments to succeed** (CI/CD)
43
+
44
+ #### Rules applied to everyone including administrators
45
+
46
+ - [x] **Do not allow bypassing the above settings**
47
+
48
+ ---
49
+
50
+ ## constitution/* 브랜치 규칙
51
+
52
+ ### Branch name pattern
53
+ ```
54
+ constitution/*
55
+ ```
56
+
57
+ ### 권장 설정
58
+
59
+ - [x] **Require a pull request before merging**
60
+ - [x] Require approvals: `3` (더 많은 리뷰어)
61
+ - [x] Dismiss stale pull request approvals
62
+
63
+ - [x] **Require status checks to pass**
64
+ - `sdd-validate`
65
+ - `constitution-check` (있는 경우)
66
+
67
+ - [x] **Restrict who can push**
68
+ - 팀 리드, 아키텍트만
69
+
70
+ ---
71
+
72
+ ## spec/* 브랜치 규칙 (선택)
73
+
74
+ 작업 중인 스펙 브랜치는 보통 보호하지 않습니다.
75
+ 필요한 경우 아래 규칙을 적용할 수 있습니다.
76
+
77
+ ### Branch name pattern
78
+ ```
79
+ spec/*
80
+ ```
81
+
82
+ ### 최소 설정 (선택)
83
+
84
+ - [ ] Require a pull request (불필요)
85
+ - [ ] Require status checks (불필요)
86
+ - [x] **Allow force pushes** (히스토리 정리용)
87
+ - [x] **Allow deletions** (병합 후 삭제)
88
+
89
+ ---
90
+
91
+ ## CODEOWNERS 설정
92
+
93
+ `.github/CODEOWNERS` 파일을 생성하여 도메인별 리뷰어를 지정합니다.
94
+
95
+ ```
96
+ # SDD 스펙 파일 오너십
97
+
98
+ # 전역 스펙 관리자
99
+ .sdd/ @sdd-maintainers
100
+
101
+ # Constitution은 리드만
102
+ .sdd/constitution.md @tech-leads @architects
103
+
104
+ # 도메인별 오너
105
+ .sdd/specs/auth/ @security-team
106
+ .sdd/specs/billing/ @billing-team
107
+ .sdd/specs/core/ @core-team
108
+
109
+ # 도메인 설정
110
+ .sdd/domains.yml @sdd-maintainers
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 상태 체크 설정
116
+
117
+ ### GitHub Actions 워크플로우
118
+
119
+ `.github/workflows/sdd-validate.yml` 파일이 있어야 상태 체크가 활성화됩니다.
120
+
121
+ ```yaml
122
+ name: SDD Validate
123
+
124
+ on:
125
+ pull_request:
126
+ paths:
127
+ - '.sdd/**'
128
+
129
+ jobs:
130
+ validate:
131
+ runs-on: ubuntu-latest
132
+ steps:
133
+ - uses: actions/checkout@v4
134
+ - name: Setup Node
135
+ uses: actions/setup-node@v4
136
+ with:
137
+ node-version: '20'
138
+ - name: Install SDD
139
+ run: npm install -g sdd-tool
140
+ - name: Validate Specs
141
+ run: sdd validate --ci
142
+ ```
143
+
144
+ ### 상태 체크 추가 방법
145
+
146
+ 1. 워크플로우 실행 후 (최소 1번)
147
+ 2. Settings → Branches → main 규칙 편집
148
+ 3. "Require status checks" 섹션
149
+ 4. 검색창에 `sdd-validate` 입력
150
+ 5. 체크 추가
151
+
152
+ ---
153
+
154
+ ## 빠른 설정 체크리스트
155
+
156
+ ### main 브랜치
157
+ - [ ] Require PR with 2 approvals
158
+ - [ ] Dismiss stale reviews
159
+ - [ ] Require status checks (sdd-validate)
160
+ - [ ] Require up-to-date branches
161
+ - [ ] Require linear history
162
+
163
+ ### constitution/* 브랜치
164
+ - [ ] Require PR with 3 approvals
165
+ - [ ] Restrict push to leads only
166
+
167
+ ### 추가 설정
168
+ - [ ] CODEOWNERS 파일 생성
169
+ - [ ] GitHub Actions 워크플로우 추가
170
+ - [ ] 자동 브랜치 삭제 활성화
171
+
172
+ ---
173
+
174
+ ## 문제 해결
175
+
176
+ ### "Status check not found"
177
+
178
+ 상태 체크가 보이지 않으면:
179
+ 1. 워크플로우가 최소 1번 실행되어야 함
180
+ 2. PR을 `.sdd/` 경로 변경으로 생성
181
+ 3. 워크플로우 이름 확인 (`sdd-validate`)
182
+
183
+ ### "Required reviews not satisfied"
184
+
185
+ 리뷰 수가 부족하면:
186
+ 1. 팀원에게 리뷰 요청
187
+ 2. CODEOWNERS에 정의된 오너 확인
188
+ 3. 본인 승인은 카운트 안 됨
189
+
190
+ ### Force push 필요
191
+
192
+ 보호된 브랜치에 force push가 필요하면:
193
+ 1. 임시로 규칙 비활성화
194
+ 2. 또는 새 브랜치에서 작업 후 PR
@@ -0,0 +1,125 @@
1
+ # SDD PR 라벨러 워크플로우
2
+ # 변경된 도메인에 따라 자동으로 라벨을 추가합니다
3
+
4
+ name: SDD Labeler
5
+
6
+ on:
7
+ pull_request:
8
+ types: [opened, synchronize]
9
+ paths:
10
+ - '.sdd/**'
11
+
12
+ jobs:
13
+ label:
14
+ name: Add Labels
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0
22
+
23
+ - name: Detect Changes
24
+ id: changes
25
+ run: |
26
+ # 변경된 도메인 감지
27
+ DOMAINS=$(git diff --name-only origin/${{ github.base_ref }} | \
28
+ grep "^\.sdd/specs/" | \
29
+ cut -d'/' -f3 | \
30
+ sort -u | \
31
+ tr '\n' ' ')
32
+ echo "domains=$DOMAINS" >> $GITHUB_OUTPUT
33
+
34
+ # Constitution 변경 감지
35
+ if git diff --name-only origin/${{ github.base_ref }} | grep -q "constitution.md"; then
36
+ echo "constitution=true" >> $GITHUB_OUTPUT
37
+ else
38
+ echo "constitution=false" >> $GITHUB_OUTPUT
39
+ fi
40
+
41
+ # 스펙 변경 타입 감지
42
+ ADDED=$(git diff --name-only --diff-filter=A origin/${{ github.base_ref }} | grep "^\.sdd/specs/" | wc -l)
43
+ MODIFIED=$(git diff --name-only --diff-filter=M origin/${{ github.base_ref }} | grep "^\.sdd/specs/" | wc -l)
44
+ DELETED=$(git diff --name-only --diff-filter=D origin/${{ github.base_ref }} | grep "^\.sdd/specs/" | wc -l)
45
+
46
+ if [ "$ADDED" -gt 0 ]; then
47
+ echo "has_added=true" >> $GITHUB_OUTPUT
48
+ fi
49
+ if [ "$MODIFIED" -gt 0 ]; then
50
+ echo "has_modified=true" >> $GITHUB_OUTPUT
51
+ fi
52
+ if [ "$DELETED" -gt 0 ]; then
53
+ echo "has_deleted=true" >> $GITHUB_OUTPUT
54
+ fi
55
+
56
+ - name: Create Labels if Not Exist
57
+ uses: actions/github-script@v7
58
+ with:
59
+ script: |
60
+ const domains = '${{ steps.changes.outputs.domains }}'.trim().split(' ').filter(Boolean);
61
+
62
+ const labelConfigs = [
63
+ ...domains.map(d => ({ name: `spec:${d}`, color: '0366d6', description: `${d} 도메인 스펙` })),
64
+ { name: 'constitution', color: 'b60205', description: 'Constitution 변경' },
65
+ { name: 'spec:new', color: '0e8a16', description: '새 스펙 추가' },
66
+ { name: 'spec:update', color: 'fbca04', description: '스펙 수정' },
67
+ { name: 'spec:remove', color: 'd93f0b', description: '스펙 삭제' },
68
+ ];
69
+
70
+ for (const label of labelConfigs) {
71
+ try {
72
+ await github.rest.issues.getLabel({
73
+ owner: context.repo.owner,
74
+ repo: context.repo.repo,
75
+ name: label.name,
76
+ });
77
+ } catch (e) {
78
+ if (e.status === 404) {
79
+ await github.rest.issues.createLabel({
80
+ owner: context.repo.owner,
81
+ repo: context.repo.repo,
82
+ name: label.name,
83
+ color: label.color,
84
+ description: label.description,
85
+ });
86
+ }
87
+ }
88
+ }
89
+
90
+ - name: Apply Labels
91
+ uses: actions/github-script@v7
92
+ with:
93
+ script: |
94
+ const labels = [];
95
+
96
+ // 도메인 라벨
97
+ const domains = '${{ steps.changes.outputs.domains }}'.trim().split(' ').filter(Boolean);
98
+ labels.push(...domains.map(d => `spec:${d}`));
99
+
100
+ // Constitution 라벨
101
+ if ('${{ steps.changes.outputs.constitution }}' === 'true') {
102
+ labels.push('constitution');
103
+ }
104
+
105
+ // 변경 타입 라벨
106
+ if ('${{ steps.changes.outputs.has_added }}' === 'true') {
107
+ labels.push('spec:new');
108
+ }
109
+ if ('${{ steps.changes.outputs.has_modified }}' === 'true') {
110
+ labels.push('spec:update');
111
+ }
112
+ if ('${{ steps.changes.outputs.has_deleted }}' === 'true') {
113
+ labels.push('spec:remove');
114
+ }
115
+
116
+ if (labels.length > 0) {
117
+ await github.rest.issues.addLabels({
118
+ issue_number: context.issue.number,
119
+ owner: context.repo.owner,
120
+ repo: context.repo.repo,
121
+ labels: labels,
122
+ });
123
+
124
+ console.log(`Added labels: ${labels.join(', ')}`);
125
+ }
@@ -0,0 +1,85 @@
1
+ # SDD 스펙 검증 워크플로우
2
+ # .sdd/ 파일 변경 시 자동으로 스펙을 검증합니다
3
+
4
+ name: SDD Validate
5
+
6
+ on:
7
+ pull_request:
8
+ paths:
9
+ - '.sdd/**'
10
+ push:
11
+ branches:
12
+ - main
13
+ - master
14
+ paths:
15
+ - '.sdd/**'
16
+
17
+ jobs:
18
+ validate:
19
+ name: Validate Specs
20
+ runs-on: ubuntu-latest
21
+
22
+ steps:
23
+ - name: Checkout
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Setup Node.js
27
+ uses: actions/setup-node@v4
28
+ with:
29
+ node-version: '20'
30
+
31
+ - name: Install SDD Tool
32
+ run: npm install -g sdd-tool
33
+
34
+ - name: Validate Specs
35
+ run: sdd validate --ci
36
+
37
+ - name: Check Dependencies
38
+ run: sdd validate --ci || true
39
+ continue-on-error: true
40
+
41
+ - name: Constitution Check
42
+ run: sdd validate --constitution --ci || true
43
+ continue-on-error: true
44
+
45
+ - name: Comment on PR (failure)
46
+ if: failure() && github.event_name == 'pull_request'
47
+ uses: actions/github-script@v7
48
+ with:
49
+ script: |
50
+ github.rest.issues.createComment({
51
+ issue_number: context.issue.number,
52
+ owner: context.repo.owner,
53
+ repo: context.repo.repo,
54
+ body: `## ❌ SDD 검증 실패
55
+
56
+ 스펙 검증에서 오류가 발견되었습니다.
57
+
58
+ ### 확인 방법
59
+ \`\`\`bash
60
+ sdd validate
61
+ \`\`\`
62
+
63
+ ### 상세 로그
64
+ [Actions 로그 확인](${context.payload.pull_request?.html_url}/checks)
65
+
66
+ ---
67
+ *이 메시지는 자동으로 생성되었습니다.*`
68
+ })
69
+
70
+ - name: Comment on PR (success)
71
+ if: success() && github.event_name == 'pull_request'
72
+ uses: actions/github-script@v7
73
+ with:
74
+ script: |
75
+ github.rest.issues.createComment({
76
+ issue_number: context.issue.number,
77
+ owner: context.repo.owner,
78
+ repo: context.repo.repo,
79
+ body: `## ✅ SDD 검증 통과
80
+
81
+ 모든 스펙 검증을 통과했습니다.
82
+
83
+ ---
84
+ *이 메시지는 자동으로 생성되었습니다.*`
85
+ })
@@ -1,71 +1,71 @@
1
- ---
2
- id: CHG-{{ID}}
3
- status: draft
4
- created: {{DATE}}
5
- ---
6
-
7
- # 변경 제안: {{TITLE}}
8
-
9
- > 변경 목적 및 배경 설명
10
-
11
- ---
12
-
13
- ## 배경
14
-
15
- 왜 이 변경이 필요한가?
16
-
17
- ---
18
-
19
- ## 영향 범위
20
-
21
- ### 영향받는 스펙
22
-
23
- - `specs/{{SPEC_PATH}}`
24
-
25
- ### 변경 유형
26
-
27
- - [ ] 신규 추가 (ADDED)
28
- - [ ] 수정 (MODIFIED)
29
- - [ ] 삭제 (REMOVED)
30
-
31
- ---
32
-
33
- ## 변경 내용
34
-
35
- ### ADDED
36
-
37
- (새로 추가되는 내용)
38
-
39
- ### MODIFIED
40
-
41
- (수정되는 내용)
42
-
43
- #### Before
44
-
45
- ```markdown
46
- 기존 내용
47
- ```
48
-
49
- #### After
50
-
51
- ```markdown
52
- 변경된 내용
53
- ```
54
-
55
- ### REMOVED
56
-
57
- (삭제되는 내용)
58
-
59
- ---
60
-
61
- ## 리스크 평가
62
-
63
- - 영향도: 낮음/중간/높음
64
- - 복잡도: 낮음/중간/높음
65
-
66
- ---
67
-
68
- ## 검토자
69
-
70
- - [ ] @reviewer1
71
- - [ ] @reviewer2
1
+ ---
2
+ id: CHG-{{ID}}
3
+ status: draft
4
+ created: {{DATE}}
5
+ ---
6
+
7
+ # 변경 제안: {{TITLE}}
8
+
9
+ > 변경 목적 및 배경 설명
10
+
11
+ ---
12
+
13
+ ## 배경
14
+
15
+ 왜 이 변경이 필요한가?
16
+
17
+ ---
18
+
19
+ ## 영향 범위
20
+
21
+ ### 영향받는 스펙
22
+
23
+ - `specs/{{SPEC_PATH}}`
24
+
25
+ ### 변경 유형
26
+
27
+ - [ ] 신규 추가 (ADDED)
28
+ - [ ] 수정 (MODIFIED)
29
+ - [ ] 삭제 (REMOVED)
30
+
31
+ ---
32
+
33
+ ## 변경 내용
34
+
35
+ ### ADDED
36
+
37
+ (새로 추가되는 내용)
38
+
39
+ ### MODIFIED
40
+
41
+ (수정되는 내용)
42
+
43
+ #### Before
44
+
45
+ ```markdown
46
+ 기존 내용
47
+ ```
48
+
49
+ #### After
50
+
51
+ ```markdown
52
+ 변경된 내용
53
+ ```
54
+
55
+ ### REMOVED
56
+
57
+ (삭제되는 내용)
58
+
59
+ ---
60
+
61
+ ## 리스크 평가
62
+
63
+ - 영향도: 낮음/중간/높음
64
+ - 복잡도: 낮음/중간/높음
65
+
66
+ ---
67
+
68
+ ## 검토자
69
+
70
+ - [ ] @reviewer1
71
+ - [ ] @reviewer2