Skip to content

release: prepare mobile app deployment#19

Merged
SeongHoonC merged 3 commits into
prodfrom
main
May 18, 2026
Merged

release: prepare mobile app deployment#19
SeongHoonC merged 3 commits into
prodfrom
main

Conversation

@SeongHoonC
Copy link
Copy Markdown
Collaborator

@SeongHoonC SeongHoonC commented May 18, 2026

Summary

  • Add Android Play release workflow support.
  • Commit generated iOS native project files for Xcode Cloud.
  • Update Xcode Cloud post-clone setup, Firebase plist restoration, environment variable handling, and CI/CD docs.
  • Bump app version/build metadata for the next release.

Validation

  • git diff --check
  • No full test suite was run in this release-prep step.

Summary by CodeRabbit

릴리스 노트

  • 문서

    • 프로젝트 개발 가이드 및 CI/CD 배포 전략 문서 추가
  • 버전 업데이트

    • iOS 버전을 1.5.1로 업그레이드
    • Android 버전 코드 증가
  • 기타 개선

    • 배너 링크 처리 로직 단순화로 안정성 향상
    • 자동 빌드 및 배포 인프라 구성 개선

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Warning

Rate limit exceeded

@SeongHoonC has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 47 minutes and 59 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d9c9108e-0b13-425d-a27e-d3d0c3798f96

📥 Commits

Reviewing files that changed from the base of the PR and between cf644ba and 932013c.

⛔ Files ignored due to path filters (1)
  • Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • AGENTS.md
  • ci_scripts/ci_post_clone.sh
  • docs/cicd.md
  • ios/app.xcodeproj/xcshareddata/xcschemes/app.xcscheme
  • plugins/withAndroidReleaseSigning.js

Walkthrough

이 PR은 Expo 기반 React Native 앱의 Android/iOS 배포 파이프라인을 완성합니다. GitHub Actions 워크플로우(Android Check, Android Release), Fastlane 기반 자동 빌드/배포, Expo config 플러그인, 완성된 iOS 네이티브 프로젝트 파일, Xcode Cloud 부트스트랩 스크립트, 포괄적인 CI/CD 문서를 추가합니다.

Changes

CI/CD 파이프라인 및 배포 자동화

Layer / File(s) Summary
배포 전략 및 프로젝트 가이드 문서화
docs/cicd.md, AGENTS.md
CI/CD 원칙(EAS Build 미사용, Android production draft 자동화, iOS Xcode Cloud 우선), 환경 변수 규칙, 커밋 제외 파일, Xcode Cloud post-clone 흐름, 빌드 번호 관리를 문서화하고, 프로젝트 구조·라우팅·API·상태 관리·디자인 시스템 규칙을 개발자 가이드로 정리합니다.
환경 변수, 버전, Expo 플러그인 설정
.env.example, app.json, app.config.js
공개 환경 변수(EXPO_PUBLIC_BASE_URL, EXPO_PUBLIC_WEBVIEW_URL, EXPO_PUBLIC_MIXPANEL_TOKEN) 예시, iOS 버전 1.5.1 및 빌드 번호 13, Android versionCode 12로 업데이트하고, app.config.jsIOS_APS_ENVIRONMENT 기반 APS 환경 보정, withAndroidReleaseSigning 플러그인 등록을 수행합니다.
Android PR/Push 검증 워크플로우
.github/workflows/android-check.yml
PR 및 main push에서 Node 20 설정, npm 캐시, 공개 환경 변수 생성, lint, placeholder google-services.json, Expo prebuild, Gradle debug assemble을 순차 실행하여 빌드 가능성을 검증합니다.
Android Release 자동화 워크플로우
.github/workflows/android-release.yml
prod 브랜치 push 시 자동 실행 또는 수동 lane 선택 가능한 워크플로우로, Node/Ruby 설정, 시크릿 검증, 환경 변수 생성, base64 키/JSON 복원, Fastlane 실행을 수행합니다.
Fastlane 빌드/배포 구성
Gemfile, fastlane/Appfile, fastlane/Fastfile
Fastlane 의존성, Supply JSON 키 및 패키지명 설정, 검증 헬퍼 및 AAB 생성 함수, internal/production_draft 레인으로 Google Play 업로드 자동화를 구현합니다.
Android 릴리즈 서명 Expo 플러그인
plugins/withAndroidReleaseSigning.js
Expo config 플러그인으로 android/app/build.gradlesigningConfigs.releasebuildTypes.release.signingConfig를 idempotent하게 주입하여 Gradle properties 기반 릴리즈 서명을 자동화합니다.

iOS 프로젝트 구조 및 네이티브 통합

Layer / File(s) Summary
iOS 프로젝트 기본 설정 및 CocoaPods
ios/.gitignore, ios/.xcode.env, ios/Podfile, ios/Podfile.properties.json
Xcode 산출물 제외, NODE_BINARY 환경 정의, Expo/React Native autolinking, Hermes, 새 아키텍처, ccache, 정적 프레임워크를 CocoaPods 및 JSON 속성으로 설정합니다.
iOS Xcode 프로젝트 및 스킴 정의
ios/app.xcodeproj/project.pbxproj, ios/app.xcodeproj/xcshareddata/xcschemes/app.xcscheme
app 네이티브 타겟, AppDelegate.swift 소스, 리소스(Expo.plist, xcassets, SplashScreen, GoogleService-Info.plist), 빌드 단계(Expo 번들링, CocoaPods 동기화, 리소스 복사), Debug/Release 설정 및 공유 스킴을 정의합니다.
iOS AppDelegate 및 부트스트랩 흐름
ios/app/AppDelegate.swift, ci_scripts/ci_post_clone.sh
AppDelegate에서 React Native 델리게이트/팩토리 생성, Firebase 초기화, 모듈 시작, URL/유니버설 링크 처리를 구현하고, ci_post_clone.sh는 npm 설치, Google Service plist 복원, 공개 환경 변수 검증, APS entitlement 보정, CocoaPods 설치를 수행합니다.
iOS 자산, 메타데이터, 리소스 정의
ios/app/Images.xcassets/*/Contents.json, ios/app/Info.plist, ios/app/SplashScreen.storyboard, ios/app/Supporting/Expo.plist, ios/app/app.entitlements, ios/app/app-Bridging-Header.h
AppIcon, SplashScreenLogo/Background 이미지, Info.plist(번들 설정, URL 스킴, ATS, React Native 플래그), 런치 스토리보드, Expo 업데이트 정책, push 환경 및 Universal Links entitlement, Swift 브리징 헤더를 정의합니다.

프로젝트 전체 정리

Layer / File(s) Summary
프로젝트 gitignore 업데이트
.gitignore
/ios 규칙 제거(iOS 폴더 커밋 준비), /android 유지, ios/**/GoogleService-Info.plist 패턴 추가로 플랫폼별 파일 무시 정책을 조정합니다.
배너 링크 처리 단순화
ui/home/components/banner.tsx
resolveLinkTo에서 APP_STORE_LINK 환경변수 치환 로직 제거로 링크 처리를 단순화합니다.

Sequence Diagram(s)

sequenceDiagram
  participant GitHub as GitHub Actions
  participant Fastlane as Fastlane
  participant Gradle as Gradle
  participant PlayStore as Google Play
  
  GitHub->>Fastlane: android release 워크플로우 트리거<br/>(prod push 또는 수동 선택)
  Fastlane->>Fastlane: 시크릿/환경변수 검증
  Fastlane->>Gradle: Expo prebuild + Gradle properties 주입
  Gradle->>Gradle: ./gradlew bundleRelease 실행
  Gradle-->>Fastlane: app-release.aab 생성
  Fastlane->>PlayStore: upload_to_play_store<br/>(internal 또는 production draft)
  PlayStore-->>GitHub: 배포 완료
Loading
sequenceDiagram
  participant XcodeCloud as Xcode Cloud
  participant PostClone as ci_post_clone.sh
  participant AppDelegate as AppDelegate
  participant RN as React Native
  
  XcodeCloud->>PostClone: 체크아웃 후 post-clone 실행
  PostClone->>PostClone: npm ci + 의존성 설치
  PostClone->>PostClone: GoogleService-Info.plist 복원
  PostClone->>PostClone: .env 생성 (BASE_URL, WEBVIEW_URL, MIXPANEL)
  PostClone->>PostClone: PlistBuddy로 aps-environment 설정
  PostClone->>PostClone: pod install 실행
  PostClone-->>XcodeCloud: 완료
  
  XcodeCloud->>AppDelegate: 앱 시작
  AppDelegate->>AppDelegate: ReactNativeDelegate + Factory 생성
  AppDelegate->>AppDelegate: FirebaseApp.configure()
  AppDelegate->>RN: 모듈 "main" 시작
  RN-->>AppDelegate: 부트스트랩 완료
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Moadong/moadong-react-native#13: 두 PR 모두 ui/home/components/banner.tsx의 링크 해석/라우팅 로직을 건드려 직접적으로 연계됩니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 'release: prepare mobile app deployment'으로 주요 변경 사항인 모바일 앱 배포 준비(Android 릴리즈 워크플로우 추가, iOS 네이티브 파일 커밋, 버전 업데이트)를 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch main

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@SeongHoonC SeongHoonC requested a review from seongwon030 May 18, 2026 12:32
Copy link
Copy Markdown
Member

@seongwon030 seongwon030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제발 어프루브

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
Gemfile (1)

3-3: ⚡ Quick win

Gemfile.lock을 커밋해 fastlane의 정확한 버전을 고정하세요.

현재는 버전 범위만 지정되어 있어 CI 실행 시점에 따라 설치되는 버전이 달라질 수 있습니다. Gemfile.lock을 함께 관리하면 릴리스 파이프라인의 재현성과 안정성을 높일 수 있습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Gemfile` at line 3, Gemfile에 fastlane의 범위(gem "fastlane", ">= 2.228", "<
3.0")만 지정되어 있어 CI마다 다른 버전이 설치될 수 있으니 Gemfile.lock을 생성하여 커밋해 정확한 fastlane 버전을
고정하세요; 로컬에서 bundle install 또는 bundle lock을 실행해 Gemfile.lock을 생성한 뒤 해당
Gemfile.lock을 저장소에 추가하고 푸시하여 릴리스 파이프라인 재현성을 확보하도록 합니다.
plugins/withAndroidReleaseSigning.js (1)

137-141: 💤 Low value

콜백 매개변수가 외부 config를 섀도잉합니다.

Line 138의 콜백 매개변수 config가 외부 함수의 config 매개변수를 섀도잉합니다. 코드는 정상 작동하지만, 명확성을 위해 다른 이름을 사용하는 것이 좋습니다.

♻️ 매개변수 이름 변경 제안
 module.exports = function withAndroidReleaseSigning(config) {
-  return withAppBuildGradle(config, (config) => {
-    config.modResults.contents = addAndroidReleaseSigning(config.modResults.contents);
-    return config;
+  return withAppBuildGradle(config, (modConfig) => {
+    modConfig.modResults.contents = addAndroidReleaseSigning(modConfig.modResults.contents);
+    return modConfig;
   });
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/withAndroidReleaseSigning.js` around lines 137 - 141, The inner
callback parameter in withAndroidReleaseSigning is shadowing the outer config;
rename the callback argument passed to withAppBuildGradle (e.g., from "config"
to "appBuildGradleConfig" or "params") so you update references inside the
callback (config.modResults.contents ->
appBuildGradleConfig.modResults.contents) while keeping the outer "config"
intact; ensure withAppBuildGradle callback returns the renamed variable after
calling addAndroidReleaseSigning on its modResults.contents.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 29-39: Add a language tag to the markdown code fence for the
file-tree block to satisfy lint rule MD040; edit the fenced block starting with
the triple backticks and change it to include a language (e.g., use "text" so
the block becomes ```text) that wraps the lines listing app/_layout.tsx,
(tabs)/index.tsx, club/[id].tsx, clubDetail/[id].tsx, webview/[slug].tsx, and
modal.tsx.

In `@ci_scripts/ci_post_clone.sh`:
- Line 13: The single-line decode command uses GNU-only `--decode` and fails on
macOS; update the decoding pipeline that writes GoogleService-Info.plist (the
line using "printf ... | base64 --decode > GoogleService-Info.plist") to be
portable by trying BSD's `-D` or openssl as a fallback (e.g. attempt `base64
--decode` or `base64 -D` or `openssl base64 -d`) so the post-clone step works on
both Linux and macOS.

In `@docs/cicd.md`:
- Line 40: Update the paragraph that states `.gitignore` contains `/ios` so it
matches the final policy that removes the `/ios` ignore rule; specifically,
revise the sentence referencing `/ios` (the current description) to reflect the
final decision (remove `/ios` from the ignored entries) and ensure the
`.gitignore` summary and the policy section about removing `/ios` are
consistent, keeping references to `.env`, `google-services.json`,
`GoogleService-Info.plist`, and the Android prebuild policy unchanged.

In `@ios/app.xcodeproj/xcshareddata/xcschemes/app.xcscheme`:
- Around line 31-39: 스킴의 TestableReference 블록이 존재하지 않는 테스트 타깃을 가리키고 있어(xcscheme의
TestableReference / BuildableReference, 특히 BlueprintName="appTests" 및 해당
BlueprintIdentifier) xcodebuild 테스트가 실패할 수 있습니다; 해결하려면 실제로 존재하는 테스트 타깃
이름/식별자(프로젝트의 타깃 정의와 일치하는 BlueprintName 및 BlueprintIdentifier)로
BuildableReference 값을 갱신하거나, 테스트 타깃을 추가하지 않을 경우 해당 TestableReference 블록 전체를 스킴의
Testables에서 제거하여 스킴과 타깃 정의를 일치시키세요.

---

Nitpick comments:
In `@Gemfile`:
- Line 3: Gemfile에 fastlane의 범위(gem "fastlane", ">= 2.228", "< 3.0")만 지정되어 있어
CI마다 다른 버전이 설치될 수 있으니 Gemfile.lock을 생성하여 커밋해 정확한 fastlane 버전을 고정하세요; 로컬에서 bundle
install 또는 bundle lock을 실행해 Gemfile.lock을 생성한 뒤 해당 Gemfile.lock을 저장소에 추가하고 푸시하여
릴리스 파이프라인 재현성을 확보하도록 합니다.

In `@plugins/withAndroidReleaseSigning.js`:
- Around line 137-141: The inner callback parameter in withAndroidReleaseSigning
is shadowing the outer config; rename the callback argument passed to
withAppBuildGradle (e.g., from "config" to "appBuildGradleConfig" or "params")
so you update references inside the callback (config.modResults.contents ->
appBuildGradleConfig.modResults.contents) while keeping the outer "config"
intact; ensure withAppBuildGradle callback returns the renamed variable after
calling addAndroidReleaseSigning on its modResults.contents.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 635be36f-957b-4c3b-88cb-398e7d284a3c

📥 Commits

Reviewing files that changed from the base of the PR and between 2433b32 and cf644ba.

⛔ Files ignored due to path filters (4)
  • ios/app/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png is excluded by !**/*.png
  • ios/app/Images.xcassets/SplashScreenLogo.imageset/image.png is excluded by !**/*.png
  • ios/app/Images.xcassets/SplashScreenLogo.imageset/image@2x.png is excluded by !**/*.png
  • ios/app/Images.xcassets/SplashScreenLogo.imageset/image@3x.png is excluded by !**/*.png
📒 Files selected for processing (30)
  • .env.example
  • .github/workflows/android-check.yml
  • .github/workflows/android-release.yml
  • .gitignore
  • AGENTS.md
  • Gemfile
  • app.config.js
  • app.json
  • ci_scripts/ci_post_clone.sh
  • docs/cicd.md
  • fastlane/Appfile
  • fastlane/Fastfile
  • ios/.gitignore
  • ios/.xcode.env
  • ios/Podfile
  • ios/Podfile.properties.json
  • ios/app.xcodeproj/project.pbxproj
  • ios/app.xcodeproj/xcshareddata/xcschemes/app.xcscheme
  • ios/app/AppDelegate.swift
  • ios/app/Images.xcassets/AppIcon.appiconset/Contents.json
  • ios/app/Images.xcassets/Contents.json
  • ios/app/Images.xcassets/SplashScreenBackground.colorset/Contents.json
  • ios/app/Images.xcassets/SplashScreenLogo.imageset/Contents.json
  • ios/app/Info.plist
  • ios/app/SplashScreen.storyboard
  • ios/app/Supporting/Expo.plist
  • ios/app/app-Bridging-Header.h
  • ios/app/app.entitlements
  • plugins/withAndroidReleaseSigning.js
  • ui/home/components/banner.tsx
💤 Files with no reviewable changes (1)
  • ui/home/components/banner.tsx

Comment thread AGENTS.md Outdated
Comment thread ci_scripts/ci_post_clone.sh Outdated
Comment thread docs/cicd.md Outdated
Comment thread ios/app.xcodeproj/xcshareddata/xcschemes/app.xcscheme Outdated
@SeongHoonC SeongHoonC merged commit 098f4ac into prod May 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants