Skip to content

kernullist/into-the-git

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

7 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Multi-Git Repository Code Analysis Dashboard

์—ฌ๋Ÿฌ Git ์ €์žฅ์†Œ์˜ ์ฝ”๋“œ๋ฅผ AST ๊ธฐ๋ฐ˜์œผ๋กœ ๋ถ„์„ํ•˜๊ณ , ์˜คํ”ˆ์†Œ์Šค ์ •์  ๋ถ„์„ ๋„๊ตฌ๋ฅผ ํ†ตํ•ฉํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ(๋ณ„์  + ์ฝ”๋ฉ˜ํŠธ)์„ ๋ฐ˜์˜ํ•œ ์ฝ”๋“œ ๊ฐœ์„  ๊ฐ€๋Šฅ์„ฑ์„ ์ œ์‹œํ•˜๋Š” ์˜จํ”„๋ ˆ๋ฏธ์Šค ์›น ๋Œ€์‹œ๋ณด๋“œ์ž…๋‹ˆ๋‹ค.

Features

  • ๋ฉ€ํ‹ฐ ์ €์žฅ์†Œ ์ง€์›: GitHub, GitLab, ๋กœ์ปฌ Git ์ €์žฅ์†Œ ์—ฐ๊ฒฐ
  • ์ •์  ๋ถ„์„ ํ†ตํ•ฉ: cppcheck (C++), pylint + bandit (Python), PMD (Java), ESLint (JavaScript)
  • AST ๊ธฐ๋ฐ˜ ๋ถ„์„: ํŒŒ์ผ/ํ•จ์ˆ˜/ํด๋ž˜์Šค ๋‹จ์œ„ ์‹ฌ๋ณผ ์ถ”์ถœ, ๋ณต์žก๋„, ์˜์กด์„ฑ ๋ถ„์„
  • ์ฝ”๋“œ ๋ฉ”ํŠธ๋ฆญ: Cyclomatic Complexity, Maintainability Index, ์ฝ”๋“œ ์ค‘๋ณต, Fan-in/Fan-out
  • ์ปค๋ฐ‹ ์ธํ…”๋ฆฌ์ „์Šค: ๋ณ€๊ฒฝ ๋นˆ๋„ ๋ถ„์„ + ML ๊ธฐ๋ฐ˜ ์ปค๋ฐ‹ ๋ชฉ์  ๋ถ„๋ฅ˜ (๋น„์ง€๋„ KMeans โ†’ ์ง€๋„ Naive Bayes ํ•˜์ด๋ธŒ๋ฆฌ๋“œ)
  • ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ: ์ „์ฒด ๋ถ„์„ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ๋ณ„์ (1~5) ๋ฐ ์ฝ”๋ฉ˜ํŠธ, ๊ฐ์„ฑ ๋ถ„์„
  • ์šฐ์„ ์ˆœ์œ„ ์ ์ˆ˜: ์ •์  ๋ฐœ๊ฒฌ์‚ฌํ•ญ(35%) + ๋ณต์žก๋„(20%) + ์ค‘๋ณต(10%) + ์˜์กด์„ฑ(10%) + ๋ณ€๊ฒฝ๋นˆ๋„(15%) + ํ”ผ๋“œ๋ฐฑ(10%)
  • ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋Œ€์‹œ๋ณด๋“œ: ์ง€ํ‘œ ์นด๋“œ, ์‹ฌ๊ฐ๋„/์Šค๋ฉœ/๋ณต์žก๋„ ์ฐจํŠธ, ์ปค๋ฐ‹ ๋ชฉ์  ๋ถ„ํฌ, Top ๊ฐœ์„  ๋Œ€์ƒ
  • ํ•„ํ„ฐ: ์ €์žฅ์†Œ, ์–ธ์–ด, ๊ธฐ๊ฐ„(1์ฃผ/1๊ฐœ์›”/3๊ฐœ์›”/์ง์ ‘์ง€์ •), ์‹ฌ๊ฐ๋„, ์Šค๋ฉœ ์œ ํ˜•, ์šฐ์„ ์ˆœ์œ„
  • ์ธ๋ผ์ธ ๋“œ๋ฆด๋‹ค์šด: ์ถ”์ฒœ ํ•ญ๋ชฉ ํด๋ฆญ ์‹œ ํŒŒ์ผ/ํ•จ์ˆ˜ ์ƒ์„ธ findings, ์‹ฌ๋ณผ, ์ปค๋ฐ‹ ๋‚ด์—ญ ํ‘œ์‹œ
  • ๋ฆฌํฌํŠธ ์ต์ŠคํฌํŠธ: Markdown (AI ์—์ด์ „ํŠธ ํ•ธ๋“œ์˜คํ”„์šฉ) + JSON (๋„๊ตฌ ์—ฐ๋™์šฉ)

Prerequisites

ํ•„์ˆ˜

์š”๊ตฌ์‚ฌํ•ญ ๋ฒ„์ „ ํ™•์ธ
Python 3.9 ์ด์ƒ python --version
Git 2.20 ์ด์ƒ git --version
pip ์ตœ์‹  python -m pip install --upgrade pip

์™ธ๋ถ€ ๋ถ„์„ ๋„๊ตฌ (์„ ํƒ - ์—†์œผ๋ฉด ๋‚ด์žฅ AST ๋ถ„์„๋งŒ ๋™์ž‘)

