Skip to content

Sensor CI

Sensor CI #4

Workflow file for this run

name: Sensor CI
on:
push:
branches: [main, master]
pull_request:
schedule:
# Every Monday at 02:00 UTC
- cron: '0 2 * * 1'
jobs:
test:
runs-on: macos-15
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Show Xcode and simulator info
run: |
xcodebuild -version
swift --version
xcrun simctl list runtimes
xcrun simctl list devices available
- name: Resolve package dependencies
run: swift package resolve
- name: Detect scheme and simulator
run: |
SCHEME=$(swift package dump-package | python3 -c "import json,sys; print(json.load(sys.stdin)['name'])")
echo "SCHEME=$SCHEME" >> "$GITHUB_ENV"
# Find the latest available iPhone simulator name (name-based, more robust than UDID)
SIM_NAME=$(xcrun simctl list devices available --json | python3 -c "
import json, sys
devs = json.load(sys.stdin)['devices']
iphones = [
(rt, d['name'])
for rt, dl in devs.items()
for d in dl
if 'iOS' in rt and 'iPhone' in d['name'] and d.get('isAvailable', True)
]
iphones.sort(reverse=True)
print(iphones[0][1] if iphones else 'iPhone 16')
")
echo "SIM_NAME=$SIM_NAME" >> "$GITHUB_ENV"
echo "Detected scheme: $SCHEME"
echo "Detected simulator: $SIM_NAME"
- name: Build
id: build
run: |
xcodebuild build \
-scheme "$SCHEME" \
-destination "platform=iOS Simulator,name=$SIM_NAME" \
-sdk iphonesimulator \
2>&1 | tee build_output.txt; exit "${PIPESTATUS[0]}"
continue-on-error: true
- name: Test
id: test
if: steps.build.outcome == 'success'
run: |
xcodebuild test \
-scheme "$SCHEME" \
-destination "platform=iOS Simulator,name=$SIM_NAME" \
-sdk iphonesimulator \
-configuration Debug \
-enableCodeCoverage YES \
2>&1 | tee test_output.txt; exit "${PIPESTATUS[0]}"
continue-on-error: true
- name: Create or update issue on failure
if: steps.build.outcome == 'failure' || steps.test.outcome == 'failure'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ "${{ steps.build.outcome }}" = "failure" ]; then
FAILED="build"
LOG_FILE="build_output.txt"
else
FAILED="test"
LOG_FILE="test_output.txt"
fi
ERRORS=$(grep -E 'error:|FAILED|\*\* BUILD FAILED' "$LOG_FILE" 2>/dev/null | head -60 || true)
[ -z "$ERRORS" ] && ERRORS="(no error lines captured — see full logs above)"
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
TODAY=$(date -u +%Y-%m-%d)
BODY="## :x: Automated CI ${FAILED} failure
| | |
|---|---|
| **Workflow run** | [View logs](${RUN_URL}) |
| **Trigger** | \`${{ github.event_name }}\` |
| **Ref** | \`${{ github.ref }}\` |
| **Commit** | \`${SHORT_SHA}\` |
## Error summary
\`\`\`
${ERRORS}
\`\`\`"
# Ensure ci-failure label exists (ignore error if already present)
gh label create ci-failure --color d73a4a --description "Automated CI test failure" 2>/dev/null || true
# Find existing open ci-failure issue number
ISSUE_NUMBER=$(gh issue list --state open --label ci-failure --json number --jq '.[0].number // empty')
if [ -n "$ISSUE_NUMBER" ]; then
gh issue comment "$ISSUE_NUMBER" --body "### :warning: New failure (${TODAY})
${BODY}"
else
gh issue create \
--title "[CI] ${FAILED} failure detected" \
--body "$BODY" \
--label ci-failure
fi
- name: Close ci-failure issue on success
if: steps.build.outcome == 'success' && steps.test.outcome == 'success'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
ISSUE_NUMBERS=$(gh issue list --state open --label ci-failure --json number --jq '.[].number')
for ISSUE_NUMBER in $ISSUE_NUMBERS; do
gh issue comment "$ISSUE_NUMBER" \
--body ":white_check_mark: All tests are passing again. See [run ${{ github.run_id }}](${RUN_URL})."
gh issue close "$ISSUE_NUMBER"
done
- name: Fail job if build or tests failed
if: steps.build.outcome == 'failure' || steps.test.outcome == 'failure'
run: |
echo "Build outcome: ${{ steps.build.outcome }}"
echo "Test outcome: ${{ steps.test.outcome }}"
exit 1