[FEAT] release를 TestFlight 검증 빌드 재사용으로 전환 #9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: TestFlight Deploy | |
| on: | |
| pull_request: | |
| branches: [main] | |
| types: [closed] | |
| workflow_dispatch: | |
| concurrency: | |
| group: testflight-deploy | |
| cancel-in-progress: false | |
| jobs: | |
| # ────────────────────────────────────────────────────────── | |
| # Deploy (TestFlight) | |
| # ────────────────────────────────────────────────────────── | |
| deploy: | |
| # PR 이 머지된 경우 또는 수동 실행일 때만 동작 (단순 close 는 스킵) | |
| if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' | |
| runs-on: macos-15 | |
| # 서명 단계가 매달려도 러너를 오래 점유하지 않도록 상한을 둔다 | |
| # (concurrency 가 cancel-in-progress: false 라 멈춘 잡이 후속 배포를 전부 막는다) | |
| timeout-minutes: 60 | |
| env: | |
| # Appfile / Fastfile | |
| APP_IDENTIFIER: ${{ secrets.APP_IDENTIFIER }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| TEAM_ID: ${{ secrets.TEAM_ID }} | |
| # match | |
| MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} | |
| MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }} | |
| # 러너에 이미 있는 login 키체인은 비밀번호를 알 수 없어 match 의 set-key-partition-list 가 실패한다 | |
| # → 전용 키체인을 새로 만들어 쓴다 (Matchfile 이 이 값을 참조) | |
| MATCH_KEYCHAIN_NAME: build.keychain | |
| # 인증서 repo(private) 클론용 토큰 — Deploy 스텝에서 MATCH_GIT_BASIC_AUTHORIZATION 로 인코딩 | |
| CONFIG_PRIVATE_REPO_TOKEN: ${{ secrets.CONFIG_PRIVATE_REPO_TOKEN }} | |
| # App Store Connect API (Fastfile 변수명) | |
| APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} | |
| APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} | |
| APP_STORE_CONNECT_API_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }} | |
| # App Store Connect API (Matchfile 변수명 호환) | |
| APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} | |
| APP_STORE_CONNECT_API_KEY_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Select Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: latest-stable | |
| - name: Setup mise & tuist | |
| uses: jdx/mise-action@v2 | |
| # 커밋된 tuisttool 바이너리는 로컬 macOS 26 기준으로 빌드되어 macos-15 러너에서 로드 불가 | |
| # → 러너 OS에 맞게 소스에서 재컴파일 (Install dependencies·fastlane 의 ./tuisttool 호출 대비) | |
| - name: Build tuisttool | |
| run: swiftc TuistTool.swift -o tuisttool | |
| - name: Setup Ruby & fastlane | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.3" | |
| bundler-cache: true | |
| - name: Download private xcconfig | |
| run: | | |
| echo "GITHUB_ACCESS_TOKEN=${CONFIG_PRIVATE_REPO_TOKEN}" > .env | |
| make download-privates | |
| # 생성 실패를 무시하면 러너의 기존 키체인을 그대로 쓰게 되고, 비밀번호 불일치로 | |
| # codesign 이 뜰 수 없는 승인 팝업을 기다리며 무한 대기한다. 실패 시 즉시 잡을 멈춘다. | |
| - name: Prepare keychain | |
| run: | | |
| security create-keychain -p "$MATCH_KEYCHAIN_PASSWORD" build.keychain | |
| security set-keychain-settings -lut 21600 build.keychain | |
| security unlock-keychain -p "$MATCH_KEYCHAIN_PASSWORD" build.keychain | |
| # xcodebuild 가 시스템 인증서를 찾을 수 있도록 login 키체인도 검색 목록에 남긴다 | |
| security list-keychains -d user -s build.keychain login.keychain-db | |
| security default-keychain -s build.keychain | |
| # SPM 의존성 설치 (fastlane 의 ensure_workspace 가 generate 하기 전 선행) | |
| - name: Install dependencies | |
| run: ./tuisttool install | |
| - name: Deploy to TestFlight | |
| run: | | |
| # match 가 private 인증서 repo 를 클론할 때 사용할 basic auth 헤더 생성 | |
| # (base64 는 긴 토큰에서 줄바꿈이 삽입되므로 제거) | |
| export MATCH_GIT_BASIC_AUTHORIZATION=$(printf 'x-access-token:%s' "${CONFIG_PRIVATE_REPO_TOKEN}" | base64 | tr -d '\n') | |
| bundle exec fastlane beta |