์™ธ๋ถ€ ์ •์  ๋ถ„์„ ๋„๊ตฌ๋ฅผ ์„ค์น˜ํ•˜์ง€ ์•Š์•„๋„ ๋Œ€์‹œ๋ณด๋“œ๋Š” ์ •์ƒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋„๊ตฌ๊ฐ€ ์—†์œผ๋ฉด ํ•ด๋‹น ์–ธ์–ด๋Š” ๋‚ด์žฅ AST ๋ถ„์„ + ๋ณต์žก๋„ ์ธก์ •๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ •์  ๋ถ„์„ findings๋Š” ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.

Windows

# C++ (cppcheck)
winget install cppcheck

# Python (pylint, bandit)
pip install pylint bandit

# Java (PMD) - https://pmd.github.io ์—์„œ pmd-bin-*.zip ๋‹ค์šด๋กœ๋“œ ํ›„ PATH ๋“ฑ๋ก
# ๋˜๋Š” scoop install pmd

# JavaScript (ESLint)
npm install -g eslint

macOS

# C++
brew install cppcheck

# Python
pip3 install pylint bandit

# Java
brew install pmd

# JavaScript
npm install -g eslint

Linux (Ubuntu/Debian)

# C++
sudo apt install cppcheck

# Python
pip install pylint bandit

# Java - https://pmd.github.io ์—์„œ ๋‹ค์šด๋กœ๋“œ
# JavaScript
npm install -g eslint

Quick Start

1. ํ”„๋กœ์ ํŠธ ํด๋ก  ๋ฐ ๊ฐ€์ƒํ™˜๊ฒฝ ์„ค์ •

git clone https://github.com/kernullist/into-the-git.git
cd into-the-git

์ž๋™ ์„ค์ • (๊ถŒ์žฅ)

# Windows (PowerShell)
.\scripts\setup.ps1

# macOS / Linux
bash scripts/setup.sh

์ˆ˜๋™ ์„ค์ •

# ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ
python -m venv venv

# ๊ฐ€์ƒํ™˜๊ฒฝ ํ™œ์„ฑํ™”
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate

# ์˜์กด์„ฑ ์„ค์น˜
pip install -e ".[dev]"        # ๊ฐœ๋ฐœ ์˜์กด์„ฑ ํฌํ•จ
# ๋˜๋Š” ์ตœ์†Œ ์„ค์น˜:
pip install -e .

Makefile ์‚ฌ์šฉ

make setup    # ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ + ์˜์กด์„ฑ ์„ค์น˜ (์ตœ์ดˆ 1ํšŒ)
make run      # ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹œ์ž‘
make test     # ํ…Œ์ŠคํŠธ ์‹คํ–‰
make clean    # ์บ์‹œ ์ •๋ฆฌ
make help     # ๋ชจ๋“  ๋ช…๋ น์–ด ํ™•์ธ

2. ์˜์กด์„ฑ ํ™•์ธ

# ์„ค์น˜๋œ ํŒจํ‚ค์ง€ ํ™•์ธ
pip list

# ๋˜๋Š” requirements.txt๋กœ ์„ค์น˜ (pyproject.toml ๊ธฐ๋ฐ˜ ์ž๋™ ์ƒ์„ฑ)
pip install -r requirements.txt

requirements.txt๋Š” pyproject.toml์—์„œ ์ƒ์„ฑ๋œ ๊ณ ์ • ๋ฒ„์ „์ž…๋‹ˆ๋‹ค. ์ตœ์‹  ํ˜ธํ™˜ ๋ฒ„์ „์ด ํ•„์š”ํ•˜๋ฉด pip install -e ".[dev]"๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

3. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • (์„ ํƒ)

# .env ํŒŒ์ผ ์ƒ์„ฑ (Windows)
echo GITHUB_TOKEN=ghp_your_token_here > .env
echo GITLAB_TOKEN=glpat_your_token_here >> .env

# .env ํŒŒ์ผ ์ƒ์„ฑ (macOS/Linux)
cat > .env << EOF
GITHUB_TOKEN=ghp_your_token_here
GITLAB_TOKEN=glpat_your_token_here
FLASK_DEBUG=1
EOF

ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋ชฉ๋ก:

๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
SECRET_KEY ๋žœ๋ค ์ƒ์„ฑ Flask ์„ธ์…˜ ์•”ํ˜ธํ™” ํ‚ค
DATABASE_URL sqlite:///data/dashboard.db DB ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด
GITHUB_TOKEN ์—†์Œ GitHub Personal Access Token
GITLAB_TOKEN ์—†์Œ GitLab Personal Access Token
FLASK_DEBUG 0 ๋””๋ฒ„๊ทธ ๋ชจ๋“œ (1 = ํ™œ์„ฑํ™”)
MAX_ANALYSIS_TIMEOUT 3600 ๋ถ„์„ ์ตœ๋Œ€ ์‹œ๊ฐ„(์ดˆ)
WORKER_THREADS 2 ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์›Œ์ปค ์Šค๋ ˆ๋“œ ์ˆ˜
CLUSTER_MIN_SAMPLES 30 ML ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ตœ์†Œ ์ƒ˜ํ”Œ ์ˆ˜
CLASSIFIER_CONFIDENCE_THRESHOLD 0.6 ์ง€๋„ ๋ถ„๋ฅ˜๊ธฐ ์‹ ๋ขฐ๋„ ์ž„๊ณ„๊ฐ’

4. ์‹คํ–‰

