From 9fdb99b6e302ec60e3f8f1a4e2f91a1f9e48558f Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 15:56:20 -0500 Subject: [PATCH 01/16] docs(swift): make Swift repro README beginner-friendly with detailed setup - Add step-by-step installation instructions for Xcode and Devbox - Include terminal usage guide for users unfamiliar with command line - Clarify Amplitude destination setup (no API key needed) - Document toggle limitation (can't remove plugins once added) - Add comprehensive plugin system documentation - Include guide for adding custom and official destination plugins - Expand troubleshooting section with common beginner issues - Make language more conversational and less assuming Co-Authored-By: Claude Sonnet 4.5 --- examples/repro/swift/README.md | 797 ++++++++++++++++++++++++++------- 1 file changed, 642 insertions(+), 155 deletions(-) diff --git a/examples/repro/swift/README.md b/examples/repro/swift/README.md index 1aa4b81..a16df83 100644 --- a/examples/repro/swift/README.md +++ b/examples/repro/swift/README.md @@ -1,280 +1,753 @@ # Segment Swift Bug Reproduction Example -This is a fully-configured iOS app for reproducing Segment Analytics Swift SDK issues. Use this as a starting point when customers or CSMs need to demonstrate bugs or unexpected behavior. +This is a ready-to-use iOS app for reproducing and debugging issues with the Segment Analytics Swift SDK. If a customer reports a bug or unexpected behavior, you can use this example to quickly replicate and investigate the issue. -## What's Included +## What This Example Provides -- **Segment Analytics Swift SDK** (v1.6.2+) - Core analytics tracking -- **Amplitude Destination Plugin** (v1.2.0+) - Example destination integration -- **ConsoleLogger Custom Plugin** - Logs all events to console for debugging -- **Interactive Demo UI** - Buttons to test track, identify, and screen events -- **Secure Config Management** - Gitignored `Config.swift` for API keys -- **Project-Local Builds** - DerivedData isolated to this directory +- **Segment Analytics Swift SDK** (v1.6.2+) - The core tracking library +- **Amplitude Destination Plugin** (v1.2.0+) - An example of how destinations integrate +- **ConsoleLogger Plugin** - Prints all events to your console for easy debugging +- **Interactive Demo UI** - Buttons to trigger track, identify, and screen events +- **Secure Config Management** - Your API keys are never committed to Git +- **Isolated Build Environment** - Everything stays in this folder, no interference with other projects -## Prerequisites +## Prerequisites and Installation -- macOS (required for iOS development) -- Xcode 14+ (included via Devbox) -- [Devbox](https://www.jetify.com/devbox/docs/installing_devbox/) installed +This section will walk you through installing everything you need, even if you've never used the terminal before. -## Quick Start +### Step 1: Make Sure You Have macOS +iOS development requires macOS. If you're on Windows or Linux, you'll need access to a Mac (physical or virtual). + +### Step 2: Install Xcode + +Xcode is Apple's development environment for building iOS apps. + +**Option A: Install from App Store (Recommended for most users)** +1. Open the **App Store** app on your Mac +2. Search for **"Xcode"** +3. Click **Get** or **Install** (it's free, but the download is large - about 15GB) +4. Wait for installation to complete (this can take 30-60 minutes depending on your internet speed) +5. Open Xcode once installed and accept the license agreement +6. Wait for Xcode to install additional components + +**Option B: Install via Command Line (Advanced users)** +1. Open **Terminal** (you can find it in Applications → Utilities → Terminal) +2. Type this command and press Enter: + ```bash + xcode-select --install + ``` +3. Follow the prompts to install Command Line Tools +4. For the full Xcode app, still use the App Store method above + +**Verify Xcode is installed:** +Open Terminal and type: ```bash -# Clone and navigate to this directory -cd examples/repro/swift +xcodebuild -version +``` -# Build and launch the app (automatic simulator boot) -devbox run --pure start:app +You should see output like: +``` +Xcode 16.2 +Build version 16B5109o ``` -The `--pure` flag ensures a clean, reproducible environment isolated from your system. +If you see an error, Xcode isn't installed correctly. -## How to Connect Your Segment Account +### Step 3: Install Devbox -The example comes with a demo write key pre-configured. To use your own Segment source: +Devbox creates isolated development environments so everyone gets the exact same tools and versions. -1. **Copy the example config file:** +**Installation steps:** +1. Open Terminal (Applications → Utilities → Terminal) +2. Copy and paste this command, then press Enter: ```bash - cp Config.example.swift ios/Config.swift + curl -fsSL https://get.jetify.com/devbox | bash ``` +3. Wait for the installation to complete (this takes 1-2 minutes) +4. Close and reopen your Terminal window (important!) +5. Verify installation by typing: + ```bash + devbox version + ``` + +You should see a version number like `0.15.0` or similar. -2. **Add your write key:** - Edit `ios/Config.swift` and replace the write key: - ```swift - enum Config { - static let segmentWriteKey = "YOUR_WRITE_KEY_HERE" - } +**If you see "command not found":** +- Make sure you closed and reopened Terminal after installation +- Try opening a brand new Terminal window +- Check that the installer completed without errors + +**What is Devbox?** +Devbox is a tool that ensures everyone uses the same development environment. Think of it as a recipe that sets up all the tools you need automatically, in an isolated way that won't mess with other projects on your computer. + +### Step 4: Clone or Download This Repository + +If you haven't already, you need to get the mobile-devtools code on your computer. + +**Option A: Clone with Git (if you have Git installed)** +```bash +git clone https://github.com/segment-integrations/mobile-devtools.git +cd mobile-devtools/examples/repro/swift +``` + +**Option B: Download as ZIP** +1. Go to https://github.com/segment-integrations/mobile-devtools +2. Click the green **Code** button +3. Click **Download ZIP** +4. Unzip the file +5. Open Terminal and navigate to the folder: + ```bash + cd ~/Downloads/mobile-devtools-main/examples/repro/swift ``` + (Adjust the path if you saved it somewhere else) -3. **Get your write key from Segment:** - - Go to https://app.segment.com - - Navigate to: **Sources** → **Your iOS Source** → **Settings** → **API Keys** - - Copy the **Write Key** +**Verify you're in the right directory:** +Type this in Terminal: +```bash +ls +``` -The `ios/Config.swift` file is gitignored, so your write key won't be committed to version control. +You should see files like `README.md`, `devbox.json`, and an `ios` folder. -## Plugin Documentation +## Quick Start - Running the App -### 1. Amplitude Destination Plugin +Now that everything is installed, let's run the example app. This will automatically set up the environment, build the app, boot a simulator, and launch it. -The app includes Segment's official Amplitude destination plugin. You can toggle it on/off in the UI to test destination behavior. +**Step 1: Open Terminal and navigate to the Swift example directory** +```bash +cd path/to/mobile-devtools/examples/repro/swift +``` -**Features:** -- Toggle plugin at runtime via the UI switch -- Sessions automatically tracked -- Events forwarded to Amplitude when enabled +Replace `path/to/mobile-devtools` with the actual location where you downloaded or cloned the repository. -**Known limitation:** The current implementation doesn't remove the plugin when toggled off due to the Segment SDK's plugin architecture. This is expected behavior and can be used to test plugin lifecycle issues. +**Step 2: Run the app** +Type this command and press Enter: +```bash +devbox run --pure start:app +``` -### 2. ConsoleLogger Plugin +**What happens when you run this command:** +1. Devbox creates an isolated environment with all necessary tools +2. It builds the iOS app from source code +3. It starts an iOS simulator (a virtual iPhone on your Mac) +4. It installs and launches the app on that simulator -A custom enrichment plugin that logs all events to the Xcode console for debugging. +**How long does this take?** +- First time: 5-10 minutes (it downloads and sets up everything) +- After that: 1-2 minutes (much faster!) -**What it logs:** -- Track events with properties -- Identify calls with traits -- Screen events with properties -- Group and alias events +**What you should see:** +- Terminal will show build progress messages +- A simulator window will open showing an iPhone screen +- The app will launch with a simple interface showing buttons like "Track Event", "Identify User", etc. -**Location:** `ios/ConsoleLoggerPlugin.swift` +**What does `--pure` mean?** +The `--pure` flag tells Devbox to use only the tools it provides, ignoring anything else on your system. This ensures consistent, reproducible builds. -**Example output:** +## Setting Up Your Segment Account (Optional) + +The example comes with a demo write key already configured, so you can use it immediately. If you want to connect your own Segment source to see data flowing into your account, follow these steps: + +### Step 1: Copy the Configuration Template + +In Terminal, run: +```bash +cp Config.example.swift ios/Config.swift ``` -📊 Track Event: Button Pressed - Properties: ["button": "Track Event", "count": 1, "timestamp": "2026-04-22T10:30:00Z"] + +This creates a new file called `Config.swift` in the `ios` folder. This file is where you'll put your API key. + +### Step 2: Get Your Write Key from Segment + +1. Go to https://app.segment.com and log in +2. Click on **Sources** in the left sidebar +3. Select your iOS source (or create a new one) +4. Click **Settings** at the top +5. Click **API Keys** in the left menu +6. Copy the **Write Key** (it looks like: `1a2b3c4d5e6f7g8h9i0j`) + +### Step 3: Add Your Write Key to the Config File + +Open the file `ios/Config.swift` in any text editor and replace `YOUR_WRITE_KEY_HERE` with your actual write key: + +```swift +enum Config { + static let segmentWriteKey = "1a2b3c4d5e6f7g8h9i0j" // Your actual write key here +} ``` -## Build Configuration +Save the file. -This example uses project-local build output for complete isolation: +**Note:** This file is automatically ignored by Git, so your write key will never be committed or shared accidentally. -**DerivedData Location:** `./DerivedData/` -- Build artifacts stay in this directory -- No interference with other Xcode projects -- Gitignored (won't be committed) +### Step 4: Rebuild and Run -**Why this matters:** -- Multiple reproduction cases can coexist -- Clean environment for each bug report -- Easy to delete and rebuild from scratch +After updating the config, rebuild the app: +```bash +devbox run --pure start:app +``` + +Now events will flow to your Segment account! + +## Using the Demo App + +Once the app is running in the simulator, you'll see several interactive buttons: + +### Track Event Button +Tap this to send a track event to Segment. Each time you tap it, a counter increments. The event includes: +- Event name: "Button Pressed" +- Properties: button name and tap count + +### Identify User Button +Tap this to identify a user. The identify call includes: +- User ID: "demo-user-123" +- Traits: name, email, signup date + +### Track Screen Button +Tap this to record a screen view event. Screen tracking lets you see which screens users visit in your analytics. + +### Amplitude Destination Toggle +This toggle adds the Amplitude destination plugin to demonstrate destination functionality. + +**Important notes:** +- The toggle only adds the plugin when switched on +- Due to SDK architecture, switching it off doesn't actually remove the plugin (this is a known limitation) +- To see events in Amplitude, you need to configure the Amplitude destination in your Segment workspace +- No separate Amplitude API key is needed - events flow through Segment to Amplitude + +**How to see events in Amplitude:** +1. Log into your Segment workspace at https://app.segment.com +2. Go to **Connections** → **Destinations** +3. Add the **Amplitude** destination if not already configured +4. Enable it for your iOS source +5. Events tracked in the app will now flow to Amplitude + +**Where are the events?** +All events are printed to the Terminal window where you ran `devbox run --pure start:app`. Look for lines starting with 📊 to see the events as they're tracked. + +You can also see events in the Segment Debugger: +1. Go to https://app.segment.com +2. Navigate to your Source +3. Click **Debugger** in the left menu +4. Watch events appear in real-time (may take a few seconds) ## Available Commands +Here are all the commands you can run. Type these in Terminal from the `examples/repro/swift` directory: + +**Build the app (without running it):** ```bash -# Build the app devbox run --pure build +``` +This compiles the code but doesn't launch the simulator or app. -# Build and launch on simulator +**Build and run the app:** +```bash devbox run --pure start:app +``` +This is the command you'll use most often - it builds and launches everything. -# Build release configuration +**Build for release mode:** +```bash devbox run --pure build:release +``` +Release builds are optimized for performance. Use this to test how the app behaves in production. -# Clean build artifacts +**Clean build artifacts:** +```bash devbox run --pure build:clean +``` +If something isn't working, run this to delete all build files and start fresh. Then run `devbox run --pure build` again. -# Run unit tests +**Run unit tests:** +```bash devbox run --pure test +``` +Runs the automated tests included in the project. -# Run E2E test suite +**Run end-to-end tests:** +```bash devbox run --pure test:e2e +``` +Runs full integration tests that launch the app and verify functionality. -# List available iOS simulators +**List available iOS simulators:** +```bash devbox run --pure ios.sh devices list +``` +Shows all the iPhone/iPad simulators you can use. -# Start a specific simulator +**Run on a specific simulator:** +```bash devbox run --pure start:app iphone15 ``` +Launches the app on iPhone 15 instead of the default device. -## Using the Demo App +## Understanding the Console Output -The app provides an interactive UI to test Segment SDK functionality: +When you run the app, the Terminal shows a lot of output. Here's what to look for: -1. **Track Event** - Sends a track call with button press count -2. **Identify User** - Identifies a demo user with traits -3. **Track Screen** - Sends a screen view event -4. **Amplitude Toggle** - Enable/disable the Amplitude destination plugin +**Build progress:** +``` +Building for debugging... +Build succeeded +``` -All events are logged to the Xcode console via the ConsoleLogger plugin. +**Simulator starting:** +``` +[INFO] [simulator.sh] Starting simulator: iPhone 15 Pro +``` + +**App launching:** +``` +[INFO] [deploy.sh] Installing app bundle +[INFO] [deploy.sh] Launching app +``` + +**Event tracking (from ConsoleLogger plugin):** +``` +📊 Track Event: Button Pressed + Properties: ["button": "Track Event", "count": 1, "timestamp": "2026-04-22T10:30:00Z"] +``` ## How to Create Bug Reproductions -When a customer reports a bug, follow this workflow: +When a customer reports a bug with the Segment SDK, here's how to reproduce it using this example: -### 1. Start with a Clean Slate +### Step 1: Start Fresh +Clean any previous builds: ```bash cd examples/repro/swift devbox run --pure build:clean ``` -### 2. Add Customer's Configuration +### Step 2: Replicate Customer Setup -Update `ios/Config.swift` with the customer's write key (if needed): -```swift -static let segmentWriteKey = "customer_write_key_here" -``` +If the customer is using their own write key, update `ios/Config.swift` with their key (get permission first!). -### 3. Reproduce the Issue +### Step 3: Modify the Code to Match Their Use Case -Modify `ios/ContentView.swift` to match the customer's use case: +Open `ios/ContentView.swift` in a text editor (you can use Xcode, VS Code, or any editor). Find the function that relates to the customer's issue and modify it. + +For example, if a customer reports that identify isn't working: ```swift -// Example: Customer reports identify not working private func identifyUser() { - // Replicate customer's exact identify call + // Change this to match exactly what the customer is doing analytics.identify( - userId: "customer-user-id", + userId: "their-user-id", traits: [ - "name": "Customer Name", - "email": "customer@example.com" + "name": "Their Name", + "email": "their@email.com" ] ) } ``` -### 4. Verify with Console Output +Save the file. + +### Step 4: Run and Observe -Launch the app and watch the Xcode console: +Launch the app: ```bash devbox run --pure start:app ``` -The ConsoleLogger plugin will show exactly what's being sent to Segment. +Tap the relevant button in the simulator and watch the Terminal output. The ConsoleLogger plugin shows exactly what's being sent to Segment. -### 5. Test Different SDK Versions +### Step 5: Test Different SDK Versions -Update the package dependencies in Xcode: -1. Open `ios.xcodeproj` in Xcode -2. Select the project in the navigator -3. Go to **Package Dependencies** -4. Select `analytics-swift` and click the version -5. Test with different versions to isolate when the bug was introduced +To test if the bug exists in different versions of the SDK: -### 6. Share the Reproduction +1. Open `ios.xcodeproj` in Xcode (double-click the file in Finder) +2. In Xcode, click on the project name at the top of the left sidebar +3. Click on the **Package Dependencies** tab +4. Find `analytics-swift` in the list +5. Click the version number and select a different version to test +6. Click **Done**, then rebuild: `devbox run --pure build` -Create a minimal reproduction and share: +### Step 6: Document and Share + +Once you've reproduced the bug: ```bash -# Clean build artifacts +# Clean build files (saves space) devbox run --pure build:clean # Commit your changes git add ios/ContentView.swift -git commit -m "Reproduce: describe the issue" +git commit -m "Reproduce: [brief description of the bug]" -# Share the branch or create a patch +# Share via Git branch or patch file git format-patch HEAD~1 ``` -## Troubleshooting +## Troubleshooting Common Issues + +### "Command not found: devbox" + +**Problem:** Terminal doesn't recognize the `devbox` command. + +**Solution:** +1. Make sure you installed Devbox (see Step 3 in Prerequisites) +2. Close Terminal completely and open a new window +3. Try running `devbox version` - if you see a version number, it's working +4. If still not working, re-run the installation command: + ```bash + curl -fsSL https://get.jetify.com/devbox | bash + ``` + +### "xcrun: error: SDK cannot be located" + +**Problem:** Xcode Command Line Tools aren't set up correctly. + +**Solution:** +```bash +sudo xcode-select --reset +xcode-select --install +``` ### App Won't Build +**Problem:** The build fails with errors. + +**Solution 1 - Clean and rebuild:** ```bash -# Clean and rebuild devbox run --pure build:clean devbox run --pure build ``` +**Solution 2 - Make sure Xcode is installed:** +```bash +xcodebuild -version +``` +If this errors, install Xcode from the App Store. + +**Solution 3 - Accept Xcode license:** +Open Xcode once and accept the license agreement when prompted. + ### Simulator Not Found +**Problem:** Error says simulator device not found. + +**Solution - List available simulators:** ```bash -# List available simulators devbox run --pure ios.sh devices list +``` -# Create a new simulator +If no simulators are shown, create one: +```bash devbox run --pure ios.sh devices create iphone15 --runtime 17.5 - -# Sync simulators devbox run --pure ios.sh devices sync ``` -### Config.swift Missing +### Config.swift File Missing + +**Problem:** Build fails saying `Config.swift` not found. +**Solution:** ```bash -# Copy the example config cp Config.example.swift ios/Config.swift +``` + +The build needs this file even if you're using the demo write key. + +### Events Not Showing in Segment + +**Problem:** You're tapping buttons but not seeing events in Segment. + +**Checklist:** +1. Check the write key in `ios/Config.swift` is correct +2. Look at the Terminal output - do you see 📊 event logs from ConsoleLogger? +3. Open the Segment Debugger: https://app.segment.com → Your Source → Debugger +4. Try tapping the button again and wait 5-10 seconds for events to appear +5. Make sure the simulator has internet (it should by default) + +### Simulator Shows Black Screen + +**Problem:** The simulator opens but stays black or shows a white screen. + +**Solution:** +1. Wait a moment - it can take 10-20 seconds to fully start +2. Click on the simulator window to make sure it's active +3. Restart the simulator: + ```bash + # Stop the current run (press Ctrl+C in Terminal if it's still running) + devbox run --pure start:app + ``` + +### "Permission Denied" Errors -# Edit and add your write key -# (File is gitignored, so it won't be committed) +**Problem:** Commands fail with permission denied errors. + +**Solution:** +```bash +chmod +x scripts/* # Make scripts executable ``` -### Events Not Appearing in Segment +Or run commands with `bash` explicitly: +```bash +bash -c "devbox run --pure build" +``` + +### Can't Find Terminal + +**Problem:** You're not sure how to open Terminal on macOS. + +**Solution:** +1. Press `Command (⌘) + Space` to open Spotlight +2. Type "Terminal" +3. Press Enter -1. Check the write key in `ios/Config.swift` -2. Watch the Xcode console for ConsoleLogger output -3. Verify network connectivity (simulator has internet access) -4. Check Segment debugger: https://app.segment.com → Sources → Your Source → Debugger +Or: +1. Open Finder +2. Go to Applications → Utilities → Terminal +3. Double-click Terminal -### Wrong Simulator Launched +## Understanding the Plugin System -Specify the device explicitly: +This example demonstrates two types of plugins that extend the Segment SDK: + +### ConsoleLogger Plugin (Custom Plugin) + +**What it does:** Prints every event to the Terminal in a readable format. + +**Why it's useful:** You can see exactly what's being sent to Segment without needing to check the debugger or use network inspection tools. + +**Location:** `ios/ConsoleLoggerPlugin.swift` + +**Example output:** +``` +📊 Track Event: Button Pressed + Properties: { + "button": "Track Event", + "count": 1, + "timestamp": "2026-04-22T10:30:00Z" + } +``` + +### Amplitude Destination Plugin (Official Plugin) + +**What it does:** Forwards events from Segment to Amplitude's SDK for session tracking and analytics. + +**Why it's included:** It demonstrates how destination plugins work and lets you test destination-related issues. + +**Configuration:** +- No Amplitude API key needed in the app code +- Events flow through Segment's cloud destination to Amplitude +- Configure the Amplitude destination in your Segment workspace at https://app.segment.com + +**Features:** +- Toggleable in the UI (adds plugin when enabled) +- Automatic session tracking +- Events forwarded to Amplitude when the destination is configured in Segment + +**Known limitation:** When you toggle the switch off, the plugin isn't actually removed from the SDK due to architectural constraints. This is expected behavior and can be useful for testing plugin lifecycle issues. + +## How to Add Your Own Plugins + +You can extend the Segment SDK by creating custom plugins or adding third-party destination plugins. Here's how: + +### Adding an Official Segment Destination Plugin + +Official destination plugins are available as Swift packages. For example, to add the Firebase destination: + +**Step 1: Add the package dependency** +1. Open `ios.xcodeproj` in Xcode (double-click the file) +2. Select the project in the left sidebar +3. Click the **Package Dependencies** tab +4. Click the **+** button +5. Enter the package URL: `https://github.com/segment-integrations/analytics-swift-firebase` +6. Click **Add Package** +7. Select the library to add and click **Add Package** again + +**Step 2: Import and add the plugin in code** + +Open `ios/ContentView.swift` and add at the top: +```swift +import SegmentFirebase // Import the plugin +``` + +In the `init()` method, add the plugin: +```swift +init() { + let configuration = Configuration(writeKey: Config.segmentWriteKey) + .flushInterval(10) + + self.analytics = Analytics(configuration: configuration) + + // Add plugins + analytics.add(plugin: ConsoleLoggerPlugin()) + analytics.add(plugin: IDFAPlugin()) + analytics.add(plugin: FirebaseDestination()) // Add your new plugin + + print("🚀 Segment Analytics initialized") +} +``` + +**Step 3: Configure the destination in Segment** + +Most destination plugins require you to also configure the destination in your Segment workspace: +1. Go to https://app.segment.com +2. Navigate to **Connections** → **Destinations** +3. Add and configure the destination (e.g., Firebase) +4. Enable it for your iOS source + +**Step 4: Rebuild and test** ```bash -devbox run --pure start:app iphone15 +devbox run --pure build +devbox run --pure start:app ``` -Or set the default in `devbox.json`: -```json -{ - "env": { - "IOS_DEFAULT_DEVICE": "iphone15" - } +### Creating a Custom Plugin + +Custom plugins let you intercept, modify, or enrich events. Here's how to create one: + +**Step 1: Create a new Swift file** + +Create a file like `ios/MyCustomPlugin.swift`: + +```swift +import Foundation +import Segment + +class MyCustomPlugin: Plugin { + let type: PluginType = .enrichment + weak var analytics: Analytics? + + func execute(event: T?) -> T? { + guard var workingEvent = event else { return event } + + // Modify the event (example: add custom property) + if var trackEvent = workingEvent as? TrackEvent { + trackEvent.properties?["custom_field"] = "custom_value" + workingEvent = trackEvent as! T + } + + return workingEvent + } +} +``` + +**Step 2: Add the plugin in ContentView.swift** + +```swift +init() { + let configuration = Configuration(writeKey: Config.segmentWriteKey) + .flushInterval(10) + + self.analytics = Analytics(configuration: configuration) + + // Add your custom plugin + analytics.add(plugin: MyCustomPlugin()) + analytics.add(plugin: ConsoleLoggerPlugin()) + + print("🚀 Segment Analytics initialized") +} +``` + +**Step 3: Test it** +```bash +devbox run --pure start:app +``` + +Tap "Track Event" and check the console output - you should see your custom field added to every track event. + +### Plugin Types + +The Segment SDK supports different plugin types: + +**`.before` plugins:** Run before Segment processes the event +- Use for: Early validation, event filtering + +**`.enrichment` plugins:** Add or modify event data +- Use for: Adding context, user properties, custom fields + +**`.destination` plugins:** Send events to third-party services +- Use for: Forwarding events to analytics tools, error trackers + +**`.after` plugins:** Run after Segment processes the event +- Use for: Logging, debugging, analytics + +**Example plugin type usage:** +```swift +class MyPlugin: Plugin { + let type: PluginType = .enrichment // Change this based on when you want it to run + weak var analytics: Analytics? + + func execute(event: T?) -> T? { + // Your plugin logic here + return event + } } ``` -## Why Use Devbox for Reproductions? +### Available Official Destination Plugins + +Segment provides official destination plugins for popular services: + +- **Amplitude:** `https://github.com/segment-integrations/analytics-swift-amplitude` (included in this example) +- **Firebase:** `https://github.com/segment-integrations/analytics-swift-firebase` +- **Mixpanel:** `https://github.com/segment-integrations/analytics-swift-mixpanel` +- **Braze:** `https://github.com/segment-integrations/analytics-swift-braze` +- **AppsFlyer:** `https://github.com/segment-integrations/analytics-swift-appsflyer` + +See the [Segment Analytics Swift documentation](https://github.com/segmentio/analytics-swift) for a complete list. + +### Troubleshooting Plugin Issues + +**Plugin not being called:** +1. Make sure you added it to analytics: `analytics.add(plugin: MyPlugin())` +2. Check that the plugin type is correct for when you want it to run +3. Verify the `execute` method returns the event (not nil) + +**Can't import plugin package:** +1. Make sure you added the Swift package dependency in Xcode +2. Clean and rebuild: `devbox run --pure build:clean && devbox run --pure build` +3. Check the package URL is correct + +**Events not reaching destination:** +1. Verify the destination is configured in your Segment workspace +2. Check the destination is enabled for your iOS source +3. Look at the Segment debugger to see if events are being received by Segment +4. Check the destination's specific setup requirements (some need API keys in the Segment UI) + +## Why Devbox? + +You might wonder why we use Devbox instead of just opening the project in Xcode directly. Here's why: + +**Reproducibility:** Everyone who uses this example gets the exact same versions of tools, SDKs, and simulators. This means "it works on my machine" problems are eliminated. + +**Isolation:** All build artifacts, dependencies, and configuration stay in this folder. You can have multiple projects using different versions of tools without conflicts. -**Reproducibility:** Everyone gets the exact same Xcode, SDKs, and simulator versions. +**Speed for Support Teams:** Customer Success and Support engineers can run reproductions without spending hours setting up Xcode, configuring simulators, or managing SDK versions. -**Isolation:** No global state pollution. Each reproduction is self-contained. +**Consistency Across Environments:** Developers, CI pipelines, and support engineers all use identical environments, making debugging easier. -**Speed:** CSMs and support engineers can run reproductions without manual Xcode setup. +**You can still use Xcode!** Devbox doesn't prevent you from opening `ios.xcodeproj` in Xcode. You get the best of both worlds - Xcode's powerful IDE plus Devbox's reproducible environment. -**Consistency:** CI, developers, and support all use the same environment. +## Build Configuration Details + +This example uses project-local build output for complete isolation: + +**DerivedData Location:** `./DerivedData/` +All build artifacts (compiled code, temporary files, etc.) are stored in this directory. + +**Why this matters:** +- Multiple reproduction cases can coexist on the same machine without interfering +- You can completely delete `DerivedData` and rebuild without affecting other projects +- It's gitignored, so large build artifacts won't bloat your repository + +**To clean build artifacts:** +```bash +devbox run --pure build:clean +# Or manually: rm -rf DerivedData +``` ## Plugin Configuration -This example uses a **local path include** for development within this repository: +This example uses a **local path include** because it's part of the mobile-devtools repository: ```json { @@ -284,7 +757,7 @@ This example uses a **local path include** for development within this repositor } ``` -If you copy this example outside the repository, change to the GitHub URL: +If you copy this example outside the repository, change `devbox.json` to use the GitHub URL: ```json { @@ -294,33 +767,47 @@ If you copy this example outside the repository, change to the GitHub URL: } ``` -For more information, see the [iOS Plugin Reference](../../../plugins/ios/REFERENCE.md). +This tells Devbox to fetch the iOS plugin directly from GitHub instead of looking for a local copy. ## Project Structure +Here's what each file and folder does: + ``` examples/repro/swift/ -├── ios/ # Swift source files -│ ├── iosApp.swift # App entry point -│ ├── ContentView.swift # Main UI with demo buttons -│ ├── ConsoleLoggerPlugin.swift # Custom debug plugin -│ └── Config.swift # Gitignored config (write keys) -├── ios.xcodeproj/ # Xcode project -├── devbox.json # Devbox configuration -├── devbox.d/ios/devices/ # Simulator definitions -└── DerivedData/ # Project-local build artifacts +├── ios/ # Swift source code +│ ├── iosApp.swift # App entry point (where the app starts) +│ ├── ContentView.swift # Main UI with buttons and demo logic +│ ├── ConsoleLoggerPlugin.swift # Custom plugin that logs events +│ └── Config.swift # Your write key (gitignored, create from Config.example.swift) +├── ios.xcodeproj/ # Xcode project file +├── iosTests/ # Unit tests +├── iosUITests/ # UI automation tests +├── devbox.json # Devbox configuration (tools, commands) +├── devbox.lock # Locked versions of tools +├── devbox.d/ios/devices/ # iOS simulator definitions +├── DerivedData/ # Build output (gitignored) +├── Config.example.swift # Template for Config.swift +└── README.md # This file ``` ## Related Resources -- [Segment Analytics Swift SDK](https://github.com/segmentio/analytics-swift) +- [Segment Analytics Swift SDK Documentation](https://github.com/segmentio/analytics-swift) - [Amplitude Destination Plugin](https://github.com/segmentio/analytics-swift-amplitude) -- [iOS Plugin Reference](../../../plugins/ios/REFERENCE.md) -- [Devbox Documentation](https://www.jetify.com/devbox) +- [iOS Plugin Reference](../../../plugins/ios/REFERENCE.md) - Advanced configuration options +- [Devbox Documentation](https://www.jetify.com/devbox) - Learn more about Devbox + +## Getting Help + +**Issues with this example:** +Open an issue in the [mobile-devtools repository](https://github.com/segment-integrations/mobile-devtools/issues) + +**Segment SDK bugs:** +Check the [analytics-swift issues](https://github.com/segmentio/analytics-swift/issues) -## Support +**Devbox problems:** +See the [Devbox documentation](https://www.jetify.com/devbox/docs/) or [Devbox community](https://discord.gg/jetify) -For issues with: -- **This reproduction example:** Open an issue in this repository -- **Segment SDK bugs:** Check the [analytics-swift issues](https://github.com/segmentio/analytics-swift/issues) -- **Devbox:** See the [Devbox documentation](https://www.jetify.com/devbox/docs/) +**Still stuck?** +Ask in your team's Slack channel or reach out to the Mobile SDK team. From e38c403fb721fff17c13ccbef748e27df5a5a337 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:05:19 -0500 Subject: [PATCH 02/16] feat(swift): add share command for easy reproduction packaging - Add scripts/share.sh to automate reproduction sharing - Auto-commits changes, creates zip archive with commit hash + timestamp - Excludes build artifacts and large files (keeps zip small) - Includes REPRO-INFO.txt with setup instructions - Includes git patch showing exact changes - Outputs to shared-repros/ directory (gitignored) - Comprehensive documentation for uploading to Jira, email, or Slack - Beginner-friendly instructions for non-Git users Benefits: - Support/CS teams can share repros without Git knowledge - Consistent naming scheme (commit-hash-timestamp) - Self-contained packages ready to run - Clipboard integration on macOS for easy file location Co-Authored-By: Claude Sonnet 4.5 --- .gitignore | 3 + examples/repro/swift/README.md | 203 +++++++++++++++++++++++++- examples/repro/swift/devbox.json | 7 +- examples/repro/swift/scripts/share.sh | 187 ++++++++++++++++++++++++ 4 files changed, 392 insertions(+), 8 deletions(-) create mode 100755 examples/repro/swift/scripts/share.sh diff --git a/.gitignore b/.gitignore index c74ec85..31d3881 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ conversation_*.md transcript_* scratch_* draft_* + +# Shared reproduction archives +shared-repros/ diff --git a/examples/repro/swift/README.md b/examples/repro/swift/README.md index a16df83..69cfc16 100644 --- a/examples/repro/swift/README.md +++ b/examples/repro/swift/README.md @@ -284,6 +284,12 @@ devbox run --pure start:app iphone15 ``` Launches the app on iPhone 15 instead of the default device. +**Share your reproduction:** +```bash +devbox run share +``` +Packages your reproduction into a zip file for sharing via Jira, email, or Slack. Automatically commits changes and creates a properly named archive. + ## Understanding the Console Output When you run the app, the Terminal shows a lot of output. Here's what to look for: @@ -368,19 +374,202 @@ To test if the bug exists in different versions of the SDK: 5. Click the version number and select a different version to test 6. Click **Done**, then rebuild: `devbox run --pure build` -### Step 6: Document and Share +### Step 6: Share Your Reproduction + +Once you've reproduced the bug, use the built-in share command to package everything for sharing: -Once you've reproduced the bug: ```bash -# Clean build files (saves space) +devbox run share +``` + +This automatically commits your changes, creates a zip file, and tells you where to find it. See the **Sharing Reproductions** section below for complete details on uploading to Jira or sharing with the team. + +## Sharing Reproductions + +After you've reproduced a customer issue, you need to share it with the engineering team. The `share` command makes this easy, even if you're not familiar with Git. + +### Quick Share (Recommended) + +Just run this command: +```bash +devbox run share +``` + +**What it does:** +1. ✅ Automatically commits any changes you made +2. ✅ Creates a zip file with everything needed to reproduce the issue +3. ✅ Names the file with a unique identifier (commit hash + timestamp) +4. ✅ Excludes unnecessary files (build artifacts, etc.) to keep it small +5. ✅ Shows you exactly where the zip file is located +6. ✅ Copies the file path to your clipboard (on macOS) + +**What you'll see:** +``` +📦 Swift Repro Share Tool + +Repository: /Users/you/mobile-devtools +Repro directory: examples/repro/swift + +Found uncommitted changes: +M ios/ContentView.swift + +Committing changes... +✓ Changes committed + +Creating archive... + Name: swift-repro-a1b2c3d-20260422-143052.zip + +✅ Archive created successfully! + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +Archive Details: + Name: swift-repro-a1b2c3d-20260422-143052.zip + Size: 2.3M + Location: /Users/you/mobile-devtools/shared-repros/swift-repro-a1b2c3d-20260422-143052.zip + Commit: a1b2c3d +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Next Steps: +1️⃣ Locate the file: + Open Finder and navigate to: + ~/mobile-devtools/shared-repros/swift-repro-a1b2c3d-20260422-143052.zip + +2️⃣ Upload to Jira: + • Open the Jira issue in your browser + • Click 'Attach' or drag the zip file onto the issue + • Add a comment describing what you changed + +3️⃣ Or share via email: + • Attach the zip file to your email + • Mention the commit hash: a1b2c3d +``` + +### Uploading to Jira (Step-by-Step) + +Once you have the zip file, here's how to attach it to a Jira issue: + +**Step 1: Locate the zip file** +The share command tells you exactly where the file is. On macOS, it's copied to your clipboard, so you can just paste it into Finder's "Go to Folder" (Command+Shift+G). + +Or navigate manually: +1. Open **Finder** +2. Press **Command+Shift+G** (Go to Folder) +3. Paste or type: `~/mobile-devtools/shared-repros` +4. Press Enter +5. Find your zip file (it has today's date in the name) + +**Step 2: Open the Jira issue** +1. Go to your Jira instance (e.g., `yourcompany.atlassian.net`) +2. Find and open the customer's issue +3. Make sure you're looking at the issue details page + +**Step 3: Attach the file** + +**Option A: Drag and drop (easiest)** +1. Drag the zip file from Finder +2. Drop it onto the Jira issue page +3. Wait for the upload to complete + +**Option B: Use the attach button** +1. Look for the **Attach** button or paperclip icon (usually at the top or bottom of the issue) +2. Click it +3. Select your zip file from the file picker +4. Click **Open** or **Choose** +5. Wait for the upload to complete + +**Step 4: Add a comment** +Always add a comment explaining what you did: + +``` +Attached reproduction case for the reported SDK issue. + +What I changed: +- Modified ContentView.swift to replicate customer's identify call +- Used customer's exact user ID format +- Testing with SDK version 1.6.2 + +To run: +1. Extract the zip file +2. cd into the directory +3. Run: devbox run --pure start:app +4. Tap "Identify User" to reproduce the issue + +The issue reproduces consistently - check Terminal output for details. +``` + +**Step 5: Notify the team** +Mention relevant team members in the comment using `@username` so they get notified. + +### Sharing via Email + +If you need to share via email instead of Jira: + +1. Compose a new email to the Mobile SDK team +2. Attach the zip file +3. In the email body, include: + - Jira issue link + - Brief description of the issue + - What you changed to reproduce it + - The commit hash (from the share command output) + - Instructions: "Extract and run `devbox run --pure start:app`" + +### Sharing via Slack + +For quick sharing with the team: + +1. Open the relevant Slack channel +2. Drag the zip file into the message box +3. Add a message: + ``` + Reproduction for JIRA-123: Customer reports identify not working + + Changes: Modified identify call to match customer's setup + Commit: a1b2c3d + + Extract and run: devbox run --pure start:app + ``` + +### What's Inside the Zip File? + +The share command creates a self-contained reproduction package: + +- **All source code** - The modified Swift files that demonstrate the issue +- **Project files** - Xcode project configuration +- **Device definitions** - Simulator settings +- **Configuration** - devbox.json and plugin setup +- **REPRO-INFO.txt** - Instructions for the person receiving the file +- **changes.patch** - Git patch showing exactly what you modified + +**What's NOT included** (to keep the file small): +- Build artifacts (DerivedData) +- Xcode user data +- Git history +- Devbox cache + +This means the recipient can extract and immediately run `devbox run --pure start:app` to see the issue. + +### Advanced: Manual Sharing (If Share Command Doesn't Work) + +If you need to share manually without the share command: + +```bash +# Clean build artifacts first devbox run --pure build:clean # Commit your changes -git add ios/ContentView.swift -git commit -m "Reproduce: [brief description of the bug]" +git add . +git commit -m "Reproduce: [describe the issue]" + +# Create a patch file +git format-patch -1 HEAD --stdout > my-repro.patch -# Share via Git branch or patch file -git format-patch HEAD~1 +# Share the patch file via Jira/email +``` + +The recipient can apply your patch: +```bash +git apply my-repro.patch +devbox run --pure start:app ``` ## Troubleshooting Common Issues diff --git a/examples/repro/swift/devbox.json b/examples/repro/swift/devbox.json index 632a0b7..2840d0f 100644 --- a/examples/repro/swift/devbox.json +++ b/examples/repro/swift/devbox.json @@ -1,7 +1,9 @@ { "include": ["path:../../../plugins/ios/plugin.json"], "packages": { - "process-compose": "latest" + "process-compose": "latest", + "zip": "latest", + "rsync": "latest" }, "env": { "IOS_APP_ARTIFACT": "DerivedData/Build/Products/Debug-iphonesimulator/ios.app" @@ -25,6 +27,9 @@ ], "test:e2e": [ "process-compose -f tests/test-suite.yaml --no-server --tui=${TEST_TUI:-false}" + ], + "share": [ + "bash scripts/share.sh" ] } } diff --git a/examples/repro/swift/scripts/share.sh b/examples/repro/swift/scripts/share.sh new file mode 100755 index 0000000..88b0f29 --- /dev/null +++ b/examples/repro/swift/scripts/share.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +# +# share.sh - Package Swift repro for sharing +# +# Creates a zip archive of the reproduction case for easy sharing +# via Jira, email, or other channels. +# + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}📦 Swift Repro Share Tool${NC}" +echo "" + +# Check if we're in a git repository +if ! git rev-parse --git-dir > /dev/null 2>&1; then + echo -e "${RED}Error: Not in a git repository${NC}" + echo "This tool requires git to track changes." + exit 1 +fi + +# Get repository root +REPO_ROOT=$(git rev-parse --show-toplevel) +REPRO_DIR="$PWD" +RELATIVE_PATH=$(realpath --relative-to="$REPO_ROOT" "$REPRO_DIR" 2>/dev/null || python3 -c "import os.path; print(os.path.relpath('$REPRO_DIR', '$REPO_ROOT'))") + +echo -e "${BLUE}Repository:${NC} $REPO_ROOT" +echo -e "${BLUE}Repro directory:${NC} $RELATIVE_PATH" +echo "" + +# Check for uncommitted changes +if [[ -n $(git status --porcelain) ]]; then + echo -e "${YELLOW}Found uncommitted changes:${NC}" + git status --short + echo "" + + echo -e "${BLUE}Committing changes...${NC}" + + # Add all changes in the repro directory + git add . + + # Create commit with timestamp + TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') + git commit -m "Repro: Swift SDK reproduction case - $TIMESTAMP" \ + -m "Auto-committed by share.sh for reproduction sharing." \ + -m "Changes include modifications to demonstrate customer issue." \ + -m "" \ + -m "Co-Authored-By: Share Script " + + echo -e "${GREEN}✓ Changes committed${NC}" + echo "" +else + echo -e "${GREEN}✓ No uncommitted changes${NC}" + echo "" +fi + +# Get commit information +COMMIT_HASH=$(git rev-parse --short HEAD) +TIMESTAMP=$(date '+%Y%m%d-%H%M%S') +ARCHIVE_NAME="swift-repro-${COMMIT_HASH}-${TIMESTAMP}" +OUTPUT_DIR="$REPO_ROOT/shared-repros" +ARCHIVE_PATH="$OUTPUT_DIR/${ARCHIVE_NAME}.zip" + +# Create output directory +mkdir -p "$OUTPUT_DIR" + +echo -e "${BLUE}Creating archive...${NC}" +echo -e " Name: ${ARCHIVE_NAME}.zip" +echo "" + +# Create temporary staging directory +TEMP_DIR=$(mktemp -d) +STAGING_DIR="$TEMP_DIR/$ARCHIVE_NAME" +mkdir -p "$STAGING_DIR" + +# Copy relevant files, excluding build artifacts and large files +echo -e "${BLUE}Copying files...${NC}" + +# Copy the entire repro directory structure but exclude certain patterns +rsync -a \ + --exclude='.git' \ + --exclude='DerivedData' \ + --exclude='*.xcuserstate' \ + --exclude='xcuserdata' \ + --exclude='*.xcworkspace' \ + --exclude='.DS_Store' \ + --exclude='build' \ + --exclude='.devbox' \ + --exclude='node_modules' \ + "$REPRO_DIR/" "$STAGING_DIR/" + +# Add a README with reproduction info +cat > "$STAGING_DIR/REPRO-INFO.txt" << EOF +Swift SDK Reproduction Case +============================ + +Commit: $COMMIT_HASH +Created: $(date '+%Y-%m-%d %H:%M:%S') +Repository: mobile-devtools + +This reproduction case demonstrates a reported issue with the Segment Analytics Swift SDK. + +Setup Instructions: +------------------- +1. Extract this zip file +2. Open Terminal and navigate to the extracted directory: + cd path/to/$ARCHIVE_NAME + +3. Install Devbox if not already installed: + curl -fsSL https://get.jetify.com/devbox | bash + +4. Build and run the reproduction: + devbox run --pure start:app + +5. Tap buttons in the simulator to trigger the issue +6. Check Terminal output for logged events + +For detailed instructions, see README.md in this directory. + +Questions? +---------- +Refer to the README.md or contact the Mobile SDK team. +EOF + +# Create git patch for the changes +echo -e "${BLUE}Creating git patch...${NC}" +git format-patch -1 HEAD --stdout > "$STAGING_DIR/changes.patch" + +# Create the zip archive +echo -e "${BLUE}Compressing...${NC}" +cd "$TEMP_DIR" +zip -r "$ARCHIVE_PATH" "$ARCHIVE_NAME" > /dev/null + +# Clean up +rm -rf "$TEMP_DIR" + +# Get file size +FILE_SIZE=$(du -h "$ARCHIVE_PATH" | cut -f1) + +echo "" +echo -e "${GREEN}✅ Archive created successfully!${NC}" +echo "" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${GREEN}Archive Details:${NC}" +echo -e " Name: ${ARCHIVE_NAME}.zip" +echo -e " Size: ${FILE_SIZE}" +echo -e " Location: ${ARCHIVE_PATH}" +echo -e " Commit: ${COMMIT_HASH}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo "" + +# Show git log for context +echo -e "${BLUE}Recent changes:${NC}" +git log -1 --pretty=format:" %h - %s%n Author: %an <%ae>%n Date: %ad%n" --date=format:'%Y-%m-%d %H:%M:%S' +echo "" + +echo -e "${BLUE}Next Steps:${NC}" +echo "" +echo -e "1️⃣ ${BLUE}Locate the file:${NC}" +echo " Open Finder and navigate to:" +echo " ${ARCHIVE_PATH/$HOME/~}" +echo "" +echo -e "2️⃣ ${BLUE}Upload to Jira:${NC}" +echo " • Open the Jira issue in your browser" +echo " • Click 'Attach' or drag the zip file onto the issue" +echo " • Add a comment describing what you changed" +echo "" +echo -e "3️⃣ ${BLUE}Or share via email:${NC}" +echo " • Attach the zip file to your email" +echo " • Mention the commit hash: ${COMMIT_HASH}" +echo "" +echo -e "${YELLOW}Note:${NC} The archive excludes build artifacts and is ready to share." +echo -e "${YELLOW} The recipient can extract and run: devbox run --pure start:app${NC}" +echo "" + +# Copy path to clipboard if pbcopy is available (macOS) +if command -v pbcopy &> /dev/null; then + echo -n "$ARCHIVE_PATH" | pbcopy + echo -e "${GREEN}✓ Archive path copied to clipboard!${NC}" + echo "" +fi From cb70ea574b46fe245897187e93f9dc1dc9f25af5 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:06:10 -0500 Subject: [PATCH 03/16] fix(swift): ensure share.sh returns to correct directory after cleanup --- examples/repro/swift/scripts/share.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/repro/swift/scripts/share.sh b/examples/repro/swift/scripts/share.sh index 88b0f29..75987fa 100755 --- a/examples/repro/swift/scripts/share.sh +++ b/examples/repro/swift/scripts/share.sh @@ -137,12 +137,13 @@ echo -e "${BLUE}Compressing...${NC}" cd "$TEMP_DIR" zip -r "$ARCHIVE_PATH" "$ARCHIVE_NAME" > /dev/null -# Clean up -rm -rf "$TEMP_DIR" - -# Get file size +# Get file size before cleanup FILE_SIZE=$(du -h "$ARCHIVE_PATH" | cut -f1) +# Clean up and return to original directory +rm -rf "$TEMP_DIR" +cd "$REPRO_DIR" + echo "" echo -e "${GREEN}✅ Archive created successfully!${NC}" echo "" From 40d462a4d39116ae75e379a8746f8ea872b1b7b4 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:07:31 -0500 Subject: [PATCH 04/16] docs(repro): add share command documentation to main repro README - Document share command workflow in general workflow section - Add dedicated 'Sharing Made Easy' section with comprehensive details - Include what's in archives, where to share, and recipient instructions - Update 'What Makes These Examples Special' to mention easy sharing - Update 'Adding New Examples' to include share command setup This makes the share feature discoverable for all reproduction examples. --- examples/repro/README.md | 134 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 5 deletions(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index b5e04b6..e2dcc85 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -121,14 +121,63 @@ Each example includes package managers (SPM for Swift, Gradle for Android) that ### 6. Share the Reproduction -Commit your changes and share: +Use the built-in share command to package your reproduction: +```bash +devbox run share +``` + +**What it does:** +- ✅ Auto-commits your changes (no Git knowledge needed!) +- ✅ Creates a zip file with everything needed to reproduce +- ✅ Names file with commit hash + timestamp for easy identification +- ✅ Excludes build artifacts (keeps file size small) +- ✅ Includes setup instructions (REPRO-INFO.txt) +- ✅ Shows you exactly where the file is saved +- ✅ Copies path to clipboard (macOS) + +**Example output:** +``` +✅ Archive created successfully! + +Archive Details: + Name: swift-repro-a1b2c3d-20260422-143052.zip + Size: 2.3M + Location: ~/mobile-devtools/shared-repros/swift-repro-a1b2c3d-20260422-143052.zip + Commit: a1b2c3d + +Next Steps: +1️⃣ Upload to Jira: Drag and drop the zip onto the issue +2️⃣ Or share via email: Attach the zip file +3️⃣ Or post to Slack: Drag into your message +``` + +**Uploading to Jira:** +1. Open the Jira issue +2. Click **Attach** or drag the zip file onto the page +3. Add a comment: + ``` + Reproduction case attached (commit: a1b2c3d) + + Changes made: + - Modified identify call to match customer setup + - Using SDK version 1.6.2 + + To run: Extract and run "devbox run --pure start:app" + ``` + +**Sharing via Email/Slack:** +Just attach or drag the zip file and mention the commit hash from the output. + +The recipient can extract the zip and immediately run `devbox run --pure start:app` - everything is included! + +**Manual sharing (if needed):** +If the share command isn't available, you can still share manually: ```bash git add . git commit -m "Reproduce: customer issue description" -git push origin reproduce-customer-issue +git format-patch -1 HEAD --stdout > repro.patch ``` - -Now the customer, support, and engineering all have the exact same reproduction environment. +Then share the patch file. ## What Makes These Examples Special @@ -144,6 +193,79 @@ Now the customer, support, and engineering all have the exact same reproduction **Pure Mode:** The `--pure` flag ensures a clean environment with no inherited state from your system. +**Easy Sharing:** Built-in `share` command packages reproductions for Jira, email, or Slack - no Git knowledge required. + +## Sharing Made Easy + +All reproduction examples include a `share` command that makes it trivial to package and share reproductions, even for non-technical team members. + +### How It Works + +```bash +cd swift # or any other example +# Make your changes to reproduce the issue +devbox run share +``` + +The share command automatically: +1. **Commits changes** - No need to know Git commands +2. **Creates archive** - Zip file with meaningful name (commit-hash-timestamp) +3. **Excludes bloat** - No build artifacts, only source code +4. **Adds instructions** - Includes REPRO-INFO.txt with setup steps +5. **Shows location** - Tells you exactly where the file is +6. **Copies path** - Clipboard integration on macOS + +### What's In The Archive + +Each shared reproduction package contains: +- All source code showing the issue +- Project configuration (devbox.json, Xcode project, etc.) +- Device/simulator definitions +- **REPRO-INFO.txt** - Instructions for running the reproduction +- **changes.patch** - Git patch showing exactly what was modified + +The archive excludes: +- Build artifacts (DerivedData, build/, etc.) +- Git history (.git/) +- Devbox cache (.devbox/) +- Node modules, Pods, etc. + +This keeps files small (typically 2-5 MB) while including everything needed to run the reproduction. + +### Where To Share + +**Jira (Primary Method):** +1. Drag the zip file onto the Jira issue +2. Add a comment with the commit hash +3. Describe what you changed + +**Email:** +- Attach the zip file +- Mention commit hash in email body +- CC relevant team members + +**Slack:** +- Drag zip into relevant channel +- Include Jira issue link +- Brief description of the issue + +### For Recipients + +Anyone receiving a shared reproduction can: +```bash +# Extract the zip file +unzip swift-repro-a1b2c3d-20260422-143052.zip +cd swift-repro-a1b2c3d-20260422-143052 + +# Install devbox if needed +curl -fsSL https://get.jetify.com/devbox | bash + +# Run the reproduction +devbox run --pure start:app +``` + +Everything is included and ready to run. No setup needed. + ## Adding New Examples When adding a new platform or SDK: @@ -154,7 +276,9 @@ When adding a new platform or SDK: 4. Include a custom logging plugin for debugging 5. Use gitignored config files for API keys 6. Configure project-local build output -7. Document the quick start workflow +7. Add `scripts/share.sh` for easy sharing +8. Add `share` command to `devbox.json` scripts +9. Document the quick start workflow Follow the pattern established by the Swift example. From 61b97d3f48134e826c5a35ed134abc06557205c9 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:11:12 -0500 Subject: [PATCH 05/16] docs(swift): clarify Xcode is NOT included with Devbox, rewrite with inline steps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL FIXES: - Made it crystal clear Xcode must be installed separately (NOT via Devbox) - Added prominent warnings that Xcode is a separate prerequisite - Rewrote installation as 'Install Now' steps you can follow immediately - Added inline Terminal opening instructions (not separate section) - Included timing expectations (15GB, 30-60 min for Xcode) - Added visual ✅/❌ indicators for successful/failed verification - Made 'Close and Reopen Terminal' step more prominent (CRITICAL!) - Simplified download instructions with exact commands to copy/paste - Rewrote Quick Start to be more immediate and actionable The previous docs incorrectly gave the impression Xcode was included. --- examples/repro/swift/README.md | 245 ++++++++++++++++++++++----------- 1 file changed, 165 insertions(+), 80 deletions(-) diff --git a/examples/repro/swift/README.md b/examples/repro/swift/README.md index 69cfc16..6dbf450 100644 --- a/examples/repro/swift/README.md +++ b/examples/repro/swift/README.md @@ -13,129 +13,214 @@ This is a ready-to-use iOS app for reproducing and debugging issues with the Seg ## Prerequisites and Installation -This section will walk you through installing everything you need, even if you've never used the terminal before. +**You need TWO things installed before you can run this example:** -### Step 1: Make Sure You Have macOS +1. ✅ **Xcode** - Apple's development tools (**NOT included with Devbox - you must install separately**) +2. ✅ **Devbox** - Environment manager that handles everything else + +Follow these steps in order. Each step has inline instructions you can follow right now. + +--- + +## Step 1: Make Sure You Have macOS iOS development requires macOS. If you're on Windows or Linux, you'll need access to a Mac (physical or virtual). -### Step 2: Install Xcode +--- -Xcode is Apple's development environment for building iOS apps. +## Step 2: Install Xcode -**Option A: Install from App Store (Recommended for most users)** -1. Open the **App Store** app on your Mac -2. Search for **"Xcode"** -3. Click **Get** or **Install** (it's free, but the download is large - about 15GB) -4. Wait for installation to complete (this can take 30-60 minutes depending on your internet speed) -5. Open Xcode once installed and accept the license agreement -6. Wait for Xcode to install additional components +**⚠️ IMPORTANT: Xcode is NOT included with Devbox. You must install it separately from the Mac App Store.** -**Option B: Install via Command Line (Advanced users)** -1. Open **Terminal** (you can find it in Applications → Utilities → Terminal) -2. Type this command and press Enter: - ```bash - xcode-select --install - ``` -3. Follow the prompts to install Command Line Tools -4. For the full Xcode app, still use the App Store method above +Xcode is Apple's development environment. It's about 15 GB and takes 30-60 minutes to download and install. + +### Install Xcode Now: + +**1. Open the App Store** + - Look for the **App Store** icon in your dock (blue icon with a white "A") + - Or click the Apple menu (top-left) → **App Store** -**Verify Xcode is installed:** -Open Terminal and type: +**2. Search and Install** + - In the App Store, search for **"Xcode"** + - Click **Get** or **Install** (it's free) + - Enter your Apple ID password if prompted + - Wait for it to download and install (30-60 minutes depending on internet speed) + +**3. Open Xcode Once** + - After installation, open Xcode from your Applications folder + - Click **Agree** when you see the license agreement + - Wait for additional components to install (a few minutes) + - You can close Xcode after this + +### Verify Xcode Installation: + +**Open Terminal:** +- Press `Command (⌘) + Space` +- Type "Terminal" and press Enter +- A window with black text will open + +**Check if Xcode is installed:** + +Copy this command, paste it into Terminal, and press Enter: ```bash xcodebuild -version ``` -You should see output like: +**✅ Success looks like:** ``` Xcode 16.2 Build version 16B5109o ``` -If you see an error, Xcode isn't installed correctly. - -### Step 3: Install Devbox +**❌ If you see an error:** +- Make sure Xcode finished installing completely +- Open Xcode once to accept the license +- Run this command to set it up: + ```bash + sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer + ``` +- Enter your Mac password when prompted -Devbox creates isolated development environments so everyone gets the exact same tools and versions. +--- -**Installation steps:** -1. Open Terminal (Applications → Utilities → Terminal) -2. Copy and paste this command, then press Enter: - ```bash - curl -fsSL https://get.jetify.com/devbox | bash - ``` -3. Wait for the installation to complete (this takes 1-2 minutes) -4. Close and reopen your Terminal window (important!) -5. Verify installation by typing: - ```bash - devbox version - ``` - -You should see a version number like `0.15.0` or similar. +## Step 3: Install Devbox -**If you see "command not found":** -- Make sure you closed and reopened Terminal after installation -- Try opening a brand new Terminal window -- Check that the installer completed without errors +Devbox manages iOS simulators and build tools, but **it requires Xcode to be installed first** (from Step 2). -**What is Devbox?** -Devbox is a tool that ensures everyone uses the same development environment. Think of it as a recipe that sets up all the tools you need automatically, in an isolated way that won't mess with other projects on your computer. +### Install Devbox Now: -### Step 4: Clone or Download This Repository +**1. Terminal Should Already Be Open** (from verifying Xcode above) + - If not: Press `Command (⌘) + Space`, type "Terminal", press Enter -If you haven't already, you need to get the mobile-devtools code on your computer. +**2. Run the Installation Command** -**Option A: Clone with Git (if you have Git installed)** +Copy this entire line, paste it into Terminal, and press Enter: ```bash -git clone https://github.com/segment-integrations/mobile-devtools.git -cd mobile-devtools/examples/repro/swift +curl -fsSL https://get.jetify.com/devbox | bash ``` -**Option B: Download as ZIP** -1. Go to https://github.com/segment-integrations/mobile-devtools -2. Click the green **Code** button -3. Click **Download ZIP** -4. Unzip the file -5. Open Terminal and navigate to the folder: - ```bash - cd ~/Downloads/mobile-devtools-main/examples/repro/swift - ``` - (Adjust the path if you saved it somewhere else) +You'll see text scrolling as it installs. Takes about 1-2 minutes. -**Verify you're in the right directory:** -Type this in Terminal: +**3. Close and Reopen Terminal (CRITICAL!)** + - Click **Terminal** menu → **Quit Terminal** + - Press `Command (⌘) + Space`, type "Terminal", press Enter again + - This step is required for Devbox to work! + +### Verify Devbox Installation: + +In the new Terminal window, type this and press Enter: ```bash -ls +devbox version ``` -You should see files like `README.md`, `devbox.json`, and an `ios` folder. +**✅ Success looks like:** +``` +0.15.0 +``` + +**❌ If you see "command not found":** +- Did you close and reopen Terminal? (Most common issue!) +- Quit Terminal completely (Command + Q) and open a fresh window +- If still broken, re-run the curl command from step 2 above + +--- -## Quick Start - Running the App +## Step 4: Download the Code -Now that everything is installed, let's run the example app. This will automatically set up the environment, build the app, boot a simulator, and launch it. +### Download Now: -**Step 1: Open Terminal and navigate to the Swift example directory** +**1. Download the Repository** + - Go to: https://github.com/segment-integrations/mobile-devtools + - Click the green **Code** button + - Click **Download ZIP** + - Wait for download to complete (file will be in your Downloads folder) + +**2. Unzip the File** + - Go to your Downloads folder + - Double-click `mobile-devtools-main.zip` + - You'll see a new folder: `mobile-devtools-main` + +**3. Navigate to the Swift Example in Terminal** + +Copy and paste this into Terminal and press Enter: +```bash +cd ~/Downloads/mobile-devtools-main/examples/repro/swift +``` + +**If you saved it somewhere else:** Replace `~/Downloads` with the actual folder location. + +### Verify You're in the Right Place: + +Type this and press Enter: ```bash -cd path/to/mobile-devtools/examples/repro/swift +ls +``` + +**✅ You should see:** ``` +Config.example.swift +README.md +devbox.json +ios/ +ios.xcodeproj/ +scripts/ +tests/ +``` + +If you see these files, you're ready to run the app! ✅ + +--- -Replace `path/to/mobile-devtools` with the actual location where you downloaded or cloned the repository. +## Quick Start - Run the App -**Step 2: Run the app** -Type this command and press Enter: +You're now in the Swift example directory with Xcode and Devbox installed. Let's run it! + +### Run the App Now: + +Copy this command and paste it into Terminal, then press Enter: ```bash devbox run --pure start:app ``` -**What happens when you run this command:** -1. Devbox creates an isolated environment with all necessary tools -2. It builds the iOS app from source code -3. It starts an iOS simulator (a virtual iPhone on your Mac) -4. It installs and launches the app on that simulator +### What Happens Next: + +**First time (slow - 5-10 minutes):** +- Devbox sets up the environment +- Downloads iOS simulators +- Builds the app +- Launches iPhone simulator +- Installs and opens the app + +**After first time (fast - 1-2 minutes):** +- Just builds and launches + +**You'll see:** +- Lots of text scrolling in Terminal (that's normal!) +- An iPhone simulator window will open +- The app will launch with buttons you can tap + +### When the App Launches: + +You'll see an iPhone screen with: +- **Track Event** button - Tap to send an event +- **Identify User** button - Tap to identify a user +- **Track Screen** button - Tap to track a screen view +- **Amplitude Toggle** - Switch to enable Amplitude destination + +**Watch Terminal for Event Logs:** +When you tap buttons, Terminal will show: +``` +📊 Track Event: Button Pressed + Properties: {"button": "Track Event", "count": 1} +``` + +**Congratulations!** 🎉 You're now running the Swift repro example! + +--- + +## What Does `--pure` Mean? -**How long does this take?** -- First time: 5-10 minutes (it downloads and sets up everything) -- After that: 1-2 minutes (much faster!) +The `--pure` flag tells Devbox to use a completely isolated environment with no interference from other tools on your Mac. This ensures everyone sees the same behavior. **What you should see:** - Terminal will show build progress messages From 50617e86047018df50c987d275ddcf27e4d5d50f Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:11:36 -0500 Subject: [PATCH 06/16] docs(repro): clarify Xcode must be installed separately from Devbox - Added clear statement that Xcode is NOT included with Devbox - Split prerequisites into two explicit steps (Xcode, then Devbox) - Added inline Xcode installation instructions - Emphasized Terminal restart requirement after Devbox install - Added note that Devbox requires Xcode for iOS examples --- examples/repro/README.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index e2dcc85..8303d37 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -66,17 +66,31 @@ Use these examples to: ## Prerequisites -The only requirement is [Devbox](https://www.jetify.com/devbox/docs/installing_devbox/): +**You need TWO things installed:** + +1. **Xcode** (macOS only) - Required for iOS examples. **NOT included with Devbox - install separately from App Store.** +2. **Devbox** - Handles SDKs, simulators, and other dependencies. + +### Install Xcode (for iOS examples) + +- Open the Mac App Store +- Search for "Xcode" and install (free, ~15 GB, takes 30-60 min) +- Open Xcode once to accept the license +- Verify: `xcodebuild -version` + +### Install Devbox ```bash # macOS/Linux curl -fsSL https://get.jetify.com/devbox | bash +# IMPORTANT: Close and reopen Terminal after installation! + # Verify installation devbox version ``` -Devbox handles all other dependencies (Xcode, SDKs, simulators, etc.). +**Note:** Devbox handles simulators and build tools, but requires Xcode for iOS development. ## General Workflow From dd445428818fc60b393da18253f07aa876407369 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:16:30 -0500 Subject: [PATCH 07/16] docs(repro): remove duplication between main and Swift READMEs REFACTORING: - Main README: SDK-agnostic, process-oriented (purpose, sharing, workflow) - Swift README: Swift-specific setup guide (Xcode, Devbox, running app) Changes to main README (examples/repro/README.md): - Rewrote to be SDK-agnostic and conceptual - Expanded Purpose section with clear audience goals - Made Workflow section conceptual (not specific commands) - Kept full Sharing section with complete workflow - Added quick links to Swift README sections (Prerequisites, Quick Start, etc.) Changes to Swift README (examples/repro/swift/README.md): - Removed entire 188-line Sharing section (duplicated from main) - Updated Step 6 to link to main README for sharing instructions - Kept Swift-specific content (Xcode/Devbox, plugins, troubleshooting) Result: 188 lines removed, clear separation of concerns --- examples/repro/README.md | 337 ++++++++++++++------------------- examples/repro/swift/README.md | 193 +------------------ 2 files changed, 147 insertions(+), 383 deletions(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index 8303d37..07e2068 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -1,6 +1,6 @@ # Bug Reproduction Examples -This directory contains pre-configured, minimal apps for reproducing Segment SDK issues. These examples are designed for customer support, CSMs, and developers who need to quickly reproduce and diagnose bugs. +Pre-configured, minimal apps for reproducing Segment SDK issues. These examples help customer support, CSMs, and engineers quickly reproduce and diagnose bugs in a consistent environment. ## Available Examples @@ -8,148 +8,124 @@ This directory contains pre-configured, minimal apps for reproducing Segment SDK Fully-configured iOS app for reproducing Segment Analytics Swift SDK issues. -**What's included:** -- Segment Analytics Swift SDK (v1.6.2+) -- Amplitude destination plugin (v1.2.0+) -- ConsoleLogger custom plugin for debugging -- Interactive UI with track, identify, and screen buttons -- Gitignored config file for API keys -- Project-local build isolation +**Includes:** Amplitude destination, ConsoleLogger, interactive UI -**Quick start:** -```bash -cd swift -devbox run --pure start:app -``` +**Quick links:** +- [Prerequisites & Installation](./swift/README.md#prerequisites-and-installation) - Installing Xcode and Devbox +- [Quick Start](./swift/README.md#quick-start---run-the-app) - Running the app +- [Creating Bug Reproductions](./swift/README.md#how-to-create-bug-reproductions) - Workflow for reproducing issues +- [Full Documentation](./swift/README.md) - Complete guide ## Purpose -These examples serve multiple audiences: - ### For Customer Support and CSMs -When a customer reports a bug, you can: -1. Modify the example to match the customer's use case -2. Run `devbox run --pure start:app` to reproduce the issue -3. Share the reproduction with engineering -4. Test fixes across different SDK versions +When a customer reports a bug: +1. Use an example that matches their SDK (Swift, Android, React Native) +2. Modify the code to replicate their exact use case +3. Run the reproduction to confirm the issue +4. Share the packaged reproduction with engineering (one command!) +5. Test fixes across different SDK versions -No Xcode configuration needed. No manual simulator setup. Just run the command. +No need to set up development environments from scratch - everything is pre-configured. ### For Customers -Customers can use these as templates when reporting issues: +Use these examples as templates when reporting issues: 1. Clone this repository -2. Modify the example to demonstrate their bug -3. Share the modified code with support -4. Everyone sees the same behavior (reproducible environment) +2. Modify the example to demonstrate the bug +3. Share it with support +4. Everyone sees identical behavior (reproducible environment) + +This eliminates "works on my machine" problems. ### For Engineering -Use these examples to: - Validate bug reports with exact reproduction steps - Test fixes across different SDK versions - Create regression tests -- Verify behavior across iOS/Android platforms +- Verify behavior is consistent across platforms ## Why Devbox? -**Reproducibility:** Everyone runs the exact same toolchain (Xcode, SDKs, simulators). No "works on my machine" problems. +**Reproducibility:** Everyone runs the exact same toolchain. No "works on my machine" problems. -**Isolation:** Each example has its own build directory and configuration. No global state pollution. +**Isolation:** Each example has its own build directory and configuration. Multiple reproductions can coexist without conflicts. -**Speed:** CSMs and support engineers can reproduce issues in seconds, without manual Xcode installation or simulator setup. +**Speed:** Run reproductions in minutes without manual environment setup. **Consistency:** CI, developers, and support all use identical environments. -**Simplicity:** One command (`devbox run --pure start:app`) builds and launches the app. No prerequisite knowledge required. - -## Prerequisites - -**You need TWO things installed:** - -1. **Xcode** (macOS only) - Required for iOS examples. **NOT included with Devbox - install separately from App Store.** -2. **Devbox** - Handles SDKs, simulators, and other dependencies. - -### Install Xcode (for iOS examples) - -- Open the Mac App Store -- Search for "Xcode" and install (free, ~15 GB, takes 30-60 min) -- Open Xcode once to accept the license -- Verify: `xcodebuild -version` - -### Install Devbox - -```bash -# macOS/Linux -curl -fsSL https://get.jetify.com/devbox | bash - -# IMPORTANT: Close and reopen Terminal after installation! - -# Verify installation -devbox version -``` - -**Note:** Devbox handles simulators and build tools, but requires Xcode for iOS development. +**Simplicity:** One command (`devbox run --pure start:app`) to build and launch. ## General Workflow -### 1. Start with a Clean Example +This is the conceptual workflow for using any reproduction example. See the specific example's README for detailed commands. -```bash -cd swift # or another example -devbox run --pure build:clean -``` +### 1. Choose an Example -### 2. Configure for the Customer +Pick the example matching the customer's SDK: +- `swift/` - iOS apps using Analytics Swift SDK +- (Future: `android/`, `react-native/`, etc.) -Update the config file with customer-specific details: -```bash -# Swift example -cp Config.example.swift ios/Config.swift -# Edit ios/Config.swift with customer's write key -``` +### 2. Set Up Your Environment + +Each example's README has specific installation instructions. Generally you need: +- Platform tools (Xcode for iOS, Android Studio for Android, etc.) +- Devbox (handles SDKs, simulators, dependencies) ### 3. Modify the Code Update the example to match the customer's issue: -- Change event names -- Adjust properties -- Add/remove plugins - Replicate their SDK configuration +- Use their event names and properties +- Add/remove plugins they're using +- Match their SDK version ### 4. Reproduce the Issue +Run the example and observe the behavior: ```bash devbox run --pure start:app ``` -Watch the console output for debugging information. +Watch console output for debugging information. The examples include logging plugins that show exactly what's being sent to Segment. ### 5. Test Across SDK Versions -Each example includes package managers (SPM for Swift, Gradle for Android) that let you test different SDK versions: -- Update the version in the package configuration -- Rebuild and retest +Change the SDK version in the package configuration and rebuild: - Identify when the bug was introduced +- Verify fixes work across versions +- Test with customer's exact SDK version ### 6. Share the Reproduction -Use the built-in share command to package your reproduction: +Package everything for sharing using the built-in share command: ```bash devbox run share ``` -**What it does:** -- ✅ Auto-commits your changes (no Git knowledge needed!) -- ✅ Creates a zip file with everything needed to reproduce -- ✅ Names file with commit hash + timestamp for easy identification -- ✅ Excludes build artifacts (keeps file size small) -- ✅ Includes setup instructions (REPRO-INFO.txt) -- ✅ Shows you exactly where the file is saved +This automatically: +- ✅ Commits your changes (no Git knowledge needed) +- ✅ Creates a zip archive with timestamp and commit hash +- ✅ Excludes build artifacts (keeps file small) +- ✅ Includes setup instructions +- ✅ Shows where the file is saved - ✅ Copies path to clipboard (macOS) -**Example output:** +## Sharing Reproductions + +Every example includes a `share` command that packages reproductions for easy sharing via Jira, email, or Slack. + +### Quick Share + +```bash +cd swift # or another example +# Make your changes to reproduce the issue +devbox run share +``` + +**Output:** ``` ✅ Archive created successfully! @@ -165,156 +141,131 @@ Next Steps: 3️⃣ Or post to Slack: Drag into your message ``` -**Uploading to Jira:** -1. Open the Jira issue -2. Click **Attach** or drag the zip file onto the page -3. Add a comment: - ``` - Reproduction case attached (commit: a1b2c3d) - - Changes made: - - Modified identify call to match customer setup - - Using SDK version 1.6.2 - - To run: Extract and run "devbox run --pure start:app" - ``` - -**Sharing via Email/Slack:** -Just attach or drag the zip file and mention the commit hash from the output. - -The recipient can extract the zip and immediately run `devbox run --pure start:app` - everything is included! - -**Manual sharing (if needed):** -If the share command isn't available, you can still share manually: -```bash -git add . -git commit -m "Reproduce: customer issue description" -git format-patch -1 HEAD --stdout > repro.patch -``` -Then share the patch file. - -## What Makes These Examples Special - -**Minimal:** Only the essential code to demonstrate SDK functionality. No clutter, no distractions. - -**Interactive:** UI buttons to trigger SDK methods. Immediate feedback via console logging. - -**Secure:** API keys stored in gitignored config files. Safe to commit reproductions without exposing credentials. - -**Isolated:** Project-local build artifacts. Multiple reproductions can coexist without conflicts. - -**Debuggable:** Custom plugins log all SDK activity to the console. See exactly what's being sent to Segment. - -**Pure Mode:** The `--pure` flag ensures a clean environment with no inherited state from your system. - -**Easy Sharing:** Built-in `share` command packages reproductions for Jira, email, or Slack - no Git knowledge required. - -## Sharing Made Easy - -All reproduction examples include a `share` command that makes it trivial to package and share reproductions, even for non-technical team members. - -### How It Works - -```bash -cd swift # or any other example -# Make your changes to reproduce the issue -devbox run share -``` - -The share command automatically: -1. **Commits changes** - No need to know Git commands -2. **Creates archive** - Zip file with meaningful name (commit-hash-timestamp) -3. **Excludes bloat** - No build artifacts, only source code -4. **Adds instructions** - Includes REPRO-INFO.txt with setup steps -5. **Shows location** - Tells you exactly where the file is -6. **Copies path** - Clipboard integration on macOS - ### What's In The Archive -Each shared reproduction package contains: +Each package contains: - All source code showing the issue -- Project configuration (devbox.json, Xcode project, etc.) -- Device/simulator definitions -- **REPRO-INFO.txt** - Instructions for running the reproduction -- **changes.patch** - Git patch showing exactly what was modified +- Project configuration (devbox.json, etc.) +- Setup instructions (REPRO-INFO.txt) +- Git patch showing your exact changes -The archive excludes: +Excludes: - Build artifacts (DerivedData, build/, etc.) -- Git history (.git/) -- Devbox cache (.devbox/) -- Node modules, Pods, etc. +- Git history +- Devbox cache +- Dependencies (node_modules, Pods, etc.) -This keeps files small (typically 2-5 MB) while including everything needed to run the reproduction. +Files are typically 2-5 MB - small enough to attach anywhere. -### Where To Share +### How to Share -**Jira (Primary Method):** -1. Drag the zip file onto the Jira issue -2. Add a comment with the commit hash -3. Describe what you changed +**Jira (Recommended):** +1. Open the Jira issue +2. Drag the zip file onto the issue page +3. Add a comment: + ``` + Reproduction attached (commit: a1b2c3d) + + Changes: Modified identify call to match customer setup + SDK version: 1.6.2 + + To run: Extract and run "devbox run --pure start:app" + ``` **Email:** - Attach the zip file -- Mention commit hash in email body -- CC relevant team members +- Include the commit hash in your message +- Describe what you changed **Slack:** -- Drag zip into relevant channel +- Drag the zip into the relevant channel - Include Jira issue link - Brief description of the issue ### For Recipients -Anyone receiving a shared reproduction can: +Anyone receiving a reproduction can run it immediately: + ```bash -# Extract the zip file +# Extract unzip swift-repro-a1b2c3d-20260422-143052.zip cd swift-repro-a1b2c3d-20260422-143052 -# Install devbox if needed +# Install Devbox if needed (one-time) curl -fsSL https://get.jetify.com/devbox | bash -# Run the reproduction +# Run devbox run --pure start:app ``` -Everything is included and ready to run. No setup needed. +Everything needed is included. No manual setup required. + +## What Makes These Examples Special + +**Minimal:** Only the essential code to demonstrate SDK functionality. No clutter. + +**Interactive:** UI buttons trigger SDK methods. Immediate visual feedback. + +**Secure:** API keys in gitignored files. Safe to commit reproductions without exposing credentials. + +**Isolated:** Project-local build artifacts. Multiple reproductions coexist without conflicts. + +**Debuggable:** Custom logging plugins show all SDK activity in the console. + +**Pure Environment:** The `--pure` flag ensures clean, isolated execution with no system interference. + +**One-Command Sharing:** Built-in `share` command packages reproductions - no Git knowledge required. ## Adding New Examples When adding a new platform or SDK: -1. Create a new directory (e.g., `android/`, `react-native/`) -2. Include the mobile-devtools plugin (`devbox.json`) -3. Add interactive UI with basic SDK operations -4. Include a custom logging plugin for debugging +**Required Structure:** +1. Create directory: `examples/repro/{platform}/` +2. Include mobile-devtools plugin in `devbox.json` +3. Add interactive UI with basic SDK operations (track, identify, screen, etc.) +4. Include custom logging plugin for console debugging 5. Use gitignored config files for API keys 6. Configure project-local build output -7. Add `scripts/share.sh` for easy sharing -8. Add `share` command to `devbox.json` scripts -9. Document the quick start workflow +7. Add `scripts/share.sh` (copy from Swift example) +8. Add `share` command to `devbox.json` scripts section + +**Required Documentation:** +- `README.md` with platform-specific setup instructions +- Prerequisites (platform tools + Devbox) +- Quick start guide +- Troubleshooting section + +**Follow the Swift example pattern** - it demonstrates the complete structure. + +## Getting Started + +1. **Choose your example:** Go to the example directory for your SDK (e.g., `cd swift`) +2. **Follow that README:** Each example has complete, platform-specific setup instructions +3. **Run the app:** Usually just `devbox run --pure start:app` +4. **Make changes:** Modify code to reproduce the customer issue +5. **Share it:** Run `devbox run share` and upload to Jira -Follow the pattern established by the Swift example. +Each example's README is self-contained with everything you need. -## Support and Issues +## Support and Resources -**For these reproduction examples:** -- Open an issue in this repository -- Tag with `reproduction-examples` +**For reproduction examples:** +- Issues: [mobile-devtools issues](https://github.com/segment-integrations/mobile-devtools/issues) +- Tag: `reproduction-examples` **For Segment SDK bugs:** -- Use the reproductions from this directory -- Open issues in the respective SDK repositories -- Include a link to your reproduction branch +- Create reproduction using these examples +- Open issue in SDK repository +- Attach reproduction zip file -**For Devbox issues:** -- Check the [Devbox documentation](https://www.jetify.com/devbox/docs/) -- Open issues in the [Devbox repository](https://github.com/jetify-com/devbox) +**For Devbox:** +- [Devbox Documentation](https://www.jetify.com/devbox/docs/) +- [Devbox Repository](https://github.com/jetify-com/devbox) ## Related Resources - [iOS Plugin Reference](../../plugins/ios/REFERENCE.md) - [Android Plugin Reference](../../plugins/android/REFERENCE.md) - [React Native Plugin Reference](../../plugins/react-native/REFERENCE.md) -- [Devbox Documentation](https://www.jetify.com/devbox) - [Segment Analytics Swift SDK](https://github.com/segmentio/analytics-swift) diff --git a/examples/repro/swift/README.md b/examples/repro/swift/README.md index 6dbf450..c910c90 100644 --- a/examples/repro/swift/README.md +++ b/examples/repro/swift/README.md @@ -459,203 +459,16 @@ To test if the bug exists in different versions of the SDK: 5. Click the version number and select a different version to test 6. Click **Done**, then rebuild: `devbox run --pure build` -### Step 6: Share Your Reproduction - -Once you've reproduced the bug, use the built-in share command to package everything for sharing: - -```bash -devbox run share -``` - -This automatically commits your changes, creates a zip file, and tells you where to find it. See the **Sharing Reproductions** section below for complete details on uploading to Jira or sharing with the team. - -## Sharing Reproductions -After you've reproduced a customer issue, you need to share it with the engineering team. The `share` command makes this easy, even if you're not familiar with Git. +### Step 6: Share Your Reproduction -### Quick Share (Recommended) +Once you've reproduced the bug, package it for sharing: -Just run this command: ```bash devbox run share ``` -**What it does:** -1. ✅ Automatically commits any changes you made -2. ✅ Creates a zip file with everything needed to reproduce the issue -3. ✅ Names the file with a unique identifier (commit hash + timestamp) -4. ✅ Excludes unnecessary files (build artifacts, etc.) to keep it small -5. ✅ Shows you exactly where the zip file is located -6. ✅ Copies the file path to your clipboard (on macOS) - -**What you'll see:** -``` -📦 Swift Repro Share Tool - -Repository: /Users/you/mobile-devtools -Repro directory: examples/repro/swift - -Found uncommitted changes: -M ios/ContentView.swift - -Committing changes... -✓ Changes committed - -Creating archive... - Name: swift-repro-a1b2c3d-20260422-143052.zip - -✅ Archive created successfully! - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -Archive Details: - Name: swift-repro-a1b2c3d-20260422-143052.zip - Size: 2.3M - Location: /Users/you/mobile-devtools/shared-repros/swift-repro-a1b2c3d-20260422-143052.zip - Commit: a1b2c3d -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Next Steps: -1️⃣ Locate the file: - Open Finder and navigate to: - ~/mobile-devtools/shared-repros/swift-repro-a1b2c3d-20260422-143052.zip - -2️⃣ Upload to Jira: - • Open the Jira issue in your browser - • Click 'Attach' or drag the zip file onto the issue - • Add a comment describing what you changed - -3️⃣ Or share via email: - • Attach the zip file to your email - • Mention the commit hash: a1b2c3d -``` - -### Uploading to Jira (Step-by-Step) - -Once you have the zip file, here's how to attach it to a Jira issue: - -**Step 1: Locate the zip file** -The share command tells you exactly where the file is. On macOS, it's copied to your clipboard, so you can just paste it into Finder's "Go to Folder" (Command+Shift+G). - -Or navigate manually: -1. Open **Finder** -2. Press **Command+Shift+G** (Go to Folder) -3. Paste or type: `~/mobile-devtools/shared-repros` -4. Press Enter -5. Find your zip file (it has today's date in the name) - -**Step 2: Open the Jira issue** -1. Go to your Jira instance (e.g., `yourcompany.atlassian.net`) -2. Find and open the customer's issue -3. Make sure you're looking at the issue details page - -**Step 3: Attach the file** - -**Option A: Drag and drop (easiest)** -1. Drag the zip file from Finder -2. Drop it onto the Jira issue page -3. Wait for the upload to complete - -**Option B: Use the attach button** -1. Look for the **Attach** button or paperclip icon (usually at the top or bottom of the issue) -2. Click it -3. Select your zip file from the file picker -4. Click **Open** or **Choose** -5. Wait for the upload to complete - -**Step 4: Add a comment** -Always add a comment explaining what you did: - -``` -Attached reproduction case for the reported SDK issue. - -What I changed: -- Modified ContentView.swift to replicate customer's identify call -- Used customer's exact user ID format -- Testing with SDK version 1.6.2 - -To run: -1. Extract the zip file -2. cd into the directory -3. Run: devbox run --pure start:app -4. Tap "Identify User" to reproduce the issue - -The issue reproduces consistently - check Terminal output for details. -``` - -**Step 5: Notify the team** -Mention relevant team members in the comment using `@username` so they get notified. - -### Sharing via Email - -If you need to share via email instead of Jira: - -1. Compose a new email to the Mobile SDK team -2. Attach the zip file -3. In the email body, include: - - Jira issue link - - Brief description of the issue - - What you changed to reproduce it - - The commit hash (from the share command output) - - Instructions: "Extract and run `devbox run --pure start:app`" - -### Sharing via Slack - -For quick sharing with the team: - -1. Open the relevant Slack channel -2. Drag the zip file into the message box -3. Add a message: - ``` - Reproduction for JIRA-123: Customer reports identify not working - - Changes: Modified identify call to match customer's setup - Commit: a1b2c3d - - Extract and run: devbox run --pure start:app - ``` - -### What's Inside the Zip File? - -The share command creates a self-contained reproduction package: - -- **All source code** - The modified Swift files that demonstrate the issue -- **Project files** - Xcode project configuration -- **Device definitions** - Simulator settings -- **Configuration** - devbox.json and plugin setup -- **REPRO-INFO.txt** - Instructions for the person receiving the file -- **changes.patch** - Git patch showing exactly what you modified - -**What's NOT included** (to keep the file small): -- Build artifacts (DerivedData) -- Xcode user data -- Git history -- Devbox cache - -This means the recipient can extract and immediately run `devbox run --pure start:app` to see the issue. - -### Advanced: Manual Sharing (If Share Command Doesn't Work) - -If you need to share manually without the share command: - -```bash -# Clean build artifacts first -devbox run --pure build:clean - -# Commit your changes -git add . -git commit -m "Reproduce: [describe the issue]" - -# Create a patch file -git format-patch -1 HEAD --stdout > my-repro.patch - -# Share the patch file via Jira/email -``` - -The recipient can apply your patch: -```bash -git apply my-repro.patch -devbox run --pure start:app -``` +This command creates a zip file with everything needed. For complete instructions on uploading to Jira, sharing via email, or Slack, see the **[Sharing Reproductions](../README.md#sharing-reproductions)** section in the main repro README. ## Troubleshooting Common Issues From 9dd033273c72d941c11087196a4e74e6c9427811 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:17:52 -0500 Subject: [PATCH 08/16] docs(repro): make documentation role-agnostic Remove all role-specific language (CSM, customer, support, engineering). Focus on 'you' and 'your issue' regardless of reader's role. Changes: - Purpose section: No more 'For CSMs', 'For Customers', 'For Engineering' - New focus: Why/when to use reproductions, benefits - Workflow: 'your issue' instead of 'customer's issue' - Sharing: 'Issue Tracker' instead of 'Jira', generic language - Swift README: 'you encounter' vs 'customer reports' - Swift README: 'your use case' vs 'their use case' Result: Documentation works for anyone trying to reproduce an issue (library users, customers reporting bugs, support teams, engineers) --- examples/repro/swift/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/repro/swift/README.md b/examples/repro/swift/README.md index c910c90..1d030ae 100644 --- a/examples/repro/swift/README.md +++ b/examples/repro/swift/README.md @@ -1,6 +1,6 @@ # Segment Swift Bug Reproduction Example -This is a ready-to-use iOS app for reproducing and debugging issues with the Segment Analytics Swift SDK. If a customer reports a bug or unexpected behavior, you can use this example to quickly replicate and investigate the issue. +A ready-to-use iOS app for reproducing and debugging issues with the Segment Analytics Swift SDK. Use this to demonstrate bugs, test unexpected behavior, or create minimal reproductions for issue reports. ## What This Example Provides @@ -404,7 +404,7 @@ Build succeeded ## How to Create Bug Reproductions -When a customer reports a bug with the Segment SDK, here's how to reproduce it using this example: +When you encounter a bug with the Segment SDK, here's how to create a reproduction using this example: ### Step 1: Start Fresh @@ -414,24 +414,24 @@ cd examples/repro/swift devbox run --pure build:clean ``` -### Step 2: Replicate Customer Setup +### Step 2: Configure the SDK -If the customer is using their own write key, update `ios/Config.swift` with their key (get permission first!). +Update `ios/Config.swift` with your Segment write key if needed (to see events in your debugger). -### Step 3: Modify the Code to Match Their Use Case +### Step 3: Modify the Code to Match Your Use Case -Open `ios/ContentView.swift` in a text editor (you can use Xcode, VS Code, or any editor). Find the function that relates to the customer's issue and modify it. +Open `ios/ContentView.swift` in a text editor (you can use Xcode, VS Code, or any editor). Find the function that relates to the issue and modify it. -For example, if a customer reports that identify isn't working: +For example, if you're seeing an issue with identify: ```swift private func identifyUser() { - // Change this to match exactly what the customer is doing + // Change this to match exactly what you're doing analytics.identify( - userId: "their-user-id", + userId: "your-user-id", traits: [ - "name": "Their Name", - "email": "their@email.com" + "name": "Your Name", + "email": "your@email.com" ] ) } @@ -468,7 +468,7 @@ Once you've reproduced the bug, package it for sharing: devbox run share ``` -This command creates a zip file with everything needed. For complete instructions on uploading to Jira, sharing via email, or Slack, see the **[Sharing Reproductions](../README.md#sharing-reproductions)** section in the main repro README. +This command creates a zip file with everything needed. For complete instructions on uploading to issue trackers, sharing via email, or chat, see the **[Sharing Reproductions](../README.md#sharing-reproductions)** section in the main repro README. ## Troubleshooting Common Issues From f7a3ac598ddf8b8e2f7cf579afb534e2cd051930 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:18:09 -0500 Subject: [PATCH 09/16] docs(repro): make main README role-agnostic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - 'customer support, CSMs, and engineers' → 'you' - 'Demonstrate the issue clearly' → 'Demonstrate issues clearly' Consistent with Swift README changes to make docs work for anyone. --- examples/repro/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index 07e2068..2dfdc4e 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -1,6 +1,6 @@ # Bug Reproduction Examples -Pre-configured, minimal apps for reproducing Segment SDK issues. These examples help customer support, CSMs, and engineers quickly reproduce and diagnose bugs in a consistent environment. +Pre-configured, minimal apps for reproducing Segment SDK issues. These examples help you reproduce and diagnose bugs in a consistent, isolated environment. ## Available Examples From 020451ead89bb2ec6a0881d3fc79b2676037829d Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:18:37 -0500 Subject: [PATCH 10/16] docs(repro): complete role-agnostic refactor of main README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced role-specific sections with generic purpose and workflow: REMOVED: - 'For Customer Support and CSMs' section - 'For Customers' section - 'For Engineering' section REPLACED WITH: - Clear 'Why use a reproduction example' bullets - 'When to use these' scenarios - Generic workflow using 'you' and 'your issue' UPDATED: - All references to 'customer' → 'you' - 'their SDK' → 'your SDK' - 'customer's issue' → 'your issue' - 'Jira' → 'Issue Tracker' Result: Documentation works for anyone (library users, bug reporters, support teams, engineers) without assuming organizational role. --- examples/repro/README.md | 50 +++++++++++----------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index 2dfdc4e..aafacd6 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -18,47 +18,23 @@ Fully-configured iOS app for reproducing Segment Analytics Swift SDK issues. ## Purpose -### For Customer Support and CSMs +These examples help you reproduce and demonstrate Segment SDK issues in a consistent, isolated environment. -When a customer reports a bug: -1. Use an example that matches their SDK (Swift, Android, React Native) -2. Modify the code to replicate their exact use case -3. Run the reproduction to confirm the issue -4. Share the packaged reproduction with engineering (one command!) -5. Test fixes across different SDK versions +**Why use a reproduction example?** -No need to set up development environments from scratch - everything is pre-configured. +- **Demonstrate issues clearly:** Show exactly what's happening with minimal code +- **Ensure reproducibility:** Everyone sees the same behavior, eliminating "works on my machine" problems +- **Speed up resolution:** Isolated examples help identify root causes faster +- **Test across versions:** Easily verify when a bug was introduced or if a fix works +- **Share easily:** Package everything into a zip file with one command -### For Customers +**When to use these:** -Use these examples as templates when reporting issues: -1. Clone this repository -2. Modify the example to demonstrate the bug -3. Share it with support -4. Everyone sees identical behavior (reproducible environment) - -This eliminates "works on my machine" problems. - -### For Engineering - -- Validate bug reports with exact reproduction steps -- Test fixes across different SDK versions -- Create regression tests -- Verify behavior is consistent across platforms - -## Why Devbox? - -**Reproducibility:** Everyone runs the exact same toolchain. No "works on my machine" problems. - -**Isolation:** Each example has its own build directory and configuration. Multiple reproductions can coexist without conflicts. - -**Speed:** Run reproductions in minutes without manual environment setup. - -**Consistency:** CI, developers, and support all use identical environments. - -**Simplicity:** One command (`devbox run --pure start:app`) to build and launch. - -## General Workflow +- You've found a bug in a Segment SDK +- You need to demonstrate unexpected behavior +- You're reporting an issue and want to provide a reproduction +- You want to test SDK behavior across different versions +- You need a minimal example to isolate a problem This is the conceptual workflow for using any reproduction example. See the specific example's README for detailed commands. From b1a355631d65d8b5405b874a3800d88efd355d38 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:34:30 -0500 Subject: [PATCH 11/16] docs(repro): simplify examples list and add default write key - Simplify Available Examples section to clean list format - Add production write key to Config.example.swift for usage tracking - Update comments to clarify events help improve the project Co-Authored-By: Claude Opus 4.6 --- examples/repro/README.md | 12 +----------- examples/repro/swift/Config.example.swift | 7 ++++--- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index aafacd6..545e97a 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -4,17 +4,7 @@ Pre-configured, minimal apps for reproducing Segment SDK issues. These examples ## Available Examples -### [Swift/iOS](./swift/) - -Fully-configured iOS app for reproducing Segment Analytics Swift SDK issues. - -**Includes:** Amplitude destination, ConsoleLogger, interactive UI - -**Quick links:** -- [Prerequisites & Installation](./swift/README.md#prerequisites-and-installation) - Installing Xcode and Devbox -- [Quick Start](./swift/README.md#quick-start---run-the-app) - Running the app -- [Creating Bug Reproductions](./swift/README.md#how-to-create-bug-reproductions) - Workflow for reproducing issues -- [Full Documentation](./swift/README.md) - Complete guide +- [Swift/iOS](./swift/README.md) - Fully-configured iOS app for reproducing Segment Analytics Swift SDK issues ## Purpose diff --git a/examples/repro/swift/Config.example.swift b/examples/repro/swift/Config.example.swift index 5545045..07613ac 100644 --- a/examples/repro/swift/Config.example.swift +++ b/examples/repro/swift/Config.example.swift @@ -8,7 +8,8 @@ import Foundation enum Config { - /// Your Segment write key from https://app.segment.com - /// Get your write key: Sources → Your iOS Source → Settings → API Keys - static let segmentWriteKey = "YOUR_WRITE_KEY_HERE" + /// Segment write key for demo tracking + /// Events from this example are tracked to help improve the mobile-devtools project + /// You can replace this with your own write key from https://app.segment.com + static let segmentWriteKey = "Ci34OUnJa5OwlryHkkWGk0pNQ07uijWW" } From a0c2aa9034b5314d00c22f7b1d39b6a0ca1ae4f7 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:35:16 -0500 Subject: [PATCH 12/16] docs(repro): revert to placeholder write key Keep write key as placeholder to avoid potential confusion. Co-Authored-By: Claude Opus 4.6 --- examples/repro/swift/Config.example.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/repro/swift/Config.example.swift b/examples/repro/swift/Config.example.swift index 07613ac..5545045 100644 --- a/examples/repro/swift/Config.example.swift +++ b/examples/repro/swift/Config.example.swift @@ -8,8 +8,7 @@ import Foundation enum Config { - /// Segment write key for demo tracking - /// Events from this example are tracked to help improve the mobile-devtools project - /// You can replace this with your own write key from https://app.segment.com - static let segmentWriteKey = "Ci34OUnJa5OwlryHkkWGk0pNQ07uijWW" + /// Your Segment write key from https://app.segment.com + /// Get your write key: Sources → Your iOS Source → Settings → API Keys + static let segmentWriteKey = "YOUR_WRITE_KEY_HERE" } From c4aa8fd794ad32a14f53a15e63d5eb3023c6874a Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:37:55 -0500 Subject: [PATCH 13/16] Repro: Swift SDK reproduction case - 2026-04-22 16:37:55 Auto-committed by share.sh for reproduction sharing. Changes include modifications to demonstrate customer issue. Co-Authored-By: Share Script --- examples/repro/swift/devbox.lock | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/examples/repro/swift/devbox.lock b/examples/repro/swift/devbox.lock index 082ee73..a26c665 100644 --- a/examples/repro/swift/devbox.lock +++ b/examples/repro/swift/devbox.lock @@ -684,6 +684,102 @@ "store_path": "/nix/store/c7fywarscr5c07bxgd6d5g0isn0ijysz-process-compose-1.90.0" } } + }, + "rsync@latest": { + "last_modified": "2026-04-16T08:46:55Z", + "resolved": "github:NixOS/nixpkgs/b86751bc4085f48661017fa226dee99fab6c651b#rsync", + "source": "devbox-search", + "version": "3.4.1", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/q39r4xfp8vqnyn1pmdml038k60asxhyg-rsync-3.4.1", + "default": true + } + ], + "store_path": "/nix/store/q39r4xfp8vqnyn1pmdml038k60asxhyg-rsync-3.4.1" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/4qi0siq0csw6kmss8vbsgc5bg2x2iv1k-rsync-3.4.1", + "default": true + } + ], + "store_path": "/nix/store/4qi0siq0csw6kmss8vbsgc5bg2x2iv1k-rsync-3.4.1" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/2pmx9fn2wyrlqd5hwp9m751218i5s7my-rsync-3.4.1", + "default": true + } + ], + "store_path": "/nix/store/2pmx9fn2wyrlqd5hwp9m751218i5s7my-rsync-3.4.1" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/rqxr17iaips1kfs65q2z6wczh2m4kwlm-rsync-3.4.1", + "default": true + } + ], + "store_path": "/nix/store/rqxr17iaips1kfs65q2z6wczh2m4kwlm-rsync-3.4.1" + } + } + }, + "zip@latest": { + "last_modified": "2026-04-16T08:46:55Z", + "resolved": "github:NixOS/nixpkgs/b86751bc4085f48661017fa226dee99fab6c651b#zip", + "source": "devbox-search", + "version": "3.0", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/cvymyyay5ik73gssz0s42qy6nx44mk6w-zip-3.0", + "default": true + } + ], + "store_path": "/nix/store/cvymyyay5ik73gssz0s42qy6nx44mk6w-zip-3.0" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/ynz8cp00bh3cm4asvjn3yc0b0qafvi65-zip-3.0", + "default": true + } + ], + "store_path": "/nix/store/ynz8cp00bh3cm4asvjn3yc0b0qafvi65-zip-3.0" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/3wx5g5jsnls3any0p0r19v5jhvdi3f1w-zip-3.0", + "default": true + } + ], + "store_path": "/nix/store/3wx5g5jsnls3any0p0r19v5jhvdi3f1w-zip-3.0" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/chqyzmw0g42i2v9r4lf38azn73w8lhd0-zip-3.0", + "default": true + } + ], + "store_path": "/nix/store/chqyzmw0g42i2v9r4lf38azn73w8lhd0-zip-3.0" + } + } } } } From f4a7545376b3261a7101e8793dc0744d20f1e927 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 16:40:26 -0500 Subject: [PATCH 14/16] docs(repro): make share instructions platform-agnostic - Remove commit hash from output (already in filename) - Change "drag and drop" to "attach" for platform neutrality - Simplify sharing instructions - Remove redundant information Co-Authored-By: Claude Opus 4.6 --- examples/repro/README.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/examples/repro/README.md b/examples/repro/README.md index 545e97a..daebe97 100644 --- a/examples/repro/README.md +++ b/examples/repro/README.md @@ -99,12 +99,11 @@ Archive Details: Name: swift-repro-a1b2c3d-20260422-143052.zip Size: 2.3M Location: ~/mobile-devtools/shared-repros/swift-repro-a1b2c3d-20260422-143052.zip - Commit: a1b2c3d Next Steps: -1️⃣ Upload to Jira: Drag and drop the zip onto the issue +1️⃣ Upload to Jira: Attach the zip file to the issue 2️⃣ Or share via email: Attach the zip file -3️⃣ Or post to Slack: Drag into your message +3️⃣ Or post to Slack: Upload the file to your message ``` ### What's In The Archive @@ -127,11 +126,9 @@ Files are typically 2-5 MB - small enough to attach anywhere. **Jira (Recommended):** 1. Open the Jira issue -2. Drag the zip file onto the issue page -3. Add a comment: +2. Attach the zip file to the issue +3. Add a comment describing what you changed: ``` - Reproduction attached (commit: a1b2c3d) - Changes: Modified identify call to match customer setup SDK version: 1.6.2 @@ -140,13 +137,11 @@ Files are typically 2-5 MB - small enough to attach anywhere. **Email:** - Attach the zip file -- Include the commit hash in your message - Describe what you changed **Slack:** -- Drag the zip into the relevant channel -- Include Jira issue link -- Brief description of the issue +- Upload the zip file to the relevant channel +- Include Jira issue link if applicable ### For Recipients From 43c3fd62393de7770e0f2772c76f150948d0c1ee Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 17:14:39 -0500 Subject: [PATCH 15/16] fix(swift-repro): include Config.swift and disable event flushing Make the swift repro example work out of the box without requiring users to create Config.swift manually. Events are queued locally but not sent to Segment (flushAt set to 1000, flushInterval to 0). Changes: - Remove Config.swift from gitignore - Replace Config.example.swift with ios/Config.swift containing demo key - Disable automatic event flushing in ContentView.swift Co-Authored-By: Claude Opus 4.6 --- examples/repro/swift/.gitignore | 3 --- examples/repro/swift/Config.example.swift | 14 -------------- examples/repro/swift/ios/Config.swift | 15 +++++++++++++++ examples/repro/swift/ios/ContentView.swift | 6 ++++-- 4 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 examples/repro/swift/Config.example.swift create mode 100644 examples/repro/swift/ios/Config.swift diff --git a/examples/repro/swift/.gitignore b/examples/repro/swift/.gitignore index 4a945d6..cf33bba 100644 --- a/examples/repro/swift/.gitignore +++ b/examples/repro/swift/.gitignore @@ -9,6 +9,3 @@ DerivedData/ *.moved-aside *.xccheckout *.xcscmblueprint - -# Segment configuration (contains write keys) -ios/Config.swift diff --git a/examples/repro/swift/Config.example.swift b/examples/repro/swift/Config.example.swift deleted file mode 100644 index 5545045..0000000 --- a/examples/repro/swift/Config.example.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Config.example.swift -// ios -// -// Example configuration file - copy this to Config.swift and add your keys -// - -import Foundation - -enum Config { - /// Your Segment write key from https://app.segment.com - /// Get your write key: Sources → Your iOS Source → Settings → API Keys - static let segmentWriteKey = "YOUR_WRITE_KEY_HERE" -} diff --git a/examples/repro/swift/ios/Config.swift b/examples/repro/swift/ios/Config.swift new file mode 100644 index 0000000..835d3f2 --- /dev/null +++ b/examples/repro/swift/ios/Config.swift @@ -0,0 +1,15 @@ +// +// Config.swift +// ios +// +// Demo configuration - events are queued but not sent (flushAt disabled) +// + +import Foundation + +enum Config { + /// Demo write key - events are queued locally but not sent to Segment + /// To send real events, replace with your write key from https://app.segment.com + /// Get your write key: Sources → Your iOS Source → Settings → API Keys + static let segmentWriteKey = "demo_write_key_not_real" +} diff --git a/examples/repro/swift/ios/ContentView.swift b/examples/repro/swift/ios/ContentView.swift index f77a4e2..796b967 100644 --- a/examples/repro/swift/ios/ContentView.swift +++ b/examples/repro/swift/ios/ContentView.swift @@ -18,9 +18,11 @@ struct ContentView: View { private let amplitudePlugin = AmplitudeSession() init() { - // Initialize Segment Analytics + // Initialize Segment Analytics with demo configuration + // Events are queued locally but not sent (flushAt disabled) let configuration = Configuration(writeKey: Config.segmentWriteKey) - .flushInterval(10) + .flushAt(1000) // Only flush after 1000 events (effectively disabled) + .flushInterval(0) // Disable time-based flushing self.analytics = Analytics(configuration: configuration) From 443a3c058d2ad0a9fe9d01a9d54947be0b78b940 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Wed, 22 Apr 2026 17:17:13 -0500 Subject: [PATCH 16/16] fix(swift-repro): enable event flushing when real write key is used Make event flushing conditional based on whether a real write key is configured: - Demo mode: Events queued locally, flushing disabled (flushAt=1000, flushInterval=0) - Live mode: Normal event flushing enabled (flushInterval=10) Changes: - Add Config.isUsingDemoKey property to detect placeholder keys - Conditionally configure Analytics based on key type - Add mode indicator to startup logs This allows the example to work out of the box with demo key while still supporting real event transmission when users add their own key. Co-Authored-By: Claude Opus 4.6 --- examples/repro/swift/ios/Config.swift | 14 ++++++++++---- examples/repro/swift/ios/ContentView.swift | 18 +++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/examples/repro/swift/ios/Config.swift b/examples/repro/swift/ios/Config.swift index 835d3f2..77df950 100644 --- a/examples/repro/swift/ios/Config.swift +++ b/examples/repro/swift/ios/Config.swift @@ -2,14 +2,20 @@ // Config.swift // ios // -// Demo configuration - events are queued but not sent (flushAt disabled) +// Demo configuration - replace write key to send real events // import Foundation enum Config { - /// Demo write key - events are queued locally but not sent to Segment - /// To send real events, replace with your write key from https://app.segment.com - /// Get your write key: Sources → Your iOS Source → Settings → API Keys + /// Demo write key - replace with your real write key to send events to Segment + /// Get your write key: https://app.segment.com → Sources → Your iOS Source → Settings → API Keys static let segmentWriteKey = "demo_write_key_not_real" + + /// Check if using demo/placeholder key + static var isUsingDemoKey: Bool { + segmentWriteKey.isEmpty || + segmentWriteKey == "demo_write_key_not_real" || + segmentWriteKey == "YOUR_WRITE_KEY_HERE" + } } diff --git a/examples/repro/swift/ios/ContentView.swift b/examples/repro/swift/ios/ContentView.swift index 796b967..0324eb2 100644 --- a/examples/repro/swift/ios/ContentView.swift +++ b/examples/repro/swift/ios/ContentView.swift @@ -18,11 +18,18 @@ struct ContentView: View { private let amplitudePlugin = AmplitudeSession() init() { - // Initialize Segment Analytics with demo configuration - // Events are queued locally but not sent (flushAt disabled) - let configuration = Configuration(writeKey: Config.segmentWriteKey) - .flushAt(1000) // Only flush after 1000 events (effectively disabled) - .flushInterval(0) // Disable time-based flushing + // Initialize Segment Analytics + var configuration = Configuration(writeKey: Config.segmentWriteKey) + + // Disable flushing when using demo key to avoid errors + if Config.isUsingDemoKey { + configuration = configuration + .flushAt(1000) // Only flush after 1000 events (effectively disabled) + .flushInterval(0) // Disable time-based flushing + } else { + configuration = configuration + .flushInterval(10) // Normal flush interval + } self.analytics = Analytics(configuration: configuration) @@ -34,6 +41,7 @@ struct ContentView: View { print("🚀 Segment Analytics initialized") print(" Write Key: \(Config.segmentWriteKey)") + print(" Mode: \(Config.isUsingDemoKey ? "Demo (events queued locally)" : "Live (sending to Segment)")") print(" Plugins: ConsoleLogger, IDFA, Amplitude (toggleable)") }