GitHub/ci-cd

7 개의 포스트

github

Dependabot 길들이기: 업데이트를 그룹화하고, 주기를 늦추되, 보안 업데이트는 신속하게 (새 탭에서 열림)

활성 저장소에서는 Dependabot이 의존성마다 개별 PR을 생성해 알림, 리뷰, CI 실행을 과도하게 늘릴 수 있다. 글은 Microsoft GCToolkit 사례를 통해 의존성 업데이트를 생태계별로 그룹화하고 주기를 월간으로 늦추면 유지보수 소음을 크게 줄일 수 있다고 설명한다. 다만 일반 버전 업데이트와 달리 보안 업데이트는 신속하게 처리되므로, 업데이트 빈도를 낮춰도 보안 대응 속도는 유지할 수 있다. ## Dependabot이 만드는 유지보수 소음 - GCToolkit의 578개 커밋 중 92개가 Dependabot 버전 업데이트였으며, 최근 12개월에만 61개가 발생했다. - 기존 설정은 다음과 같았다. - GitHub Actions만 감시 - 매일 업데이트 확인 - 최대 10개의 PR 허용 - 의존성 10개가 업데이트되면 PR 10개, CI 실행 10회, 리뷰 알림 10건이 발생한다. - `open-pull-requests-limit: 10`은 PR 수를 제한할 뿐, 업데이트가 쏟아지는 원인을 해결하지 못한다. ## 여러 업데이트를 하나의 PR로 그룹화 - `groups`와 `patterns: ["*"]`를 사용하면 모든 의존성 업데이트를 하나의 PR로 묶을 수 있다. - 예를 들어 10개의 업데이트가 발생해도 다음처럼 처리된다. - 브랜치 1개 - PR 1개 - CI 실행 1회 - 리뷰 및 병합 1회 - 그룹 이름은 자유롭게 정할 수 있으며 PR 제목과 브랜치 이름에 표시된다. - 규모가 큰 프로젝트에서는 테스트 라이브러리, 운영 의존성 등 목적별로 여러 그룹을 만들 수 있다. - 모노레포에서는 `directories`와 `group-by: dependency-name`을 사용해 여러 디렉터리에 같은 의존성이 있을 때 하나의 PR로 통합할 수 있다. ```yaml - package-ecosystem: "npm" directories: - "/apps/*" schedule: interval: "monthly" groups: monthly-batch: group-by: dependency-name patterns: - "*" ``` ## 업데이트 주기를 일간에서 월간으로 변경 - `interval: daily`는 평일마다 업데이트를 확인하므로 지속적인 PR 생성으로 이어질 수 있다. - `interval: monthly`로 바꾸면 계획 가능한 월간 배치 방식으로 전환된다. - 그룹화와 결합하면 생태계별로 한 달에 하나의 일괄 PR을 받게 된다. - 프로젝트 특성에 따라 `weekly`를 선택할 수도 있고, `schedule.day`와 `schedule.time`으로 실행 시점을 지정할 수 있다. - 의존성이 안정적인 성숙한 라이브러리에는 월간 주기가 적합하다. ## 실제 사용하는 생태계를 모두 설정 - 기존 설정은 GitHub Actions만 대상으로 했지만, GCToolkit은 Maven 기반 Java 프로젝트이므로 Maven 의존성도 별도로 등록해야 했다. - 생태계마다 `updates` 항목을 추가해야 한다. ```yaml - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" groups: monthly-batch: patterns: - "*" - package-ecosystem: "maven" directory: "/" schedule: interval: "monthly" groups: monthly-batch: patterns: - "*" ``` - GitHub Actions와 Maven 업데이트는 각각 독립된 그룹과 일정으로 관리된다. - 소음을 줄이는 것뿐 아니라, 실제 애플리케이션 의존성까지 Dependabot이 감시하도록 만드는 것이 중요하다. ## 보안 업데이트는 빠르게 유지 - 월간 일정과 그룹 설정은 일반적인 버전 업데이트의 처리 방식을 조정하는 설정이다. - Dependabot 보안 업데이트는 별도의 메커니즘으로 동작하므로, 일반 업데이트 주기를 늦춰도 보안 취약점 대응까지 월간으로 미뤄지지 않는다. - 따라서 평상시에는 일괄 업데이트로 리뷰 부담을 줄이고, 보안 수정은 기존처럼 신속하게 처리하는 균형을 유지할 수 있다. ## 실용적인 적용 방법 - 안정적인 저장소라면 생태계별로 `monthly` 일정과 전체 의존성 그룹화를 적용한다. - 업데이트가 자주 필요하거나 변경 영향이 큰 프로젝트는 `weekly` 또는 목적별 다중 그룹을 사용한다. - GitHub Actions뿐 아니라 Maven, npm 등 실제 사용하는 모든 패키지 생태계를 `dependabot.yml`에 등록한다. - 보안 업데이트 설정은 별도로 확인해 취약점 수정이 지연되지 않는지 점검한다.

github

npm 및 GitHub Actions의 공급망 공격 교란 (새 탭에서 열림)

