For the complete documentation index, see llms.txt. This page is also available as Markdown.

CODEOWNERS-Based Team Assignment

Assign crashes to the right team automatically from your repository CODEOWNERS file. How name matching and specificity-based paths work.

How It Works

When you upload a CODEOWNERS file, Luciq maps your crash reports to the right team automatically based on where the crash happened in your code.

Here's what happens under the hood:

  1. Team Mapping: Team names from your CODEOWNERS file are matched to your existing teams on the Luciq dashboard. This matching is flexible since it's case-insensitive and treats hyphens, underscores, and spaces as the same thing. So @org/my-team will match a team called "My Team" without any extra configuration.

  2. Frame Selection: When a crash comes in, Luciq looks at the crashed thread and picks the top application frame (the first frame that belongs to your code, not system libraries). The file path from that frame is what gets used for team matching.

  3. Path Matching: That file path is compared against the paths in your CODEOWNERS rules. The matching works on path segments (split by /), so a rule for LibraryA will match any crash in LibraryA/SomeFile.swift, LibraryA/SubDir/AnotherFile.swift, etc.

  4. Specificity-Based Resolution: When multiple rules match the same crash, Luciq picks the most specific one. Specificity is determined by the number of path segments in the matching rule — more segments means a more specific match. See Specificity-Based Matching below for details.

CODEOWNERS File Example

A CODEOWNERS file lives in your repository and defines which team owns which part of the codebase. Here's what a typical one looks like:

# Each line maps a path pattern to a team
# The format is: <path>    <team>

# Networking layer owned by the platform team
/Sources/Networking/                    @org/platform-team

# Authentication module owned by the identity team
/Sources/Auth/                          @org/identity-team

# Checkout and payments owned by the commerce team
/Sources/Checkout/                      @org/commerce-team
/Sources/Payments/                      @org/commerce-team

# Everything under the analytics module
/Sources/Analytics/                     @org/data-team

With this file uploaded, if a crash happens in Sources/Checkout/CartViewController.swift, Luciq will automatically assign it to Commerce Team. A crash in Sources/Auth/LoginManager.swift goes to Identity Team, and so on.

A team can own multiple paths (like the commerce team above owning both Checkout and Payments), and paths can be as broad as a top-level directory or as specific as a single file.

Specificity-Based Matching

When multiple ownership rules match the same crash, Luciq uses specificity to determine which team gets assigned. The rule with the most path segments wins.

How Specificity Is Calculated

Specificity is based on the number of segments in the matching path token, where segments are separated by / (for file paths) or . (for Android packages).

Rule token
Segments
Specificity

Sources

1

1

Sources/Networking

2

2

Sources/Networking/WebSocket

3

3

Example

Consider the following ownership definitions:

Team
Rule

Platform Team

Path matches Sources/Networking

Real-Time Team

Path matches Sources/Networking/WebSocket

If a crash occurs in Sources/Networking/WebSocket/ConnectionManager.swift:

  • Platform Team matches with specificity 2 (Sources/Networking has 2 segments)

  • Real-Time Team matches with specificity 3 (Sources/Networking/WebSocket has 3 segments)

Result: The crash is assigned to Real-Time Team because it has the more specific rule.

Tie-Breaking

When two rules have the same specificity (same number of path segments), the rule that was most recently updated wins. This ensures that if you update a definition, it takes priority over older definitions with the same level of specificity.

How It Works Across Platforms

Specificity-based matching applies across all platforms:

Platform
Field
Separator
Example

iOS

Path

/

Controllers/Auth → 2 segments

Android

Package

.

com.example.app.auth → 4 segments

Flutter

Flutter Path

/

lib/features/auth → 3 segments

React Native

React Native Path

/

src/screens/Auth → 3 segments

For filename-based rules (as opposed to path/package), the specificity is always 1 regardless of the filename. This means path-based rules will generally take precedence over filename-based rules when both match.

How to Test

To verify that team assignment is working correctly for your CODEOWNERS setup, keep in mind that Luciq needs server-side symbolication to extract file paths from crash frames, and that only happens when dSYMs are available.

Here's what you need to do:

  1. Build in Release mode: Debug builds don't generate dSYM files. You need to archive or build your app in Release configuration for Xcode to produce them.

  2. Upload your dSYMs: Once you have the dSYM files, upload them to Luciq (either manually through the dashboard or via your CI/CD pipeline). Without dSYMs, Luciq can't resolve the file paths needed for team matching.

  3. Trigger a crash: Run the Release build, trigger a crash, and relaunch the app so the crash report gets sent.

Once the crash appears on your dashboard, you should see it assigned to the expected team based on your CODEOWNERS rules.

Last updated