나 포함 3명에서 알고리즘 스터디를 진행하는데 한 명의 팀원이 워낙 알고리즘을 빼먹어서 주기적으로 알람을 줄 수 있는 방법이 없을까 고민하다가 해당 토이 프로젝트를 시작하게 됐다.
구현 기능
1번 기능 구현
먼저 특정 레포지토리에서 커밋 이력을 가져올 수 있는 지 확인해본다.
GitHub Actions 공식 문서에서 List commits 를 가져올 수 있는 API를 제공해주는 것을 확인했다.
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer <YOUR-TOKEN>" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/OWNER/REPO/commits
예제 응답
[
{
"url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
"sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
"node_id": "MDY6Q29tbWl0NmRjYjA5YjViNTc4NzVmMzM0ZjYxYWViZWQ2OTVlMmU0MTkzZGI1ZQ==",
"html_url": "https://github.com/octocat/Hello-World/commit/6dcb09b5b57875f334f61aebed695e2e4193db5e",
"comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/comments",
"commit": {
"url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
"author": {
"name": "Monalisa Octocat",
"email": "support@github.com",
"date": "2011-04-14T16:00:49Z"
},
"committer": {
"name": "Monalisa Octocat",
"email": "support@github.com",
"date": "2011-04-14T16:00:49Z"
},
"message": "Fix all the bugs",
"tree": {
"url": "https://api.github.com/repos/octocat/Hello-World/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e",
"sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
},
"comment_count": 0,
"verification": {
"verified": false,
"reason": "unsigned",
"signature": null,
"payload": null
}
},
"author": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"committer": {
"login": "octocat",
"id": 1,
"node_id": "MDQ6VXNlcjE=",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"parents": [
{
"url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
"sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
}
]
}
]
해당 API는 본인 GITHUB 토큰만 있으면 어떤 레포지토리든지 확인 가능했다.
해당 API를 요청하고 가장 최근에 올라온 커밋의 날짜를 확인해 전 날 올라온 커밋인지 체크한다. 예를 들면 1월 24일 0시에 액션이 돌아간다면 1월 23일 0시부터 1월 24일 0시까지 확인한다.
확인 결과는 README.md 파일에 날짜 별로 업데이트 해두려고 한다.
그리고 결과들을 추후에 활용할 수 있도록 history.json 파일에 인원 별로 날짜별 커밋 유무를 업데이트 해놓으려고 한다.
README.md 파일은 추후에 다시 꾸미는 것으로 하고 매일매일 커밋 여부 확인하는 MVP 기능만 먼저 만들겠다.
[
{
"name": "smilejune",
"repo": "daily-problem-solving/daily-ps"
},
{
"name": "2522001",
"repo": "daily-problem-solving/252"
},
{
"name": "harin1212",
"repo": "daily-problem-solving/algo"
}
]
각각의 레포지토리 리스트를 json 파일로 저장해두고 리스트에 추가, 변경이 발생 시 간편하게 바꿀 수 있도록 유도했다.
객체를 다루게 되면서 파이썬으로 작성할까 고민했지만 리눅스 상에서 반복문, 조건문을 연습하는 셈 치고 그대로 밀고 나가기로 했다.
#!/usr/bin/bash
cat $0
count=$(cat users.json | jq '. | length')
for((i = 0; i < $count; i++)); do
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{secrets.TOKEN_GITHUB}}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/daily-problem-solving/252/commits
done
해당 스크립트를 실행하려고 하는데 for문을 인식하지 못하는 문제가 있었다.
최상단에 선언된 #!/bin/sh 을 #!/bin/bash 로 변경해주었고, 현재는 #!/usr/bin/bash로 변경해봤지만 해결하지 못했다.
GitHub Actions runner 에서 기본으로 bash를 사용하고 있기 때문에 쉘 스크립트를 따로 만들어주지 않고 yml파일에 바로 작성하기로 했다.
name: algo commit autocheck
on:
schedule:
- cron: '0 15 * * 2-6'
workflow_dispatch:
jobs:
check-commit:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: check commit
run: |
count=$(cat users.json | jq '. | length')
for ((i = 0; i < count; i++)); do
cat users.json | jq -r ".[0].name" >> README.md
repo=$(cat users.json | jq -r ".[$i].repo")
latest_date=$(curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.TOKEN_GITHUB }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$repo/commits | jq -r ".[0].commit.committer.date")
done
cat README.md
on:
schedule:
- cron: '0 15 * * 1-5'
먼저 월요일 자정부터 금요일 자정까지 확인 해야하기 때문에 해당 액션은 UTC기준 월요일 15시 - 금요일 15시에 각각 돌아가면 된다.
시간은 00:00시 부터 24:00시 사이인지 확인해야 하기 때문에 UTC 기준으로는 전날 15:00 부터 당일 15:00시 사이에 있는지 확인하며 된다.
타임 스탬프는 복잡하기 때문에 epoch time으로 사이 값에 있는지 확인해준다.
중간 코드
name: algo commit autocheck
on:
schedule:
- cron: '0 15 * * 1-5'
workflow_dispatch:
jobs:
check-commit:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: check commit
run: |
count=$(cat users.json | jq '. | length')
date -u -I >> temp.txt
for ((i = 0; i < count; i++)); do
cat users.json | jq -r ".[$i].name" >> temp.txt
repo=$(cat users.json | jq -r ".[$i].repo")
latest_date=$(curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.TOKEN_GITHUB }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$repo/commits | jq -r ".[0].commit.committer.date")
latest_date_epoch=$(date -d "$latest_date" +%s)
start_date_epoch=$(date -d "yesterday 15:00" +%s)
end_date_epoch=$(date -d "today 15:00" +%s)
if [[ $latest_date_epoch -ge $start_date_epoch && $latest_date_epoch -le $end_date_epoch ]]; then
echo "Y" >> temp.txt
else
echo "N" >> temp.txt
fi
done
cat temp.txt >> README.md
정상적으로 나오는 것을 확인했고 이후에는 변경된 README.md 파일을 반영하기 위해 커밋, 푸시가 가능한 actions를 찾아서 적용했다.
아래는 최종 코드이다.
name: algo commit autocheck
on:
schedule:
- cron: '0 15 * * 1-5'
workflow_dispatch:
permissions: write-all
jobs:
check-commit:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: check commit
run: |
count=$(cat users.json | jq '. | length')
date -u -I >> temp.txt
for ((i = 0; i < count; i++)); do
cat users.json | jq -r ".[$i].name" >> temp.txt
repo=$(cat users.json | jq -r ".[$i].repo")
latest_date=$(curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.TOKEN_GITHUB }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$repo/commits | jq -r ".[0].commit.committer.date")
latest_date_epoch=$(date -d "$latest_date" +%s)
start_date_epoch=$(date -d "yesterday 15:00" +%s)
end_date_epoch=$(date -d "today 15:00" +%s)
if [[ $latest_date_epoch -ge $start_date_epoch && $latest_date_epoch -le $end_date_epoch ]]; then
echo "Y" >> temp.txt
else
echo "N" >> temp.txt
fi
echo " / " >> temp.txt
done
cat temp.txt >> README.md
rm -rf temp.txt
echo "<br>" >> README.md
- name: Commit & Push changes
uses: actions-js/push@master
with:
github_token: ${{ secrets.TOKEN_GITHUB }}
commit, push가 안되는 문제도 있었지만 permissions를 추가적으로 적용하면서 해결했다.
액션 테스트
추후에 이메일 기능과 json으로 데이터를 저장하는 기능을 구현할 예정이다.