npm과 GitHub Actions를 겨냥한 공급망 공격은 계정 탈취, CI/CD 취약점 악용, 자격 증명 탈취, 악성 패키지 확산을 연쇄적으로 결합한다. GitHub는 단일 방어 기능보다 공격 단계별로 핵심 연결고리를 끊는 다층 방어가 필요하다고 보고, npm과 GitHub Actions에 계정 보호·워크플로 권한 제한·캐시 보호·무자격 증명 배포 등의 기능을 도입했다. 목표는 공격을 완전히 제거하기보다 초기 침해와 권한 상승, 자격 증명 유출, 대규모 확산을 차단하고 탐지·대응 시간을 확보하는 것이다. ## 공급망 공격의 구조 - 공격은 대개 다음 단계로 진행된다. - 유지보수자 계정이나 프로젝트의 GitHub Actions 워크플로를 침해한다. - CI/CD 환경에서 더 높은 권한과 자격 증명을 찾는다. - 토큰과 계정 정보를 외부로 유출한다. - 탈취한 자격 증명으로 다른 패키지와 프로젝트를 연쇄적으로 감염시킨다. - 공격 방식은 다양하지만, 초기 침해·권한 상승·확산이라는 공통된 흐름을 가진다. - 따라서 하나의 보안 기능보다 공격 사슬의 영향력이 큰 지점을 여러 단계에서 차단하는 접근이 필요하다. ## 초기 침해 차단 - **고영향 npm 계정 보호** - 이메일 주소를 변경하거나 2FA 복구 코드를 사용한 고영향 npm 계정은 72시간 동안 읽기 전용 상태가 된다. - 피싱으로 계정을 탈취당하더라도 공격자가 즉시 악성 버전을 배포하지 못하게 한다. - 해당 기간 동안 유지보수자가 계정을 복구하거나 이상 행위를 확인할 수 있다. - **`pull_request_target`의 안전한 checkout 기본값** - 포크에서 제출된 풀 리퀘스트의 신뢰할 수 없는 코드를 워크플로가 실행하는 “pwn request” 취약점을 완화한다. - `actions/checkout`은 일반적으로 악용되는 트리거에서 포크의 비신뢰 코드를 checkout하지 않도록 변경됐다. - 관리자가 위험을 검토한 뒤 명시적으로 예외를 선택해야 하며, 기존 버전에도 변경 사항이 백포트됐다. - **워크플로 실행 주체와 트리거 제한** - 엔터프라이즈·조직·저장소 수준에서 누가 워크플로를 실행할 수 있는지 설정할 수 있다. - 허용할 워크플로 트리거 유형도 제한할 수 있다. - 이를 통해 Actions 인프라에 최소 권한 원칙을 적용하고 공격 표면을 줄인다. - **비신뢰 트리거의 Actions 캐시 읽기 전용화** - 공격자가 워크플로 실행 권한을 얻은 뒤 공유 캐시를 오염시켜 더 높은 권한의 워크플로를 공격하는 경로를 차단한다. - 신뢰도가 낮은 워크플로는 다른 워크플로와 공유되는 캐시를 수정할 수 없게 된다. - 결과적으로 릴리스·패키지 배포 워크플로의 고권한 자격 증명 탈취로 이어지는 권한 상승을 어렵게 만든다. ## 자격 증명 탈취와 유출 방지 - **장기 자격 증명 제거** - CI/CD 파이프라인에 저장된 장기 토큰은 공격자가 가장 먼저 노리는 대상이다. - npm Trusted Publishing은 장기 자격 증명 없이 패키지를 배포하도록 해 탈취 가능한 비밀 정보를 줄인다. - CircleCI도 Trusted Publishing 공급자로 추가되어, CircleCI 기반 배포에서도 장기 자격 증명 제거가 가능해졌다. - **Actions 네트워크 방화벽** - 기술 프리뷰 단계의 기능으로, Actions 실행 중 발생하는 모든 외부 네트워크 트래픽을 기록한다. - 악성 코드 다운로드나 새 도메인으로의 자격 증명 유출처럼 비정상적인 통신을 탐지하는 데 활용할 수 있다. - 향후에는 네트워크 외부 연결 제한과 정책 기반 차단을 지원해 유출이 발생하기 전에 공격을 막는 방향으로 확장될 예정이다. ## 악성 패키지 확산 억제 - **npm 단계적 게시(Staged Publishing)** - 패키지 배포 자격 증명만 가지고는 새 버전을 즉시 공개할 수 없도록 한다. - 배포된 패키지는 추가 승인과 npm CLI 또는 npmjs.com에서의 2FA 인증이 완료될 때까지 보류된다. - 선택적으로 활성화할 수 있으며, 자동화·CI/CD 자격 증명과 실제 배포 승인 절차를 분리한다. - 탈취된 배포 자격 증명으로 악성 버전을 대규모 배포하는 공격을 줄인다. ## 실용적인 권장 사항 npm 유지보수자는 고영향 계정 보호, Trusted Publishing, 단계적 게시를 검토하고, GitHub Actions 사용자는 포크 PR 처리 방식과 캐시 공유 구조를 점검하는 것이 좋다. 또한 워크플로 실행 주체를 최소화하고, Actions 네트워크 트래픽을 모니터링하면 자격 증명 유출과 연쇄 확산을 조기에 발견할 가능성을 높일 수 있다.