# ๊ฐœ๋ฐœ ์„œ๋ฒ„
python app.py

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:5000 ์œผ๋กœ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

5. ์„ค์น˜ ํ™•์ธ

# ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์‹คํ–‰
python -m unittest discover tests -v

# 55 tests OK ๊ฐ€ ์ถœ๋ ฅ๋˜๋ฉด ์ •์ƒ

์‚ฌ์šฉ ๊ฐ€์ด๋“œ

์ „์ฒด ์›Œํฌํ”Œ๋กœ์šฐ

Project ์ƒ์„ฑ โ†’ Repository ์—ฐ๊ฒฐ โ†’ Branch ์„ ํƒ โ†’ ๋ถ„์„ ์‹คํ–‰ โ†’ ๋Œ€์‹œ๋ณด๋“œ ๊ฒ€ํ†  โ†’ ํ”ผ๋“œ๋ฐฑ โ†’ ๋ฆฌํฌํŠธ Export

1. Project ์ƒ์„ฑ

  1. ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ "+ New Project" ํด๋ฆญ
  2. Project ์ด๋ฆ„๊ณผ ์„ค๋ช… ์ž…๋ ฅ
  3. "Create Project" ํด๋ฆญ

2. Repository ์—ฐ๊ฒฐ

Project ํŽ˜์ด์ง€์—์„œ "+ Add Repository" ํด๋ฆญ:

Provider URL ์˜ˆ์‹œ ํ† ํฐ ํ•„์š”
Local Path C:\Projects\my-repo ๋˜๋Š” /home/user/my-repo ์•„๋‹ˆ์˜ค
GitHub https://github.com/user/repo.git ๊ถŒ์žฅ
GitLab https://gitlab.com/user/repo.git ๊ถŒ์žฅ

3. Branch ์„ ํƒ

  1. Repository ์นด๋“œ์—์„œ "Select Branch" ํด๋ฆญ
  2. ๋ถ„์„ํ•  Branch ์„ ํƒ (๋“œ๋กญ๋‹ค์šด์—์„œ ์ž๋™ ์กฐํšŒ)
  3. ๋ถ„์„ ๊ธฐ๊ฐ„ ์„ ํƒ: ๊ธฐ๋ณธ๊ฐ’ Last 1 Month
    • Last 1 Week / Last 1 Month / Last 3 Months / Custom (๋‚ ์งœ ์ง์ ‘ ์ง€์ •)
  4. "Confirm & Analyze" ํด๋ฆญ

4. ๋ถ„์„ ์‹คํ–‰ ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง

  • Project ํŽ˜์ด์ง€์—์„œ "Run Analysis" ํด๋ฆญ
  • ๋ถ„์„ ์‹คํ–‰ ํŽ˜์ด์ง€์—์„œ ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ, ์ง„ํ–‰๋ฅ , ์ƒํƒœ ํ™•์ธ
  • ์‹คํ–‰ ์ค‘์ธ ์ž‘์—…์€ Cancel ๊ฐ€๋Šฅ
  • ์‹คํŒจํ•œ ์ž‘์—…์€ Retry ๊ฐ€๋Šฅ (์„ฑ๊ณตํ•œ ์ €์žฅ์†Œ ๊ฒฐ๊ณผ ๋ณด์กด)

5. ๋Œ€์‹œ๋ณด๋“œ ๊ฒ€ํ† 

๋Œ€์‹œ๋ณด๋“œ ํ™”๋ฉด ๊ตฌ์„ฑ:

  • ์ƒ๋‹จ: 6๊ฐœ ์ง€ํ‘œ ์นด๋“œ (Findings, Recommendations, Avg Rating, Feedbacks, Complexity, Changes)
  • ์ค‘๋‹จ ์ขŒ์ธก: Findings by Severity (๋ง‰๋Œ€ ์ฐจํŠธ), Top Functions by Complexity (์ˆ˜ํ‰ ๋ง‰๋Œ€)
  • ์ค‘๋‹จ ์šฐ์ธก: Code Smell Distribution (๋„๋„› ์ฐจํŠธ), Commit Purpose Distribution (๋„๋„› ์ฐจํŠธ)
  • ํ•˜๋‹จ ์ขŒ์ธก: Top Improvement Targets (์šฐ์„ ์ˆœ์œ„ ์ˆœ ์ถ”์ฒœ ๋ชฉ๋ก)
  • ํ•˜๋‹จ ์šฐ์ธก: Recent Feedback (์ตœ์‹  ํ”ผ๋“œ๋ฐฑ ์ฝ”๋ฉ˜ํŠธ)
  • ์ตœํ•˜๋‹จ: ๋ณ„์  + ์ฝ”๋ฉ˜ํŠธ ํ”ผ๋“œ๋ฐฑ ์ œ์ถœ ํผ

6. ํ•„ํ„ฐ ์‚ฌ์šฉ

์ขŒ์ธก ์‚ฌ์ด๋“œ๋ฐ”์—์„œ ํ•„ํ„ฐ ์ ์šฉ:

  • Project: ํ”„๋กœ์ ํŠธ ์„ ํƒ
  • Repository: ์ €์žฅ์†Œ๋ณ„ ํ•„ํ„ฐ
  • Language: Python / JavaScript / Java / C++
  • Period: 1์ฃผ / 1๊ฐœ์›” / 3๊ฐœ์›”
  • Severity: Critical / Major / Minor / Info
  • Smell Type: ๋ถ„์„ ์‹คํ–‰ ์‹œ ๋ฐœ๊ฒฌ๋œ ์นดํ…Œ๊ณ ๋ฆฌ ๊ธฐ์ค€ ๋™์  ์ƒ์„ฑ
  • Priority: High (75+) / Medium (50-74) / Low (<50)

