Post

PS 자동화: 풀고 Push 하면 끝!(2)

문서 자동화를 더 효율적으로 개선해보자

PS 자동화: 풀고 Push 하면 끝!(2)

들어가며

저번에 적용했던 github actions 워크 플로우에서 다소 불편한 점이 있어 더 편리하고 효율적으로 워크 플로우를 개선해서 적용해보고자 한다.

기존의 방법과 한계

alt text

기존에는 위에 그림과 같이 Algorithm 레포지토리에서 문제의 코드를 push하면 문제에 해당하는 리드미가 생성되고 메인 레포지토리에 리드미에도 반영되는 방식이었다. 하지만 이런 방식은 내가 기존에 운영하는 기술 블로그에 반영하려면 Algorithm 레포지토리에 있는 문제 글을 복사하여 블로그 테마에 맞는 태그를 작성한 후 내 블로그 레포지토리에 한번 더 push 해야하는 불편한 일이 발생하게 된다.

이런 불편함을 기존에 작성했던 github actions를 수정하여 해결해보고자 한다.

다른 repository로의 push

alt text 위에서 설명했던 일련의 과정들을 도식화 하면 다음과 같다. 따라서 하나의 레포지토리의 actions에서 다른 repository에 write해야한다.

alt text 그러므로 github 전역 PAT 토큰을 하나 발급 받고(repo write 권한이 있는) Algorithm 레포에 적용해주면 된다.

update-readme.yml 수정

이제 Algorithm 레포에서 기존에 작성했던 워크 플로우를 수정해야한다.

기존 워크플로우

기존에는 단순히 Algorithm 레포에만 README를 생성하는 구조였다:

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
name: Update README

on:
  push:
    branches: [main]
    paths:
      - 'src/ver2/**'

jobs:
  update-readme:
    runs-on: ubuntu-latest
    
    permissions:
      contents: write
    
    steps:
      - name: code checkout
        uses: actions/checkout@v4
          
      - name: run update_readme.py
        run: python scripts/update_readme.py
        
      - name: commit
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add .
          git diff --staged --quiet || git commit -m "docs: update README.md"
          git push

개선 방안

1. 문제 정보 추출

블로그 포스트의 제목과 카테고리를 자동으로 채우려면 방금 push한 문제의 정보가 필요하다. 하지만 어떤 문제가 방금 추가되었는지 알 수 없기 때문에, 수정 시간을 기준으로 가장 최근에 변경된 폴더를 찾도록 작성했다.

1
LATEST_DIR=$(find src/ver2 -type d -maxdepth 1 -mindepth 1 -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2)

해당 폴더의 README에는 update_readme.py가 생성한 구조화된 정보가 있다. 이 중 문제명과 카테고리를 추출해야 블로그 front matter를 채울 수 있기 때문에, grepsed를 사용해 파싱하도록 작성했다.

1
2
PROBLEM_TITLE=$(grep -m 1 "^# " "$README_FILE" | sed 's/# //')
FIRST_CATEGORY=$(grep -A 1 "## 카테고리" "$README_FILE" | tail -1 | sed 's/`//g' | awk '{print $1}')

2. 파일명 자동 증가

Jekyll은 YYYY-MM-DD-title.md 형식의 파일명으로 포스트를 관리한다. 하루에 여러 문제를 풀 경우 파일명이 중복될 수 있고, 이는 기존 포스트를 덮어쓰는 문제를 일으킨다. 따라서 같은 날짜에도 순서를 보장하기 위해 날짜 뒤에 증가하는 숫자를 붙이도록 작성했다.

1
2
3
4
5
6
7
8
9
LAST_NUM=$(ls ${DATE}-*.md 2>/dev/null | sed "s/${DATE}-\([0-9]*\)\.md/\1/" | sort -n | tail -1)

if [ -z "$LAST_NUM" ]; then
  NEXT_NUM=0
else
  NEXT_NUM=$((LAST_NUM + 1))
fi

FILENAME="${DATE}-${NEXT_NUM}.md"

이렇게 하면 2026-01-15-0.md, 2026-01-15-1.md, 2026-01-15-2.md 형식으로 파일이 생성되어 중복을 방지할 수 있다.

3. Front Matter 자동 생성

블로그에서 포스트를 제대로 렌더링하려면 Jekyll 테마에 맞는 front matter가 필요하다. 매번 수동으로 작성하는 것은 번거롭기 때문에, 앞서 추출한 문제 정보를 템플릿에 자동으로 삽입하도록 작성했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat > blog-repo/_posts/${FILENAME} << EOF
---
layout: post
title: "[Algorithm] $"
description: "$ 접근방식"
date: ${DATETIME}
tags:
  - Algorithm
author: choijangwoo
toc: true
published: true
categories: [Algorithm, $]
---

EOF

Front matter만으로는 포스트 내용이 없기 때문에 이미 생성된 README 전체 내용을 이어 붙여서 저장해둔 /tmp에 있는 걸 사용했다.

1
cat /tmp/problem_readme.md >> blog-repo/_posts/${FILENAME}

4. PAT 적용

이제 워크플로우에서 PAT를 사용하여 블로그 레포지토리에 접근하는 부분인데

1
2
3
4
5
6
7
- name: checkout blog repo
  if: steps.problem_info.outputs.readme_exists == 'true'
  uses: actions/checkout@v4
  with:
    repository: choijw1004/choijw1004.github.io
    token: $
    path: blog-repo

token 파라미터에 Secret으로 등록한 PAT를 전달하면, 해당 토큰의 권한으로 다른 레포지토리를 blog-repo/ 경로에 체크아웃할 수 있어서 일반적인 git 명령어를 통해 commit, push 트리거를 작성했다.

1
2
3
4
5
6
7
8
- name: commit to blog repo
  if: steps.problem_info.outputs.readme_exists == 'true'
  run: |
    cd blog-repo
    git config user.name "github-actions[bot]"
    git config user.email "github-actions[bot]@users.noreply.github.com"
    git add .
    git diff --staged --quiet || (git commit -m "docs: add algorithm problem post" && git push)

테스트

alt text

Algorithm에 문제를 push하게 되면 성공적으로 블로그에 포스팅이 된 것을 확인할 수 있다.

마치며

혼자 공부하면서 제일 귀찮았던 작업을 자동화하니 그동안의 밀린 숙제를 해결한 기분이다. 자동화한 것이 아까워서라도 더 열심히 ps 공부를 해야겠다.

This post is licensed under CC BY 4.0 by the author.