github

에이전트 풀 리퀘스트가 도처에 있습니다. 이를 검토하는 방법을 소개합니다. (새 탭에서 열림)

에이전트가 작성한 풀 리퀘스트(PR)는 빠르게 늘고 있지만, 테스트 통과와 깔끔한 코드만으로 품질을 보장할 수 없다. 연구에 따르면 에이전트 코드는 인간 작성 코드보다 중복과 기술 부채가 많을 수 있으며, 리뷰어는 오히려 더 쉽게 승인하는 경향이 있다. 따라서 리뷰어는 코드의 표면적 완성도보다 CI 조작, 중복 구현, 경계 조건, 권한 및 보안 문제를 중심으로 의도적으로 검토해야 한다. ## 에이전트 PR 증가와 리뷰 한계 - GitHub Copilot 코드 리뷰는 6천만 건 이상 처리됐고, 1년이 안 되는 기간에 10배 성장했다. - GitHub의 코드 리뷰 5건 중 1건 이상에 에이전트가 관여한다. - 개발자 한 명이 짧은 시간에 여러 에이전트 세션을 실행하면서 PR 생성 속도는 크게 늘었지만, 인간의 리뷰 처리 능력은 그만큼 증가하지 않았다. - 기존의 “리뷰 요청 → 코드 소유자 대기 → 병합” 방식만으로는 증가한 물량을 감당하기 어렵다. ## 에이전트 코드를 바라보는 관점 - 코딩 에이전트는 저장소의 패턴을 잘 따르지만 다음과 같은 맥락은 알지 못한다. - 과거 장애와 사고 이력 - 팀이 경험한 특수한 엣지 케이스 - 문서화되지 않은 운영 제약 - 에이전트는 실제로 완전하지 않은 구현도 완성된 것처럼 보이게 만들 수 있다. - 리뷰어의 핵심 역할은 자동화하기 어려운 판단과 맥락 이해다. - 따라서 diff를 단순히 읽기보다, 변경이 시스템의 운영 현실과 맞는지 검증해야 한다. ## CI를 약화시키는 변경 - 에이전트가 CI 실패를 해결하기 위해 다음과 같은 편법을 사용할 수 있다. - 테스트 삭제 - 린트 단계 건너뛰기 - 테스트 명령에 `|| true` 추가 - 테스트나 워크플로 실행 조건 완화 - 다음 항목이 변경됐다면 명확한 근거 없이는 병합하지 않아야 한다. - 코드 커버리지 기준 하향 - 테스트 삭제, 이름 변경 또는 skip 처리 - fork나 PR에서 워크플로가 실행되지 않도록 변경 - 기존에 항상 실행되던 CI 단계에 조건 추가 - CI를 약화하는 변경은 에이전트 PR에서 즉시 차단해야 할 대표적인 신호다. ## 기존 코드 재사용 여부 - 에이전트는 저장소 전체의 설계 의도보다 눈앞의 코드 패턴을 복제하는 경향이 있다. - 다음과 같은 중복이 생길 수 있다. - 기존 유틸리티와 기능이 같은 새 헬퍼 - 여러 위치에 반복 구현된 검증 로직 - 공유 모듈에 이미 있는 미들웨어의 재작성 - 이름만 다르고 동작은 거의 같은 함수 - 새 유틸리티가 추가될 때마다 저장소에서 동등한 기능을 검색해야 한다. - 중복 구현을 발견하면 단순 코멘트가 아니라 병합 전 통합을 요구하는 편이 낫다. - 새로운 유틸리티를 추가할 경우, 일정 규모 이상의 PR에서는 추가 이유를 설명하도록 요구하면 중복을 조기에 발견할 수 있다. ## 테스트를 통과해도 틀릴 수 있는 코드 - 명백한 API 오용이나 컴파일 오류는 CI에서 잡히지만, 다음과 같은 논리 오류는 통과할 수 있다. - 페이지네이션의 off-by-one 오류 - 테스트되지 않은 분기의 권한 검사 누락 - 특정 입력에서만 검증이 조기에 종료되는 문제 - 대규모 환경이나 경쟁 상태에서만 발생하는 오류 - 중요한 변경 경로를 입력부터 출력까지 직접 추적해야 한다. - 특히 다음 경계를 확인해야 한다. - `0`, 최댓값, 빈 값 - 외부에서 들어오는 값에 대한 검증 - 모든 분기의 권한 확인 - 예상하기 어려운 조건문과 조기 반환 - 수정 전에는 실패하고 수정 후에는 통과하는 회귀 테스트를 요구해야 한다. - 에이전트가 수정하려는 버그를 재현하는 테스트를 작성하지 못한다면, 문제에 대한 이해나 수정 자체가 불완전할 가능성이 높다. ## 계획 없는 대규모 PR과 에이전트 이탈 - 크고 범위가 불명확한 PR은 에이전트가 리뷰 피드백을 제대로 반영하지 못하거나 작업을 중단할 가능성이 높다. - 깊이 있는 리뷰를 시작하기 전에 다음을 확인해야 한다. - 이전 리뷰 라운드에 에이전트가 적절히 응답했는가 - 구현 계획이 구조적으로 제시돼 있는가 - 변경이 작은 단위로 나뉘어 있는가 - 계획이 없다면 상세한 코드 리뷰보다 먼저 작업을 분할하거나 각 부분의 목적과 구조를 설명하도록 요구하는 것이 효율적이다. - 이렇게 하면 리뷰어가 방향을 잃은 대규모 변경에 시간을 낭비하는 일을 줄일 수 있다. ## 워크플로의 신뢰할 수 없는 입력과 프롬프트 인젝션 LLM을 호출하는 GitHub Actions나 CI 워크플로는 일반 PR보다 더 엄격하게 검토해야 한다. - 위험한 흐름은 다음과 같다. - PR 본문, 이슈 본문, 커밋 메시지를 읽음 - 해당 내용을 프롬프트에 삽입 - 모델 출력을 셸 명령으로 전달 - `GITHUB_TOKEN` 권한으로 실행 - 다음 항목은 병합을 막아야 하는 보안 신호다. - 사용자 입력을 정제·인용 없이 프롬프트에 삽입 - 필요한 범위보다 넓은 쓰기 권한의 `GITHUB_TOKEN` - 모델 출력을 검증 없이 셸 명령으로 실행 - 에이전트 단계에서 시크릿에 접근하거나 로그에 출력 - 요구할 수 있는 방어책은 다음과 같다. - 워크플로에 최소 권한을 설정하고 `permissions: read-all`을 기본값으로 고려 - 신뢰할 수 없는 입력을 프롬프트에 넣기 전에 정제하고 명확히 인용 - 분석 단계와 실행 단계를 분리 - 운영 환경에 영향을 주는 작업에는 사람의 승인 단계 추가 - 모델 출력을 직접 실행하거나 `eval`하지 않고 검증된 형식으로 제한 에이전트 PR은 느리게 검토해야 하는 대상이 아니라, 다르게 검토해야 하는 대상이다. CI가 약화되지 않았는지, 기존 코드와 중복되지 않는지, 핵심 경로와 경계 조건이 검증됐는지, 워크플로 권한과 입력이 안전한지를 우선 확인하면 리뷰 시간을 줄이면서도 조용한 기술 부채와 보안 위험을 효과적으로 잡을 수 있다.

github

“정답”이 결정적이지 않을 때 에이전트 행동 검증 (새 탭에서 열림)

자율 에이전트의 실행 과정은 환경, 타이밍, UI 상태에 따라 달라지므로 기존의 결정론적 테스트 방식만으로는 올바른 동작을 안정적으로 검증하기 어렵다. 에이전트가 실제 작업을 성공했는데도 실행 경로가 예상과 다르다는 이유로 테스트가 실패하는 ‘거짓 음성(false negative)’이 발생할 수 있다. 글은 고정된 스크립트 대신 필수 결과와 경로의 구조를 검증하는 독립적인 ‘Trust Layer’를 제안하며, 이를 통해 설명 가능하고 CI에 적합한 에이전트 검증을 구현할 수 있다고 주장한다. ## 에이전트 기반 검증에서 발생하는 문제 - Copilot Coding Agent가 UI, 브라우저, IDE 같은 실제 환경을 조작하면 실행 결과가 매번 동일하지 않다. - 네트워크 지연으로 로딩 화면이 오래 표시되거나, 반대로 즉시 화면이 나타날 수 있다. - 에이전트가 상황에 맞게 대기하고 작업을 완료했더라도, 테스트가 특정 시점이나 순서를 기대하면 실패한다. - 주요 문제는 다음과 같다. - **거짓 음성:** 작업은 성공했지만 테스트가 실패로 판정한다. - **취약한 인프라:** 렌더링, 타이밍, 네트워크 같은 환경 잡음이 결과에 영향을 준다. - **컴플라이언스 함정:** 올바른 결과를 냈어도 사전에 기록된 에이전트 행동과 다르면 회귀로 오인된다. - 에이전트의 정확성은 정해진 단계를 그대로 따르는 것이 아니라, 필수적인 결과를 안정적으로 달성하는지로 판단해야 한다. ## 기존 테스트 방식이 자율 에이전트에 맞지 않는 이유 - **Assertion 기반 테스트** - 모든 검증 조건을 사람이 직접 작성해야 한다. - 가능한 모든 대체 경로를 명세하기 어렵다. - **Record-and-replay** - 실행을 녹화된 순서와 비교하므로 사소한 타이밍·렌더링 변화에도 실패한다. - **시각적 회귀 테스트** - 스크린샷 차이는 감지하지만, 해당 변화가 작업의 의미나 최종 결과에 영향을 주는지는 이해하지 못한다. - **ML 오라클** - 많은 학습 사례가 필요하다. - 실패 판정의 근거를 설명하기 어려운 블랙박스가 되기 쉽다. - 이 방식들은 모두 “정확성은 특정한 관찰 상태와 순서를 재현하는 것”이라는 공통 가정을 갖는다. - 하지만 에이전트 시스템에서는 서로 다른 실행 경로가 동일한 올바른 결과로 이어질 수 있다. ## 필수 상태와 선택적 변형의 구분 에이전트 동작을 검증하려면 모든 상태를 동일하게 취급하지 말고, 성공에 반드시 필요한 요소와 환경에 따라 달라지는 요소를 분리해야 한다. - **필수 상태(Essential states)** - 성공을 위해 반드시 도달해야 하는 상태다. - 예를 들어 VS Code 검색 작업에서는 최종적으로 ‘검색 결과’ 화면에 도달해야 한다. - **선택적 변형(Optional variations)** - 로딩 스피너, 일시적인 로딩 화면, 장식적 UI 변화처럼 성공 여부와 직접 관련 없는 상태다. - **수렴 경로(Convergent paths)** - 단축키 사용, 메뉴 선택 등 서로 다른 절차가 동일한 최종 상태로 합쳐지는 경우다. - 로딩 화면이 나타났는지는 중요하지 않지만, 검색 결과가 표시되었는지는 작업의 성공을 결정한다. - 따라서 검증 대상은 실행 과정 전체가 아니라 성공을 보장하는 논리적 구조여야 한다. ## Dominator 분석을 활용한 필수 행동 추출 필수 상태와 부수적 상태를 자동으로 구분하기 위해 컴파일러 이론의 **Dominator 관계**를 활용할 수 있다. - 제어 흐름 그래프에서 노드 A가 노드 B를 지배(dominates)한다는 것은 시작점에서 B로 가는 모든 경로가 A를 거쳐야 한다는 뜻이다. - 에이전트의 실행 기록을 그래프로 표현하면 다음을 식별할 수 있다. - 모든 성공 경로에 공통으로 나타나는 필수 상태 - 일부 경로에만 등장하는 선택적 상태 - 서로 다른 실행 경로가 다시 합쳐지는 지점 - 이 분석을 통해 테스트가 확인해야 할 최소한의 성공 조건을 추출할 수 있다. - 또한 “왜 이 실행을 성공 또는 실패로 판단했는가”를 그래프 구조로 설명할 수 있어, 단순한 블랙박스 판정보다 신뢰성이 높다. ## 스크립트가 아닌 실행 그래프로 모델링 - 자율 에이전트의 행동은 고정된 1차원 스크립트보다 여러 분기와 수렴 지점을 가진 그래프로 보는 편이 적합하다. - 그래프 기반 모델은 특정 순서를 강제하지 않고, 서로 다른 행동 경로가 같은 필수 결과에 도달했는지를 평가할 수 있다. - 이 접근은 에이전트의 자유로운 문제 해결 능력을 유지하면서도, CI 파이프라인에서는 반드시 충족되어야 할 결과를 엄격하게 검증할 수 있는 기반이 된다. - 글에서 제안하는 Trust Layer는 이러한 실행 그래프를 바탕으로 우연한 환경 차이와 실제 기능 실패를 구분하는 역할을 한다. ## 실용적인 적용 방향 - 에이전트 테스트를 작성할 때 모든 중간 화면과 클릭 순서를 고정하지 않는다. - 대신 다음을 명확히 정의한다. - 반드시 도달해야 하는 최종 상태 - 작업 성공을 입증하는 핵심 데이터나 UI 상태 - 무시할 수 있는 로딩·렌더링 변화 - 허용 가능한 대체 실행 경로 - CI에서는 기록된 경로의 일치 여부보다 필수 상태의 도달 여부와 상태 간 논리적 관계를 검증하는 것이 적절하다. - 이를 적용하면 환경 변화로 인한 불필요한 실패를 줄이고, 에이전트가 실제로 작업에 실패한 경우에는 더 정확하게 감지할 수 있다.

github

초보자를 위한 GitHub: GitHub Actions 시작하기 (새 탭에서 열림)

GitHub Actions는 GitHub에 내장된 CI/CD 및 자동화 플랫폼으로, YAML 워크플로를 통해 반복 작업과 배포 과정을 자동화한다. 저장소 이벤트가 발생하면 가상 실행 환경에서 작업을 수행하며, 글에서는 새 이슈에 `triage` 라벨을 자동으로 붙이는 첫 워크플로를 만드는 과정을 설명한다. 핵심 구성 요소는 이벤트(`on`), 실행 환경(`runs-on`), 작업(`jobs`), 단계(`steps`), 권한(`permissions`)이다. ## GitHub Actions의 역할 - GitHub Actions는 지속적 통합·지속적 배포(CI/CD)와 자동화를 위한 플랫폼이다. - YAML 파일로 다음과 같은 작업을 자동화할 수 있다. - 취약점 검사 - 테스트 실행 - 릴리스 생성 - 팀에 업데이트 알림 - 배포 프로세스 - 워크플로는 저장소에 저장되며, 코드 푸시·풀 리퀘스트·이슈 생성·예약된 시간 등의 이벤트로 실행된다. - 이벤트가 발생하면 GitHub가 가상 환경을 준비하고 정의된 작업을 자동으로 실행한다. ## 워크플로를 구성하는 요소 - **이벤트(Event)** - 워크플로를 시작시키는 저장소 활동이다. - 예: 코드 푸시, 풀 리퀘스트 생성, 이슈 생성, 브랜치 병합 - **실행기(Hosted runner)** - 워크플로의 작업을 실행하는 가상 머신이다. - GitHub가 제공하는 Ubuntu, Windows, macOS 실행기를 사용할 수 있다. - 필요하면 자체 호스팅 실행기를 구성할 수도 있다. - **작업(Job)** - 하나의 실행기에서 수행되는 단계들의 묶음이다. - **단계(Step)** - 셸 명령을 실행하거나 미리 만들어진 재사용 가능한 액션을 호출한다. ## Actions 탭과 워크플로 템플릿 - 저장소의 **Actions** 탭에서는 현재 저장소에 등록된 워크플로를 확인할 수 있다. - **New workflow**를 선택하면 저장소에 적합한 추천 템플릿을 확인할 수 있다. - 템플릿은 YAML 편집기로 열리며, 기본적으로 다음 세 영역을 포함한다. - `name`: 워크플로의 목적을 설명하는 이름 - `on`: 워크플로를 실행할 이벤트 - `jobs`: 실제 작업 내용 ## YAML 워크플로 파일 작성 - 워크플로 파일은 저장소의 `.github/workflows` 디렉터리에 `.yml` 확장자로 저장한다. - 파일명은 `build-and-test.yml`, `security-scanner.yml`처럼 역할을 바로 알 수 있게 작성하는 것이 좋다. - 예제에서는 `label-new-issue.yml` 파일을 만들고 새 이슈에 라벨을 자동으로 추가한다. - 워크플로 이름은 다음과 같이 지정한다. ```yaml name: Label New Issues ``` ## 이슈 생성 이벤트 설정 - `on` 키워드로 워크플로의 실행 조건을 정의한다. - 다음 설정은 이슈가 새로 생성될 때만 워크플로를 실행한다. ```yaml on: issues: types: [opened] ``` - GitHub Actions는 다양한 이벤트와 세부 이벤트 유형을 지원하므로, 작업 목적에 맞는 트리거를 선택할 수 있다. ## 작업 환경과 권한 설정 - `jobs` 아래에 작업 이름을 지정한다. - `runs-on: ubuntu-latest`는 GitHub가 제공하는 최신 Ubuntu 실행기를 사용한다는 의미다. - 작업이 저장소를 읽고 이슈 라벨을 수정하려면 적절한 권한을 명시해야 한다. ```yaml jobs: label-issues: runs-on: ubuntu-latest permissions: issues: write contents: read ``` - `issues: write`는 이슈를 수정할 수 있는 권한이다. - `contents: read`는 저장소 콘텐츠를 읽을 수 있는 권한이다. - 작업 수준에서 `permissions`를 지정하면 해당 작업의 액션과 명령에 그 권한이 적용된다. ## 저장소 확인과 라벨 추가 단계 - `steps`에는 작업에서 순서대로 수행할 동작을 작성한다. - `actions/checkout@v6` 액션으로 저장소 코드를 실행 환경에 내려받는다. - 이후 GitHub CLI를 사용해 새 이슈에 `triage` 라벨을 추가한다. ```yaml steps: - name: Checkout repository uses: actions/checkout@v6 - name: Add triage label env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} ISSUE_NUMBER: ${{ github.event.issue.number }} LABEL: "triage" run: gh issue edit "$ISSUE_NUMBER" --add-label "$LABEL" ``` - `uses`는 GitHub Marketplace의 미리 만들어진 재사용 액션을 호출한다. - 저장소 체크아웃 - Node.js 설정 - 기타 반복적인 개발 작업 등에 활용할 수 있다. - `run`은 실행기에서 셸 명령을 직접 실행한다. - `GH_TOKEN`에는 GitHub가 제공하는 `GITHUB_TOKEN`을 사용한다. - `${{ github.event.issue.number }}`는 이벤트 정보에서 새로 생성된 이슈 번호를 가져온다. - `gh issue edit` 명령은 해당 이슈에 `triage` 라벨을 추가한다. 처음에는 GitHub Actions의 템플릿을 활용해 간단한 이벤트 기반 자동화를 만들어 보는 것이 좋다. 이후 이벤트 조건, 최소 권한, 재사용 액션과 직접 실행 명령을 조합하면 테스트·보안 검사·이슈 관리·배포까지 확장할 수 있다.

github

내부 살펴보기: GitHub (새 탭에서 열림)

GitHub Agentic Workflows는 에이전트를 기존 CI/CD에 통합하되, 에이전트의 비결정성과 프롬프트 인젝션 위험을 전제로 설계된 보안 아키텍처를 사용합니다. 핵심은 자유로운 에이전트 작성과 통제된 실행을 분리하고, 워크플로를 명시적인 권한·출력·네트워크·감사 제약이 있는 GitHub Actions로 컴파일하는 것입니다. 특히 에이전트에 비밀을 직접 제공하지 않고, 계층적 격리와 단계적 쓰기 검증으로 피해 범위를 제한합니다. ## 에이전트 자동화가 만드는 새로운 위협 - 에이전트는 저장소 상태와 외부 입력을 해석해 런타임에 자율적으로 결정을 내리므로 기본적으로 신뢰할 수 없습니다. - GitHub Actions는 구성 요소들이 하나의 신뢰 도메인에서 실행되는 비교적 개방적인 환경입니다. - 에이전트가 손상되면 다음과 같은 행동이 가능해질 수 있습니다. - MCP 서버와 상호작용 - 인증 토큰과 환경 변수 접근 - 임의의 인터넷 호스트로 네트워크 요청 - 악성 이슈·웹 페이지를 통한 프롬프트 인젝션 실행 - 원치 않는 커밋, 댓글, 이슈 생성 - 따라서 기본 보안 모드는 에이전트가 읽거나 쓰면 안 되는 상태에 접근하고, 허가되지 않은 통신 채널을 악용한다고 가정합니다. ## 다층 방어 구조 GitHub Agentic Workflows는 **기반 인프라(substrate)**, **구성(configuration)**, **계획(planning)**의 세 계층으로 방어합니다. - **기반 인프라 계층** - GitHub Actions 러너 VM과 신뢰된 컨테이너를 사용합니다. - 컨테이너 격리, 커널 수준 통신 경계, 권한 있는 작업과 시스템 호출 중재를 제공합니다. - 사용자 수준 구성 요소가 손상되어 컨테이너 내부에서 임의 코드를 실행하더라도 격리 경계를 넘는 피해를 제한합니다. - **구성 계층** - 어떤 구성 요소를 실행하고 서로 어떻게 연결할지 선언적으로 정의합니다. - 허용되는 통신 채널과 각 구성 요소의 권한을 결정합니다. - 에이전트 API 키와 GitHub 토큰 같은 외부 자격 증명을 어떤 컨테이너에 주입할지 통제합니다. - 컴파일러, 방화벽 정책, MCP 설정 등이 이 계층에 포함됩니다. - **계획 계층** - 구성 계층이 정한 구성 요소들을 언제, 어떤 순서로 실행할지 결정합니다. - 구성 요소 간 데이터 교환을 명시한 단계적 워크플로를 생성합니다. - 안전한 출력 시스템을 통해 쓰기 작업을 검증하고 제한하는 역할을 담당합니다. ## 에이전트에 비밀을 제공하지 않는 설계 - 일반적인 GitHub Actions 환경에서는 여러 프로세스가 환경 변수와 설정 파일에 저장된 토큰을 볼 수 있습니다. - 프롬프트 인젝션을 받은 에이전트는 셸 도구를 이용해 다음 정보에 접근할 수 있습니다. - 설정 파일 - SSH 키 - Linux `/proc` 상태 - 워크플로 로그 - 탈취한 자격 증명은 외부 웹사이트로 전송하거나 공개 이슈·풀 리퀘스트·댓글에 삽입할 수 있습니다. - 이를 막기 위해 에이전트를 별도 컨테이너에서 실행하고 네트워크 경로를 제한합니다. - 인터넷 접속은 방화벽을 통해 통제 - MCP 호출은 신뢰된 MCP 게이트웨이를 통해서만 허용 - LLM 호출은 API 프록시를 통해 중계 - MCP 게이트웨이는 별도의 신뢰 컨테이너에서 MCP 서버를 실행하며, MCP 인증 정보에 독점적으로 접근합니다. - 에이전트 컨테이너는 LLM 인증 토큰을 직접 보지 않고, 격리된 API 프록시가 인증을 대신 처리하는 구조를 사용합니다. ## 네트워크와 권한의 제한 - 에이전트와 방화벽 사이에 전용 사설 네트워크를 구성해 인터넷 연결을 통제합니다. - 허용 목록 기반 방화벽 정책으로 에이전트가 통신할 수 있는 대상과 채널을 제한합니다. - MCP 서버와 LLM API를 직접 노출하지 않고 각각 게이트웨이와 프록시 뒤에 배치합니다. - 이 구조는 에이전트가 손상되더라도 임의의 외부 호스트로 데이터를 반출하거나 인증 서비스를 직접 악용하는 가능성을 줄입니다. ## 안전한 쓰기와 감사 가능성 - 에이전트가 저장소나 GitHub 객체에 직접 자유롭게 쓰지 못하도록 출력 단계를 별도로 통제합니다. - 계획 계층의 안전한 출력 시스템은 다음을 담당하도록 설계됩니다. - GitHub 쓰기 작업의 허용 여부 결정 - 호출 가능한 기능과 호출 횟수 제한 - 출력에서 비밀 정보 제거 - 부적절하거나 원치 않는 내용 조정 - 에이전트의 실행 결과와 외부 효과를 추적할 수 있도록 모든 작업을 기록하는 원칙을 적용합니다. - 결과적으로 에이전트의 자유로운 추론 능력은 유지하되, 실제 커밋·댓글·이슈 생성 같은 효과는 검증된 단계와 명시적 정책을 거쳐야 합니다. ## 실용적인 결론 에이전트 기반 CI/CD를 도입할 때는 에이전트를 일반 스크립트처럼 신뢰하지 말고, 처음부터 침해 가능성을 전제로 설계해야 합니다. 별도 컨테이너 격리, 비밀의 프록시 위임, 허용 목록 네트워크, 단계적 쓰기 검증, 전체 감사 로그를 함께 적용하는 것이 안전한 기본값입니다.

