Link Health Check #45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "Link Health Check" | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| file_to_check: | |
| description: '검사할 파일' | |
| required: false | |
| default: 'both' | |
| type: choice | |
| options: | |
| - 'README.md' | |
| - 'README_EN.md' | |
| - 'both' | |
| schedule: | |
| - cron: '0 9 * * 1' | |
| push: | |
| branches: [ main, master ] | |
| paths: | |
| - 'README.md' | |
| - 'README_EN.md' | |
| jobs: | |
| check_links: | |
| name: "API 링크 상태 검사" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: [3.9] | |
| steps: | |
| - name: 📁 체크아웃 | |
| uses: actions/checkout@v4 | |
| - name: 🐍 Python 설정 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: 📦 의존성 설치 | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install aiohttp | |
| - name: 🔍 README.md 링크 검사 | |
| id: check_readme | |
| if: github.event.inputs.file_to_check != 'README_EN.md' | |
| run: | | |
| echo "=== 한국어 README 검사 시작 ===" | |
| python scripts/link_health_check.py README.md --save-json --concurrent 25 | |
| continue-on-error: true | |
| - name: 🔍 README_EN.md 링크 검사 | |
| id: check_readme_en | |
| if: github.event.inputs.file_to_check == 'README_EN.md' || github.event.inputs.file_to_check == 'both' | |
| run: | | |
| echo "=== 영어 README 검사 시작 ===" | |
| python scripts/link_health_check.py README_EN.md --save-json --concurrent 25 | |
| mv link_health_report.json link_health_report_en.json | |
| continue-on-error: true | |
| - name: 📊 검사 결과 업로드 | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: link-health-reports | |
| path: | | |
| link_health_report.json | |
| link_health_report_en.json | |
| retention-days: 30 | |
| - name: 🚨 깨진 링크 이슈 생성 | |
| if: failure() && github.event_name == 'schedule' # 현재는 continue-on-error -> true로 해당 job skip | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| let brokenLinks = []; | |
| let reportContent = ''; | |
| // 한국어 README 결과 확인 | |
| try { | |
| const koReport = JSON.parse(fs.readFileSync('link_health_report.json', 'utf8')); | |
| const koBroken = koReport.results.filter(link => !link.is_working); | |
| brokenLinks = brokenLinks.concat(koBroken.map(link => ({...link, file: 'README.md'}))); | |
| } catch (e) { | |
| console.log('한국어 리포트 파일을 찾을 수 없습니다.'); | |
| } | |
| // 영어 README 결과 확인 | |
| try { | |
| const enReport = JSON.parse(fs.readFileSync('link_health_report_en.json', 'utf8')); | |
| const enBroken = enReport.results.filter(link => !link.is_working); | |
| brokenLinks = brokenLinks.concat(enBroken.map(link => ({...link, file: 'README_EN.md'}))); | |
| } catch (e) { | |
| console.log('영어 리포트 파일을 찾을 수 없습니다.'); | |
| } | |
| if (brokenLinks.length > 0) { | |
| // 에러 타입별로 그룹화 | |
| const errorGroups = {}; | |
| brokenLinks.forEach(link => { | |
| const errorType = link.error_type; | |
| if (!errorGroups[errorType]) { | |
| errorGroups[errorType] = []; | |
| } | |
| errorGroups[errorType].push(link); | |
| }); | |
| let issueBody = `## 🚨 링크 부패 감지 알림\n\n`; | |
| issueBody += `**총 ${brokenLinks.length}개의 깨진 링크가 발견되었습니다.**\n\n`; | |
| // 에러 타입별 상세 내용 | |
| for (const [errorType, links] of Object.entries(errorGroups)) { | |
| issueBody += `### 📋 ${errorType} (${links.length}개)\n\n`; | |
| links.forEach(link => { | |
| issueBody += `- ❌ **[${link.api_name}](${link.url})**\n`; | |
| issueBody += ` - 📁 파일: ${link.file}\n`; | |
| issueBody += ` - 📂 카테고리: ${link.category}\n`; | |
| issueBody += ` - ⚠️ 오류: ${link.error_message}\n`; | |
| if (link.redirect_url) { | |
| issueBody += ` - 🔄 리다이렉트: ${link.redirect_url}\n`; | |
| } | |
| issueBody += `\n`; | |
| }); | |
| } | |
| issueBody += `\n### 🔧 수정 방법\n\n`; | |
| issueBody += `1. **서비스 상태 확인**: 해당 API 서비스가 종료되었는지 확인\n`; | |
| issueBody += `2. **URL 변경 확인**: 공식 문서에서 새로운 URL 확인\n`; | |
| issueBody += `3. **대체 서비스 조사**: 동일한 기능의 대체 API 조사\n`; | |
| issueBody += `4. **항목 제거**: 복구 불가능한 경우 해당 항목 제거\n\n`; | |
| issueBody += `---\n`; | |
| issueBody += `**자동 생성 시간**: ${new Date().toLocaleString('ko-KR', {timeZone: 'Asia/Seoul'})}\n`; | |
| issueBody += `**검사 주기**: 매주 월요일\n`; | |
| // 이슈 생성 | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: `🔗 주간 링크 상태 점검: ${brokenLinks.length}개 링크 수정 필요`, | |
| body: issueBody, | |
| labels: ['🐛 bug', '🔗 link-rot', '🔧 maintenance', '📋 weekly-check'] | |
| }); | |
| console.log(`이슈가 생성되었습니다: ${brokenLinks.length}개 깨진 링크`); | |
| } else { | |
| console.log('모든 링크가 정상적으로 작동합니다! 🎉'); | |
| } |