Skip to main content

릴리즈 업무를 "반복 작업"이 아니라 "자동 기여"로 바꾸기

릴리즈는 코드 작성보다 더 자주 사람을 소모시킵니다. 버전 올리고, 변경 로그를 정리하고, 릴리즈 노트를 쓰고, 누락된 테스트를 확인하고, 배포 결과를 기록합니다. 이 일들은 매번 조금씩 다르지만, 대부분은 같은 구조를 가집니다.

여기서 Codex의 포지션을 한 단계 바꾸면 효과가 커집니다. Codex를 "개발자 도구"로만 두지 않고, CI에서 리포지토리에 실제 변경을 남기는 자동 기여자(automatic contributor) 로 취급하는 겁니다. 즉, 사람이 하던 릴리즈 잔업을 Codex가 커밋/PR 형태로 제출하고, 사람은 승인과 최종 배포 결정만 담당합니다.

이 챕터의 목표는 다음 세 가지를 파이프라인에 묶어 반복 가능하게 만드는 것입니다.

  • Secrets로 키를 안전하게 관리한다.

  • codex exec --full-auto로 CHANGELOG/버전 파일 업데이트 같은 작업을 자동화한다.

  • 결과물을 커밋/PR/릴리즈 노트로 연결해 "릴리즈 준비 시간"을 줄인다.

왜 CI에서는 codex exec인가

GitHub Actions 같은 비대화형 환경에서 Codex를 쓰려면, 대화형 TUI가 아니라 헤드리스 실행 모드인 codex exec가 맞습니다. codex exec는 한 번의 실행(태스크)을 끝까지 밀고 나간 뒤 종료하며, 파이프에 연결하기 쉬운 출력 규칙을 갖습니다. 보통 실행 중 활동 로그는 stderr로, 최종 메시지는 stdout으로 내보내서 다른 도구와 결합하기가 좋습니다.1

권한과 안전 모드도 CI 설계의 핵심입니다.

여기서 조심할 점이 하나 있습니다. codex exec의 기본 승인/샌드박스 동작은 버전·설정·프로파일에 따라 달라질 수 있습니다. 그래서 CI에서는 "기본값을 기대"하기보다, job 단계에서 --full-auto, --sandbox ... 같은 스위치(또는 profile)를 통해 의도를 명시하는 것이 안전합니다.2

요약하면, CI에서의 기본 전략은 이렇습니다.

  • CHANGELOG 갱신, 버전 파일 수정처럼 "레포 내부 파일 변경"이 목적이면 --full-auto + 보수적 샌드박스(워크스페이스 제한)로 끝낸다.

  • 릴리즈 생성, 패키지 퍼블리시처럼 "네트워크/외부 시스템"이 얽히면 job을 분리하고, 보호 규칙(환경 승인, 브랜치 제한) 아래에서만 확장 권한을 준다.

키 관리: GitHub Secrets로 Codex를 'CI 구성원'으로 등록하기

CI에서 Codex를 움직이려면 최소 두 종류의 자격 증명이 필요합니다.

첫째는 Codex가 모델에 접근하기 위한 키입니다. 어떤 환경변수를 써야 하는지는 config.toml의 model provider 설정(env_key)에 의해 결정됩니다.1 가장 흔한 기본값은 OPENAI_API_KEY이며, Azure 등 다른 provider를 쓰면 AZURE_OPENAI_API_KEY처럼 달라질 수 있습니다.1

둘째는 리포지토리에 변경을 반영하기 위한 GitHub 토큰입니다. 단순 커밋/푸시는 GITHUB_TOKEN으로 가능하고, 조직 정책상 더 강한 권한이 필요하면 별도의 PAT를 환경별로 둘 수도 있습니다.

GitHub Actions의 Secrets는 저장 위치에 따라 레벨이 나뉩니다. 저장소(Repository), 환경(Environment), 조직(Organization) 단위로 둘 수 있고, 더 구체적인 범위가 우선합니다.3 특히 프로덕션 릴리즈에 쓰는 키는 환경 Secrets로 두고, 해당 환경에 승인 규칙(Required reviewers)을 걸어 "승인 없이는 키가 풀리지 않게" 만드는 편이 안전합니다.3

또한 워크플로에서 Secrets를 다룰 때는 다음 제약을 기억해야 합니다.

  • 포크에서 트리거된 워크플로에는(특히 GITHUB_TOKEN을 제외하면) Secrets가 전달되지 않는 것이 기본 동작입니다.3

  • Secrets는 로그에서 자동 마스킹되지만, 가장 안전한 방법은 애초에 출력하지 않는 것입니다. GitHub는 필요 시 ::add-mask::VALUE로 추가 마스킹을 권고합니다.3

