SwiftXcodeXCTestTestFlight

iOS + TestFlight + XCTest

A Swift workflow shaped for XCTest and TestFlight delivery.

ADesigned for a clean Pipegrade scan
.github/workflows/ci.yml
# Created by https://pipegrade.io# Template: iOS + TestFlight + XCTest# Edit at https://pipegrade.io/github-actions/ios-testflight-xctest name: iOS CIon:  # Limit expensive macOS minutes to iOS source and package changes.  push:    branches:      - main    paths:      - ios/**      - Package.swift      - Package.resolved  pull_request:    paths:      - ios/**      - Package.swift      - Package.resolved permissions:  # XCTest and archive steps only need read access to repository contents.  contents: read concurrency:  # Cancel stale simulator/archive work when a newer commit supersedes it.  group: ios-${{ github.workflow }}-${{ github.ref }}  cancel-in-progress: true jobs:  test:    # macOS minutes are expensive; keep simulator/archive jobs bounded.    timeout-minutes: 45    runs-on: macos-latest    steps:      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd      # SwiftPM/Xcode caches are runner-specific; add actions/cache only after measuring hit rates.      - run: xcodebuild test -scheme App -destination 'platform=iOS Simulator,name=iPhone 16'      - run: xcodebuild archive -scheme App -archivePath build/App.xcarchive      # No artifacts are uploaded by default. If you preserve archives, set retention-days.      - name: Upload to TestFlight        if: github.ref == 'refs/heads/main'        env:          APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}          APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}          APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}        run: xcrun altool --upload-app --type ios --file build/App.ipa      - name: Notify on failure        if: failure()        run: echo "Send a failure notification to your team channel."

Why it grades A

Why this template grades A

Cost

Cost

Scoped triggers and cancellation matter more on expensive macOS runners.

Security

Security

Actions are pinned to full commit SHAs and workflow permissions are read-only by default.

Performance

Performance

Build and test work is kept in one deterministic job unless the stack has a real dependency boundary.

Standards

Standards

Every job has timeout-minutes, a concurrency group, and clear deploy gating on main.

Already have a workflow?

Scan it before copying a starter.

Scan your workflow

Customize

Adapt before merging

  • Confirm the path filters match the directories that should trigger CI.
  • Replace deploy commands and secret names with your actual deployment target.
  • Adjust runner labels, language versions, and timeout-minutes for your workload.
  • Scan the adapted workflow before merging it.

Rules addressed

Checks covered by this template

unpinned-actionmissing-top-level-permissionsmissing-path-filtersmissing-pr-cancel-concurrencymissing-timeout-minutesmissing-concurrency-groupmissing-failure-notification

Related templates

Updates

Get template updates

These templates use reviewed action SHAs. Get notified when the template library expands.