Skip to content
Merged
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
63 changes: 63 additions & 0 deletions .github/workflows/sonarqube.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: SonarQube
concurrency: sonarqube-check

on:
workflow_run:
workflows: [Unit Tests]
types: [completed]

jobs:
sonarqube-step:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: tillhub-org-runner

steps:
- name: 'Download artifact'
uses: actions/github-script@v7
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
let matchArtifact = allArtifacts.data.artifacts.find(artifact => artifact.name === "test-results");
if (!matchArtifact) {
throw new Error("Artifact 'test-results' not found");
}
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
const fs = require('fs');
const path = require('path');
const temp = '${{ runner.temp }}/artifacts';
if (!fs.existsSync(temp)){
fs.mkdirSync(temp);
}
fs.writeFileSync(path.join(temp, 'test-results.zip'), Buffer.from(download.data));

- name: 'Unzip artifact'
run: |
unzip '${{ runner.temp }}/artifacts/test-results.zip' -d "${{ runner.temp }}/artifacts"

- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=${{ github.event.repository.name }}
-Dsonar.sources=Sources
-Dsonar.tests=Tests
-Dsonar.inclusions=**/*.swift
-Dsonar.exclusions=**/*.h,**/*.m,**/*.mm,**/*.xib,**/*.storyboard,**/*.plist,**/*.strings,**/*.xcodeproj/**/*,**/*.xcworkspace/**/*,**/*.xcassets/**/*,**/*.xcscmblueprint,**/*.xccheckout,**/*.xcuserstate,**/*.xcworkspace,**/*.xcodeproj/project.pbxproj,**/*.xcodeproj/xcshareddata/**/*,**/*.xcodeproj/project.xcworkspace/**/*,**/*.xcodeproj/xcuserdata/**/*,**/*.xcuserdata/**/*,**/*Tests/**,**/*UITests/**,**/Pods/**,**/fastlane/**,**/Example/**
-Dsonar.coverageReportPaths=${{ runner.temp }}/artifacts/sonarqube-generic-coverage.xml
46 changes: 46 additions & 0 deletions .github/workflows/unit_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Unit Tests

on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:

jobs:
test:
name: Run Xcode Tests
runs-on: macos-15

steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Build and Test
run: |
mkdir -p build/reports
DEST_ID=$(xcrun simctl list devices available | grep "iPhone" | head -1 | grep -oE "[0-9A-F-]{36}")
echo "Using simulator $DEST_ID"
xcodebuild test \
-workspace Telegraph.xcworkspace \
-scheme "Telegraph iOS" \
-destination "platform=iOS Simulator,id=$DEST_ID" \
-configuration Debug \
-enableCodeCoverage YES \
-resultBundlePath build/TestResults.xcresult \
ENABLE_TESTABILITY=YES \
| xcpretty -c --report junit --output build/reports/junit.xml

- name: Generate Code Coverage Report
run: |
mkdir -p build/reports
bash xccov-to-sonarqube-generic.sh build/TestResults.xcresult > build/reports/sonarqube-generic-coverage.xml

- name: Upload Test Results
uses: actions/upload-artifact@v4
with:
name: test-results
path: build/reports/
retention-days: 7
46 changes: 46 additions & 0 deletions xccov-to-sonarqube-generic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail

function convert_xccov_to_xml {
sed -n \
-e '/:$/s/&/\&amp;/g;s/^\(.*\):$/ <file path="\1">/p' \
-e 's/^ *\([0-9][0-9]*\): 0.*$/ <lineToCover lineNumber="\1" covered="false"\/>/p' \
-e 's/^ *\([0-9][0-9]*\): [1-9].*$/ <lineToCover lineNumber="\1" covered="true"\/>/p' \
-e 's/^$/ <\/file>/p'
}

function xccov_to_generic {
local xcresult="$1"

echo '<coverage version="1">'
# Strip $pwd (to make the file paths relative)
xcrun xccov view --archive "$xcresult" | while read -r line; do echo "${line#$PWD/}"; done | convert_xccov_to_xml
echo '</coverage>'
}

function check_xcode_version() {
local major=${1:-0} minor=${2:-0}
return $(( (major >= 14) || (major == 13 && minor >= 3) ))
}

if ! xcode_version="$(xcodebuild -version | sed -n '1s/^Xcode \([0-9.]*\)$/\1/p')"; then
echo 'Failed to get Xcode version' 1>&2
exit 1
elif check_xcode_version ${xcode_version//./ }; then
echo "Xcode version '$xcode_version' not supported, version 13.3 or above is required" 1>&2;
exit 1
fi

xcresult="$1"
if [[ $# -ne 1 ]]; then
echo "Invalid number of arguments. Expecting 1 path matching '*.xcresult'"
exit 1
elif [[ ! -d $xcresult ]]; then
echo "Path not found: $xcresult" 1>&2;
exit 1
elif [[ $xcresult != *".xcresult"* ]]; then
echo "Expecting input to match '*.xcresult', got: $xcresult" 1>&2;
exit 1
fi

xccov_to_generic "$xcresult"
Loading