7. ๋“œ๋ฆด๋‹ค์šด

์ถ”์ฒœ ๋ชฉ๋ก์˜ ํ•ญ๋ชฉ์„ ํด๋ฆญํ•˜๋ฉด ์šฐ์ธก ํŒจ๋„์— ์ƒ์„ธ ์ •๋ณด ํ‘œ์‹œ:

  • Contributing Signals: ๊ฐ ์‹ ํ˜ธ๋ณ„ ์ ์ˆ˜์™€ ๊ฐ€์ค‘์น˜
  • Findings: ํŒŒ์ผ๋ณ„ ์ •์  ๋ถ„์„ ๋ฐœ๊ฒฌ์‚ฌํ•ญ (๋„๊ตฌ, ๊ทœ์น™, ์‹ฌ๊ฐ๋„)
  • Symbols: ํ•จ์ˆ˜/ํด๋ž˜์Šค ๋ชฉ๋ก, ๋ณต์žก๋„, ๋ผ์ธ ์œ„์น˜
  • Commit History: ํ•ด๋‹น ํŒŒ์ผ์˜ ์ตœ๊ทผ ์ปค๋ฐ‹ ๋‚ด์—ญ (์ž‘์„ฑ์ž, ๋ชฉ์ , ๋ฉ”์‹œ์ง€)

8. ํ”ผ๋“œ๋ฐฑ ์ œ์ถœ

๋Œ€์‹œ๋ณด๋“œ ํ•˜๋‹จ์—์„œ:

  1. ๋ณ„์  1~5 ์„ ํƒ (ํด๋ฆญ)
  2. ์ฝ”๋ฉ˜ํŠธ ์ž‘์„ฑ (ํ•œ๊ตญ์–ด/์˜์–ด ๋ชจ๋‘ ์ง€์›)
  3. "Submit Feedback" ํด๋ฆญ

์ œ์ถœ ์‹œ:

  • ๊ฐ์„ฑ ์ ์ˆ˜ ์ž๋™ ๊ณ„์‚ฐ (๊ธ์ •/๋ถ€์ • ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜)
  • ๋ชจ๋“  ์ถ”์ฒœ ํ•ญ๋ชฉ์˜ feedback_score ์žฌ๊ณ„์‚ฐ
  • ๋Œ€์‹œ๋ณด๋“œ ์ง€ํ‘œ ์ž๋™ ๊ฐฑ์‹ 

9. ๋ฆฌํฌํŠธ ์ต์ŠคํฌํŠธ

  1. ๋ถ„์„ ์™„๋ฃŒ ํ›„ "Export Report" ํด๋ฆญ
  2. Format ์„ ํƒ:
    • Markdown: AI ์ฝ”๋”ฉ ์—์ด์ „ํŠธ์—๊ฒŒ ์ „๋‹ฌํ•  ํ•ธ๋“œ์˜คํ”„ ๋ฌธ์„œ
    • JSON: ์ž๋™ํ™” ๋„๊ตฌ/API ์—ฐ๋™์šฉ ๊ธฐ๊ณ„ ํŒ๋… ํ˜•์‹
  3. "Generate Export" โ†’ "Download" ํด๋ฆญ

API Reference

Projects

# ํ”„๋กœ์ ํŠธ ๋ชฉ๋ก
curl http://localhost:5000/api/projects

# ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
curl -X POST http://localhost:5000/api/projects \
  -H "Content-Type: application/json" \
  -d '{"name": "My Project", "description": "ํ”„๋กœ์ ํŠธ ์„ค๋ช…"}'

# ํ”„๋กœ์ ํŠธ ์‚ญ์ œ
curl -X DELETE http://localhost:5000/api/projects/1

Repositories

# ์ €์žฅ์†Œ ์ถ”๊ฐ€
curl -X POST http://localhost:5000/api/projects/1/repositories \
  -H "Content-Type: application/json" \
  -d '{"provider": "local", "remote_url": "/path/to/repo", "default_branch": "main"}'

# ์ €์žฅ์†Œ ๋ธŒ๋žœ์น˜ ์กฐํšŒ
curl http://localhost:5000/api/repositories/1/branches

# ์ €์žฅ์†Œ ์ •๋ณด ์ˆ˜์ • (๋ธŒ๋žœ์น˜ ์„ ํƒ)
curl -X PUT http://localhost:5000/api/repositories/1 \
  -H "Content-Type: application/json" \
  -d '{"selected_branches": ["main"], "default_branch": "main"}'

Analysis Runs

# ๋ถ„์„ ์‹คํ–‰
curl -X POST http://localhost:5000/api/analysis-runs \
  -H "Content-Type: application/json" \
  -d '{"project_id": 1, "repository_ids": [1], "period": "1m"}'

# ์‹คํ–‰ ์ƒํƒœ ํ™•์ธ
curl http://localhost:5000/api/analysis-runs/1

# ์‹คํ–‰ ์ทจ์†Œ
curl -X POST http://localhost:5000/api/analysis-runs/1/cancel

