Skip to content

Conversation

graycreate
Copy link
Member

Summary

  • Implement automated iOS release pipeline similar to Android
  • Configure Fastlane Match for certificate management
  • Add single workflow that handles version detection, tagging, and TestFlight release

Changes

GitHub Actions Workflow

  • Modified .github/workflows/release.yml - Unified pipeline with two jobs:
    • version-check: Detects version changes and creates tags
    • build-and-release: Builds and uploads to TestFlight when new tag is created

Fastlane Configuration

  • Added fastlane/Fastfile - Defines lanes for beta and release
  • Added fastlane/Matchfile - Certificate management configuration
  • Added fastlane/Appfile - App identifier and team configuration

Other Changes

  • Updated .gitignore - Added Fastlane artifacts
  • Added SETUP_RELEASE_PIPELINE.md - Comprehensive setup documentation

How It Works

  1. Push to main branch with updated version in Info.plist
  2. Workflow detects version change
  3. Creates git tag automatically (format: v1.2.0)
  4. Builds and uploads to TestFlight
  5. Creates GitHub Release

Setup Required

Before merging, the following secrets need to be configured in GitHub:

  • DEPLOY_KEY - SSH private key for certificates repo
  • MATCH_GIT_URL - Certificates repository URL
  • MATCH_PASSWORD - Match encryption password
  • APP_STORE_CONNECT_KEY_ID - API Key ID
  • APP_STORE_CONNECT_ISSUER_ID - Issuer ID
  • APP_STORE_CONNECT_API_KEY_BASE64 - Base64 encoded .p8 file
  • TEAM_ID - Apple Developer Team ID

Testing

  • Verify Fastlane configuration locally
  • Test certificate sync with Match
  • Confirm GitHub Actions workflow syntax

Related

  • Similar to Android release pipeline implementation
  • Uses SSH Deploy Keys instead of PAT for better security
  • API Keys use base64 encoding to avoid parsing issues

- Add unified release.yml workflow for version detection and auto-release
- Configure Fastlane with Match for certificate management
- Add Fastfile, Matchfile, and Appfile configurations
- Update .gitignore for Fastlane artifacts
- Create comprehensive setup documentation

This pipeline automatically:
1. Detects version changes in Info.plist
2. Creates git tags for new versions
3. Builds and uploads to TestFlight
4. Creates GitHub releases
@Copilot Copilot AI review requested due to automatic review settings September 22, 2025 15:14
@github-actions
Copy link

Code Coverage Report ❌

Current coverage: 0%

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements an automated iOS release pipeline similar to the existing Android release process. It adds Fastlane for build automation and certificate management, replacing the previous manual approach with a streamlined workflow that automatically detects version changes, creates tags, and uploads to TestFlight.

Key Changes

  • Automated pipeline: Single workflow with version detection and automated tagging
  • Fastlane integration: Complete configuration for certificate management via Match and TestFlight uploads
  • Security improvements: Uses SSH deploy keys and base64-encoded API keys instead of PAT tokens

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

File Description
.github/workflows/release.yml Complete workflow rewrite with two-job pipeline for version checking and TestFlight release
fastlane/Fastfile Defines lanes for certificate sync, beta releases, and App Store submissions
fastlane/Matchfile Configuration for code signing certificate management via git repository
fastlane/Appfile App-specific configuration with bundle ID and team settings

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 22 to 27
api_key = app_store_connect_api_key(
key_id: ENV["APP_STORE_CONNECT_API_KEY_KEY_ID"],
issuer_id: ENV["APP_STORE_CONNECT_API_KEY_ISSUER_ID"],
key_filepath: ENV["APP_STORE_CONNECT_API_KEY_KEY"],
in_house: false
)
Copy link

Copilot AI Sep 22, 2025

Choose a reason for hiding this comment

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

The API key creation is duplicated across multiple lanes (beta, release, create_app_version, download_metadata). Consider extracting this into a helper method to reduce code duplication.

Copilot uses AI. Check for mistakes.

Comment on lines +30 to +41
build_app(
scheme: "V2er",
export_method: "app-store",
export_options: {
provisioningProfiles: {
"v2er.app" => "match AppStore v2er.app"
}
},
clean: true,
output_directory: "./build",
output_name: "V2er.ipa"
)
Copy link

Copilot AI Sep 22, 2025

Choose a reason for hiding this comment

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

The build_app configuration is duplicated between beta and release lanes. Consider extracting this into a shared method to maintain consistency and reduce duplication.

Copilot uses AI. Check for mistakes.

Comment on lines 41 to 43
# Get current version from Info.plist
CURRENT_VERSION=$(grep -A1 "CFBundleShortVersionString" V2er/Info.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>/\1/' | xargs)
CURRENT_BUILD=$(grep -A1 "CFBundleVersion" V2er/Info.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>/\1/' | xargs)
Copy link

Copilot AI Sep 22, 2025

Choose a reason for hiding this comment

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

The regex patterns for parsing Info.plist are complex and fragile. Consider using a more robust XML parser like plutil or PlistBuddy which are available on the runner and handle XML parsing more reliably.

Suggested change
# Get current version from Info.plist
CURRENT_VERSION=$(grep -A1 "CFBundleShortVersionString" V2er/Info.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>/\1/' | xargs)
CURRENT_BUILD=$(grep -A1 "CFBundleVersion" V2er/Info.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>/\1/' | xargs)
# Get current version from Info.plist using plutil for robust XML parsing
CURRENT_VERSION=$(/usr/bin/plutil -extract CFBundleShortVersionString xml1 -o - V2er/Info.plist | grep '<string>' | sed 's/.*<string>\(.*\)<\/string>.*/\1/' | xargs)
CURRENT_BUILD=$(/usr/bin/plutil -extract CFBundleVersion xml1 -o - V2er/Info.plist | grep '<string>' | sed 's/.*<string>\(.*\)<\/string>.*/\1/' | xargs)

Copilot uses AI. Check for mistakes.

- name: Archive app
mkdir -p ~/.appstoreconnect/private_keys
echo "$APP_STORE_CONNECT_API_KEY_BASE64" | base64 --decode > ~/.appstoreconnect/private_keys/AuthKey_${APP_STORE_CONNECT_KEY_ID}.p8
Copy link

Copilot AI Sep 22, 2025

Choose a reason for hiding this comment

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

The API key file is created with default permissions which may be too permissive. Consider setting restrictive file permissions (e.g., 600) on the private key file to improve security.

Suggested change
echo "$APP_STORE_CONNECT_API_KEY_BASE64" | base64 --decode > ~/.appstoreconnect/private_keys/AuthKey_${APP_STORE_CONNECT_KEY_ID}.p8
echo "$APP_STORE_CONNECT_API_KEY_BASE64" | base64 --decode > ~/.appstoreconnect/private_keys/AuthKey_${APP_STORE_CONNECT_KEY_ID}.p8
chmod 600 ~/.appstoreconnect/private_keys/AuthKey_${APP_STORE_CONNECT_KEY_ID}.p8

Copilot uses AI. Check for mistakes.

- Extract duplicated API key and build config into helper methods in Fastfile
- Use plutil for robust Info.plist parsing instead of fragile regex
- Set restrictive permissions (600) on API key file for improved security
- Reduce code duplication across lanes
@github-actions github-actions bot added size/XL and removed size/XL labels Sep 22, 2025
@github-actions
Copy link

Code Coverage Report ❌

Current coverage: 0%

@graycreate graycreate merged commit 664e67e into main Sep 22, 2025
6 of 9 checks passed
@graycreate graycreate deleted the feature/ios-release-pipeline branch September 22, 2025 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant