์ƒˆ์†Œ์‹

๐Ÿ’ป Programming/GitHub

GitHub Actions๋กœ pushํ•  ๋•Œ๋งˆ๋‹ค README.md ์—…๋ฐ์ดํŠธํ•˜๊ธฐ

2023. 1. 9. 01:09

  • -

๊ทธ๋™์•ˆ ์ฝ”ํ…Œ ๋ฌธ์ œ๋Š” private ๋ ˆํฌ์— ์ €์žฅํ–ˆ์—ˆ๋Š”๋ฐ

22๋…„ 12์›”๋ถ€ํ„ฐ public์œผ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ’€์ด ๋ ˆํฌ์— ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ฆฌ๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

 

https://github.com/monzheld/Algorithms

 

GitHub - monzheld/Algorithms: ๐Ÿ ํŒŒ์ด์ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ’€์ด ๐Ÿ

๐Ÿ ํŒŒ์ด์ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ’€์ด ๐Ÿ. Contribute to monzheld/Algorithms development by creating an account on GitHub.

github.com

 

 

๋ ˆํฌ๋ฅผ ๊ณต๊ฐœํ•˜๋‹ค ๋ณด๋‹ˆ ์ปค๋ฐ‹ํ•  ๋•Œ๋งˆ๋‹ค ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ ๊ฐœ์ˆ˜๋ฅผ ์นด์šดํŠธํ•ด์„œ README.md๋ฅผ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

๊ทธ๋ž˜์„œ ์ฐพ์•„๋ณด๋˜ ์ค‘ ์•„์ฃผ ์นœ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑ๋œ ๊ธ€์„ ๋ฐœ๊ฒฌํ•ด์„œ ์ด ๊ธ€์„ ์ฐธ๊ณ ํ•ด์„œ ๋งŒ๋“ค์–ด๋ดค๋‹ค!

 

github actions๋ฅผ ํ™œ์šฉํ•˜์—ฌ push ํ•  ๋•Œ ๋งˆ๋‹ค README.md ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋ฐฉ๋ฒ•! ( feat. ์ฝ”๋”ฉ 1์ผ 1๋ฌธ์ œ! ) 

 

 

 

์ž๋™์œผ๋กœ ์นด์šดํŠธ ํ•ด์ฃผ๋Š” ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ

 

๊นƒํ—ˆ๋ธŒ ๋ ˆํฌ์— utils ํด๋”๋ฅผ ๋งŒ๋“  ๋‹ค์Œ

ํ•ด๋‹น ํด๋”์— ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ ์ˆ˜๋ฅผ ์ž๋™์œผ๋กœ ์นด์šดํŠธํ•ด์ฃผ๋Š” count_solved_problems.py๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

 

from collections import defaultdict
import os
import re


def count_solved_problems():
    """์‚ฌ์ดํŠธ๋ณ„ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ ๊ฐœ์ˆ˜ ์นด์šดํŠธ
    
    ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ์‚ฌ์ดํŠธ๋ณ„๋กœ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
    
    name_list (list): ๋””๋ ‰ํ† ๋ฆฌ๋ช…์ด์ž ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ์‚ฌ์ดํŠธ๋ช…
    code_dict (collections.defaultdict): ์‚ฌ์ดํŠธ๋ณ„๋กœ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ipynb ํŒŒ์ผ๋ช… (default: list)
    code_cnt_info (collections.defaultdict): ์‚ฌ์ดํŠธ๋ณ„๋กœ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ๊ฐœ์ˆ˜ (default: 0)
    total_code_num (int): ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ์ด๊ฐœ์ˆ˜ 
    
    Returns:
        total_code_num (int): ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ์ด๊ฐœ์ˆ˜ 
        code_cnt_info (collections.defaultdict): ์‚ฌ์ดํŠธ๋ณ„๋กœ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ๊ฐœ์ˆ˜ (default: 0)
    """    
    r = [re.findall(r"^[A-Z]+", dirctory) for dirctory in os.listdir("./")]
    name_list = [dir_name[0].replace("[", "").replace("]", "") for dir_name in r if len(dir_name) > 0]
    name_list.remove("README")

    solved_problem_list = []
    code_dict = defaultdict(list) 
    code_cnt_info = defaultdict(lambda:0) 

    for name in name_list:
        code_list = [file for file in os.listdir(f"./{name}") if file.endswith(".ipynb")] 
        code_dict[name] = code_list 
        code_cnt_info[name] = len(code_list) 
        solved_problem_list += code_list 

    total_code_num = len(solved_problem_list) 

    return total_code_num, code_cnt_info


def make_count_info(total_code_num, code_cnt_info):
    """์‚ฌ์ดํŠธ๋ณ„ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ ๊ฐœ์ˆ˜ ์ •๋ณด ์ž‘์„ฑ
    
    ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ์‚ฌ์ดํŠธ๋ณ„๋กœ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ๊ฐœ์ˆ˜ ์ •๋ณด๋ฅผ ์ž‘์„ฑํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
    
    Arguments:
        total_code_num (int): ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ์ด๊ฐœ์ˆ˜ 
        code_cnt_info (collections.defaultdict): ์‚ฌ์ดํŠธ๋ณ„๋กœ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ๊ฐœ์ˆ˜ (default: 0)
    
    Returns:
        count_info (str): ์‚ฌ์ดํŠธ๋ณ„ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ ๊ฐœ์ˆ˜ ์ •๋ณด ์ž‘์„ฑ
    """   
    count_info = f"### ํ•ด๊ฒฐํ•œ ์ด ๋ฌธ์ œ ์ˆ˜ : {total_code_num}๊ฐœ\n"

    for k,v in code_cnt_info.items():
        temp = f"- {k} - {v}๊ฐœ\n"
        count_info += temp
    
    return count_info


def make_read_me(count_info):
    """README.md ํŒŒ์ผ ์ž‘์„ฑ
    
    README.md ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
    
    Arguments:
        count_info (str): ์‚ฌ์ดํŠธ๋ณ„ ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ ๊ฐœ์ˆ˜ ์ •๋ณด ์ž‘์„ฑ
        
    Returns:
        README.md ํŒŒ์ผ์— ์ž‘์„ฑ๋  ์ถœ๋ ฅ๋ฌธ
    """   

    return f"""# Algorithms
ํŒŒ์ด์ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ’€์ด
### Since 2022.12.13 ~
{count_info}
[์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ’€์ด ๋ธ”๋กœ๊ทธ](url)
#### ๋ชจ๋“  ๋ฌธ์ œ๋Š” Python3 ๋กœ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
"""


def update_readme_md():
    """README.md ํŒŒ์ผ ์—…๋ฐ์ดํŠธ
    
    README.md ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
    
    Returns:
        README.md ํŒŒ์ผ์— ์ž‘์„ฑ๋  ์ถœ๋ ฅ๋ฌธ
    """   
    total_code_num, code_cnt_info = count_solved_problems()

    count_info = make_count_info(total_code_num=total_code_num, code_cnt_info=code_cnt_info)

    readme = make_read_me(count_info=count_info)

    return readme


if __name__ == "__main__":
    readme = update_readme_md()
    with open("./README.md", 'w', encoding='utf-8') as f:
        f.write(readme)

 

์›๋ž˜๋Š” PROGRAMMERS ํด๋” ์•ˆ์— ๋ ˆ๋ฒจ๋ณ„๋กœ ๋”ฐ๋กœ ํด๋”๋กœ ๊ตฌ๋ถ„ํ–ˆ์—ˆ๋Š”๋ฐ 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๊ฒฐํ•œ ๋ฌธ์ œ์˜ ipynb ํŒŒ์ผ๋“ค์„ ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ ธ์„œ ๋ ˆ๋ฒจ ํด๋”๋Š” ์—†์• ๊ณ  ๊ทธ๋ƒฅ ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ์‚ฌ์ดํŠธ๋ณ„๋กœ๋งŒ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋‚˜๋ˆด๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์ฐธ๊ณ ๋กœ make_read_me() ํ•จ์ˆ˜๊ฐ€ returnํ•  ์ถœ๋ ฅ๋ฌธ ๋ถ€๋ถ„์€ ์ฝ”๋“œ์— ๋‚˜์™€์žˆ๋Š” ๋Œ€๋กœ ๋“ค์—ฌ ์“ฐ๊ธฐ๋ฅผ ํ•˜์ง€ ์•Š์•„์•ผ 

๋งˆํฌ๋‹ค์šด์ด ์ œ๋Œ€๋กœ ์ ์šฉ๋ผ์„œ README.md ํŒŒ์ผ์— ๋‚˜์˜จ๋‹ค!

 

 

 

GitHub Actions ์„ค์ •ํ•˜๊ธฐ

 

Actions์˜ Python application์„ ํ™œ์šฉํ•ด์„œ workflow ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

 

# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]


jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python 3.10
      uses: actions/setup-python@v3
      with:
        python-version: "3.10"
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
    - name: Run count_solved_problems.py
      run: |
        python utils/count_solved_problems.py
    - name: Update README.md file
      run: |
        git config --local user.email "{๋ฉ”์ผ ์ฃผ์†Œ}"
        git config --local user.name "{user name}" 
        git status
        git add README.md
        git diff
        git commit -m "docs: Update README.md file"
        git push

 

์ฝ”๋“œ ์ž์ฒด๋Š” ๊ฐ„๋‹จํ•œ๋ฐ 

์ฒ˜์Œ์— ๊ณ„์† ๊ฐ™์€ ์—๋Ÿฌ๋กœ 7๋ฒˆ์ด๋‚˜ ์‹คํŒจํ–ˆ์—ˆ๋‹ค... ๐Ÿ˜… (์œ„์— ๋‚˜์˜จ ์ฝ”๋“œ๋Š” ์„ฑ๊ณตํ•œ ์ฝ”๋“œ!)

 

 

 

