diff --git a/.github/workflows/appstore_release.yml b/.github/workflows/appstore_release.yml index 86232d01..eb4a9a2e 100644 --- a/.github/workflows/appstore_release.yml +++ b/.github/workflows/appstore_release.yml @@ -1,57 +1,185 @@ -# This workflow will build a Swift project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift - -name: appstore-release +name: App Store Release on: pull_request: branches: - main + types: + - closed + + workflow_dispatch: jobs: - build: + deploy: + if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} runs-on: macos-26 + timeout-minutes: 120 + + env: + # App Store Connect + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} + + # Team IDs + DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} + APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} + + # Match (Code Signing) + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_KEYCHAIN_NAME: fastlane_tmp.keychain-db + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + + # Review Information + DEMO_USER: ${{ secrets.DEMO_USER }} + DEMO_PASSWORD: ${{ secrets.DEMO_PASSWORD }} + PHONE_NUMBER: ${{ secrets.PHONE_NUMBER }} + + # Fastlane + FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: '120' + FASTLANE_XCODE_LIST_TIMEOUT: '120' + FASTLANE_DISABLE_COLORS: 'true' steps: - - uses: actions/checkout@v4 - - - name: Set up Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - - uses: shimataro/ssh-key-action@v2 - with: - key: ${{ secrets.SSH_KEY }} - known_hosts: ${{ secrets.KNOWN_HOSTS }} - - - name: initial mise - run: | - curl https://mise.jdx.dev/install.sh | sh - echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH - echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH - - - name: initial tuist - run: mise install tuist - - - name: Generate Project - env: - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} - run: | - fastlane appstore_profile - make release - - - name: Build Archive - env: - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} - run: fastlane archive - - - name: Appstore Release - env: - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} - run: fastlane appstore_release + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Setup SSH for Match + if: env.MATCH_GIT_PRIVATE_KEY != '' + run: | + mkdir -p "$HOME/.ssh" + echo "$MATCH_GIT_PRIVATE_KEY" > "$HOME/.ssh/match_git_key" + chmod 600 "$HOME/.ssh/match_git_key" + + eval "$(ssh-agent -s)" + ssh-add "$HOME/.ssh/match_git_key" + ssh-keyscan -H github.com >> "$HOME/.ssh/known_hosts" + + cat >> "$HOME/.ssh/config" << EOF + Host github.com + IdentityFile ~/.ssh/match_git_key + StrictHostKeyChecking yes + User git + EOF + + - name: Setup SSH for Private repo + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_KEY }} + known_hosts: ${{ secrets.KNOWN_HOSTS }} + + - name: Setup keychain + if: env.MATCH_PASSWORD != '' + run: | + security create-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + security set-keychain-settings -lut 21600 "$MATCH_KEYCHAIN_NAME" + security unlock-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + + existing_keychains=$(security list-keychains | tr -d '"') + security list-keychains -s "$MATCH_KEYCHAIN_NAME" $existing_keychains + security default-keychain -s "$MATCH_KEYCHAIN_NAME" + + - name: Setup mise + run: | + curl https://mise.jdx.dev/install.sh | sh + echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH + echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH + + - name: Install Tuist + run: mise install tuist + + - name: Setup code signing + run: bundle exec fastlane appstore_profile + + - name: Generate project with Tuist + run: make release + + - name: Update release notes from PR description + env: + GH_TOKEN: ${{ github.token }} + run: | + PR_BODY=$(gh pr view ${{ github.event.pull_request.number }} --json body --jq '.body') + + if [ -z "$PR_BODY" ]; then + echo "버그 수정 및 성능 개선" > fastlane/release_notes.txt + else + echo "$PR_BODY" > fastlane/release_notes.txt + fi + + echo "Release notes updated:" + cat fastlane/release_notes.txt + + - name: Build archive + run: bundle exec fastlane archive + + - name: Submit to App Store + run: bundle exec fastlane appstore_release + + - name: Get app version + id: version + run: | + VERSION=$(xcodebuild -project Projects/App/App.xcodeproj -showBuildSettings | grep MARKETING_VERSION | head -1 | awk '{print $3}') + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Create Git tag and Release draft + env: + GH_TOKEN: ${{ github.token }} + run: | + VERSION="${{ steps.version.outputs.version }}" + TAG="v$VERSION" + + # 태그 생성 + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "$TAG" -m "Release $VERSION" + git push origin "$TAG" + + # Release draft 생성 + PR_BODY=$(gh pr view ${{ github.event.pull_request.number }} --json body --jq '.body') + if [ -z "$PR_BODY" ]; then + RELEASE_NOTES="버그 수정 및 성능 개선" + else + RELEASE_NOTES="$PR_BODY" + fi + + gh release create "$TAG" \ + --title "Release $VERSION" \ + --notes "$RELEASE_NOTES" \ + --draft + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: xcode-logs + path: | + ~/Library/Logs/gym + ~/Library/Developer/Xcode/DerivedData + /Users/runner/Library/Developer/Xcode/Archives + if-no-files-found: ignore + retention-days: 3 + + - name: Cleanup + if: always() + run: | + # SSH cleanup + if [ -n "$MATCH_GIT_PRIVATE_KEY" ]; then + ssh-add -D >/dev/null 2>&1 || true + rm -f "$HOME/.ssh/match_git_key" + fi + + # Keychain cleanup + if [ -n "$MATCH_PASSWORD" ]; then + security delete-keychain "$MATCH_KEYCHAIN_NAME" 2>/dev/null || true + fi diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index e7a6fb32..f3f5d9ec 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -1,7 +1,4 @@ -# This workflow will build a Swift project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift - -name: build-test +name: Build Test on: pull_request: @@ -13,36 +10,111 @@ on: jobs: build: runs-on: macos-26 + timeout-minutes: 60 + + env: + # Team IDs + DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} + + # Match (Code Signing) + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_KEYCHAIN_NAME: fastlane_tmp.keychain-db + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + + # Fastlane + FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: '120' + FASTLANE_XCODE_LIST_TIMEOUT: '120' + FASTLANE_DISABLE_COLORS: 'true' steps: - - uses: actions/checkout@v4 - - - name: Set up Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - - uses: shimataro/ssh-key-action@v2 - with: - key: ${{ secrets.SSH_KEY }} - known_hosts: ${{ secrets.KNOWN_HOSTS }} - - - name: initial mise - run: | - curl https://mise.jdx.dev/install.sh | sh - echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH - echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH - - - name: initial tuist - run: mise install tuist - - - name: Test Generate - env: - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} - run: | - fastlane development_profile - make test - - - name: Build Test - run: fastlane build + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Setup SSH for Match + if: env.MATCH_GIT_PRIVATE_KEY != '' + run: | + mkdir -p "$HOME/.ssh" + echo "$MATCH_GIT_PRIVATE_KEY" > "$HOME/.ssh/match_git_key" + chmod 600 "$HOME/.ssh/match_git_key" + + eval "$(ssh-agent -s)" + ssh-add "$HOME/.ssh/match_git_key" + ssh-keyscan -H github.com >> "$HOME/.ssh/known_hosts" + + cat >> "$HOME/.ssh/config" << EOF + Host github.com + IdentityFile ~/.ssh/match_git_key + StrictHostKeyChecking yes + User git + EOF + + - name: Setup SSH for Private repo + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_KEY }} + known_hosts: unnecessary + + - name: Setup keychain + if: env.MATCH_PASSWORD != '' + run: | + security create-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + security set-keychain-settings -lut 21600 "$MATCH_KEYCHAIN_NAME" + security unlock-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + + existing_keychains=$(security list-keychains | tr -d '"') + security list-keychains -s "$MATCH_KEYCHAIN_NAME" $existing_keychains + security default-keychain -s "$MATCH_KEYCHAIN_NAME" + + - name: Setup mise + run: | + curl https://mise.jdx.dev/install.sh | sh + echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH + echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH + + - name: Install Tuist + run: mise install tuist + + - name: Setup code signing + run: bundle exec fastlane development_profile + + - name: Generate project with Tuist + run: make test + + - name: Build Test + run: bundle exec fastlane build + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build-logs + path: | + ~/Library/Logs/gym + ~/Library/Developer/Xcode/DerivedData + if-no-files-found: ignore + retention-days: 3 + + - name: Cleanup + if: always() + run: | + # SSH cleanup + if [ -n "$MATCH_GIT_PRIVATE_KEY" ]; then + ssh-add -D >/dev/null 2>&1 || true + rm -f "$HOME/.ssh/match_git_key" + fi + + # Keychain cleanup + if [ -n "$MATCH_PASSWORD" ]; then + security delete-keychain "$MATCH_KEYCHAIN_NAME" 2>/dev/null || true + fi diff --git a/.github/workflows/check_appstore_status.yml b/.github/workflows/check_appstore_status.yml new file mode 100644 index 00000000..3fc6f9df --- /dev/null +++ b/.github/workflows/check_appstore_status.yml @@ -0,0 +1,41 @@ +name: Publish Release on App Store Approval + +on: + schedule: + # 매일 오전 9시, 오후 3시, 오후 9시 (KST 기준 오전 6시, 정오, 오후 6시 UTC) + - cron: '0 0,6,12 * * *' + + workflow_dispatch: + +jobs: + publish-release: + runs-on: macos-26 + timeout-minutes: 30 + + env: + # App Store Connect + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} + + # Team IDs + DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} + APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Check App Store status and publish release + env: + GH_TOKEN: ${{ github.token }} + run: | + bundle exec fastlane check_and_publish_release || echo "Release publish skipped or failed" diff --git a/.github/workflows/develop_hotfix.yml b/.github/workflows/develop_hotfix.yml index 8a0ef29f..8efdeca8 100644 --- a/.github/workflows/develop_hotfix.yml +++ b/.github/workflows/develop_hotfix.yml @@ -1,7 +1,4 @@ -# This workflow will build a Swift project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift - -name: develop-hotfix +name: Develop Hotfix on: push: @@ -10,50 +7,121 @@ on: workflow_dispatch: jobs: - build: + deploy: if: startsWith(github.event.head_commit.message, '[hotfix]') runs-on: macos-26 + timeout-minutes: 90 + + env: + # App Store Connect + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} + + # Team IDs + DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} + APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} + + # Match (Code Signing) + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_KEYCHAIN_NAME: fastlane_tmp.keychain-db + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + + # Fastlane + FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: '120' + FASTLANE_XCODE_LIST_TIMEOUT: '120' + FASTLANE_DISABLE_COLORS: 'true' steps: - - uses: actions/checkout@v4 - - - name: Set up Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - - uses: shimataro/ssh-key-action@v2 - with: - key: ${{ secrets.SSH_KEY }} - known_hosts: ${{ secrets.KNOWN_HOSTS }} - - - name: initial mise - run: | - curl https://mise.jdx.dev/install.sh | sh - echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH - echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH - - - name: initial tuist - run: mise install tuist - - - name: Generate Project - env: - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} - run: | - fastlane appstore_profile - make release - - - name: Build Archive - env: - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} - run: fastlane archive - - - name: Testflight Release - env: - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} - run: fastlane testflight_release + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Setup SSH for Match + if: env.MATCH_GIT_PRIVATE_KEY != '' + run: | + mkdir -p "$HOME/.ssh" + echo "$MATCH_GIT_PRIVATE_KEY" > "$HOME/.ssh/match_git_key" + chmod 600 "$HOME/.ssh/match_git_key" + + eval "$(ssh-agent -s)" + ssh-add "$HOME/.ssh/match_git_key" + ssh-keyscan -H github.com >> "$HOME/.ssh/known_hosts" + + cat >> "$HOME/.ssh/config" << EOF + Host github.com + IdentityFile ~/.ssh/match_git_key + StrictHostKeyChecking yes + User git + EOF + + - name: Setup SSH for Private repo + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_KEY }} + known_hosts: unnecessary + + - name: Setup keychain + if: env.MATCH_PASSWORD != '' + run: | + security create-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + security set-keychain-settings -lut 21600 "$MATCH_KEYCHAIN_NAME" + security unlock-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + + existing_keychains=$(security list-keychains | tr -d '"') + security list-keychains -s "$MATCH_KEYCHAIN_NAME" $existing_keychains + security default-keychain -s "$MATCH_KEYCHAIN_NAME" + + - name: Setup mise + run: | + curl https://mise.jdx.dev/install.sh | sh + echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH + echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH + + - name: Install Tuist + run: mise install tuist + + - name: Setup code signing + run: bundle exec fastlane appstore_profile + + - name: Generate project with Tuist + run: make release + + - name: Build and upload to TestFlight + run: bundle exec fastlane archive && bundle exec fastlane testflight_release + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: hotfix-logs + path: | + ~/Library/Logs/gym + ~/Library/Developer/Xcode/DerivedData + /Users/runner/Library/Developer/Xcode/Archives + if-no-files-found: ignore + retention-days: 3 + + - name: Cleanup + if: always() + run: | + # SSH cleanup + if [ -n "$MATCH_GIT_PRIVATE_KEY" ]; then + ssh-add -D >/dev/null 2>&1 || true + rm -f "$HOME/.ssh/match_git_key" + fi + + # Keychain cleanup + if [ -n "$MATCH_PASSWORD" ]; then + security delete-keychain "$MATCH_KEYCHAIN_NAME" 2>/dev/null || true + fi diff --git a/.github/workflows/testflight_release.yml b/.github/workflows/testflight_release.yml index f8aebfd3..a9ea4b65 100644 --- a/.github/workflows/testflight_release.yml +++ b/.github/workflows/testflight_release.yml @@ -1,7 +1,4 @@ -# This workflow will build a Swift project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift - -name: testflight-release +name: TestFlight Release on: pull_request: @@ -13,50 +10,121 @@ on: workflow_dispatch: jobs: - build: + deploy: if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} runs-on: macos-26 + timeout-minutes: 90 + + env: + # App Store Connect + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} + + # Team IDs + DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} + APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} + + # Match (Code Signing) + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_KEYCHAIN_NAME: fastlane_tmp.keychain-db + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + + # Fastlane + FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: '120' + FASTLANE_XCODE_LIST_TIMEOUT: '120' + FASTLANE_DISABLE_COLORS: 'true' steps: - - uses: actions/checkout@v4 - - - name: Set up Xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - - uses: shimataro/ssh-key-action@v2 - with: - key: ${{ secrets.SSH_KEY }} - known_hosts: ${{ secrets.KNOWN_HOSTS }} - - - name: initial mise - run: | - curl https://mise.jdx.dev/install.sh | sh - echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH - echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH - - - name: initial tuist - run: mise install tuist - - - name: Generate Project - env: - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }} - run: | - fastlane appstore_profile - make release - - - name: Build Archive - env: - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} - run: fastlane archive - - - name: Testflight Release - env: - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API: ${{ secrets.APP_STORE_CONNECT_API }} - run: fastlane testflight_release + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Setup SSH for Match + if: env.MATCH_GIT_PRIVATE_KEY != '' + run: | + mkdir -p "$HOME/.ssh" + echo "$MATCH_GIT_PRIVATE_KEY" > "$HOME/.ssh/match_git_key" + chmod 600 "$HOME/.ssh/match_git_key" + + eval "$(ssh-agent -s)" + ssh-add "$HOME/.ssh/match_git_key" + ssh-keyscan -H github.com >> "$HOME/.ssh/known_hosts" + + cat >> "$HOME/.ssh/config" << EOF + Host github.com + IdentityFile ~/.ssh/match_git_key + StrictHostKeyChecking yes + User git + EOF + + - name: Setup SSH for Private repo + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_KEY }} + known_hosts: ${{ secrets.KNOWN_HOSTS }} + + - name: Setup keychain + if: env.MATCH_PASSWORD != '' + run: | + security create-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + security set-keychain-settings -lut 21600 "$MATCH_KEYCHAIN_NAME" + security unlock-keychain -p "$MATCH_PASSWORD" "$MATCH_KEYCHAIN_NAME" + + existing_keychains=$(security list-keychains | tr -d '"') + security list-keychains -s "$MATCH_KEYCHAIN_NAME" $existing_keychains + security default-keychain -s "$MATCH_KEYCHAIN_NAME" + + - name: Setup mise + run: | + curl https://mise.jdx.dev/install.sh | sh + echo "$HOME/.local/share/mise/bin" >> $GITHUB_PATH + echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH + + - name: Install Tuist + run: mise install tuist + + - name: Setup code signing + run: bundle exec fastlane appstore_profile + + - name: Generate project with Tuist + run: make release + + - name: Build and upload to TestFlight + run: bundle exec fastlane archive && bundle exec fastlane testflight_release + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: xcode-logs + path: | + ~/Library/Logs/gym + ~/Library/Developer/Xcode/DerivedData + /Users/runner/Library/Developer/Xcode/Archives + if-no-files-found: ignore + retention-days: 3 + + - name: Cleanup + if: always() + run: | + # SSH cleanup + if [ -n "$MATCH_GIT_PRIVATE_KEY" ]; then + ssh-add -D >/dev/null 2>&1 || true + rm -f "$HOME/.ssh/match_git_key" + fi + + # Keychain cleanup + if [ -n "$MATCH_PASSWORD" ]; then + security delete-keychain "$MATCH_KEYCHAIN_NAME" 2>/dev/null || true + fi diff --git a/.gitignore b/.gitignore index c6809d8e..3fcb69ea 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,7 @@ fastlane/key.json ### fastlane environment fastlane/.env fastlane/.env.default + +### Environment variables +.env +.env.local diff --git a/fastlane/Appfile b/fastlane/Appfile index 40383a02..c2270b35 100644 --- a/fastlane/Appfile +++ b/fastlane/Appfile @@ -1,8 +1,7 @@ -app_identifier("com.pokitmons.pokit") # The bundle identifier of your app -apple_id("shapekim98@gmail.com") # Your Apple Developer Portal username - -itc_team_id(ENV['APP_STORE_CONNECT_TEAM_ID']) # App Store Connect Team ID -team_id(ENV['DEVELOPMENT_TEAM']) # Developer Portal Team ID +app_identifier(ENV["APP_IDENTIFIER"]) +apple_id(ENV["APPLE_ID"]) +team_id(ENV["DEVELOPMENT_TEAM"]) +itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"]) # For more information about the Appfile, see: # https://docs.fastlane.tools/advanced/#appfile diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 164214f1..e24562ec 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,150 +1,296 @@ -# This file contains the fastlane.tools configuration -# You can find the documentation at https://docs.fastlane.tools -# -# For a list of all available actions, check out -# -# https://docs.fastlane.tools/actions -# -# For a list of all available plugins, check out -# -# https://docs.fastlane.tools/plugins/available-plugins -# - -# Uncomment the line if you want fastlane to automatically update itself -# update_fastlane +# frozen_string_literal: true default_platform(:ios) -platform :ios do - lane :appstore_profile do - setup_ci +# ============================================================================= +# MARK: - Configuration +# ============================================================================= - match( - type: "appstore", - app_identifier:["com.pokitmons.pokit", "com.pokitmons.pokit.ShareExtension"], - readonly: true - ) +APP_CONFIG = { + apple_id: "shapekim98@gmail.com", + app_store_team_id: ENV["APP_STORE_CONNECT_TEAM_ID"], + development_team_id: ENV["DEVELOPMENT_TEAM"], + match_git_url: "git@github.com:stealmh/Pokit_iOS_Private.git", + match_git_branch: "main" +}.freeze + +APP_IDENTIFIERS = { + app: "com.pokitmons.pokit", + share_extension: "com.pokitmons.pokit.ShareExtension" +}.freeze + +# ============================================================================= +# MARK: - Helper Methods +# ============================================================================= + +# 필수 환경변수 검증 +def ensure_env_values(env_vars:) + missing = env_vars.select { |key| ENV[key].to_s.strip.empty? } + UI.user_error!("필수 환경변수 누락: #{missing.join(', ')}") unless missing.empty? +end + +# Match에 사용할 Bundle Identifier 목록 생성 +def match_bundle_identifiers + [APP_IDENTIFIERS[:app], APP_IDENTIFIERS[:share_extension]] +end + +# Match 키체인 이름 반환 +def match_keychain_name + ENV["MATCH_KEYCHAIN_NAME"] || "fastlane_tmp.keychain-db" +end + +# App Store Connect API Key 내용 반환 +def app_store_connect_key_content + # 환경변수에서 직접 읽기 + key = ENV["APP_STORE_CONNECT_API"] + return key unless key.to_s.strip.empty? + + # 파일에서 읽기 + path = ENV["APP_STORE_CONNECT_PRIVATE_KEY_PATH"] + UI.user_error!("APP_STORE_CONNECT_API 또는 APP_STORE_CONNECT_PRIVATE_KEY_PATH 환경변수가 필요합니다.") if path.to_s.strip.empty? + + expanded_path = File.expand_path(path.strip) + UI.user_error!("파일을 찾을 수 없습니다: #{expanded_path}") unless File.exist?(expanded_path) + + File.read(expanded_path) +end + +# App Store Connect API Key 생성 +def create_api_key + app_store_connect_api_key( + key_id: ENV["APP_STORE_CONNECT_KEY_ID"], + issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"], + key_content: app_store_connect_key_content, + duration: 1200, + in_house: false + ) +end + +# 다음 빌드 번호 계산 +def get_next_build_number(api_key:, app_identifier:) + latest_testflight_build_number( + api_key: api_key, + app_identifier: app_identifier, + platform: "ios" + ).to_i + 1 +rescue StandardError => e + UI.message("최신 빌드 번호 확인 실패: #{e.message}. 1부터 시작합니다.") + 1 +end + +# Match 코드 사이닝 설정 +def setup_code_signing(type:) + return UI.message("MATCH_PASSWORD가 없어 코드 사이닝을 건너뜁니다.") if ENV["MATCH_PASSWORD"].to_s.strip.empty? + + ensure_env_values(env_vars: %w[MATCH_PASSWORD]) + + match_params = { + type: type, + readonly: true, + app_identifier: match_bundle_identifiers, + username: APP_CONFIG[:apple_id], + team_id: APP_CONFIG[:development_team_id], + git_branch: APP_CONFIG[:match_git_branch], + git_url: APP_CONFIG[:match_git_url], + clone_branch_directly: true + } + + # CI 환경에서는 키체인 설정 추가 (MATCH_PASSWORD 재사용) + if ENV["CI"] == "true" || ENV["GITHUB_ACTIONS"] == "true" + match_params[:keychain_name] = match_keychain_name + match_params[:keychain_password] = ENV["MATCH_PASSWORD"] end - lane :development_profile do - setup_ci + # Git private key가 있으면 추가 + if !ENV["MATCH_GIT_PRIVATE_KEY"].to_s.strip.empty? + match_params[:git_private_key] = ENV["MATCH_GIT_PRIVATE_KEY"].strip + end - match( - type: "development", - app_identifier:["com.pokitmons.pokit", "com.pokitmons.pokit.ShareExtension"], - readonly: true - ) + match(match_params) +end + +# Tuist 프로젝트 생성 +def generate_tuist_project + UI.message("Tuist 프로젝트를 생성합니다...") + + development_team = ENV["DEVELOPMENT_TEAM"] + + if development_team.to_s.empty? + sh("tuist generate") + else + sh("TUIST_DEVELOPMENT_TEAM=#{development_team} tuist generate") end +end - lane :build do - build_app( +# 앱 빌드 +def build_app_for_release(scheme:, output_name:, export_method:) + build_app( workspace: "Pokit.xcworkspace", - scheme: "App", - configuration: "Debug", - export_method: "development", + scheme: scheme, + configuration: "Release", + derived_data_path: "build/DerivedData", + output_directory: "build/artifacts", + output_name: output_name, + clean: true, + skip_profile_detection: true, + export_method: export_method, + xcargs: "-skipMacroValidation", export_options: { - provisioningProfiles: { - "com.pokitmons.pokit" => "match Development com.pokitmons.pokit", - "com.pokitmons.pokit.ShareExtension" => "match Development com.pokitmons.pokit.ShareExtension" - } + provisioningProfiles: { + APP_IDENTIFIERS[:app] => "match #{export_method == 'app-store' ? 'AppStore' : 'Development'} #{APP_IDENTIFIERS[:app]}", + APP_IDENTIFIERS[:share_extension] => "match #{export_method == 'app-store' ? 'AppStore' : 'Development'} #{APP_IDENTIFIERS[:share_extension]}" + } } + ) +end + +# ============================================================================= +# MARK: - Lanes +# ============================================================================= + +platform :ios do + desc "앱스토어용 프로비저닝 프로파일 설정" + lane :appstore_profile do + setup_ci if ENV["CI"] == "true" + setup_code_signing(type: "appstore") + end + + desc "개발용 프로비저닝 프로파일 설정" + lane :development_profile do + setup_ci if ENV["CI"] == "true" + setup_code_signing(type: "development") + end + + desc "개발 빌드 테스트" + lane :build do + generate_tuist_project + + xcodebuild( + workspace: "Pokit.xcworkspace", + scheme: "App", + configuration: "Debug", + xcargs: "-skipMacroValidation", + build: true ) end + desc "릴리즈 빌드 및 아카이브" lane :archive do - api_key = app_store_connect_api_key( - key_id: ENV['APP_STORE_CONNECT_KEY_ID'], - issuer_id: ENV['APP_STORE_CONNECT_ISSUER_ID'], - key_content: ENV['APP_STORE_CONNECT_API'] - ) + begin + # 환경변수 검증 + ensure_env_values(env_vars: %w[APP_STORE_CONNECT_KEY_ID APP_STORE_CONNECT_ISSUER_ID]) - latest_build_number = latest_testflight_build_number( - api_key: api_key, - app_identifier: "com.pokitmons.pokit" - ) + # Tuist 프로젝트 생성 + generate_tuist_project - increment_build_number( - xcodeproj: "Projects/App/App.xcodeproj", - build_number: (latest_build_number + 1).to_s - ) + # API Key 생성 + api_key = create_api_key - build_app( - workspace: "Pokit.xcworkspace", - scheme: "App", - configuration: "Release", - export_method: "app-store", - export_options: { - provisioningProfiles: { - "com.pokitmons.pokit" => "match AppStore com.pokitmons.pokit", - "com.pokitmons.pokit.ShareExtension" => "match AppStore com.pokitmons.pokit.ShareExtension" - } - } - ) + # 빌드 번호 업데이트 + next_build_number = get_next_build_number(api_key: api_key, app_identifier: APP_IDENTIFIERS[:app]) + increment_build_number(xcodeproj: "Projects/App/App.xcodeproj", build_number: next_build_number.to_s) + + # 빌드 + build_app_for_release( + scheme: "App", + output_name: "Pokit.ipa", + export_method: "app-store" + ) + ensure + clean_build_artifacts + end end + desc "TestFlight에 업로드" lane :testflight_release do - api_key = app_store_connect_api_key( - key_id: ENV['APP_STORE_CONNECT_KEY_ID'], - issuer_id: ENV['APP_STORE_CONNECT_ISSUER_ID'], - key_content: ENV['APP_STORE_CONNECT_API'] - ) + begin + # 환경변수 검증 + ensure_env_values(env_vars: %w[APP_STORE_CONNECT_KEY_ID APP_STORE_CONNECT_ISSUER_ID]) - upload_to_testflight( - api_key: api_key, - distribute_external: true, - groups: ["Pokitmons"], - changelog: "" - ) + # API Key 생성 + api_key = create_api_key + + # TestFlight 업로드 + upload_to_testflight( + api_key: api_key, + skip_waiting_for_build_processing: false, + distribute_external: true, + groups: ["Pokitmons"], + changelog: "" + ) + + UI.success("✅ TestFlight 업로드 완료!") + ensure + clean_build_artifacts + end end + desc "App Store에 제출" lane :appstore_release do - api_key = app_store_connect_api_key( - key_id: ENV['APP_STORE_CONNECT_KEY_ID'], - issuer_id: ENV['APP_STORE_CONNECT_ISSUER_ID'], - key_content: ENV['APP_STORE_CONNECT_API'] - ) + begin + # 환경변수 검증 + ensure_env_values(env_vars: %w[APP_STORE_CONNECT_KEY_ID APP_STORE_CONNECT_ISSUER_ID]) - release_notes = File.read("release_notes.txt") + # API Key 생성 + api_key = create_api_key - upload_to_app_store( - api_key: api_key, - skip_metadata: false, - skip_screenshots: true, - skip_binary_upload: true, - precheck_include_in_app_purchases: false, - release_notes: { - 'default' => release_notes - }, - submit_for_review: true, - automatic_release: true, - force: true - ) + # App Store Connect에 업로드 및 메타데이터 업데이트 + deliver( + api_key: api_key, + app_identifier: APP_IDENTIFIERS[:app], + skip_screenshots: true, + skip_metadata: false, + force: true, + submit_for_review: true, + automatic_release: true, + submission_information: { + add_id_info_uses_idfa: false + }, + precheck_include_in_app_purchases: false + ) + + UI.success("✅ App Store 심사 제출 완료!") + ensure + clean_build_artifacts + end end - lane :update_github_release do + desc "App Store 승인 확인 및 Release draft publish" + lane :check_and_publish_release do require 'spaceship' - api_key = app_store_connect_api_key( - key_id: ENV['APP_STORE_CONNECT_KEY_ID'], - issuer_id: ENV['APP_STORE_CONNECT_ISSUER_ID'], - key_content: ENV['APP_STORE_CONNECT_API'] - ) - + api_key = create_api_key Spaceship::ConnectAPI.login(api_key: api_key) - app = Spaceship::ConnectAPI::App.find("com.pokitmons.pokit") - + app = Spaceship::ConnectAPI::App.find(APP_IDENTIFIERS[:app]) live_version = app.get_live_version app_state = live_version.app_store_state app_version = live_version.version_string + UI.message("현재 앱 상태: #{app_state}, 버전: #{app_version}") + if app_state == 'READY_FOR_SALE' - pr_number = ENV['PR_NUMBER'] - pr_body = sh("gh pr view #{pr_number} --json body --jq '.body'") - release_notes = pr_body.strip + tag = "v#{app_version}" + + # Draft release 확인 + release_info = sh("gh release view #{tag} --json isDraft,name 2>/dev/null || echo ''").strip + + if release_info.empty? + UI.message("Release #{tag}가 존재하지 않습니다. 건너뜁니다.") + return + end + + is_draft = sh("echo '#{release_info}' | jq -r '.isDraft'").strip - # GitHub 릴리즈 버전 및 릴리즈 노트 업데이트 - sh("gh release create v#{app_version} --notes '#{release_notes}'") + if is_draft == "true" + # Draft release를 publish + sh("gh release edit #{tag} --draft=false") + UI.success("✅ GitHub Release #{tag} 를 publish 했습니다!") + else + UI.message("GitHub Release #{tag}는 이미 published 상태입니다.") + end + else + UI.message("앱이 아직 'READY_FOR_SALE' 상태가 아닙니다. 현재 상태: #{app_state}") end end end diff --git a/fastlane/Matchfile b/fastlane/Matchfile index 6648ebc2..6df69ed3 100644 --- a/fastlane/Matchfile +++ b/fastlane/Matchfile @@ -4,9 +4,15 @@ storage_mode("git") type("development") # The default type, can be: appstore, adhoc, enterprise or development -app_identifier(["com.pokitmons.pokit"]) +app_identifier([ + "com.pokitmons.pokit", + "com.pokitmons.pokit.ShareExtension" +]) username("shapekim98@gmail.com") # Your Apple Developer Portal username +git_branch("main") +shallow_clone(true) + # For all available options run `fastlane match --help` # Remove the # in the beginning of the line to enable the other options diff --git a/fastlane/README.md b/fastlane/README.md index dd35e59d..c2ce6ab9 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -21,7 +21,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios appstore_profile ``` - +앱스토어용 프로비저닝 프로파일 설정 ### ios development_profile @@ -29,7 +29,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios development_profile ``` - +개발용 프로비저닝 프로파일 설정 ### ios build @@ -37,7 +37,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios build ``` - +개발 빌드 테스트 ### ios archive @@ -45,7 +45,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios archive ``` - +릴리즈 빌드 및 아카이브 ### ios testflight_release @@ -53,7 +53,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios testflight_release ``` - +TestFlight에 업로드 ### ios appstore_release @@ -61,7 +61,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios appstore_release ``` - +App Store에 제출 ### ios update_github_release @@ -69,7 +69,7 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do [bundle exec] fastlane ios update_github_release ``` - +GitHub Release 업데이트 (App Store 승인 후) ---- diff --git a/fastlane/metadata/copyright.txt b/fastlane/metadata/copyright.txt new file mode 100644 index 00000000..cf6dcc63 --- /dev/null +++ b/fastlane/metadata/copyright.txt @@ -0,0 +1 @@ +포킷몬즈 diff --git a/fastlane/metadata/ko/apple_tv_privacy_policy.txt b/fastlane/metadata/ko/apple_tv_privacy_policy.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/ko/apple_tv_privacy_policy.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/ko/description.txt b/fastlane/metadata/ko/description.txt new file mode 100644 index 00000000..d703bada --- /dev/null +++ b/fastlane/metadata/ko/description.txt @@ -0,0 +1,14 @@ +저장해뒀던 링크, 찾지 못한 경험이 있으신가요? +저희 서비스는 흩어져 있던 링크를 한곳에 모아 관리하고, 잊지 않고 리마인드할 수 있도록 돕습니다. + +1. 복잡한 링크 저장 과정을 개선했어요. +바로 붙여넣기 기능, 자동 제목 생성 기능으로 복잡했던 링크 저장 과정을 개선해 편리성을 제공해요. + +2. 카테고리별로 나눠 분류해요. +저장한 링크를 주제별로 나눠서 깔끔하게 정리해요. + +3. 저장한 링크들을 한번에 공유해요. +비슷한 카테고리들로 분류한 링크들을 다른 사람들에게 한번에 공유할 수 있어요. + +4. 저장한 링크를 잊지 않고 볼 수 있도록 도와줘요. +사용자 맞춤 리마인드 콘텐츠 제공, 리마인드 푸시 메시지를 통해 지속적으로 관리하도록 동기부여해요. diff --git a/fastlane/metadata/ko/keywords.txt b/fastlane/metadata/ko/keywords.txt new file mode 100644 index 00000000..81748f15 --- /dev/null +++ b/fastlane/metadata/ko/keywords.txt @@ -0,0 +1 @@ +아카이빙,링크,저장,즐겨찾기,리마인드,콘텐츠,링크저장,콘텐츠저장 diff --git a/fastlane/metadata/ko/marketing_url.txt b/fastlane/metadata/ko/marketing_url.txt new file mode 100644 index 00000000..b6a03cba --- /dev/null +++ b/fastlane/metadata/ko/marketing_url.txt @@ -0,0 +1 @@ +https://luminous-captain-c68.notion.site/bb6d0d6569204d5e9a7b67e5825f9d10 diff --git a/fastlane/metadata/ko/name.txt b/fastlane/metadata/ko/name.txt new file mode 100644 index 00000000..709c18ba --- /dev/null +++ b/fastlane/metadata/ko/name.txt @@ -0,0 +1 @@ +Pokit 포킷 - 간편 링크 아카이빙 앱 diff --git a/fastlane/metadata/ko/privacy_url.txt b/fastlane/metadata/ko/privacy_url.txt new file mode 100644 index 00000000..c718ae0c --- /dev/null +++ b/fastlane/metadata/ko/privacy_url.txt @@ -0,0 +1 @@ +https://www.notion.so/de3468b3be1744538c22a333ae1d0ec8 diff --git a/fastlane/metadata/ko/promotional_text.txt b/fastlane/metadata/ko/promotional_text.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/ko/promotional_text.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/ko/release_notes.txt b/fastlane/metadata/ko/release_notes.txt new file mode 100644 index 00000000..6196984a --- /dev/null +++ b/fastlane/metadata/ko/release_notes.txt @@ -0,0 +1 @@ +- 자잘한 오류들을 수정했어요. diff --git a/fastlane/metadata/ko/subtitle.txt b/fastlane/metadata/ko/subtitle.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/ko/subtitle.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/ko/support_url.txt b/fastlane/metadata/ko/support_url.txt new file mode 100644 index 00000000..104ccab8 --- /dev/null +++ b/fastlane/metadata/ko/support_url.txt @@ -0,0 +1 @@ +https://luminous-captain-c68.notion.site/POKIT-d97c81534b354cfebe677fbf1fbfe2b2 diff --git a/fastlane/metadata/primary_category.txt b/fastlane/metadata/primary_category.txt new file mode 100644 index 00000000..cd65e793 --- /dev/null +++ b/fastlane/metadata/primary_category.txt @@ -0,0 +1 @@ +PRODUCTIVITY diff --git a/fastlane/metadata/primary_first_sub_category.txt b/fastlane/metadata/primary_first_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/primary_first_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/primary_second_sub_category.txt b/fastlane/metadata/primary_second_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/primary_second_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/review_information/demo_password.txt b/fastlane/metadata/review_information/demo_password.txt new file mode 100644 index 00000000..4bdb14f2 --- /dev/null +++ b/fastlane/metadata/review_information/demo_password.txt @@ -0,0 +1 @@ +ENV["DEMO_PASSWORD"] diff --git a/fastlane/metadata/review_information/demo_user.txt b/fastlane/metadata/review_information/demo_user.txt new file mode 100644 index 00000000..50f4e145 --- /dev/null +++ b/fastlane/metadata/review_information/demo_user.txt @@ -0,0 +1 @@ +ENV["DEMO_USER"] diff --git a/fastlane/metadata/review_information/email_address.txt b/fastlane/metadata/review_information/email_address.txt new file mode 100644 index 00000000..6b32d791 --- /dev/null +++ b/fastlane/metadata/review_information/email_address.txt @@ -0,0 +1 @@ +kmh922@naver.com diff --git a/fastlane/metadata/review_information/first_name.txt b/fastlane/metadata/review_information/first_name.txt new file mode 100644 index 00000000..26c87279 --- /dev/null +++ b/fastlane/metadata/review_information/first_name.txt @@ -0,0 +1 @@ +민호 diff --git a/fastlane/metadata/review_information/last_name.txt b/fastlane/metadata/review_information/last_name.txt new file mode 100644 index 00000000..34bb12d0 --- /dev/null +++ b/fastlane/metadata/review_information/last_name.txt @@ -0,0 +1 @@ +김 diff --git a/fastlane/metadata/review_information/notes.txt b/fastlane/metadata/review_information/notes.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/review_information/notes.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/review_information/phone_number.txt b/fastlane/metadata/review_information/phone_number.txt new file mode 100644 index 00000000..410a4fbf --- /dev/null +++ b/fastlane/metadata/review_information/phone_number.txt @@ -0,0 +1 @@ +ENV["PHONE_NUMBER"] diff --git a/fastlane/metadata/secondary_category.txt b/fastlane/metadata/secondary_category.txt new file mode 100644 index 00000000..cc525525 --- /dev/null +++ b/fastlane/metadata/secondary_category.txt @@ -0,0 +1 @@ +LIFESTYLE diff --git a/fastlane/metadata/secondary_first_sub_category.txt b/fastlane/metadata/secondary_first_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/secondary_first_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/secondary_second_sub_category.txt b/fastlane/metadata/secondary_second_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/secondary_second_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/release_notes.txt b/fastlane/release_notes.txt deleted file mode 100644 index 5baff929..00000000 --- a/fastlane/release_notes.txt +++ /dev/null @@ -1,3 +0,0 @@ -- 이제부터 어디서든 아이폰 공유하기로 링크를 저장할 수 있어요. -- 인스타그램 링크에서 썸네일이 나오지 않는 문제를 수성했어요. -- 자잘한 버그 및 사용성을 개선했어요. \ No newline at end of file diff --git a/fastlane/report.xml b/fastlane/report.xml index 9d5a5bf3..7e813271 100644 --- a/fastlane/report.xml +++ b/fastlane/report.xml @@ -5,17 +5,7 @@ - - - - - - - - - - - + diff --git a/fastlane/screenshots/ko/0_APP_IPHONE_55_0.png b/fastlane/screenshots/ko/0_APP_IPHONE_55_0.png new file mode 100644 index 00000000..778b70a3 Binary files /dev/null and b/fastlane/screenshots/ko/0_APP_IPHONE_55_0.png differ diff --git a/fastlane/screenshots/ko/0_APP_IPHONE_67_0.png b/fastlane/screenshots/ko/0_APP_IPHONE_67_0.png new file mode 100644 index 00000000..eb153584 Binary files /dev/null and b/fastlane/screenshots/ko/0_APP_IPHONE_67_0.png differ diff --git a/fastlane/screenshots/ko/1_APP_IPHONE_55_1.png b/fastlane/screenshots/ko/1_APP_IPHONE_55_1.png new file mode 100644 index 00000000..9b944f70 Binary files /dev/null and b/fastlane/screenshots/ko/1_APP_IPHONE_55_1.png differ diff --git a/fastlane/screenshots/ko/1_APP_IPHONE_67_1.png b/fastlane/screenshots/ko/1_APP_IPHONE_67_1.png new file mode 100644 index 00000000..15fd19c2 Binary files /dev/null and b/fastlane/screenshots/ko/1_APP_IPHONE_67_1.png differ diff --git a/fastlane/screenshots/ko/2_APP_IPHONE_55_2.png b/fastlane/screenshots/ko/2_APP_IPHONE_55_2.png new file mode 100644 index 00000000..6f846cff Binary files /dev/null and b/fastlane/screenshots/ko/2_APP_IPHONE_55_2.png differ diff --git a/fastlane/screenshots/ko/2_APP_IPHONE_67_2.png b/fastlane/screenshots/ko/2_APP_IPHONE_67_2.png new file mode 100644 index 00000000..7f15bf38 Binary files /dev/null and b/fastlane/screenshots/ko/2_APP_IPHONE_67_2.png differ diff --git a/fastlane/screenshots/ko/3_APP_IPHONE_55_3.png b/fastlane/screenshots/ko/3_APP_IPHONE_55_3.png new file mode 100644 index 00000000..929b9ac1 Binary files /dev/null and b/fastlane/screenshots/ko/3_APP_IPHONE_55_3.png differ diff --git a/fastlane/screenshots/ko/3_APP_IPHONE_67_3.png b/fastlane/screenshots/ko/3_APP_IPHONE_67_3.png new file mode 100644 index 00000000..2a9cb4ff Binary files /dev/null and b/fastlane/screenshots/ko/3_APP_IPHONE_67_3.png differ diff --git a/fastlane/screenshots/ko/4_APP_IPHONE_67_4.png b/fastlane/screenshots/ko/4_APP_IPHONE_67_4.png new file mode 100644 index 00000000..d3de615d Binary files /dev/null and b/fastlane/screenshots/ko/4_APP_IPHONE_67_4.png differ