Skip to content

Commit 9a8362f

Browse files
committed
Migrate from Fastlane to GitHub Actions
1 parent f619d31 commit 9a8362f

File tree

12 files changed

+214
-392
lines changed

12 files changed

+214
-392
lines changed

.github/workflows/continuous_integration.yml

Lines changed: 0 additions & 51 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
name: Test Suite
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- misc/RMET-4346/ci-cd # Temporary for testing
8+
pull_request:
9+
types: [opened, synchronize, reopened]
10+
11+
jobs:
12+
test:
13+
name: Run Tests
14+
runs-on: macos-latest
15+
16+
env:
17+
IOS_SIMULATOR_DEVICE: "iPhone 16"
18+
PROJECT_NAME: "OSInAppBrowserLib" # Name used for output files
19+
SCHEME_NAME: "OSInAppBrowserLib" # Xcode scheme to build/test
20+
XCODEPROJ_PATH: "OSInAppBrowserLib.xcodeproj" # Path to .xcodeproj file
21+
COVERAGE_TARGET_FILTER: "OSInAppBrowserLib" # Target name for coverage filtering
22+
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
27+
- name: Install Dependencies
28+
run: |
29+
# Install SwiftLint
30+
if ! command -v swiftlint &> /dev/null; then
31+
brew install swiftlint
32+
fi
33+
34+
# Install xcbeautify for better output formatting
35+
if ! command -v xcbeautify &> /dev/null; then
36+
brew install xcbeautify
37+
fi
38+
39+
# Install slather for coverage conversion
40+
if ! gem list slather -i &> /dev/null; then
41+
gem install slather
42+
fi
43+
44+
- name: Run Unit Tests
45+
run: |
46+
mkdir -p build/reports
47+
set -o pipefail
48+
xcodebuild test \
49+
-project ${{ env.XCODEPROJ_PATH }} \
50+
-scheme ${{ env.SCHEME_NAME }} \
51+
-destination "platform=iOS Simulator,name=${{ env.IOS_SIMULATOR_DEVICE }}" \
52+
-configuration Debug \
53+
-enableCodeCoverage YES \
54+
-resultBundlePath TestResults.xcresult \
55+
SKIP_SCRIPT_PHASES=YES \
56+
CODE_SIGNING_ALLOWED=NO | xcbeautify --report junit --report-path build/reports/junit.xml
57+
58+
- name: Generate Code Coverage Report for SonarQube
59+
run: |
60+
# Display coverage report for logs
61+
xcrun xccov view --report TestResults.xcresult
62+
63+
# Extract coverage percentage and save to environment variable
64+
coverage_percentage=$(xcrun xccov view --report TestResults.xcresult | grep "${{ env.COVERAGE_TARGET_FILTER }}" | head -1 | grep -o '[0-9]\+\.[0-9]\+%' | head -1)
65+
if [ -z "$coverage_percentage" ]; then
66+
# Fallback: try to get overall coverage
67+
coverage_percentage=$(xcrun xccov view --report TestResults.xcresult | grep -E "^\s*[0-9]+\.[0-9]+%" | head -1 | grep -o '[0-9]\+\.[0-9]\+%')
68+
fi
69+
70+
if [ -n "$coverage_percentage" ]; then
71+
echo "COVERAGE_PERCENTAGE=$coverage_percentage" >> $GITHUB_ENV
72+
echo "✅ Code coverage: $coverage_percentage"
73+
else
74+
echo "COVERAGE_PERCENTAGE=N/A" >> $GITHUB_ENV
75+
echo "⚠️ Could not extract coverage percentage"
76+
fi
77+
78+
# Create sonar-reports directory
79+
mkdir -p sonar-reports
80+
81+
# Use Slather to convert coverage to SonarQube format
82+
if slather coverage \
83+
--sonarqube-xml \
84+
--output-directory sonar-reports \
85+
--scheme ${{ env.SCHEME_NAME }} \
86+
${{ env.XCODEPROJ_PATH }}; then
87+
88+
# Verify coverage file was generated
89+
if [ -f "sonar-reports/sonarqube-generic-coverage.xml" ]; then
90+
echo "✅ Coverage converted successfully with Slather"
91+
echo "📄 Generated: sonar-reports/sonarqube-generic-coverage.xml"
92+
else
93+
echo "⚠️ Slather succeeded but output file not found in expected location"
94+
echo "📁 Files in sonar-reports:"
95+
ls -la sonar-reports/ || echo "Directory doesn't exist"
96+
fi
97+
else
98+
echo "❌ Slather failed to generate coverage report"
99+
echo "ℹ️ SonarCloud will run without coverage data"
100+
echo "🔍 This is usually due to no test coverage or build issues"
101+
fi
102+
103+
- name: Run SwiftLint for SonarQube
104+
run: |
105+
mkdir -p sonar-reports
106+
swiftlint --reporter checkstyle > sonar-reports/${{ env.PROJECT_NAME }}-swiftlint.xml || true
107+
108+
- name: Setup SonarQube Scanner
109+
uses: warchant/setup-sonar-scanner@v8
110+
111+
- name: Send to SonarCloud
112+
id: sonarcloud
113+
continue-on-error: true
114+
run: |
115+
if [ -f "sonar-project.properties" ]; then
116+
SONAR_PROJECT_KEY=$(grep "^sonar.projectKey=" sonar-project.properties | cut -d'=' -f2)
117+
echo "🔍 Attempting to send results to SonarCloud..."
118+
echo "📋 Project Key: $SONAR_PROJECT_KEY"
119+
echo "🌿 Branch: ${{ github.ref_name }}"
120+
121+
sonar-scanner \
122+
-Dsonar.projectKey="$SONAR_PROJECT_KEY" \
123+
-Dsonar.branch.name=${{ github.ref_name }} \
124+
-Dsonar.projectVersion=${{ github.sha }}
125+
else
126+
echo "⚠️ sonar-project.properties not found, skipping SonarCloud upload"
127+
exit 0
128+
fi
129+
env:
130+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
131+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
132+
133+
- name: Upload Test Results
134+
uses: actions/upload-artifact@v4
135+
if: always()
136+
with:
137+
name: test-results
138+
path: |
139+
TestResults.xcresult
140+
sonar-reports/
141+
build/reports/
142+
143+
# Slack notification - Uncomment when ready to use
144+
# - name: Slack Notification
145+
# if: always()
146+
# uses: 8398a7/action-slack@v3
147+
# with:
148+
# status: ${{ job.status }}
149+
# fields: repo,message,commit,author,action,eventName,ref,workflow
150+
# webhook_url: ${{ secrets.SLACK_WEBHOOK }}
151+
# env:
152+
# SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
153+
154+
- name: Comment Test Results
155+
if: github.event_name == 'pull_request' && always()
156+
uses: actions/github-script@v7
157+
with:
158+
script: |
159+
const { execSync } = require('child_process');
160+
161+
// Get Xcode version dynamically
162+
const xcodeVersion = execSync('xcodebuild -version | head -1', { encoding: 'utf8' }).trim();
163+
164+
// Get coverage percentage from environment
165+
const coveragePercentage = process.env.COVERAGE_PERCENTAGE || 'N/A';
166+
167+
// Check if SonarCloud step succeeded by checking job status
168+
const sonarStepSucceeded = '${{ steps.sonarcloud.outcome }}' === 'success';
169+
170+
// Dynamic message based on SonarCloud success/failure
171+
const sonarMessage = sonarStepSucceeded
172+
? '☁️ **SonarCloud**: Analysis completed - [View detailed report →](https://sonarcloud.io)'
173+
: '⚠️ **SonarCloud**: Upload failed - check workflow logs for details';
174+
175+
const nextStepsMessage = sonarStepSucceeded
176+
? '📋 **Next Steps**: Review the SonarCloud analysis for code quality insights and coverage details.'
177+
: '📋 **Next Steps**: Coverage data is available in test artifacts. SonarCloud integration needs attention.';
178+
179+
await github.rest.issues.createComment({
180+
issue_number: context.issue.number,
181+
owner: context.repo.owner,
182+
repo: context.repo.repo,
183+
body: `## 🧪 Test Results
184+
185+
✅ **Tests**: All tests passed successfully!
186+
📊 **Code Coverage**: ${coveragePercentage}
187+
${sonarMessage}
188+
189+
**Environment:**
190+
- ${xcodeVersion}
191+
- iOS Simulator (${{ env.IOS_SIMULATOR_DEVICE }})
192+
- macOS runner: ${{ runner.os }}
193+
194+
${nextStepsMessage}`
195+
});

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,9 @@ iOSInjectionProject/
9191

9292
# macOS
9393
.DS_Store
94+
95+
# GitHub Actions CI/CD artifacts
96+
# Generated by test workflow
97+
TestResults.xcresult/
98+
build/reports/
99+
sonar-reports/

Gemfile

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)