🚦 Summary
- 개인 포트폴리오로 하나의 레포지토리에 다양한 프로젝트를 관리하곤 합니다.
- 이때, README에 프로젝트를 간결하게 표로 정리하고 각 폴더의 링크를 제공하면 내 프로젝트들을 한눈에 보기 쉽게 제시할 수 있습니다.
- 하지만, 이 README의 표를 프로젝트를 추가할 때마다 매번 작성하는 건 번거로운 일입니다.
- 간단한 Python 코드와 Github Actions를 사용해 이를 자동화 하는 방법을 소개 합니다.
- 더 이상 프로젝트를 추가할 때 마다 표의 내용을 넣거나 링크를 개별적으로 걸어줄 필요없어집니다!
-
이 방법을 응용한다면 다양한 Github의 자동화를 구현할 수 있을 것입니다.
📌Intro
- 최근에 부트캠프에 참여하면서 퀘스트를 통해 다양한 프로그래밍 코드들을 작성하기도하고, ML이나 DL 관련 사이드 프로젝트 수준의 코드들을 구현해서 하나의 Repository에 업로드 하고 있습니다.
- 처음에는 폴더명으로 구분을 하면 충분하리라 생각했는데, 추가되는 폴더가 10개를 넘어가다 보니 커밋순서에 따라 폴더의 순서가 바뀌기도하는 등 한눈에 작업물을 파악하기가 어려워 지고 있었습니다.
- 다른 포트폴리오를 기록하는 repository들을 찾아보니 README.md에 간단한 표와 링크를 사용해 가독성 좋게 프로젝트들을 정리한 것을 보았습니다.
- 비교적 간단한 형태였기에 매번 프로젝트를 수정하거나 추가할때마다 이 표를 작성하는 것을 자동화하면 좋겠다고 생각했습니다.
- 이 포스팅에서는 간단한 python 코드와 Github Actions를 응용해 나만의 포트폴리오의 README.md 작성을 자동화 하는 방법을 소개합니다.
- 이 방법을 기반으로 다양한 Github의 자동화를 구현할 수 있을 것입니다.
💡 이런걸 정리합니다.
- 내 메인 Repository 의 README.md 파일의 생성을 자동화 하는 방법
- (Sub) Github Action의 기초 개념
Target
GitHub Action 의 주요 개념들
- GitHub Actions란?
- GitHub Actions는 GitHub 저장소에서 직접 CI(Continuous Integration) 및 CD(Continuous Deployment) 워크플로우를 자동화할 수 있는 도구입니다.
- 워크플로우(Workflow)
- 워크플로우는 하나 이상의 작업(job)을 정의하고, 이 작업들이 언제 실행될지를 결정하는 자동화된 프로세스입니다.
.yml
또는.yaml
파일로 작성되며, 저장소의.github/workflows
디렉토리에 위치합니다.
- 이벤트(Event)
- 이벤트는 워크플로우를 트리거(시작)하는 활동입니다. 예를 들어,
push
,pull request
,issue
생성 등이 있습니다.
- 이벤트는 워크플로우를 트리거(시작)하는 활동입니다. 예를 들어,
- 작업(Job)
- 워크플로우 내에서 실행되는 일련의 단계(step)를 의미합니다.
- 각 작업은 독립적으로 실행될 수 있으며, 다른 작업과 병렬 또는 순차적으로 실행될 수 있습니다.
- 단계(Step)
- 작업 내부에서 실행되는 개별 명령 또는 작업 단위입니다.
- 스크립트 실행, 명령어 실행, 액션 실행 등이 포함됩니다.
- 액션(Action)
- 재사용 가능한 워크플로우의 구성 요소입니다.
- 공개적으로 공유되어 다른 사용자가 사용할 수 있으며, 커스텀 액션을 만들 수도 있습니다.
- 러너(Runner)
- 워크플로우가 실행되는 서버입니다.
- GitHub에서 호스팅하는 러너를 사용하거나, 자체적으로 호스팅하는 러너를 구성할 수 있습니다.
- 비밀(Secrets)
- 중요한 정보(예: 액세스 토큰, 비밀번호)를 안전하게 저장하고 워크플로우에서 사용할 수 있도록 하는 방법입니다.
- 아티팩트(Artifacts)
- 워크플로우 실행 동안 생성된 파일을 저장하고, 나중에 다운로드할 수 있게 하는 기능입니다.
GitHub Actions 사용 방법
- 워크플로우 파일 생성
- 리포지토리의
.github/workflows
디렉토리에 YAML 형식의 워크플로우 파일을 생성합니다.
- 리포지토리의
- 워크플로우 정의
- 워크플로우 파일 내에서 실행할 작업을 정의합니다. 이벤트 트리거, 실행할 작업, 필요한 액션 등을 지정합니다.
- 커밋 및 푸시
- 워크플로우 파일을 리포지토리에 커밋하고 푸시합니다.
- 워크플로우 실행 및 모니터링
- GitHub 리포지토리의 ‘Actions’ 탭에서 워크플로우의 실행 상태를 확인하고 결과를 모니터링합니다.
GitHub Actions는 이러한 개념들을 기반으로 다양한 자동화 작업을 수행할 수 있습니다.
이번 포스팅에서는 이 GitHub Action과 python 코드를 활용해 내 Repository의 README.md에 자동으로 표를 만들고 링크를 입력하는 방법을 정리합니다.
단계별 구현 방법 설명
💡 기능 구현을 위해 몇가지 단계를 거쳐야 합니다.
1
2
3
4
5
1. Python 스크립트 작성
2. GitHub Action 설정
3. 스크립트 실행 및 확인
- 해당 과정을 단계별로 예제 코드와 함께 설명드리도록 하겠습니다.
1. Python 스크립트 작성
- 제가 작성한 코드를 예제코드로 하여 코드별로 상세한 설명을 드리겠습니다.
- 예제 코드의 경우 표를 만들때 몇가지 전제 조건을 설정했습니다.
- 기존 README.md의 작성 내용 밑에 표를 추가합니다.
- 추가되는 표는 가장 최신의 repository 정보를 사용해 항상 기존표를 삭제하고 새로 생성한 표를 입력합니다. (중복 생성 방지)
- 이름이
.
으로 시작하는 폴더(GitHub Action의 workflow 가 저장된 폴더) 를 제외한 나머지 폴더만을 표로 정리 - 폴더명 앞에 붙은 숫자를 기준으로 Ascending하게 Sorting하도록 되어 있습니다.
- 이를 위해 GitHub API를 사용해서 리포지토리의 폴더 목록을 가져오고, 이를
README.md
파일에 업데이트하는 Python 코드를 작성했습니다.
1️⃣ GitHub API를 통한 폴더 목록 가져오기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests
import re
def get_folders(repo):
# GitHub API를 사용하기 위한 URL 생성
url = f"https://api.github.com/repos/{repo}/contents/"
response = requests.get(url)
# API로부터 받은 응답을 JSON 형식으로 파싱하여 저장
folders = [item for item in response.json() if item['type'] == 'dir' and not item['name'].startswith('.')]
return folders
requests
: HTTP 요청을 보내기 위해 사용하는 라이브러리입니다. 여기서는 GitHub API와 통신하는 데 사용됩니다.re
: 정규 표현식을 사용하기 위한 라이브러리입니다. 여기서는 폴더 이름에서 숫자를 추출하는 데 사용됩니다.get_folders
함수는 GitHub API를 사용하여 지정된 저장소의 모든 폴더 목록을 가져옵니다.- 숨김 폴더나 특수 폴더(예:
.
으로 시작하는 폴더)는 제외됩니다. - 결과는 폴더 객체의 리스트로 반환됩니다.
2️⃣ 폴더 이름에서 숫자 추출
1
2
3
4
5
6
7
8
9
10
11
12
13
# 폴더 이름에서 숫자를 추출하는 함수
def extract_number(folder_name):
# 정규 표현식을 사용하여 폴더 이름에서 숫자를 추출
match = re.search(r'\d+', folder_name)
if match:
return int(match.group())
return float('inf') # 숫자가 없는 경우 무한대 값을 반환
extract_number
함수는 폴더 이름에서 숫자를 추출합니다.- 폴더 이름에 숫자가 포함되어 있으면 해당 숫자를 반환하고, 없으면 매우 큰 수(
float('inf')
)를 반환합니다. - 이는 폴더를 숫자 순으로 정렬할 때 사용됩니다.
3️⃣ README.md 파일 업데이트 로직
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def update_readme(repo, folders, original_content):
# 기존 "📑Quest List📑" 섹션과 그 이하 내용을 제거
start_index = original_content.find("## 📑Quest List📑")
if start_index != -1:
original_content = original_content[:start_index]
# 새로운 "## 📑Quest List📑" 섹션 및 테이블을 생성
new_table = "## 📑Quest List📑\n\n"
new_table += "| 퀘스트명 | URL |\n"
new_table += "| --- | --- |\n"
# 폴더를 숫자로 정렬하여 목록을 만듭니다.
sorted_folders = sorted(folders, key=lambda x: extract_number(x['name']))
for folder in sorted_folders:
folder_name = folder['name']
folder_url = folder['html_url']
new_table += f"| {folder_name} | [Link]({folder_url}) |\n"
# README.md 파일의 기존 내용 끝에 새로운 테이블을 추가
updated_content = original_content + new_table
return updated_content
update_readme
함수는README.md
파일을 업데이트합니다.- 먼저, 기존 내용에서 “## 📑Quest List📑” 섹션을 찾아 해당 섹션 이후의 내용을 제거합니다.
- 새로운 테이블을 생성하여 폴더 목록을 추가합니다.
README.md
파일의 기존 내용 끝에 새로운 테이블을 추가합니다.
4️⃣ 로직 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# GitHub 저장소와 폴더 목록을 설정
repo = "Kimgabe/AIFFEL_Online_Quest"
# 기존 README.md 내용을 읽어옵니다.
with open("README.md", "r") as file:
original_content = file.read()
# 저장소에서 폴더 목록을 가져오고 README.md 파일을 업데이트
folders = get_folders(repo)
updated_content = update_readme(repo, folders, original_content)
# 업데이트된 내용을 README.md 파일에 업데이트
with open("README.md", "w") as file:
file.write(updated_content)
- 저장소 이름을 설정하고
README.md
파일을 읽습니다. get_folders
함수를 통해 현재 저장소의 폴더 목록을 가져옵니다.update_readme
함수로 새로운 내용으로README.md
를 업데이트합니다.-
변경된 내용을 다시
README.md
파일에 저장합니다. - 위 코드를 적용할 수 있도록 예제 코드로 만든 전체 코드는 다음과 같습니다.
README.md
를 업데이트하는 📑전체 코드📑 입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import requests
import re
# GitHub API를 통해 특정 저장소의 폴더 목록을 가져오는 함수
def get_folders(repo):
# GitHub API를 사용하기 위한 URL 생성
url = f"https://api.github.com/repos/{repo}/contents/"
response = requests.get(url)
# API로부터 받은 응답을 JSON 형식으로 파싱하여 저장
folders = [item for item in response.json() if item['type'] == 'dir' and not item['name'].startswith('.')]
return folders
# 폴더 이름에서 숫자를 추출하는 함수
def extract_number(folder_name):
# 정규 표현식을 사용하여 폴더 이름에서 숫자를 추출
match = re.search(r'\d+', folder_name)
if match:
return int(match.group())
return float('inf') # 숫자가 없는 경우 무한대 값을 반환
# README.md 파일을 업데이트하는 함수
def update_readme(repo, folders, original_content):
# 기존 "## 📑Quest List📑" 섹션과 그 이하 내용을 제거
start_index = original_content.find("## 📑Quest List📑")
if start_index != -1:
original_content = original_content[:start_index]
# 새로운 "## 📑Quest List📑" 섹션 및 테이블을 생성
new_table = "## 📑Quest List📑\n\n"
new_table += "| 퀘스트명 | URL |\n"
new_table += "| --- | --- |\n"
# 폴더를 숫자로 정렬하여 목록을 만듭니다.
sorted_folders = sorted(folders, key=lambda x: extract_number(x['name']))
for folder in sorted_folders:
folder_name = folder['name']
folder_url = folder['html_url']
new_table += f"| {folder_name} | [Link]({folder_url}) |\n"
# README.md 파일의 기존 내용 끝에 새로운 테이블을 추가
updated_content = original_content + new_table
return updated_content
# 사용자가 자신의 GitHub 리포지토리 이름을 여기에 입력
user_repo = # Enter your GitHub repository (format: username/repository)
# 기존 README.md 내용을 읽어옵니다.
try:
with open("README.md", "r") as file:
original_content = file.read()
except FileNotFoundError:
original_content = ""
# 저장소에서 폴더 목록을 가져오고 README.md 파일을 업데이트
folders = get_folders(user_repo)
updated_content = update_readme(user_repo, folders, original_content)
# 업데이트된 내용을 README.md 파일에 업데이트
with open("README.md", "w") as file:
file.write(updated_content)
- 제가 사용하는 것과 동일하게 사용하고자 한다면 예제코드에서 본인의 github user명과 적용할 respsitory만 변경하여 사용하면 됩니다.
update_readme.py
로 repository의 가장 main 페이지에 저장하면 됩니다.- 이후 이
update_readme.py
를 GitHub Action에서 불러와서 사용하도록 할 예정입니다.
- 표의 내용을 바꾸고 싶다면
update_readme
함수의 내용을 수정하시면 됩니다. - 예제 코드 다운 받기 👉 파일 다운로드 링크
2. GitHub Action 설정
- 이제 위에서 설정한 Python 스크립트가 GitHub의 Repository에 새로운 commit이 있을 때 마다 자동으로 실행되도록 GitHub Action을 설정합니다.
1️⃣ GitHub Action 설정 항목 몇 가지를 조정
settings
👉Actions
👉General
을 선택해 GitHub Action의 옵션으로 이동합니다.
- 2가지 옵션을 확인합니다.
- Actions permisssions
Allow all actions and reusable workflows
에 체크가 되어야 합니다.
Workflow permissions
Read and write permissions
에 체크가 되어 있어야 합니다.
- Actions permisssions
2️⃣
.github/workflows
폴더 생성
- 작업을 적용할 Repository의 root dir에
.github/workflows
라는 폴더를 생성합니다.- 이 폴더는 GitHub Action의 워크플로우 설정 파일들을 저장하는 곳입니다.
3️⃣ 워크플로우 설정 파일 생성 및 설정 작성
update-readme.yml
파일을 생성한 뒤 워크플로우 설정을 작성합니다.- 워크플로우 작성시에는 2가지를 설정해주면 됩니다.
- 트리거 : 워크플로우가 언제 실행될지 설정
- 작업설정 : 워크플로우에서 실행할 작업 설정정
- 제가 사용하고 있는 워크플로우 설정은 아래와 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
name: Update README
on:
push:
branches:
- main
jobs:
update-readme:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install dependencies
run: pip install requests
- name: Update README
run: python update_readme.py
- name: Commit and Push
run: |
git config --global user.name 'Your Name'
git config --global user.email 'your-email@example.com'
git add README.md
git commit -m "Update README"
git push
- 각 내용에 대한 설명은 아래와 같습니다.
- 워크플로우 이름 설정 (
name
):Update README
: 이 워크플로우의 이름입니다. GitHub Actions 탭에서 이 이름으로 워크플로우를 찾을 수 있습니다.
- 트리거 설정 (
on
):push
: 이 워크플로우는push
이벤트에 의해 트리거됩니다.- main
:main
브랜치에 대한push
이벤트가 발생할 때마다 이 워크플로우가 실행됩니다.
- 작업 설정 (
jobs
):update-readme
: 이 작업의 ID입니다. 여기서는 ‘README 파일을 업데이트하는 작업’이라는 의미입니다.runs-on: ubuntu-latest
: 이 작업은 최신 버전의 Ubuntu 가상 환경에서 실행됩니다.
- 작업 단계 (
steps
):- Checkout: 현재 리포지토리를 체크아웃합니다. 이를 통해 리포지토리의 파일에 접근할 수 있습니다.
- Set up Python: Python 환경을 설정합니다.
python-version: '3.8'
을 통해 Python 3.8 버전을 사용하도록 설정합니다. - Install dependencies: 필요한 Python 패키지를 설치합니다. 여기서는
requests
모듈을 설치합니다. - Update README:
update_readme.py
라는 Python 스크립트를 실행합니다. 이 스크립트는README.md
파일을 업데이트하는 로직을 포함하고 있습니다. - Commit and Push: 변경된
README.md
파일을 깃허브 리포지토리에 커밋하고 푸시합니다. 사용자 이름과 이메일 주소를 설정한 후,git add
,git commit
,git push
명령을 사용합니다.
- 예제 코드 다운 받기 👉 파일 다운로드 링크
3. 스크립트 실행 및 확인
- 이제 생성한 워크플로우 파일을 저장한 뒤 실제 스크립트가 잘 작동하는지 확인합니다.
- 새로운 폴더를 추가하거나 기존 폴더 이름을 변경해
README.md
의 파일이 올바르게 업데이트 되는지 확인합니다. - 올바르게 작성이 되었다면 아래의 이미지처럼 기존 README.md의 내용을 유지하면서 repository에 포함된 폴더명을 기반으로 표를 만들고 링크가 작성되어 있을 것입니다.
- 위 작업이 적용된 저의 Repository입니다. 👉 Repository 구경하기
😀 Outro.
- 이번 포스팅에서는 GitHub Action과 파이썬을 활용해 내 GitHub의 Repository의 목록을 자동으로 업데이트하는 방법에 대해 살펴봤습니다.
- 이 방법을 적용해 프로젝트 관리를 수월하게 할 수 있고, 외부인에게 해당 Repository의 내용을 좀 더 높은 가독성과 접근성을 제공할 수 있습니다.
- 또한 이 과정을 통해 기본적인 GitHub Action의 작동 방식을 이해함으로서 다른 자동화 방법을 발굴 및 적용할 수 있을 것입니다.
댓글남기기