Skip to content

chore: bump version to 1.0.41 #48

chore: bump version to 1.0.41

chore: bump version to 1.0.41 #48

Workflow file for this run

name: Build iOS IPA (Sideload - AltStore/Sideloadly)
on:
push:
branches: [main]
paths:
- "src/**"
- "ios/**"
- "app.json"
- "package.json"
- ".github/workflows/build-ios.yml"
pull_request:
branches: [main]
workflow_dispatch:
inputs:
version:
description: "Version to use (e.g. 1.2.3). Leave empty to use app.json version."
required: false
default: ""
create_release:
description: "Create a GitHub Release with the IPA"
required: false
type: boolean
default: false
release_notes:
description: "Release notes for GitHub Release"
required: false
default: ""
permissions:
contents: write
jobs:
build:
runs-on: macos-15
outputs:
version: ${{ steps.version.outputs.version }}
ipa_name: ${{ steps.rename.outputs.ipa_name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate Release Notes from Commit History
id: release_notes
run: |
echo "Recent tags:"
git tag --sort=-v:refname | head -n 5
if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
CURRENT_REF="${{ github.ref_name }}"
PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${CURRENT_REF}^" 2>/dev/null || echo "")
else
CURRENT_REF="HEAD"
PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
fi
echo "Generating notes from '$PREVIOUS_TAG' to '$CURRENT_REF'"
if [[ -z "$PREVIOUS_TAG" ]]; then
echo "No previous tag found. Getting last 20 commits."
COMMITS=$(git log -n 20 --pretty=format:"- %s (%h)" "$CURRENT_REF")
else
COMMITS=$(git log "$PREVIOUS_TAG..$CURRENT_REF" --pretty=format:"- %s (%h)")
fi
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "LOG<<$EOF" >> $GITHUB_OUTPUT
echo "$COMMITS" >> $GITHUB_OUTPUT
echo "$EOF" >> $GITHUB_OUTPUT
- name: Determine version
id: version
run: |
if [[ -n "${{ github.event.inputs.version || '' }}" ]]; then
VERSION="${{ github.event.inputs.version }}"
echo "Using manual input version: $VERSION"
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
echo "Using tag-based version: $VERSION"
else
# Read version from app.json
VERSION=$(node -p "require('./app.json').expo.version")
echo "Using app.json version: $VERSION"
fi
VERSION=${VERSION#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: "npm"
- name: Install dependencies
run: |
npm install
# Install expo-cli globally to ensure prebuild works
npm install -g expo-cli @expo/cli
- name: Update app.json version
run: |
node -e "
const fs = require('fs');
const appJson = JSON.parse(fs.readFileSync('app.json', 'utf8'));
appJson.expo.version = '${{ steps.version.outputs.version }}';
appJson.expo.ios.buildNumber = '${{ github.run_number }}';
fs.writeFileSync('app.json', JSON.stringify(appJson, null, 2));
"
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.2"
bundler-cache: false
- name: Install CocoaPods
run: |
gem install cocoapods -v '~> 1.16'
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22.x"
- name: Verify iOS directory
run: |
echo "Checking iOS directory structure..."
ls -la ios/
echo "Checking for xcodeproj..."
ls -la ios/*.xcodeproj/ || echo "No xcodeproj found"
echo "Checking for xcworkspace..."
ls -la ios/*.xcworkspace/ || echo "No xcworkspace found"
- name: Install iOS dependencies
run: |
cd ios
pod install --repo-update
- name: Update iOS Info.plist versions
run: |
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${{ steps.version.outputs.version }}" ios/CBVVPN/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${{ github.run_number }}" ios/CBVVPN/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${{ steps.version.outputs.version }}" ios/CBVVPNProxyExtension/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${{ github.run_number }}" ios/CBVVPNProxyExtension/Info.plist
- name: Verify workspace creation
run: |
cd ios
if [ ! -d "CBVVPN.xcworkspace" ]; then
echo "Error: CBVVPN.xcworkspace not found!"
echo "Contents of ios directory:"
ls -la
exit 1
fi
echo "Workspace found successfully"
ls -la CBVVPN.xcworkspace/
- name: Build iOS Archive (Unsigned for Sideloading)
run: |
cd ios
set -o pipefail
set +e
xcodebuild \
-workspace CBVVPN.xcworkspace \
-scheme CBVVPN \
-configuration Release \
-archivePath "$PWD/build/CBProProxy.xcarchive" \
-sdk iphoneos \
-destination 'generic/platform=iOS' \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO \
DEVELOPMENT_TEAM="" \
PROVISIONING_PROFILE_SPECIFIER="" \
clean archive 2>&1 | tee "$PWD/build/xcodebuild.log"
build_status=${PIPESTATUS[0]}
set -e
echo "---- Xcode build errors (if any) ----"
rg -n "error:|fatal error:|clang: error:" "$PWD/build/xcodebuild.log" || true
echo "---- Xcode build tail (last 200 lines) ----"
tail -n 200 "$PWD/build/xcodebuild.log" || true
exit $build_status
- name: Install ldid for TrollStore signing
run: |
if ! command -v ldid &> /dev/null; then
echo "Installing ldid..."
brew install ldid
fi
ldid --version || echo "ldid installed"
- name: Create IPA with ldid signing for TrollStore
run: |
cd ios
echo "Creating IPA with ldid signing for TrollStore..."
mkdir -p "$PWD/build/output/Payload"
# Investigate archive structure
echo "Examining archive structure..."
ls -la "$PWD/build/CBProProxy.xcarchive/Products/Applications/" || true
# Find .app bundle (app name may vary based on archive name)
APP_PATH=$(find "$PWD/build/CBProProxy.xcarchive/Products/Applications" -name "*.app" -type d -maxdepth 1 | head -n 1)
if [ -z "$APP_PATH" ]; then
# Fallback: try Products/ directly
APP_PATH=$(find "$PWD/build/CBProProxy.xcarchive/Products" -name "*.app" -type d -maxdepth 1 | head -n 1)
fi
if [ -z "$APP_PATH" ]; then
# Last resort: search entire archive
APP_PATH=$(find "$PWD/build/CBProProxy.xcarchive" -name "*.app" -type d | grep -v "Plugins" | head -n 1)
fi
if [ -n "$APP_PATH" ]; then
echo "✅ Found app at: $APP_PATH"
else
echo "❌ Error: No .app bundle found in archive"
echo "Archive structure:"
find "$PWD/build/CBProProxy.xcarchive" -type d -maxdepth 3
exit 1
fi
# Copy the .app to Payload
cp -r "$APP_PATH" "$PWD/build/output/Payload/"
# Get app name from path
APP_NAME=$(basename "$APP_PATH")
BINARY_NAME="${APP_NAME%.app}"
echo "📱 App bundle: $APP_NAME"
echo "📱 Binary name: $BINARY_NAME"
# Sign with ldid for TrollStore VPN support
echo "🔐 Signing with ldid for TrollStore..."
MAIN_ENTITLEMENTS="$GITHUB_WORKSPACE/ios/CBVVPN/CBVVPN.entitlements"
EXT_ENTITLEMENTS="$GITHUB_WORKSPACE/ios/CBVVPNProxyExtension/CBVVPNProxyExtension.entitlements"
# Sign main app
MAIN_BINARY="$PWD/build/output/Payload/$APP_NAME/$BINARY_NAME"
if [ -f "$MAIN_BINARY" ] && [ -f "$MAIN_ENTITLEMENTS" ]; then
echo "Signing main app: $MAIN_BINARY"
ldid "-S$MAIN_ENTITLEMENTS" "$MAIN_BINARY"
echo "✅ Main app signed with entitlements"
# Verify
ldid -e "$MAIN_BINARY" > /tmp/main-ent-check.xml
if [ -s /tmp/main-ent-check.xml ]; then
echo "✅ Main app entitlements verified:"
head -15 /tmp/main-ent-check.xml
fi
else
echo "⚠️ Main binary or entitlements not found"
fi
# Sign extensions
if [ -d "$PWD/build/output/Payload/$APP_NAME/PlugIns" ]; then
for EXTENSION in "$PWD/build/output/Payload/$APP_NAME/PlugIns"/*.appex; do
if [ -d "$EXTENSION" ]; then
EXT_NAME=$(basename "$EXTENSION" .appex)
EXT_BINARY="$EXTENSION/$EXT_NAME"
if [ -f "$EXT_BINARY" ] && [ -f "$EXT_ENTITLEMENTS" ]; then
echo "Signing extension: $EXT_NAME"
ldid "-S$EXT_ENTITLEMENTS" "$EXT_BINARY"
echo "✅ Extension signed: $EXT_NAME"
fi
fi
done
fi
# Remove Apple code signatures (keep ldid signatures)
echo "Removing Apple code signatures..."
find "$PWD/build/output/Payload/$APP_NAME" -name "_CodeSignature" -type d -prune -exec rm -rf {} + 2>/dev/null || true
find "$PWD/build/output/Payload/$APP_NAME" -name "embedded.mobileprovision" -type f -exec rm -f {} + 2>/dev/null || true
find "$PWD/build/output/Payload/$APP_NAME" -name "embedded.entitlements" -type f -exec rm -f {} + 2>/dev/null || true
echo "✅ Apple signatures removed (ldid signatures preserved)"
# Create IPA with proper structure
cd "$PWD/build/output"
zip -qr CBProProxy.ipa Payload
rm -rf Payload
echo "✅ IPA created with ldid signing for TrollStore VPN support"
echo "📱 Compatible with: TrollStore (VPN works!), AltStore, Sideloadly"
ls -lh CBProProxy.ipa
- name: Rename IPA with version
id: rename
run: |
cd ios/build/output
IPA_NAME="CBProProxy-${{ steps.version.outputs.version }}-b${{ github.run_number }}-unsigned.ipa"
mv CBProProxy.ipa "$IPA_NAME"
echo "ipa_name=$IPA_NAME" >> $GITHUB_OUTPUT
echo "📦 IPA: $IPA_NAME"
- name: Upload IPA artifact
uses: actions/upload-artifact@v4
with:
name: ios-unsigned-ipa
path: ios/build/output/*.ipa
retention-days: 30
# Optional: Create GitHub Release
release:
needs: build
runs-on: ubuntu-latest
if: github.event.inputs.create_release == 'true' || startsWith(github.ref, 'refs/tags/')
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download IPA artifact
uses: actions/download-artifact@v4
with:
name: ios-unsigned-ipa
path: ./release
- name: Generate Release Notes
id: notes
run: |
if [[ -n "${{ github.event.inputs.release_notes }}" ]]; then
NOTES="${{ github.event.inputs.release_notes }}"
else
# Get commits since last tag
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
if [[ -n "$PREVIOUS_TAG" ]]; then
COMMITS=$(git log "$PREVIOUS_TAG..HEAD" --pretty=format:"- %s" | head -20)
else
COMMITS=$(git log -n 10 --pretty=format:"- %s")
fi
NOTES="$COMMITS"
fi
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "notes<<$EOF" >> $GITHUB_OUTPUT
echo "$NOTES" >> $GITHUB_OUTPUT
echo "$EOF" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.build.outputs.version }}
name: CB Pro Proxy v${{ needs.build.outputs.version }} (iOS)
body: |
## 📱 CB Pro Proxy v${{ needs.build.outputs.version }}
### Installation Guide
**Using AltStore:**
1. Download the IPA file below
2. Open AltStore on your device
3. Go to "My Apps" tab → tap "+" button
4. Select the downloaded IPA file
5. Wait for installation to complete
**Using Sideloadly:**
1. Download the IPA file below
2. Connect your iPhone to computer
3. Open Sideloadly and drag the IPA into it
4. Enter your Apple ID and install
**Using TrollStore:**
1. Download the IPA file below
2. Open in TrollStore and tap "Install"
---
### Changes
${{ steps.notes.outputs.notes }}
---
Build: #${{ github.run_number }}
files: ./release/*.ipa
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}