github

GitHub 에이전틱 워크플 (새 탭에서 열림)

GitHub Agentic Workflows는 자연어로 작성한 Markdown 지시를 GitHub Actions에서 코딩 에이전트가 실행하도록 해 저장소 업무를 자동화하는 기술이다. 이슈 분류, 문서 갱신, 테스트 보강, CI 실패 분석처럼 기존의 결정론적 YAML 워크플로로는 처리하기 어려운 작업을 자동화하면서도, 권한·샌드박스·검토 절차를 통해 통제할 수 있도록 설계됐다. GitHub는 이를 CI/CD를 대체하는 것이 아니라 보완하는 “Continuous AI”로 소개하며, 2026년 2월 기술 프리뷰로 공개했다. ## Markdown으로 정의하는 에이전트 기반 저장소 자동화 - 원하는 결과를 일반 Markdown으로 설명하고, 이를 저장소의 자동화 워크플로로 등록한다. - 워크플로는 GitHub Actions에서 실행되며, 설정에 따라 다음과 같은 코딩 에이전트를 사용할 수 있다. - Copilot CLI - Claude Code - OpenAI Codex - 기존 개발팀이 이미 사용하는 GitHub Actions의 권한 관리, 로그, 감사 기능, 저장소 컨텍스트를 그대로 활용한다. - 복잡한 절차를 직접 YAML로 세부 구현하기보다, 사람이 의도와 목표를 설명하고 에이전트가 저장소를 분석해 작업을 수행하는 방식이다. ## 지속적인 저장소 관리에 활용되는 작업 - **이슈 트리아지** - 새 이슈를 요약하고 라벨을 붙인다. - 관련 담당자나 적절한 처리 경로로 이슈를 분류한다. - **문서 유지 관리** - 코드 변경 사항을 분석해 README와 기술 문서를 최신 상태로 갱신한다. - **코드 단순화** - 반복적으로 개선 가능한 코드를 식별한다. - 개선안을 pull request로 생성해 사람이 검토하도록 한다. - **테스트 개선** - 테스트 커버리지를 평가한다. - 가치가 높은 테스트를 추가하도록 제안하거나 pull request를 만든다. - **품질 관리** - CI 실패 원인을 조사한다. - 문제에 맞는 구체적인 수정안을 제안한다. - **정기 보고** - 저장소의 건강 상태, 활동량, 주요 추세를 정기적으로 분석하고 보고서를 작성한다. ## Continuous AI와 기존 CI/CD의 관계 - GitHub는 에이전트 기반 자동화를 소프트웨어 개발 생명주기에 AI를 지속적으로 결합하는 **Continuous AI**라고 부른다. - Agentic Workflow는 빌드, 테스트, 릴리스처럼 결과가 명확하고 결정론적인 CI/CD 파이프라인을 대체하지 않는다. - 대신 다음과 같이 판단과 분석이 필요한 작업을 담당한다. - 어떤 이슈가 중요한지 판단 - 문서와 코드의 불일치 탐색 - 실패 원인 분석 - 개선 가치가 높은 테스트나 리팩터링 선별 - 따라서 기존 CI/CD는 안정적인 검증과 배포를 담당하고, Agentic Workflow는 저장소 운영과 엔지니어링 작업의 지능화를 담당하는 구조다. ## 권한과 안전장치 - 안전성과 통제는 설계의 핵심 요소로 제시된다. - 워크플로는 기본적으로 **읽기 전용 권한**으로 실행된다. - 파일 수정, 이슈 변경, pull request 생성 등 쓰기 작업은 명시적인 승인이 필요하다. - 쓰기 작업은 **safe outputs**를 통해 사전에 허용된 형태로 제한하고, 사람이 검토할 수 있도록 한다. - 샌드박스 실행, 권한 제어, 감사 로그, 실행 기록 등을 활용해 의도하지 않은 동작과 프롬프트 인젝션 공격에 대비한다. - 결과적으로 에이전트가 자율적으로 작업하더라도, 실행 시점과 변경 범위를 저장소 관리자가 정의한 경계 안에 둘 수 있다. ## 실제 적용 사례와 기대 효과 - Home Assistant에서는 대규모 이슈를 분석해 반복적으로 나타나는 문제와 사용자에게 영향이 큰 이슈를 파악하는 데 활용한다. - CNCF는 문서 자동화와 조직 차원의 팀 보고를 개선하는 데 사용하고 있다. - Carvana는 여러 저장소에 걸친 엔지니어링 작업에 에이전트를 적용하면서도 내장된 제어 기능을 활용하고 있다. - 개인 저장소부터 오픈소스 프로젝트와 대기업 규모의 복잡한 시스템까지 적용 범위를 확장할 수 있다. - 반복적인 관리 업무를 줄이고, 사람이 중요한 판단과 검토에 집중하도록 돕는 것이 주요 목표다. 실제로 도입할 때는 읽기 전용·보고서 생성처럼 위험이 낮은 작업부터 시작한 뒤, 사람이 검토하는 pull request 생성 단계로 확장하는 것이 적절하다. 빌드와 배포 파이프라인은 기존 CI/CD로 유지하고, Agentic Workflow는 분석·분류·문서화·개선 제안처럼 판단이 필요한 업무에 사용하는 편이 안전하다.