마지막으로 권한은 "되게 만들기"가 아니라 "되게 하되 최소로"가 원칙입니다. GitHub는 환경 보호, CODEOWNERS, 브랜치 보호를 조합해 Secrets가 의도된 방식으로만 사용되게 설계하라고 강조합니다.4

파이프라인 설계: 사람의 개입 지점을 '릴리즈 결정'으로만 남기기

릴리즈 자동화를 잘 나누는 기준은 "사람이 책임져야 하는 결정이 어디에 있는가"입니다.

보통 다음 두 구간만 사람이 책임지면 됩니다.

  • 릴리즈 내용이 맞는지(CHANGELOG/릴리즈 노트) 승인한다.

  • 실제 배포/퍼블리시를 실행한다(프로덕션 환경 승인).

따라서 워크플로는 대개 2단(혹은 3단)으로 나누는 것이 깔끔합니다.

  • 준비 단계: Codex가 CHANGELOG/버전/릴리즈 노트 초안을 만들고 PR을 연다.

  • 배포 단계: PR이 머지된 뒤 태그/릴리즈/퍼블리시를 수행한다.

이 챕터에서는 "준비 단계를 Codex가 수행하는 패턴"을 중심으로 설명합니다.

실전 1: codex exec --full-auto로 CHANGELOG·버전 업데이트 PR 만들기

아래 예시는 릴리즈 준비 작업을 Codex에게 맡기는 워크플로입니다. 핵심은 Codex에게 "문서만 고쳐"가 아니라, 파일 변경 + 검증 + 커밋 가능한 상태까지 요구하는 것입니다.

다만 14장에서 PR 자동 생성 자체(gh/create-pull-request)의 패턴을 이미 다뤘으므로, 여기서는 "릴리즈 업무"에 필요한 부분만 남기고 PR 생성은 간단히 연결합니다.

name: release-prep-with-codex

on:
  workflow_dispatch:
    inputs:
      next_version:
        description: "예: 1.8.0"
        required: true

permissions:
  contents: write
  pull-requests: write

jobs:
  prep:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install Codex CLI
        run: npm i -g @openai/codex

      - name: Run Codex (update changelog + bump version)
        env:
          # 기본 provider(OpenAI)를 쓰는 경우 보통 OPENAI_API_KEY를 사용합니다.
          # Azure 등 다른 provider를 쓰면 env_key에 맞춰 바꾸세요.
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          codex exec --full-auto   
            -o .codex_release_notes.md   
            "Prepare release ${{ inputs.next_version }}.

            Requirements:
            - Update CHANGELOG.md for version ${{ inputs.next_version }} based on commits since the latest tag.
            - Bump version in the appropriate file(s) (package.json, pyproject.toml, etc.) depending on this repo.
            - Run the project's test command (detect from docs/scripts). Fix failures if trivial; otherwise explain.
            - Do not introduce unrelated refactors.
            - End with a concise release note draft (Markdown) and a checklist of what a human must verify."

      - name: Create release prep PR
        uses: peter-evans/create-pull-request@v8
        with:
          commit-message: "chore(release): prep v${{ inputs.next_version }}"
          title: "chore(release): prep v${{ inputs.next_version }}"
          body-path: .codex_release_notes.md
          branch: release/prep-v${{ inputs.next_version }}
          delete-branch: true

이 워크플로가 실무에서 유용한 이유는 두 가지입니다.

첫째, Codex의 최종 메시지를 -o로 파일에 저장해 PR 본문으로 그대로 사용합니다.1 릴리즈 노트를 사람이 "나중에 쓰자"로 미루지 않게 됩니다.

둘째, --full-auto로 파일 편집을 허용하되, 네트워크까지 열지 않아도 되는 범위(CHANGELOG/버전/테스트 실행)로 릴리즈 준비의 70%를 처리합니다.2 네트워크가 필요해지는 단계(패키지 퍼블리시, 클라우드 배포)는 다음 job으로 분리하는 편이 안전합니다.

실전 2: release 이벤트에서 CHANGELOG 반영을 자동화하고, Codex로 '형식/품질'을 보정하기