๊ณ„์† Error: Process completed with exit code 128. ์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋Š”๋ฐ

 

The requested URL returned error: 403 ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๋„ ์‹œ๋„ํ•ด ๋ณด๊ณ , 

Personal access tokens์˜ scope๋„ ๋ณ€๊ฒฝํ•ด๋ณด๊ณ  ํ–ˆ์ง€๋งŒ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‹ค.

 

 

  • ์ฐธ๊ณ ํ–ˆ๋˜ The requested URL returned error: 403 ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

https://velog.io/@arthur/GitHub-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0-The-requested-URL-returned-error-403

 

โš ๏ธ [GitHub] The requested URL returned error: 403

[GitHub] The requested URL returned error: 403 ์—๋Ÿฌ

velog.io

 

 

๋‚˜์ค‘์— ๋‹ค์‹œ ๋ณด๋‹ˆ ์ง„์งœ ๊ฐ„๋‹จํ•œ ๊ฒƒ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋˜ ๊ฒƒ์ด์—ˆ์Œ

 

 

๋‚ด๊ฐ€ ๋งจ ์ฒ˜์Œ ์ž‘์„ฑํ–ˆ๋˜ workflow ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์•˜๋‹ค

# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python 3.10
      uses: actions/setup-python@v3
      with:
        python-version: "3.10"
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
    - name: Run update python script
      run: |
        python utils/count_solved_problems.py
    - name: Run update README.md file
      run: |
        git config --local user.email "{๋ฉ”์ผ ์ฃผ์†Œ}"
        git config --local user.name "{user name}" 
        git status
        git add README.md
        git diff
        git commit -m "docs: Update README.md file"
        git push

 

์ €๊ธฐ ์žˆ๋Š” 'permissions:' ๋ถ€๋ถ„ ๋•Œ๋ฌธ์— ๊ณ„์† ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋˜ ๊ฒƒ์ด์—ˆ๋‹ค... 

 

๊ทธ๋ž˜์„œ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ write๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ดค๋Š”๋ฐ 

permissions:
  contents: read|write

 

Invalid workflow file ์—๋Ÿฌ๊ฐ€ ๋–ด๋‹ค

Invalid workflow file
The workflow is not valid. .github/workflows/python-app.yml (Line: 13, Col: 13): Unexpected value 'read|write'

 

  • ์ฐธ๊ณ ํ–ˆ๋˜ ๊ณต์‹ ๋ฌธ์„œ 

https://docs.github.com/ko/actions/using-jobs/assigning-permissions-to-jobs

 

์ž‘์—…์— ๊ถŒํ•œ ํ• ๋‹น - GitHub Docs

๊ฐœ์š” permissions๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GITHUB_TOKEN์— ๋ถ€์—ฌ๋œ ๊ธฐ๋ณธ ์‚ฌ์šฉ ๊ถŒํ•œ์„ ์ˆ˜์ •ํ•˜๋ฉด ํ•„์š”์— ๋”ฐ๋ผ ์•ก์„ธ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜์—ฌ ํ•„์š”ํ•œ ์ตœ์†Œ ์•ก์„ธ์Šค๋งŒ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ “์›Œํฌํ”Œ๋กœ์˜

docs.github.com

 

 

๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ permissions ๋ถ€๋ถ„์„ ์‚ญ์ œํ–ˆ๋”๋‹ˆ ๋ง๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐ๋๋‹ค..!

 

 

 

์ ์šฉ๋œ README.md ๋ชจ์Šต

 

 

! ์•ž์œผ๋กœ๋Š” actions๊ฐ€ ๋ณ€๊ฒฝํ•ด๋‘” ๋‚ด์šฉ์„ ๋กœ์ปฌ์—๋„ ๋ฐ˜์˜ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋จผ์ € pull์„ ํ•˜๊ณ  push๋ฅผ ํ•ด์•ผ ํ•จ !

 

 

์ด๋ ‡๊ฒŒ ์ •๋ฆฌํ•˜๊ณ  ๋ณด๋‹ˆ ์ƒ๋‹นํžˆ ๊ฐ„๋‹จํ•ด ๋ณด์ด์ง€๋งŒ 

์„ฑ๊ณตํ•˜๊ธฐ๊นŒ์ง€ ์ƒ๊ฐ๋ณด๋‹ค ํ—˜๋‚œํ•œ ๊ณผ์ •์ด์—ˆ๋‹คใ…‹ใ…‹ใ…‹ 

๊ทธ๋ž˜๋„ ๋•๋ถ„์— ์˜ค๋Š˜๋„ ๋งŽ์€ ๊ฑธ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ๋‹ค!

 

 

Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค!