콘텐츠로 이동

CI 통합

다른 ddakit 베이스에서 마지막 운영 자리는 배포(distribution)입니다. e2e-base에는 배포할 앱이 없으니 그 자리를 CI 통합이 받습니다. implement-ci-workflowe2e-suite-config.jsoncitargets를 읽어 .github/workflows/e2e.yml을 만듭니다. ci.providernone이면 생성하지 않습니다. targets에 있는 트랙의 잡만 들어가고 없는 트랙은 만들지 않습니다.

테스트를 여러 샤드로 쪼개 병렬로 돌리고, 각 샤드가 blob 리포트를 올리면 별도 잡이 하나로 머지합니다.

jobs:
web:
strategy:
fail-fast: false
matrix: { shardIndex: [1,2,3,4], shardTotal: [4] }
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npx playwright install --with-deps # 캐싱하지 않음
- run: npx playwright test --project=chromium --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- uses: actions/upload-artifact@v4
if: always()
with: { name: blob-report-${{ matrix.shardIndex }}, path: blob-report, retention-days: 1 }
merge-reports:
needs: [web]
if: always()
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- uses: actions/download-artifact@v4
with: { path: all-blob-reports, pattern: blob-report-* }
- run: npx playwright merge-reports --reporter html ./all-blob-reports
- uses: actions/upload-artifact@v4
with: { name: html-report, path: playwright-report, retention-days: 14 }

fail-fast: false라 한 샤드가 깨져도 나머지가 끝까지 돕니다. 각 샤드의 blob은 하루만 보관하고, 머지된 HTML 리포트는 14일 둡니다.

브라우저 바이너리를 캐싱하지 않는 이유

섹션 제목: “브라우저 바이너리를 캐싱하지 않는 이유”

매 잡에서 npx playwright install --with-deps를 돕니다. 캐싱이 빨라 보이지만 Playwright 버전이 올라가면 캐시된 바이너리와 버전이 어긋나고, --with-deps가 까는 OS 레벨 의존성이 캐시에 안 잡혀 러너 이미지가 바뀔 때 깨집니다. 매번 install이 금지 패턴(§5)을 피하는 자리입니다.

electron은 세 OS에서 돕니다. Linux 러너만 디스플레이가 없어 xvfb-run으로 감싸고, mac과 windows는 그대로 둡니다.

electron:
strategy: { fail-fast: false, matrix: { os: [ubuntu-latest, windows-latest, macos-latest] } }
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npx playwright install --with-deps
- name: e2e (Linux)
if: runner.os == 'Linux'
run: xvfb-run --auto-servernum -- npx playwright test --project=electron
- name: e2e (mac/win)
if: runner.os != 'Linux'
run: npx playwright test --project=electron

runner.os 분기로 같은 잡 안에서 Linux만 다른 명령을 탑니다. electron은 단일 인스턴스라 config가 workers: 1인 점은 tracks에서 봤습니다.

Android는 reactivecircus/android-emulator-runner로 에뮬레이터를 띄웁니다. KVM을 활성화해야 가속이 붙고, AVD 캐싱으로 부팅 시간을 줄입니다.

mobile-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules && sudo udevadm trigger --name-match=kvm
- uses: reactivecircus/android-emulator-runner@v2
with: { api-level: 30, arch: x86_64, force-avd-creation: false,
script: maestro test tests/mobile/flows } # 또는 detox test

iOS는 macos-latest 러너에서 xcrun simctl로 시뮬레이터를 띄웁니다. 실기기 검증이나 병렬 확장이 필요한 릴리스 게이트에서는 Maestro Cloud(mobile-dev-inc/action-maestro-cloud)나 디바이스 팜을 씁니다. 클라우드 팜의 api-key와 project-id는 ${{ secrets.* }}로만 넣습니다.

시크릿은 ${{ secrets.* }}로만 전달하고 실키를 하드코딩하지 않습니다(S2). 아티팩트에 토큰이나 PII가 찍히지 않게 주의합니다(S4). 워크플로 env가 가리키는 SUT는 스테이징이나 전용 테스트만이고 프로덕션은 금지입니다(S6).

다음 섹션은 updates입니다. 베이스가 새 스킬이나 훅을 내놓을 때 fork에 안전하게 가져오는 /update-from-base, 이미 e2e가 있는 앱 repo에 패턴을 얹는 /adopt를 봅니다.