벨로그 깃허브 연동

JooSehyun·2025년 1월 2일
0

[Study]

목록 보기
52/56
post-thumbnail

벨로그 깃허브 연동 test


🕵️ Velog에 글을 작성하면 GitHub에 업로드가 되게 하고 싶었다.


연동 방법 순서

📂 폴더 구조

📁 프로젝트 루트 
├── 📁 .github 
│ └── 📁 workflows 
│ └── python-workflow.yml # GitHub Actions 워크플로우 정의 파일 
├── 📁 scripts 
│ └── my_script.py # 실행할 Python 스크립트 파일 
└── README.md

1. Github 리포지토리 생성

2. 로컬 폴더에서 Git 초기화 및 리포지토리 연결

echo "# velog" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/NuyHesHUB/velog.git
git push -u origin main

3. update_velog.yml 파일 생성

해당 로컬 디렉토리에서 입력하여 .github/workflows 폴더를 생성한다.

# terminal
mkdir -p .github/workflows

.github/workflows 폴더 생성 후 update_velog.yml 파일 생성하고 yml 설정코드를 작성한다.


🕵️ Github Actions 이란?

Github-Actions 문서

GitHub Actions는 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI/CD(연속 통합 및 지속적인 업데이트) 플랫폼입니다. 리포지토리에 대한 모든 끌어오기 요청을 빌드 및 테스트하거나 병합된 끌어오기 요청을 프로덕션에 배포하는 워크플로를 만들 수 있습니다.

GitHub Actions은(는) 단순한 DevOps 수준을 넘어 리포지토리에서 다른 이벤트가 발생할 때 워크플로를 실행할 수 있도록 합니다. 예를 들어 누군가가 리포지토리에서 새 이슈를 만들 때마다 워크플로를 실행하여 적절한 레이블을 자동으로 추가할 수 있습니다.

GitHub에서 워크플로를 실행할 Linux, Windows, macOS 가상 머신을 제공하거나, 사용자 고유의 데이터 센터 또는 클라우드 인프라에서 자체 호스트형 실행기를 호스트할 수 있습니다.

주요기능

자동화된 워크플로우

  • 코드 변경 시 빌드, 테스트, 배포 등의 작업을 자동으로 실행할 수 있습니다.
  • 워크플로우는 .github/workflows 디렉토리 아래에 작성된 YAML파일로 정의됩니다.

이벤트 기반 실행

  • Github Actions는 다양한 이벤트를 트리거로 실행됩니다. 예 ) main 브랜치에 코드가 푸시되면 자동으로 테스트를 실행 등

멀티 플랫폼 지원

  • Linux, macOS, Windows 환경에서 작업을 실행할 수 있습니다.

직접 작성 가능한 커스텀 작업

  • GitHub Actions에서 제공하는 기본 작업 외에도 사용자가 JavaScript 또는 Docker 기반으로 커스텀 작업을 작성할 수 있습니다.

시크릿 및 환경 변수 관리

  • 민감한 데이터(예: API 키, 토큰)는 GitHub Secrets로 안전하게 저장하고, Actions에서 사용할 수 있습니다.

다양한 마켓플레이스

  • GitHub Actions 마켓플레이스에서 다양한 사전 정의된 액션(예: AWS 배포, Docker 빌드 등)을 사용할 수 있습니다.

4. 📂.github/workflows/📄update_velog.yml 코드 작성

코드

name: Update Velog

on:
    push:
        branches:
            - master
    schedule:
        - cron: '0 0 * * *'

jobs:
    update_velog:
        runs-on: ubuntu-latest
        steps:
            - name: Checkout
              uses: actions/checkout@v2
              
            - name: Push changes
              run: |
                git config --global user.name 'github-actions[bot]'
                git config --global user.email 'github-actions[bot]@user.noreply.github.com'
                git push https://${{ secrets.GH_PAT }}@github.com/🟢깃허브ID🟢/velog.git
                
            - name: Set up Python
              uses: actions/setup-python@v2
              with:
                python-version: '3.x'
                
            - name: Install dependencies
              run: |
                pip install feedparser gitpython

            - name: Run script
              run: python scripts/update_velog.py

🕵️ secrets.GH_PAT 변수

git push https://${{ secrets.GH_PAT }}@github.com/🟢깃허브ID🟢/velog.git 에서

변수 sercrets.GH_PAT 은 잠시 PAT 생성한는 NAME과 동일하게 한다.


5. 📂scripts/📄update_velog.py 파일 생성 & 코드

벨로그 RSS 피드를 파싱하여 새로운 글을 로컬 깃 저장소에 마크다운 파일로 저장하고, 이를 커밋 및 푸시하는 스크립트다.

  1. 필요한 라이브러리(feedparsergitos)를 임포트한다.
  2. 벨로그 RSS 피드 URL과 깃허브 레포지토리 경로를 설정한다.
  3. velog-posts 폴더 경로를 설정하고, 폴더가 없으면 생성한다.
  4. 로컬 깃 저장소를 로드한다.
  5. RSS 피드를 파싱하여 각 글을 가져온다.
  6. 각 글을 파일로 저장하고 커밋한다:
    • 글 제목을 파일 이름으로 사용하며, 파일 이름에 유효하지 않은 문자를 제거하거나 대체한다.
    • 파일 경로를 설정하고, 파일이 존재하지 않으면 새 파일을 생성하여 글 내용을 저장한다.
    • 파일을 깃에 추가하고 커밋 메시지를 작성하여 커밋한다.
  7. 변경 사항을 원격 저장소에 푸시한다.

