GitHub Actions에서 워크플로우가 재트리거되지 않는 문제 — GITHUB_TOKEN, PAT, 그리고 GitHub Apps

2026-03-03 hit count image

GitHub Actions에서 GITHUB_TOKEN으로 push하면 다른 워크플로우가 트리거되지 않는 문제의 원인과, PAT와 GitHub Apps를 사용한 해결 방법을 비교하고 GitHub Apps 설정 가이드를 소개합니다.

github_actions

문제 상황

Yarn Workspaces 기반의 모노레포에서는 Dependabot이 package.json만 업데이트하고 yarn.lock은 갱신하지 않는 문제가 있습니다. 이를 해결하기 위해 Dependabot이 생성한 PR에서 yarn.lock 파일을 자동으로 업데이트하는 워크플로우를 운영하고 있었습니다. 이 워크플로우는 lockfile을 갱신한 뒤 커밋을 push하는데, push 이후 CI 워크플로우(lint, build, test 등)가 재실행되지 않는 문제가 발생했습니다.

모노레포에서의 Dependabot 운용에 대해서는 이전 포스트를 참고해 주세요.

문제가 된 워크플로우의 핵심 부분은 다음과 같습니다.

steps:
  - name: Checkout repository
    uses: actions/checkout@v4
    with:
      ref: ${{ github.head_ref }}
      token: ${{ secrets.GITHUB_TOKEN }} # 이 토큰으로 push하면 다른 워크플로우가 트리거되지 않음

  # ... yarn.lock 업데이트 ...

  - name: Commit updated lockfile
    run: |
      git add yarn.lock
      git diff --staged --quiet || git commit -m "chore: update yarn.lock"
      git push  # 이 push가 CI를 트리거하지 않음

원인

GitHub Actions에서 기본으로 제공되는 GITHUB_TOKEN으로 push하면, 다른 워크플로우가 트리거되지 않습니다. 이는 GitHub의 의도적인 설계로, 워크플로우 간 무한 재귀 실행을 방지하기 위한 것입니다.

When you use the repository’s GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN will not create a new workflow run.

GitHub Docs: Triggering a workflow from a workflow

즉, GITHUB_TOKEN으로 push한 커밋은 push 이벤트나 pull_request 이벤트의 synchronize 타입을 발생시키지 않으므로, CI 워크플로우가 실행되지 않습니다.

해결 방법 비교

이 문제를 해결하려면 GITHUB_TOKEN 대신 다른 인증 수단을 사용해야 합니다. 대표적으로 **PAT(Personal Access Token)**과 GitHub Apps가 있습니다.

항목PATGitHub Apps
소유자개인Organization
권한 범위사용자의 접근 권한에 종속앱에 설정한 권한만
토큰 수명수동 설정 (최대 1년)자동 발급, 1시간 후 만료
퇴사 리스크있음없음
감사 추적개인 계정 기반Bot 전용 계정으로 표시
Rate Limit개인 계정 공유앱 전용 (더 높은 제한)

방법 1: PAT (Personal Access Token)

가장 빠르게 적용할 수 있는 방법입니다.

설정 방법

PAT는 다음과 같은 절차로 생성하고, 설정할 수 있습니다.

  1. GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Generate new token 클릭
  3. 설정:
    • Resource owner: Organization 선택
    • Repository access: 해당 repository만 선택
    • Permissions:
      • Contents: Read and write
      • Pull requests: Read and write (필요한 경우)
  4. 생성된 토큰을 Repository의 Settings → Secrets → Actions에 등록

워크플로우 수정

이렇게 생성하고 설정한 PAT를 actions/checkout에 전달하면, push 시 다른 워크플로우가 정상적으로 트리거됩니다.

- name: Checkout repository
  uses: actions/checkout@v4
  with:
    ref: ${{ github.head_ref }}
    token: ${{ secrets.PAT_TOKEN }} # PAT로 변경

PAT의 단점

PAT는 빠르게 문제를 해결할 수 있지만, 프로덕션 환경에서 장기적으로 운영하기에는 다음과 같은 리스크가 있습니다.

