콘텐츠로 건너뛰기

⚙️ GitHub Actions 생성기

워크플로 타입과 트리거를 선택하면 .github/workflows/ 에 바로 사용할 YAML 생성. Node.js · Python · PHP · Go · Docker · Pages · Vercel · Netlify · Release · Cron · Lint 지원.

완전 무료 가입 불필요 브라우저 완결 5 개 언어 다크 모드

🔒 개인정보 보호

트리거
(위의 YAML 생성 버튼을 누르세요)

📖 자주 걸리는 지점

워크플로 종류 (Node / Python / PHP / Go / Docker / Pages / Vercel / Netlify / Release / Cron / Lint) 와 트리거를 고르면 .github/workflows/ 에 그대로 둘 수 있는 YAML 을 생성합니다. 처리는 브라우저 안에서 끝나며 브랜치명이나 버전은 전송되지 않습니다. 생성되는 것은 구문적으로 올바른 워크플로이지 당신의 프로젝트에서 통과하는 워크플로가 아닙니다의존성 설치도 테스트 실행도 실제 명령은 리포지터리마다 다릅니다. 그리고 CI 에서 정말 아픈 것은 YAML 서식이 아니라 「권한」과 「시간」입니다. 아래가 그 이야기입니다.

사례 무슨 일이 일어나는가 어떻게 하면 되는가
fork 에서 온 PR 에는 secrets 가 넘어가지 않는다 pull_request 로 트리거된 워크플로는 fork 에서 온 PR 인 경우 GITHUB_TOKEN 이 읽기 전용이 되고 리포지터리의 secrets 도 넘어가지 않습니다. 이것은 의도된 안전장치입니다 — 그렇지 않으면 누구나 PR 을 보내는 것만으로 당신의 비밀을 출력하게 만들 수 있습니다. 그러나 결과적으로 배포나 커버리지 전송을 포함한 워크플로는 fork 의 PR 에서 반드시 실패합니다. 여기서 위험한 우회책이 알려져 있습니다: pull_request_target 으로 바꾸면 secrets 가 넘어갑니다이 트리거는 베이스 브랜치의 권한으로 동작하므로 거기서 PR 의 코드를 actions/checkout 해서 실행하면 외부 사람이 쓴 코드가 당신의 secrets 를 들고 돌아갑니다사실상 리포지터리의 탈취입니다. 워크플로를 둘로 나누세요. 테스트와 lint 는 pull_request 에서 (secrets 불필요), 배포는 push 의 main 브랜치나 release 에서 실행합니다. 이렇게 하면 fork 의 PR 도 정상적으로 CI 를 통과하고 secrets 가 밖으로 나갈 경로도 존재하지 않습니다. pull_request_target 을 쓴다면 PR 의 코드를 절대 checkout 하지 마세요라벨 붙이기나 댓글 작성처럼 코드를 실행하지 않는 용도로 한정합니다. 아울러 모든 워크플로의 맨 앞에 permissions: 를 명시하세요permissions: {contents: read} 라고 쓰는 것만으로 그 워크플로의 GITHUB_TOKEN 에서 쓰기 권한이 사라집니다. 필요한 권한만을 잡 단위로 더해 나가는 것이 올바른 순서입니다.
서드파티 action 을 태그로 참조한다 uses: some/action@v1v1브랜치나 태그, 즉 움직일 수 있는 참조입니다 — action 의 작성자 (또는 그 계정을 빼앗은 사람) 가 내용을 바꿔치기하면 당신의 CI 는 다음 실행에서 다른 코드를 돌립니다. 그 코드는 GITHUB_TOKEN 과 그 잡에 넘긴 secrets 에 접근할 수 있습니다. 이것은 이론상의 이야기가 아니라 인기 있는 action 이 침해되어 비밀을 수집한 사례가 실제로 일어났습니다. 공식 (actions/*) 은 그렇다 쳐도, star 가 적은 편리한 action 을 무심코 @main 으로 참조하는 것은 남에게 당신의 리포지터리에 대한 쓰기 권한을 건네는 것과 다르지 않습니다. 서드파티 action 은 commit SHA 로 고정하세요uses: some/action@a1b2c3d4... 형태입니다. SHA 는 고쳐 쓸 수 없으므로 다음에 무엇이 도는지가 확정됩니다. 갱신은 Dependabot 에 맡깁니다 (.github/dependabot.ymlpackage-ecosystem: "github-actions" 를 추가하면 SHA 갱신 PR 을 자동으로 만들어 줍니다) — 고정과 갱신은 양립합니다. 애초에 action 을 줄이는 것도 유효합니다: 파일을 하나 복사할 뿐인 action 이라면 run:cp 라고 쓰면 의존이 하나 사라집니다. 그리고 secrets 는 잡 단위로 최소한만 넘기세요워크플로 전체에 환경 변수로 두면 그 안의 모든 action 에서 읽을 수 있습니다.
cron 은 시각대로 돌지 않고 60 일에 멈춘다 schedule 트리거에는 서식 이외에 세 가지 함정이 있습니다. 시각은 반드시 UTC이지 당신의 타임존이 아닙니다 — 0 3 * * * 은 「UTC 의 오전 3 시」입니다. 실행은 정시가 아닙니다 — 혼잡할 때는 수 분에서 수십 분 늦어지고 부하가 높을 때는 실행 자체가 건너뛰어질 수 있습니다. 매시 0 분이 가장 붐비므로 딱 떨어지는 시각을 피하는 것만으로도 안정됩니다. 그리고 가장 놀라는 것이 세 번째입니다: 60 일간 커밋이 없는 리포지터리에서는 스케줄된 워크플로가 자동으로 무효화됩니다메일은 오지만 놓치면 「알고 보니 몇 달째 안 돌고 있었다」는 일이 예사로 일어납니다. cron 식은 UTC 로 쓰고 노리는 시각에서 몇 분 어긋나게 하세요0 3 * * * 가 아니라 17 3 * * * 처럼. 그리고 반드시 workflow_dispatch 를 함께 적으세요수동으로 실행할 수 있는 것만으로 동작 확인도 재실행도 가능해집니다 (스케줄이 올 때까지 기다리지 않으면 시험할 수 없는 상태는 그 자체가 사고의 근원입니다). 무효화에 대한 대책은 「알아챌 수 있게」 하는 것입니다: 잡의 마지막에 성공을 외부로 통지하게 하고 통지가 끊긴 것을 알아챌 수 있는 구조를 만드세요실패 통지만으로는 실행되지 않게 된 것을 검출할 수 없습니다. 정확한 시각이나 높은 신뢰성이 필요하다면 GitHub Actions 의 cron 이 아니라 전용 스케줄러를 쓰세요.

캐시는 락 파일과 함께 키를 만드세요. actions/setup-nodecache: npm 이나 actions/cachekey락 파일의 해시를 포함하지 않으면 의존을 갱신해도 예전 캐시가 계속 쓰입니다로컬에서는 고쳐졌는데 CI 만 오래된 의존으로 실패하는 원인 알기 어려운 상태가 됩니다. hashFiles('**/package-lock.json') 을 키에 넣으세요. 그리고 캐시는 브랜치를 넘나들며 공유됩니다망가진 캐시가 다른 브랜치로 전염되므로 의심스러울 때는 이름을 바꿔 다시 만드는 편이 빠릅니다. 또 하나, 로그에 비밀을 내보내지 않도록 주의하세요: GitHub 은 등록된 secrets 를 자동으로 마스킹하지만 가공한 값 (Base64 화한, JSON 에 심은, 일부만 잘라 낸) 은 마스킹되지 않습니다. set -x 나 디버그 출력을 켜면 커맨드라인째 기록됩니다그리고 Actions 의 로그는 퍼블릭 리포지터리라면 누구나 읽을 수 있습니다.

📖 사용법

  1. 1
    워크플로 타입 선택
    Node.js · Python · PHP · Go · Docker · Pages 등에서 선택.
  2. 2
    트리거와 브랜치 설정
    push · pull_request · schedule · 수동 실행 활성화.
  3. 3
    YAML 생성 후 커밋
    YAML 생성을 누르고 .github/workflows/ 에 저장 후 푸시.

❓ 자주 묻는 질문

시크릿은 어떻게 설정합니까?
저장소 Settings → Secrets and variables → Actions 에서 동일한 이름으로 추가.
어떤 actions 버전이 들어갑니까?
actions/checkout@v4, actions/setup-* @v5 위주로 안정 버전 사용.
Self-hosted runner 도 됩니까?
예. runs-on 을 self-hosted 로 바꾸기만 하면 됩니다.
🐛 이 도구에서 문제가 발생했나요?

무료 · 가입 불필요. 재현 절차만이라도 도움이 됩니다. 보고는 운영자에게 직접 전달되어 개선에 사용됩니다.

※ 재현을 위해 브라우저 정보 (UA / 화면 / 언어 / URL) 가 자동 전송됩니다