코드

import feedparser
import git
import os

# 벨로그 RSS 피드 URL
rss_url = 'https://api.velog.io/rss/@nuyhes'

# 깃허브 레포지토리 경로
repo_path = '.'

# 'velog-posts' 폴더 경로
posts_dir = os.path.join(repo_path, 'velog-posts')

# 'velog-posts' 폴더가 없으면 생성
if not os.path.exists(posts_dir):
    os.makedirs(posts_dir)

# 레포지토리 로드
repo = git.Repo(repo_path)

# RSS 피드 파싱
feed = feedparser.parse(rss_url)

# 각 글을 파일로 저장하고 커밋
for entry in feed.entries:
    # 파일 이름에서 유효하지 않은 문자 제거 또는 대체
    file_name = entry.title
    file_name = file_name.replace('/', '-') # 슬래시는 하위 폴더로 인식되므로 대시로 대체
    file_name = file_name.replace('\\', '') # 역슬래시는 파일 이름에 사용할 수 없으므로 제거
    file_name += '.md' # 마크다운 파일 확장자 추가
    file_path = os.path.join(posts_dir, file_name) # 파일 경로

    if not os.path.exists(file_path):
        with open(file_path, 'w', encoding='utf-8') as file:
            file.write(entry.discription) # 글 내용을 파일에 쓰기
        repo.git.add(file_path) # 깃에 파일 추가
        repo.git.commit('-m', f'Add post: {entry.title}') # 커밋
  
# 푸시

repo.git.push()

6. PAT 권한 받기

1️⃣ Github 계정
2️⃣ Settings
3️⃣ Developer Settings
4️⃣ Personal access tokens
5️⃣ Tokens(classic)

6️⃣ Generate New Token 버튼 클릭
1️⃣ Note에 토큰 이름을 적는다
2️⃣ repo 체크 , workflow 체크
3️⃣ Generate Token 버튼 클릭

4️⃣ 토큰 값 복사 (토큰 값은 메모해둔다)


velog 레포지토리 이동

1️⃣ Settings
2️⃣ Security 목록 > Secret and variables > Actions

3️⃣ Secrets 탭 > Repository secrets > New repository secret 버튼 클릭

4️⃣ Name 이름 작성 (yml 변수에 넣은 이름) GH_PAT_이름 / Secret 란 토큰 값 입력


레포지토리 외부 권한 부여

1️⃣ 해당 레포지토리 > Settings
2️⃣ Actions > General
3️⃣ Actions permissions > 첫번째 Allow all actions and reusable workflows 체크
4️⃣ Approval for running fork pull request workflows from contributors > 세번째 Require approval for all external contributors 체크
5️⃣ Workflow permissions > 첫번째 Read and write permissions 체크
6️⃣ Allow GitHub Actions to create and approve pull requests 활성화


테스트 실패

Actions 확인

1️⃣ 해당 레포지토리 > Actions > jobs
2️⃣ Run script 부분에서 에러가 발생했다.

에러 로그

Run python scripts/update_velog.py

[7](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:8)Traceback (most recent call last):
[8](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:9) File "/opt/hostedtoolcache/Python/3.12.8/x64/lib/python3.12/site-packages/feedparser/util.py", line 156, in __getattr__
[9](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:10) return self.__getitem__(key)
[10](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:11) ^^^^^^^^^^^^^^^^^^^^^
[11](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:12) File "/opt/hostedtoolcache/Python/3.12.8/x64/lib/python3.12/site-packages/feedparser/util.py", line 113, in __getitem__
[12](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:13) return dict.__getitem__(self, key)
[13](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:14) ^^^^^^^^^^^^^^^^^^^^^^^^^^^
[14](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:15)KeyError: 'discription'
[15](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:16)
[16](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:17)During handling of the above exception, another exception occurred:
[17](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:18)
[18](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:19)Traceback (most recent call last):
[19](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:20) File "/home/runner/work/velog/velog/scripts/update_velog.py", line 35, in <module>
[20](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:21) file.write(entry.discription) # 글 내용을 파일에 쓰기
[21](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:22) ^^^^^^^^^^^^^^^^^
[22](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:23) File "/opt/hostedtoolcache/Python/3.12.8/x64/lib/python3.12/site-packages/feedparser/util.py", line 158, in __getattr__
[23](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:24) raise AttributeError("object has no attribute '%s'" % key)
[24](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:25)AttributeError: object has no attribute 'discription'
[25](https://github.com/NuyHesHUB/velog/actions/runs/12578392936/job/35057054076#step:6:26)Error: Process completed with exit code 1.

📄update_velog.py

if not os.path.exists(file_path):
        with open(file_path, 'w', encoding='utf-8') as file:
            🔴file.write(entry.description) # 글 내용을 파일에 쓰기
            
        repo.git.add(file_path) # 깃에 파일 추가
        repo.git.commit('-m', f'Add post: {entry.title}') # 커밋

🔴부분 : entry.discription 오타가 있었다. entry.description로 수정


성공


참고


0개의 댓글