항목설명
개인 계정 종속토큰 소유자가 퇴사하거나 계정이 비활성화되면 CI가 중단됨
넓은 권한 범위Fine-grained로 제한해도 개인의 접근 권한에 종속됨
수동 갱신 필요만료 기간을 설정하면 주기적으로 갱신해야 함
감사 추적커밋이 개인 계정 기반으로 추적됨

방법 2: GitHub Apps (권장)

Organization 소유의 GitHub App을 만들어 토큰을 발급받는 방법입니다. PAT의 단점을 모두 해소할 수 있으며, 프로덕션 환경에서 권장되는 방식입니다.

GitHub Apps 설정 가이드

GitHub Apps를 설정하는 과정은 다음과 같습니다.

Step 1: GitHub App 생성

Organization의 GitHub App을 생성하기 위해서는 Organization Owner 권한이 필요합니다. 권한이 있다면 다음 단계를 따라 진행합니다.

  1. GitHub에서 Organization 페이지로 이동
  2. SettingsDeveloper settingsGitHub AppsNew GitHub App

입력 항목:

항목설명
GitHub App namemy-ci-botOrganization 내 유니크한 이름
Homepage URLRepository URL필수이지만 내부용이므로 repo URL로 충분
WebhookActive 체크 해제CI 토큰 발급용이므로 웹훅 불필요

Permissions 설정 (최소 권한 원칙)

이번 문제를 해결하기 위해서 필요한 최소 권한은 다음과 같습니다. 나머지 권한은 모두 불필요하므로, 최소 권한 원칙에 따라 필요한 권한만 부여합니다.

Repository permissions:

PermissionAccess용도
ContentsRead and write코드 push
MetadataRead-only자동 선택됨
Pull requestsRead and writePR 관련 작업이 필요한 경우

Organization permissions / Account permissions: 모두 불필요

설치 범위

이번 문제는 특정 repository에서 발생하는 문제이므로, GitHub App의 설치 범위를 Only on this account로 제한합니다. 이렇게 하면 App이 다른 repository에 설치되는 것을 방지할 수 있습니다.

  • Where can this GitHub App be installed?Only on this account

Create GitHub App 클릭으로 생성을 완료합니다.

Step 2: Private Key 생성

GitHub App을 사용하려면 App ID와 Private Key가 필요합니다. App ID는 App 설정 페이지 상단에서 확인할 수 있고, Private Key는 다음 절차로 생성할 수 있습니다.

  1. 생성된 App 설정 페이지에서 App ID를 메모 (페이지 상단에 표시됨)
  2. 페이지 하단 Private keys 섹션 → Generate a private key 클릭
  3. .pem 파일이 자동 다운로드됨

이 두 값(App ID, Private Key)이 이후 워크플로우에서 토큰을 발급받는 데 사용됩니다.

Step 3: Repository에 App 설치

이렇게 생성한 GitHub App을 실제로 사용할 repository에 설치해야 합니다. 다음 단계를 통해 GitHub App을 설치합니다.

  1. App 설정 페이지 좌측 메뉴 → Install App
  2. Organization 선택 → Install
  3. Only select repositories → 대상 repository 선택
  4. Install 클릭

Step 4: Secrets 등록

이제 App ID와 Private Key를 GitHub Actions에서 사용할 수 있도록 Secrets로 등록합니다.

Repository Settings → Secrets and variables 에서 ActionsDependabot 각각에 동일한 Secret을 등록합니다.

  • Actions: Settings → Secrets and variables → ActionsNew repository secret
  • Dependabot: Settings → Secrets and variables → DependabotNew repository secret
Secret Name
MY_CI_BOT_APP_IDStep 2에서 확인한 App ID
MY_CI_BOT_PRIVATE_KEY.pem 파일의 전체 내용
Note

왜 두 곳 모두에 등록해야 하나요?

GitHub Actions는 워크플로우를 트리거한 주체에 따라 참조하는 secrets 저장소가 다릅니다. Dependabot이 트리거한 워크플로우는 공급망 공격 방지를 위해 제한된 보안 컨텍스트에서 실행되며, Dependabot secrets만 참조할 수 있습니다. 반면 일반적인 이벤트(수동 push, 일반 PR, workflow_dispatch 등)로 트리거된 워크플로우는 Actions secrets를 참조합니다. 따라서 동일한 워크플로우가 어떤 주체에 의해 트리거되더라도 정상 동작하려면 양쪽 모두에 등록해야 합니다.

GitHub Docs: Using secrets with Dependabot

.pem 파일 내용은 아래와 같은 형식입니다. 전체를 그대로 복사해서 등록합니다.

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
...
-----END RSA PRIVATE KEY-----
Tip

여러 repository에서 같은 App을 사용한다면, Organization Settings → Secrets에 등록하면 공유할 수 있습니다.

Step 5: 워크플로우 수정

actions/create-github-app-token 액션을 사용하여 런타임에 토큰을 생성합니다.

steps:
  # 1. checkout은 GITHUB_TOKEN(read)으로 — 토큰을 .git/config에 남기지 않음
  - name: Checkout repository
    uses: actions/checkout@v4
    with:
      ref: ${{ github.head_ref }}
      persist-credentials: false

  # 2. 의존성 설치 (이 시점에서 .git/config에 credential 없음 → 안전)
  - name: Setup node
    uses: actions/setup-node@v4
    with:
      node-version-file: '.nvmrc'

  - name: Update lockfile
    run: yarn install --no-immutable

  # 3. push 직전에만 App 토큰 생성 → 노출 시간 최소화
  - name: Generate GitHub App token
    id: app-token
    uses: actions/create-github-app-token@v1
    with:
      app-id: ${{ secrets.MY_CI_BOT_APP_ID }}
      private-key: ${{ secrets.MY_CI_BOT_PRIVATE_KEY }}

  # 4. 토큰으로 remote URL 설정 후 push
  - name: Commit and push
    run: |
      git config user.name "my-ci-bot[bot]"
      git config user.email "<APP_ID>+my-ci-bot[bot]@users.noreply.github.com"
      git remote set-url origin "https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git"
      git add .
      git diff --staged --quiet || git commit -m "chore: automated update"
      git push

핵심 포인트는 다음과 같습니다.

  • actions/create-github-app-token@v1이 App ID와 Private Key로 **설치 토큰(installation token)**을 발급
  • 이 토큰은 약 1시간 동안 유효하며, 워크플로우 실행마다 새로 발급됨
  • 이 토큰으로 push하면 다른 워크플로우가 정상적으로 트리거됨
  • git commit의 author는 <app-name>[bot] 형식을 사용

보안: 토큰 노출 범위를 최소화하는 구성

보안을 위해서는 단순히 GITHUB_TOKEN을 GitHub App 토큰으로 교체하는 것만으로는 충분하지 않습니다. 토큰이 노출되는 시간과 범위도 고려해야 합니다.

actions/checkout은 기본적으로 persist-credentials: true이므로, 전달한 토큰을 .git/configextraheader에 저장합니다. 만약 App 토큰으로 checkout한 뒤 yarn install을 실행하면, 의존 패키지의 post-install script.git/config를 읽어 write 권한을 가진 토큰을 탈취할 수 있습니다.

Dependabot PR은 외부 패키지를 업데이트하는 것이므로, 이 공급망(supply chain) 공격 시나리오에 특히 취약합니다.

[위험한 구성]
checkout (App token) → .git/config에 토큰 저장 → yarn install → post-install script가 토큰 탈취 가능

[안전한 구성]
checkout (persist-credentials: false) → .git/config에 토큰 없음 → yarn install (안전) → App 토큰 생성 → push

이를 방지하기 위해서는 다음과 같은 구성을 권장합니다.

  1. persist-credentials: false: checkout 시 .git/config에 credential을 저장하지 않음
  2. 토큰 생성을 push 직전으로 이동: yarn install 등 외부 코드 실행 이후에 토큰을 생성
  3. git remote set-url로 push 시에만 토큰 사용: 토큰이 필요한 순간에만 설정

permissions 설정에 대한 주의점

GitHub App 토큰으로 전환하면 잡의 permissions 블록도 재검토해야 합니다. permissionsGITHUB_TOKEN에 대한 권한 설정이므로, 잡 내에서 GITHUB_TOKEN을 사용하지 않는다면 contents: write를 부여할 필요가 없습니다.

# Before: GITHUB_TOKEN으로 push하므로 write 필요
permissions:
  contents: write

# After: push는 GitHub App 토큰이 담당하므로 read로 충분
permissions:
  contents: read

최소 권한 원칙에 따라, 실제로 사용하지 않는 토큰에 불필요한 권한을 부여하지 않도록 하는 것이 보안 강화에 도움이 됩니다.

테스트 방법

GitHub App 토큰이 올바르게 작동하는지 확인하기 위해, 아래와 같은 테스트 워크플로우를 만들어 검증할 수 있습니다.

name: Test GitHub App Token

on:
  push:
    branches:
      - test/app-token # 테스트용 브랜치에서만 실행

jobs:
  test-token:
    name: Test App Token
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Generate GitHub App token
        id: app-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.MY_CI_BOT_APP_ID }}
          private-key: ${{ secrets.MY_CI_BOT_PRIVATE_KEY }}

      - name: Verify token was generated
        run: |
          if [ -z "${{ steps.app-token.outputs.token }}" ]; then
            echo "::error::Token generation failed"
            exit 1
          fi
          echo "Token generated successfully"

      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          token: ${{ steps.app-token.outputs.token }}

      - name: Test push (empty commit on temp branch)
        run: |
          git config user.name "my-ci-bot[bot]"
          git config user.email "<APP_ID>+my-ci-bot[bot]@users.noreply.github.com"
          git checkout -b test/app-token-verify
          git commit --allow-empty -m "test: verify GitHub App token push"
          git push origin test/app-token-verify
          echo "Push succeeded"

      - name: Cleanup temp branch
        if: always()
        run: git push origin --delete test/app-token-verify || true

테스트 순서

이렇게 작성한 테스트 워크플로우를 test/app-token 브랜치에 추가하고 push하면, 다음과 같은 과정을 통해 설정이 올바른지 검증할 수 있습니다.

  1. 위 워크플로우 파일을 test/app-token 브랜치에 추가하고 push
  2. Actions 탭에서 워크플로우 실행 결과 확인
  3. 각 스텝 성공 여부로 설정 검증:
    • Generate token 성공 → Secrets 설정이 올바름
    • Checkout 성공 → 토큰으로 repo 접근 가능
    • Push 성공 → 토큰으로 push 가능
  4. 테스트 완료 후 워크플로우 파일 삭제

트러블슈팅

에러 메시지원인해결
could not create workflow dispatch event: HTTP 404App이 repository에 설치되지 않음Step 3의 Install App 확인
The permissions requested are not granted to this installationApp의 권한 부족App Settings → Permissions에서 권한 추가
Could not resolve to a valid refPrivate Key가 잘못됨.pem 파일 전체 내용이 Secret에 등록되었는지 확인
Resource not accessible by integration설치 범위 문제App이 해당 repository에 설치되었는지 확인

마무리

GitHub Actions에서 GITHUB_TOKEN으로 push하면 다른 워크플로우가 트리거되지 않는 것은 무한 재귀를 방지하기 위한 의도적인 설계입니다. 이를 해결하는 방법은 크게 두 가지입니다.

방법적합한 상황
PAT빠른 임시 해결이 필요한 경우
GitHub Apps프로덕션 환경에서 권장되는 방법

GitHub Apps는 초기 설정에 Organization Owner 권한이 필요하다는 진입 장벽이 있지만, 한 번 설정하면 개인에 종속되지 않는 안전하고 관리하기 쉬운 토큰 관리가 가능합니다. 특히 Dependabot PR처럼 외부 패키지를 다루는 워크플로우에서는 토큰 노출 범위를 최소화하는 구성까지 고려하는 것을 추천합니다.

참고 자료

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

앱 홍보

책 홍보

블로그를 운영하면서 좋은 기회가 생겨 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.



SHARE
Twitter Facebook RSS