릴리즈를 GitHub Release로 만드는 팀이라면, 릴리즈 본문을 CHANGELOG로 반영하는 작업이 반복됩니다. 이 부분은 전용 액션으로도 자동화할 수 있습니다. 예를 들어 stefanzweifel/changelog-updater-action은 release 이벤트(예: released)에서 릴리즈 노트를 CHANGELOG에 삽입하고 커밋까지 할 수 있습니다.5

여기에 Codex를 붙이는 방식은 "대체"가 아니라 "보정"입니다.

  • 액션이 기계적으로 CHANGELOG를 업데이트한다.

  • Codex가 프로젝트 규칙에 맞게 섹션을 정리하고, 누락된 링크/범주를 보완하며, 테스트를 한 번 더 확인한다.

name: post-release-changelog-polish

on:
  release:
    types: [released]

permissions:
  contents: write

jobs:
  update:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.release.target_commitish }}
          fetch-depth: 0

      - name: Update CHANGELOG from release notes
        uses: stefanzweifel/changelog-updater-action@v1
        with:
          latest-version: ${{ github.event.release.tag_name }}
          release-notes: ${{ github.event.release.body }}

      - name: Install Codex CLI
        run: npm i -g @openai/codex

      - name: Codex polish + verify
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          codex exec --full-auto   
            "Review CHANGELOG.md formatting and consistency.
            - Keep existing style.
            - Fix obvious typos/format issues.
            - Ensure headings, links, and dates look correct.
            - Run the fastest available test/lint command and report status.
            If you change anything, keep it minimal."

      - name: Commit updated files
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

          if [[ -n "$(git status --porcelain)" ]]; then
            git add -A
            git commit -m "docs: update CHANGELOG"
            git push
          fi

여기서 포인트는 "릴리즈 이벤트가 트리거되는 브랜치/태그 정책"을 팀이 이미 갖고 있다는 전제입니다. 정책이 없다면, 먼저 14장에서 다룬 PR 기반 흐름으로 릴리즈 준비를 표준화한 다음, 릴리즈 이벤트 자동화는 그 이후에 붙이는 것이 순서상 안전합니다.

안전장치: 샌드박스·네트워크·승인 규칙을 릴리즈 단계에 맞춰 쓴다

CI에서 Codex를 굴릴 때 가장 위험한 순간은, 자동화가 외부로 "나가야" 할 때입니다. 따라서 권한은 단계별로 분리합니다.

  • 릴리즈 준비(CHANGELOG/버전/테스트): codex exec --full-auto 중심. 파일 편집은 허용하되 네트워크는 기본적으로 닫힌 상태를 유지합니다.2

  • 릴리즈/배포(퍼블리시, 배포 API 호출): 별도 job으로 분리하고, GitHub Environment(예: production)에 승인 규칙을 걸어 사람 승인 후에만 실행되게 만듭니다.3

그리고 Secrets 접근도 같은 논리로 쪼갭니다. 프로덕션 토큰은 환경 Secrets로 옮기고, 그 환경을 대상으로 하는 job에서만 environment: production을 선언해 키가 주입되게 합니다.3

운영 팁: 실패 로그를 '다음 실행의 입력'으로 남기기

자동화는 한 번에 완성되지 않습니다. 중요한 건 실패했을 때 사람이 다시 "상황 파악"을 하지 않게 만드는 것입니다.

codex exec는 최종 메시지를 파일로 저장할 수 있으니(-o) 실패 시에도 그 파일을 아티팩트로 올려 두면, 다음 사람이 PR이나 Actions 화면에서 바로 읽을 수 있습니다.1 또한 민감한 값이 로그에 섞일 가능성이 있는 단계는 GitHub가 권고하는 마스킹(::add-mask::)을 적극적으로 써서 "실수해도 새지 않게" 만드는 편이 좋습니다.3


이제 Codex는 로컬에서 코드를 도와주는 도구를 넘어, CI 안에서 변경을 제출하는 자동 기여자가 됩니다. 다음 단계는 이 자동 기여자가 어떤 권한을 가져야 하고(또 가져서는 안 되는지), 팀의 보안·프라이버시 가드레일과 어떻게 맞물려야 하는지를 정리하는 일입니다.

참고

1Codex CLI reference / configuration (OpenAI Developers)

2Non-interactive mode (OpenAI Developers)

3Using secrets in GitHub Actions

4Implementing least privilege for secrets in GitHub Actions

5Changelog Updater · Actions · GitHub Marketplace · GitHub

책 목록

OpenAI Codex 활용법: IDE·CLI·클라우드에서 코딩 에이전트로 일하기

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기