# ์‹คํŒจํ•œ ์ €์žฅ์†Œ๋งŒ ์žฌ์‹œ๋„
curl -X POST http://localhost:5000/api/analysis-runs/1/retry \
  -H "Content-Type: application/json" \
  -d '{"repository_ids": [1], "period": "1m"}'

Findings & Metrics

# ๋ฐœ๊ฒฌ์‚ฌํ•ญ ์กฐํšŒ (ํŽ˜์ด์ง• + ํ•„ํ„ฐ)
curl "http://localhost:5000/api/analysis-runs/1/findings?page=1&per_page=50&severity=critical&repository_id=1"

# ๋ฐœ๊ฒฌ์‚ฌํ•ญ ์š”์•ฝ
curl http://localhost:5000/api/analysis-runs/1/findings/summary

# ๋ฉ”ํŠธ๋ฆญ ์กฐํšŒ
curl http://localhost:5000/api/analysis-runs/1/metrics

# ์ถ”์ฒœ ๋ชฉ๋ก
curl http://localhost:5000/api/analysis-runs/1/recommendations

Dashboard & Details

# ๋Œ€์‹œ๋ณด๋“œ ๊ฐœ์š” (ํ•„ํ„ฐ ํฌํ•จ)
curl "http://localhost:5000/api/dashboard/overview?project_id=1&repository_id=1&severity=critical&period=1m"

# ํŒŒ์ผ ์ƒ์„ธ (๋“œ๋ฆด๋‹ค์šด)
curl "http://localhost:5000/api/analysis-runs/1/files/src/main.py"

# ๋ณต์žก๋„ ํŠธ๋ Œ๋“œ
curl http://localhost:5000/api/analysis-runs/1/complexity-trend

Feedback & Export

# ํ”ผ๋“œ๋ฐฑ ์ œ์ถœ
curl -X POST http://localhost:5000/api/analysis-runs/1/feedback \
  -H "Content-Type: application/json" \
  -d '{"rating": 4, "comment": "๋ถ„์„ ๊ฒฐ๊ณผ๊ฐ€ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค"}'

# ํ”ผ๋“œ๋ฐฑ ์กฐํšŒ
curl http://localhost:5000/api/analysis-runs/1/feedback

# ๋ฆฌํฌํŠธ ์ต์ŠคํฌํŠธ (Markdown)
curl "http://localhost:5000/api/analysis-runs/1/export?format=markdown"

# ๋ฆฌํฌํŠธ ์ต์ŠคํฌํŠธ (JSON)
curl "http://localhost:5000/api/analysis-runs/1/export?format=json"

# ์ต์ŠคํฌํŠธ ๋‹ค์šด๋กœ๋“œ
curl -O http://localhost:5000/api/exports/1/download

Architecture

into-the-git/
โ”œโ”€โ”€ app.py                     # Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง„์ž…์ 
โ”œโ”€โ”€ config.py                  # ์„ค์ • (ํ™˜๊ฒฝ๋ณ€์ˆ˜, DB ๊ฒฝ๋กœ, ํ† ํฐ)
โ”œโ”€โ”€ database.py                # SQLAlchemy ์ดˆ๊ธฐํ™”
โ”œโ”€โ”€ models.py                  # 11๊ฐœ ์—”ํ‹ฐํ‹ฐ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ
โ”œโ”€โ”€ requirements.txt           # Python ์˜์กด์„ฑ
โ”‚
โ”œโ”€โ”€ connectors/                # Git ์ €์žฅ์†Œ ์ปค๋„ฅํ„ฐ
โ”‚   โ”œโ”€โ”€ base.py                #   ์ถ”์ƒ ๋ฒ ์ด์Šค ํด๋ž˜์Šค
โ”‚   โ”œโ”€โ”€ local.py               #   ๋กœ์ปฌ Git (clone/fetch/branch/commit)
โ”‚   โ”œโ”€โ”€ github.py              #   GitHub (ํ† ํฐ ์ธ์ฆ)
โ”‚   โ””โ”€โ”€ gitlab.py              #   GitLab (ํ† ํฐ ์ธ์ฆ)
โ”‚
โ”œโ”€โ”€ analysis/                  # ๋ถ„์„ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜
โ”‚   โ””โ”€โ”€ runner.py              #   ๋ถ„์„ ์‹คํ–‰๊ธฐ (ThreadPoolExecutor, timeout, ๋กœ๊ทธ)
โ”‚
โ”œโ”€โ”€ analyzers/                 # ์ •์  ๋ถ„์„ ์–ด๋Œ‘ํ„ฐ + AST ์—”์ง„
โ”‚   โ”œโ”€โ”€ base.py                #   ์–ด๋Œ‘ํ„ฐ ๋ฒ ์ด์Šค (subprocess ์‹คํ–‰, timeout)
โ”‚   โ”œโ”€โ”€ adapters.py            #   cppcheck / pylint / bandit / PMD / ESLint
โ”‚   โ”œโ”€โ”€ ast_engine.py          #   ๋‹ค์ค‘ ์–ธ์–ด AST ํŒŒ์‹ฑ (Python ast + ์ •๊ทœ์‹)
โ”‚   โ”œโ”€โ”€ complexity.py          #   Cyclomatic Complexity, MI (radon + ์ž์ฒด)
โ”‚   โ”œโ”€โ”€ duplication.py         #   ์ฝ”๋“œ ๋ธ”๋ก ์ค‘๋ณต ํƒ์ง€ (ํ•ด์‹œ ๊ธฐ๋ฐ˜)
โ”‚   โ””โ”€โ”€ dependency.py          #   Import/Include ์˜์กด์„ฑ ๋ถ„์„
โ”‚
โ”œโ”€โ”€ commit_intel/              # ์ปค๋ฐ‹ ์ธํ…”๋ฆฌ์ „์Šค
โ”‚   โ”œโ”€โ”€ frequency.py           #   ๋ณ€๊ฒฝ ๋นˆ๋„ ๊ณ„์‚ฐ
โ”‚   โ””โ”€โ”€ classifier.py          #   ML ์ปค๋ฐ‹ ๋ชฉ์  ๋ถ„๋ฅ˜ (KMeans โ†’ NaiveBayes)
โ”‚
โ”œโ”€โ”€ scoring/                   # ์ ์ˆ˜ ์—”์ง„
โ”‚   โ”œโ”€โ”€ engine.py              #   ์šฐ์„ ์ˆœ์œ„ ์ ์ˆ˜, ์ถ”์ฒœ ์ƒ์„ฑ
โ”‚   โ””โ”€โ”€ sentiment.py           #   ๊ฐ์„ฑ ๋ถ„์„ (ํ•œ/์˜ ํ‚ค์›Œ๋“œ)
โ”‚
โ”œโ”€โ”€ normalization/             # ์ •๊ทœํ™” ์Šคํ‚ค๋งˆ
โ”‚   โ””โ”€โ”€ schemas.py             #   Finding/Metric/CommitSignal ์ •๊ทœํ™” ํ•จ์ˆ˜
โ”‚
โ”œโ”€โ”€ api/                       # REST API
โ”‚   โ””โ”€โ”€ routes.py              #   Flask Blueprint (16+ ์—”๋“œํฌ์ธํŠธ)
โ”‚
โ”œโ”€โ”€ templates/                 # Jinja2 HTML ํ…œํ”Œ๋ฆฟ
โ”‚   โ”œโ”€โ”€ base.html              #   ๊ณตํ†ต ๋ ˆ์ด์•„์›ƒ (์‚ฌ์ด๋“œ๋ฐ” + Chart.js CDN)
โ”‚   โ”œโ”€โ”€ index.html             #   ํ”„๋กœ์ ํŠธ ๋ชฉ๋ก + ์ƒ์„ฑ
โ”‚   โ”œโ”€โ”€ project.html           #   ์ €์žฅ์†Œ ์—ฐ๊ฒฐ + ๋ธŒ๋žœ์น˜/๊ธฐ๊ฐ„ ์„ ํƒ
โ”‚   โ”œโ”€โ”€ analysis.html          #   ๋ถ„์„ ์‹คํ–‰ ๋ชจ๋‹ˆํ„ฐ๋ง
โ”‚   โ”œโ”€โ”€ dashboard.html         #   ๋ฉ”์ธ ๋Œ€์‹œ๋ณด๋“œ (์ฐจํŠธ, ํ•„ํ„ฐ, ๋“œ๋ฆด๋‹ค์šด)
โ”‚   โ””โ”€โ”€ export.html            #   ๋ฆฌํฌํŠธ ์ต์ŠคํฌํŠธ
โ”‚
โ”œโ”€โ”€ static/                    # ์ •์  ํŒŒ์ผ
โ”‚   โ”œโ”€โ”€ css/style.css          #   ์Šคํƒ€์ผ์‹œํŠธ
โ”‚   โ””โ”€โ”€ js/dashboard.js        #   ๊ณตํ†ต ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜
โ”‚
โ”œโ”€โ”€ tests/                     # ํ…Œ์ŠคํŠธ
โ”‚   โ”œโ”€โ”€ test_core.py           #   55๊ฐœ ๋‹จ์œ„/ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ
โ”‚   โ””โ”€โ”€ fixtures/              #   ์–ธ์–ด๋ณ„ ์ƒ˜ํ”Œ ์ฝ”๋“œ
โ”‚       โ”œโ”€โ”€ sample.py
โ”‚       โ”œโ”€โ”€ sample.java
โ”‚       โ”œโ”€โ”€ sample.js
โ”‚       โ””โ”€โ”€ sample.cpp
โ”‚
โ””โ”€โ”€ data/                      # ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ (์ž๋™ ์ƒ์„ฑ)
    โ”œโ”€โ”€ dashboard.db           #   SQLite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
    โ”œโ”€โ”€ repos/                 #   ํด๋ก ๋œ ์ €์žฅ์†Œ
    โ””โ”€โ”€ reports/               #   ์ต์ŠคํฌํŠธ๋œ ๋ฆฌํฌํŠธ

๋ฐ์ดํ„ฐ ๋ชจ๋ธ (11๊ฐœ ์—”ํ‹ฐํ‹ฐ)

์—”ํ‹ฐํ‹ฐ ์ฃผ์š” ํ•„๋“œ ๊ด€๊ณ„
Project id, name, description has many Repositories, AnalysisRuns
Repository id, project_id, provider, remote_url, branches has many SourceFiles, Findings, CommitSignals
AnalysisRun id, project_id, repository_ids, status, progress, logs has many Findings, Metrics, Feedbacks, Recommendations, Exports
SourceFile id, repository_id, path, language, size, hash, owner_hint has many CodeSymbols
CodeSymbol id, file_id, kind, name, location, signature, complexity belongs to SourceFile
Finding id, run_id, repository_id, file_id, tool, rule_id, severity, category, fingerprint belongs to AnalysisRun, Repository
MetricSnapshot id, run_id, scope_type, scope_id, metric_name, value belongs to AnalysisRun
CommitSignal id, repository_id, file_id, commit_sha, author, purpose_category belongs to Repository
Feedback id, run_id, rating (1-5), comment, sentiment_score belongs to AnalysisRun
Recommendation id, run_id, target_type, priority_score, rationale, contributing_signals belongs to AnalysisRun
ExportReport id, run_id, title, format, content belongs to AnalysisRun

์ƒํƒœ ์ „์ด

queued โ†’ running โ†’ completed
                  โ†’ failed
                  โ†’ cancelled

Scoring System

์šฐ์„ ์ˆœ์œ„ ์ ์ˆ˜ ๊ณ„์‚ฐ

priority_score = (
    finding_score     ร— 0.35 +
    complexity_score  ร— 0.20 +
    duplication_score ร— 0.10 +
    dependency_score  ร— 0.10 +
    change_freq_score ร— 0.15 +
    feedback_score    ร— 0.10
) ร— 10

ํ”ผ๋“œ๋ฐฑ ์ ์ˆ˜ ๊ณ„์‚ฐ

improvement_score = star_rating ร— 0.7 + sentiment_score ร— 0.3
  • star_rating: ์‚ฌ์šฉ์ž ๋ณ„์  (1~5)
  • sentiment_score: ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ๊ฐ์„ฑ ์ ์ˆ˜ (1.0~5.0)
    • ๊ธ์ •/๋ถ€์ • ํ‚ค์›Œ๋“œ ๋น„์œจ์— ๋”ฐ๋ผ ๊ณ„์‚ฐ
    • ํ‚ค์›Œ๋“œ ์—†์œผ๋ฉด ์ค‘๋ฆฝ (3.0)

ํ”ผ๋“œ๋ฐฑ ์ œ์ถœ ์‹œ ์ถ”์ฒœ ์ ์ˆ˜ ์žฌ๊ณ„์‚ฐ

new_feedback_score = (old_feedback_score + improvement_score) / 2

Testing

# ์ „์ฒด ํ…Œ์ŠคํŠธ ์‹คํ–‰ (55 tests)
python -m unittest discover tests -v

# ํŠน์ • ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋งŒ ์‹คํ–‰
python -m unittest tests.test_core.TestModels -v
python -m unittest tests.test_core.TestAPI -v
python -m unittest tests.test_core.TestCommitClassifier -v

# ํŠน์ • ํ…Œ์ŠคํŠธ๋งŒ ์‹คํ–‰
python -m unittest tests.test_core.TestRetryPreservation.test_retry_preserves_other_repo_findings -v

ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€

์˜์—ญ ํ…Œ์ŠคํŠธ ์ˆ˜ ์„ค๋ช…
Models 6 CRUD, ๊ด€๊ณ„, ๋ผ์ดํ”„์‚ฌ์ดํด
API 5 ํ”„๋กœ์ ํŠธ, ์ €์žฅ์†Œ, ํ”ผ๋“œ๋ฐฑ, ์ต์ŠคํฌํŠธ, ๋ฐธ๋ฆฌ๋ฐ์ด์…˜
AST Engine 4 Python/JS AST ํŒŒ์‹ฑ, ๋ณต์žก๋„, import ์ถ”์ถœ
Complexity 2 Python ๋ณต์žก๋„, Generic ๋ณต์žก๋„
Duplication 2 ์ค‘๋ณต ํƒ์ง€, ์ค‘๋ณต ์—†์Œ ์ผ€์ด์Šค
Dependencies 1 ๋‚ด๋ถ€/์™ธ๋ถ€ ์˜์กด์„ฑ ๋ถ„์„
Commit Classifier 9 ๊ทœ์น™ ๊ธฐ๋ฐ˜ ๋ถ„๋ฅ˜, ๋ฐฐ์น˜ ๋ถ„๋ฅ˜, ํด๋Ÿฌ์Šคํ„ฐ๋ง, ์ง€๋„ ์ „ํ™˜
Change Frequency 1 ํŒŒ์ผ/์ž‘์„ฑ์ž ๋ณ€๊ฒฝ ๋นˆ๋„
Scoring 2 finding ์ ์ˆ˜, ์šฐ์„ ์ˆœ์œ„ ์ ์ˆ˜
Sentiment 5 ๊ธ์ •/๋ถ€์ •/์ค‘๋ฆฝ/ํ•œ๊ตญ์–ด/๊ฐœ์„  ์ ์ˆ˜
Fixture Files 10 4๊ฐœ ์–ธ์–ด ร— AST + ๋ณต์žก๋„ + ์ค‘๋ณต + import
Frontend Pages 6 ๋ชจ๋“  ํŽ˜์ด์ง€ ๋ Œ๋”๋ง ํ™•์ธ
Retry Preservation 2 ์„ ํƒ์  ์žฌ์‹œ๋„, ํ”ผ๋“œ๋ฐฑ ์žฌ๊ณ„์‚ฐ

Production Deployment

Gunicorn (Linux/macOS)

pip install gunicorn

# 4 worker๋กœ ์‹คํ–‰
gunicorn -w 4 -b 0.0.0.0:5000 app:create_app\()

# ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์‹คํ–‰
gunicorn -w 4 -b 0.0.0.0:5000 app:create_app\(\) --daemon

Windows (Waitress)

pip install waitress

