Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 175 additions & 47 deletions .github/workflows/appstore_release.yml
Original file line number Diff line number Diff line change
@@ -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
142 changes: 107 additions & 35 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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
Loading
Loading