๐ŸŒณ velog ํฌ์ŠคํŒ…์œผ๋กœ github์— ์ž”๋””์‹ฌ๊ธฐ

๋ƒ ๋ƒ ยท2024๋…„ 8์›” 21์ผ
post-thumbnail
๐Ÿ˜ญ ํด๋” ์ƒ์„ฑ๊ณผ ํŒŒ์ผ์ƒ์„ฑ๊นŒ์ง€๋Š” ์–ด๋ ต์ง€ ์•Š์•„์š”!! ๊ทธ๋Ÿฐ๋ฐ ์ •๋ง ๋งŽ์€ ์‹œ๊ฐ„์„ ์†Œ๋น„ํ–ˆ๋˜ Permission ์—๋Ÿฌ... ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ–ˆ์„๊นŒ์š”!!

๐Ÿ“Ž Reference
โœ” velog์™€ github ์—ฐ๋™ : ๋ฒจ๋กœ๊ทธ ๊ธ€์“ฐ๊ณ  ์ž”๋””์‹ฌ๊ธฐ ๐ŸŒฑ
โœ” velog ๊ธ€ ์ž‘์„ฑ ์‹œ, ์ž๋™์œผ๋กœ github์— ์ปค๋ฐ‹ํ•˜๊ธฐ
โœ” Permission denied to github-actions[bot]

1. github์— ์ƒˆ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ

๐Ÿ“Œ public์œผ๋กœ ์ƒ์„ฑ

2. ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ํด๋” ๋ฐ ํŒŒ์ผ ์ƒ์„ฑ

๐Ÿ“Œ.githubํด๋” ์•ˆ์— workflows/update_blog.yml ์ƒ์„ฑ

velog_hub
โ”œโ”€ .github
|   โ””โ”€ workflows
|      โ””โ”€ update_blog.yml
โ””โ”€ scripts
   โ””โ”€ update_blog.py

3. github action

3-1. update_blog.yml ํŒŒ์ผ ์ƒ์„ฑ

๐Ÿ“Œ permissions ๊ผญ ์ž‘์„ฑํ•ด์ฃผ๊ธฐ!! ์ธ์ฆ๋ฌธ์ œ ํ•ด๊ฒฐ๋ฒ• ๋ฐ”๋กœ๊ฐ€๊ธฐ>>>

๋งค์ผ ์ž์ • / push ๋  ๋•Œ ํŒŒ์ด์ฌ ์Šคํฌ๋ฆฝํŠธ์‹คํ–‰

name: Update Blog Posts

on:
  push:
    branches:
      - main # ๋˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ณ  ์‹ถ์€ ๋ธŒ๋žœ์น˜ ์ด๋ฆ„
  schedule:
    - cron: "0 0 * * *" # ๋งค์ผ ์ž์ •์— ์‹คํ–‰

jobs:
  update_blog:
    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]@users.noreply.github.com'
          git push https://<username>${{ secrets.GH_PAT }}@github.com/<username>/velog_hub.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_blog.py

    # ์‚ฌ์šฉ์ž ์ธ์ฆ
    permissions:
      contents: write

3-2. update_blog.py ํŒŒ์ผ ์ƒ์„ฑ

import feedparser
import git
import os

# ๋ฒจ๋กœ๊ทธ RSS ํ”ผ๋“œ URL
# example : rss_url = 'https://api.velog.io/rss/@soozi'
rss_url = 'https://api.velog.io/rss/@<velog_์•„์ด๋””>'

# ๊นƒํ—ˆ๋ธŒ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฒฝ๋กœ
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.description)  # ๊ธ€ ๋‚ด์šฉ์„ ํŒŒ์ผ์— ์ž‘์„ฑ

        # ๊นƒํ—ˆ๋ธŒ ์ปค๋ฐ‹
        repo.git.add(file_path)
        repo.git.commit('-m', f':sparkles: new post: {entry.title}')

# ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊นƒํ—ˆ๋ธŒ์— ํ‘ธ์‹œ
repo.git.push()

4. PAT ๊ถŒํ•œ ๋ฐ›๊ธฐ

4-1. token ์ƒ์„ฑ

๐Ÿ“Œ ๋ฐ›์€ token ๋ณต์‚ฌ (๋”ฑ ํ•œ ๋ฒˆ๋งŒ ๋ณผ ์ˆ˜ ์žˆ์œผ๋‹ˆ ๋ฐ˜๋“œ์‹œ ๋ณต์‚ฌ!!!)

github ๊ณ„์ • -> Settings -> Developer Settings
-> Personal access tokens (classic) -> Generate New Token
-> Note ์ž‘์„ฑ -> repo, workflow ํด๋ฆญ -> Generate new token

4-2. ๋ ˆํฌ์ง€ํ† ๋ฆฌ(velog_hub)์— secret ์„ค์ •

velog_hub -> Settings -> Actions secrets and variables -> Actions -> New Repository Secret
โœ” Name : GH_PAT
โœ” Secret : [2๋ฒˆ์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ํ† ํฐ]

5. ์—ฌ๊ธฐ๊นŒ์ง€ push!

๐Ÿ˜ต ๊ทธ๋ฆฌ๊ณ  ์žฅ๋ ฌํ•˜๊ฒŒ ์‹คํŒจ

6. ํ•ด๊ฒฐ

6-1. ์›๊ฒฉ ์ €์žฅ์†Œ URL ๋ณ€๊ฒฝ

๐Ÿ“Œ ๊ถŒํ•œ ์ธ์ฆํ•„์š” - ์›๊ฒฉ ์ €์žฅ์†Œ URL์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ณ€๊ฒฝํ•ด์•ผํ•จ!!

$ git remote set-url origin https://
"user-name"@github.com/"user-name"/"repository-name".git

6-2. update_blog.yml ํŒŒ์ผ์—์„œ github ์ฃผ์†Œ ์ˆ˜์ •

run: |
   git config --global user.name 'github-actions[bot]'
   git config --global user.email 'github-actions[bot]@users.noreply.github.com'
   git push https://<USERNAME>${{ secrets.GH_PAT }}@github.com/<USERNAME>/velog_hub.git
๐Ÿคข 6-2, 6-3์„ ์‹œํ–‰ํ•œ ๊ฒฐ๊ณผ -> ์‘ ๋˜ ์‹คํŒจ์•ผ~ ๋˜ Permission ์—๋Ÿฌ


(fix: ์‚ฌ์šฉ์ž ์ธ์ฆ ์ปค๋ฐ‹์€ ๊ทธ๋ƒฅ ์ฃผ์„๋งŒ ์ถ”๊ฐ€ํ•œ ๊ฒƒ)

6-3. ์—๋Ÿฌ ๋ฉ”์‹œ์ง€์— ์ฃผ๋ชฉํ•˜๋ผ!

remote: Permission to USERNAME/velog_hub.git denied to github-actions[bot]

๐Ÿ“Œ github-actions[bot]์ด USERNAME/velog_hub.git์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์—†๋‹ค!!
=> ๊ทธ๋ ‡๋‹ค๋ฉด github-actions[bot]์ด ์ ‘๊ทผํ•  ๊ถŒํ•œ์„ ์„ค์ •ํ•ด์ค˜์•ผ๊ฒ ๋„ค?

โœจ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• 1

๐Ÿ“Œ Settings -> Actions -> General ์—์„œ Workflow Permissions ์„ค์ •ํ•˜๊ธฐ

๐Ÿ˜ฑ ๊ทธ๋Ÿฌ๋‚˜ ์ด ๋ฐฉ๋ฒ•์€ ๋ณด์•ˆ์ƒ ๋ฌธ์ œ๊ฐ€ ์žˆ์Œ...

โœจ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• 2 -> ์ฑ„ํƒ!!!

๐Ÿ“Œ update_blog.yml ํŒŒ์ผ์— permissions ์†์„ฑ ์ถ”๊ฐ€ํ•˜๊ธฐ

jobs:
  update_blog:
  	...
    # ์•„๋ž˜ ๋‚ด์šฉ ์ถ”๊ฐ€!!!
    permissions:
      contents: write

contents: write : ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ปค๋ฐ‹/ํ‘ธ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ฒŒ ๋จ!!

๐Ÿ’ฃ ์ฐจ์ด์ 

Workflow Permissions ์„ค์ • permissions ์†์„ฑ ์ถ”๊ฐ€
๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ ๋ชจ๋“  ์›Œํฌํ”Œ๋กœ์šฐ์— ๋Œ€ํ•ด ์ผ๊ด„์ ์œผ๋กœ ์ ์šฉ์›Œํฌํ”Œ๋กœ์šฐ ํŒŒ์ผ ๋‚ด์—์„œ ๊ฐ ์›Œํฌํ”Œ๋กœ์šฐ์— ๋Œ€ํ•ด ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ๊ถŒํ•œ์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ์„ค์ •. ๋”ฐ๋ผ์„œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜์ง€ ์•Š์Œ์œผ๋กœ์จ ๋ณด์•ˆ ๊ฐ•ํ™”

7. ์„ฑ๊ณต!!!!

8. ํ›„๊ธฐ

๋‹ค์Œํฌ์ŠคํŒ…์— ๊ณ„์†...

profile
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€