# waitress ์‹คํ–‰
python -c "from waitress import serve; from app import create_app; serve(create_app(), host='0.0.0.0', port=5000)"

๋ณด์•ˆ ๊ถŒ์žฅ์‚ฌํ•ญ

  1. SECRET_KEY ์„ค์ •: export SECRET_KEY=$(python -c "import secrets; print(secrets.token_hex(32))")
  2. ๋ฐฉํ™”๋ฒฝ: data/repos/ ๋””๋ ‰ํ† ๋ฆฌ์— ์™ธ๋ถ€ ์ ‘๊ทผ ์ฐจ๋‹จ
  3. ํ† ํฐ: GITHUB_TOKEN, GITLAB_TOKEN์„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ๋งŒ ์ฃผ์ž… (์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉ ๊ธˆ์ง€)
  4. ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ: Nginx ๋’ค์—์„œ ์‹คํ–‰ํ•˜์—ฌ HTTPS, rate limiting ์ ์šฉ
server {
    listen 443 ssl;
    server_name dashboard.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Troubleshooting

git clone ์‹คํŒจ

# GitHub ์ธ์ฆ ์˜ค๋ฅ˜
โ†’ GITHUB_TOKEN ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ • ํ™•์ธ
โ†’ Personal Access Token์— repo ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ

# ๋กœ์ปฌ ๊ฒฝ๋กœ ์ ‘๊ทผ ๋ถˆ๊ฐ€
โ†’ provider๋ฅผ "local"๋กœ ์„ค์ •ํ•˜๊ณ  ์ ˆ๋Œ€๊ฒฝ๋กœ ์‚ฌ์šฉ
โ†’ Windows: C:\Projects\my-repo  (์—ญ์Šฌ๋ž˜์‹œ)
โ†’ Linux/macOS: /home/user/my-repo

๋ถ„์„๊ธฐ ๋„๊ตฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ

# ๊ฐ ๋„๊ตฌ๊ฐ€ PATH์— ์žˆ๋Š”์ง€ ํ™•์ธ
cppcheck --version
pylint --version
bandit --version
pmd --version
eslint --version

# ์—†์œผ๋ฉด ๋Œ€์‹œ๋ณด๋“œ๋Š” ๋‚ด์žฅ AST ๋ถ„์„๋งŒ ์ˆ˜ํ–‰
โ†’ ๋กœ๊ทธ์— "No <language> static analyzers available" ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ดˆ๊ธฐํ™” ์˜ค๋ฅ˜

# SQLite DB ์žฌ์ƒ์„ฑ
rm data/dashboard.db   # macOS/Linux
del data\dashboard.db  # Windows
python app.py           # ์žฌ์‹œ์ž‘ ์‹œ ์ž๋™ ์ƒ์„ฑ

๋ถ„์„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆผ

โ†’ MAX_ANALYSIS_TIMEOUT ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ œํ•œ ์‹œ๊ฐ„ ์„ค์ •
โ†’ ๋ถ„์„ ๊ธฐ๊ฐ„์„ 1์ฃผ(1w)๋กœ ์ค„์ด๊ธฐ
โ†’ ๋Œ€์šฉ๋Ÿ‰ ์ €์žฅ์†Œ๋Š” ๋ธŒ๋žœ์น˜ ํ•„ํ„ฐ ์‚ฌ์šฉ
โ†’ ๋กœ๊ทธ์—์„œ "WARNING: Truncating analysis to 200 files" ๋ฉ”์‹œ์ง€ ํ™•์ธ

ํฌํŠธ ์ถฉ๋Œ

# ๋‹ค๋ฅธ ํฌํŠธ๋กœ ์‹คํ–‰ (Linux/macOS)
FLASK_RUN_PORT=8080 python app.py

# Windows PowerShell
$env:FLASK_RUN_PORT = "8080"
python app.py

Export Guide

Format ๋Œ€์ƒ ์šฉ๋„
Markdown (.md) AI ์ฝ”๋”ฉ ์—์ด์ „ํŠธ Findings, Recommendations, Feedback ํฌํ•จ ํ•ธ๋“œ์˜คํ”„ ๋ฌธ์„œ
JSON (.json) ์ž๋™ํ™” ๋„๊ตฌ CI/CD ํŒŒ์ดํ”„๋ผ์ธ, ์•Œ๋ฆผ ์‹œ์Šคํ…œ ์—ฐ๋™
Dashboard HTML ๊ฐœ๋ฐœ์ž, ํŒ€์žฅ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์ฐจํŠธ, ํ•„ํ„ฐ, ๋“œ๋ฆด๋‹ค์šด์œผ๋กœ ์ง์ ‘ ํƒ์ƒ‰

License

์ด ํ”„๋กœ์ ํŠธ๋Š” ์˜คํ”ˆ์†Œ์Šค ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ†ตํ•ฉ๋œ ์™ธ๋ถ€ ๋„๊ตฌ์˜ ๋ผ์ด์„ ์Šค๋ฅผ ๋ฐฐํฌ ์ „์— ๊ฒ€ํ† ํ•˜์„ธ์š”:

  • cppcheck: GPL v3
  • pylint: GPL v2
  • bandit: Apache 2.0
  • PMD: BSD-style
  • ESLint: MIT

About

Multi-repo code analysis dashboard with AST parsing, open-source linter integration (cppcheck/pylint/PMD/ESLint), ML-based commit purpose classification, and hybrid feedback scoring. On-premises Flask app.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors