Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
8 changes: 8 additions & 0 deletions .github/file-filters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -541,3 +541,11 @@ run_size_analysis_for_prs: &run_size_analysis_for_prs
# Build configuration
- "Makefile"
- "Brewfile*"

run_swift_log_for_prs: &run_swift_log_for_prs
- "integrations/logs/sentry-cocoa-swiftlog/**"

# GH Actions
- ".github/workflows/integrations-common.yml"
- ".github/workflows/integrations-swift-log.yml"
- ".github/file-filters.yml"
105 changes: 105 additions & 0 deletions .github/workflows/integrations-common.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Test Integrations

on:
workflow_call:
inputs:
name:
description: "The name of the integration to test"
required: true
type: string
working_directory:
description: "The working directory to run the tests in"
required: true
type: string
xcode_version:
description: "The Xcode version to use for the job"
required: true
type: string
test-destination-os:
description: "The test destination OS to use for the job"
required: true
type: string
device:
description: "The device to test on"
required: false
default: ""
type: string
platform:
description: "The platform to test on"
required: true
type: string
package-name:
description: "The package name to test (same as Package.swift name)"
required: true
type: string
macos_version:
description: "macOS version"
required: true
default: macos-26
type: string

jobs:
Copy link
Member

@philipphofmann philipphofmann Dec 4, 2025

Choose a reason for hiding this comment

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

m: There are many similarities to unit-test-common.yml. Can't we reuse unit-test-common.yml instead of having plenty of code duplicated?

xcode-build-integrations-tests:
name: "XCode for Integration: ${{ inputs.name }}"
runs-on: ${{ inputs.macos_version }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- name: Select Xcode version
env:
XCODE_VERSION: ${{ inputs.xcode_version }}
run: ./scripts/ci-select-xcode.sh "$XCODE_VERSION"
- name: Ensure required runtime is loaded
if: ${{ inputs.platform == 'iOS' }}
timeout-minutes: 5 # 5 minutes timeout
env:
OS_VERSION: ${{ inputs.test-destination-os }}
run: ./scripts/ci-ensure-runtime-loaded.sh --os-version "$OS_VERSION"
- name: Boot simulator
if: ${{ inputs.platform == 'iOS' }}
env:
XCODE_VERSION: ${{ inputs.xcode_version }}
DEVICE_NAME: ${{ inputs.device }}
OS_VERSION: ${{ inputs.test-destination-os }}
run: ./scripts/ci-boot-simulator.sh --xcode "$XCODE_VERSION" --device "$DEVICE_NAME" --os-version "$OS_VERSION"

- name: Prepare Package.swift
shell: bash
run: |
./scripts/use-local-sentry-dependency.sh \
--package-file ${{ inputs.working_directory }}/Package.swift \
--path-to-sentry-cocoa "../../../"

# We split building and running tests in two steps so we know how long running the tests takes.
- name: Build Tests
working-directory: ${{ inputs.working_directory }}
env:
PLATFORM: ${{ inputs.platform }}
OS_VERSION: ${{ inputs.test-destination-os }}
REF_NAME: ${{ github.ref_name }}
DEVICE_NAME: ${{ inputs.device }}
SCHEME: ${{ inputs.package-name }}
run: |
../../../scripts/integration-xcodebuild.sh \
--platform "$PLATFORM" \
--os "$OS_VERSION" \
--command build-for-testing \
--device "$DEVICE_NAME" \
--scheme "$SCHEME"

- name: Run Tests
working-directory: ${{ inputs.working_directory }}
env:
PLATFORM: ${{ inputs.platform }}
OS_VERSION: ${{ inputs.test-destination-os }}
REF_NAME: ${{ github.ref_name }}
DEVICE_NAME: ${{ inputs.device }}
SCHEME: ${{ inputs.package-name }}
run: |
../../../scripts/integration-xcodebuild.sh \
--platform "$PLATFORM" \
--os "$OS_VERSION" \
--command test-without-building \
--device "$DEVICE_NAME" \
--scheme "$SCHEME" \
--result-bundle integration-results.xcresult
131 changes: 131 additions & 0 deletions .github/workflows/integrations-swift-log.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: Test Integrations
on:
push:
branches:
- main
- release/**

pull_request:
types: [opened, synchronize, reopened, labeled]

# Concurrency configuration:
# - We use workflow-specific concurrency groups to allow independent test runs across different workflows
# while preventing multiple runs of the same test suite on the same branch/commit.
# - For pull requests, we cancel in-progress runs when new commits are pushed to save CI resources
# and provide faster feedback on the latest changes.
# - For main branch pushes and scheduled runs, we never cancel in-progress runs to ensure the complete
# test suite always finishes, maintaining the integrity of our main branch quality gates.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
ready-to-merge-gate:
name: Ready-to-merge gate
uses: ./.github/workflows/ready-to-merge-workflow.yml

# This job detects if the PR contains changes that require running unit tests.
# If yes, the job will output a flag that will be used by the next job to run the unit tests.
# If no, the job will output a flag that will be used by the next job to skip running the unit tests.
# At the end of this workflow, we run a check that validates that either all unit tests passed or were
# called unit-tests-required-check.
files-changed:
name: Detect File Changes
runs-on: ubuntu-latest
needs: ready-to-merge-gate
# Map a step output to a job output
outputs:
run_swift_log_for_prs: ${{ steps.changes.outputs.run_swift_log_for_prs }}
steps:
- uses: actions/checkout@v6
- name: Get changed files
id: changes
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
token: ${{ github.token }}
filters: .github/file-filters.yml

spm-integrations-tests:
name: "SPM Tests for Swift Log"
needs: files-changed
if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_swift_log_for_prs == 'true'
runs-on: macos-15
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- name: Select Xcode version
env:
XCODE_VERSION: 16.4
run: ./scripts/ci-select-xcode.sh "$XCODE_VERSION"
- name: Prepare Package.swift
shell: bash
run: |
./scripts/use-local-sentry-dependency.sh \
--package-file integrations/logs/sentry-cocoa-swiftlog/Package.swift \
--path-to-sentry-cocoa "../../../"
- name: Run SPM Tests
working-directory: integrations/logs/sentry-cocoa-swiftlog
run: swift test

test-integration:
name: Unit Tests for Swift Log
if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_swift_log_for_prs == 'true'
needs: files-changed
uses: ./.github/workflows/integrations-common.yml
with:
name: SwiftLog
package-name: SentrySwiftLog
working_directory: integrations/logs/sentry-cocoa-swiftlog
xcode_version: ${{ matrix.xcode }}
test-destination-os: ${{ matrix.test-destination-os }}
device: ${{ matrix.device }}
platform: ${{ matrix.platform }}
macos_version: ${{ matrix.macos_version }}
strategy:
fail-fast: false
matrix:
include:
- name: iOS 18
xcode: "16.4"
macos_version: macos-15
test-destination-os: "18.4"
platform: "iOS"
device: "iPhone 16 Pro"

- name: iOS 26
macos_version: macos-26
xcode: "26.1.1"
test-destination-os: "26.1"
platform: "iOS"
device: "iPhone 17 Pro"

- name: macOS 15
macos_version: macos-15
xcode: "16.4"
test-destination-os: "latest"
platform: "macOS"

- name: macOS 26
macos_version: macos-26
xcode: "26.1.1"
test-destination-os: "26.1"
platform: "macOS"

unit-tests-required-check:
needs:
[
ready-to-merge-gate,
files-changed,
test-integration,
]
name: Swift Log Tests
# This is necessary since a failed/skipped dependent job would cause this job to be skipped
if: always()
runs-on: ubuntu-latest
steps:
# If any jobs we depend on fails gets cancelled or times out, this job will fail.
# Skipped jobs are not considered failures.
- name: Check for failures
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: |
echo "One of the unit test jobs has failed." && exit 1
128 changes: 128 additions & 0 deletions scripts/integration-xcodebuild.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/bin/bash
set -euxo pipefail

# Disable SC1091 because it won't work with pre-commit
Copy link
Member

@philipphofmann philipphofmann Dec 4, 2025

Choose a reason for hiding this comment

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

m: This script is quite similar to sentry-xcodebuild.sh. I would really appreciate if we don't have all of that logic duplicated.

# shellcheck source=./scripts/ci-utils.sh disable=SC1091
source "$(cd "$(dirname "$0")" && pwd)/ci-utils.sh"

# This is a helper script for GitHub Actions Matrix.
# If we would specify the destinations in the GitHub Actions
# Matrix, the name of the job would include the destination, which would
# be, for example, platform=tvOS Simulator,OS=latest,name=Apple TV 4K.
# To fix this, we specify a readable platform in the matrix and then call
# this script to map the platform to the destination.

# Parse named arguments
PLATFORM=""
OS="latest"
COMMAND="test"
DEVICE="iPhone 14 Pro"
TEST_SCHEME="Sentry"
RESULT_BUNDLE_PATH="results.xcresult"

usage() {
echo "Usage: $0"
echo " -p|--platform <platform> Platform (macOS/Catalyst/iOS/tvOS)"
echo " -o|--os <os> OS version (default: latest)"
echo " -c|--command <command> Command (build/build-for-testing/test-without-building/test)"
echo " -d|--device <device> Device name (default: iPhone 14 Pro)"
echo " -s|--scheme <scheme> Test scheme (default: Sentry)"
echo " -R|--result-bundle <path> Result bundle path (default: results.xcresult)"
exit 1
}

# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-p|--platform)
PLATFORM="$2"
shift 2
;;
-o|--os)
OS="$2"
shift 2
;;
-c|--command)
COMMAND="$2"
shift 2
;;
-d|--device)
DEVICE="$2"
shift 2
;;
-s|--scheme)
TEST_SCHEME="$2"
shift 2
;;
-R|--result-bundle)
RESULT_BUNDLE_PATH="$2"
shift 2
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done

case $PLATFORM in

"macOS")
DESTINATION="platform=macOS"
;;

"Catalyst")
DESTINATION="platform=macOS,variant=Mac Catalyst"
;;

"iOS")
DESTINATION="platform=iOS Simulator,OS=$OS,name=$DEVICE"
;;

"tvOS")
DESTINATION="platform=tvOS Simulator,OS=$OS,name=Apple TV"
;;

*)
echo "Xcode Test: Can't find destination for platform '$PLATFORM'"
exit 1
;;
esac

case $COMMAND in
"build-for-testing")
RUN_BUILD_FOR_TESTING=true
RUN_TEST_WITHOUT_BUILDING=false
;;
"test-without-building")
RUN_BUILD_FOR_TESTING=false
RUN_TEST_WITHOUT_BUILDING=true
;;
esac

if [ "$RUN_BUILD_FOR_TESTING" == true ]; then
# When no test plan is provided, we skip the -testPlan argument so xcodebuild uses the default test plan
log_notice "Running xcodebuild build-for-testing"

set -o pipefail && NSUnbufferedIO=YES xcodebuild \
-scheme "$TEST_SCHEME" \
-destination "$DESTINATION" \
build-for-testing 2>&1 |
tee raw-build-for-testing-output.log |
xcbeautify --preserve-unbeautified
fi

if [ "$RUN_TEST_WITHOUT_BUILDING" == true ]; then
# When no test plan is provided, we skip the -testPlan argument so xcodebuild uses the default test plan
log_notice "Running xcodebuild test-without-building"

set -o pipefail && NSUnbufferedIO=YES xcodebuild \
-scheme "$TEST_SCHEME" \
-destination "$DESTINATION" \
-resultBundlePath "$RESULT_BUNDLE_PATH" \
test-without-building 2>&1 |
tee raw-test-output.log |
xcbeautify --report junit
fi

log_notice "Finished xcodebuild"
Loading
Loading