Skip to content
C.W.K.
Stream
Lesson 07 of 07 · published

From Processed to Installed: Reading the Last Three Facts

~14 min · testflight, app-store-connect, internal-testing, verification, reporting

Level 0Bundle Opener
0 XP0/81 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete
"Say which one is true."

Fact Two: Apple Has Processed It

An upload is only the start of App Store Connect's work. The build has to be processed before it appears for testing, and App Store Connect sends an email when that finishes. This is also where the late refusals from the gate lesson surface: an ITMS notice arrives by email about a build whose upload line was green. And a build whose export-compliance question is unanswered waits in App Store Connect until someone answers it, which is why family apps declare ITSAppUsesNonExemptEncryption in their Info.plist. Until the email or the TestFlight page says processed, fact two is unknown, whatever the log says.

Fact Three: The Group Has It

Internal testers belong to groups. When a group is created with Enable automatic distribution, builds uploaded from Xcode tooling go to every member of that group on their own; without it, every build must be added to the group by hand, and a build that nobody added is processed and still unreachable. The group's build list is where fact three is read. Family apps use one internal group each with automatic distribution on, so fact three normally follows fact two within minutes, but it is still checked rather than assumed.

Fact Four: It Is on the Device

App Store Connect's tester list shows a status per tester: Invited, Accepted, and Installed, which means the tester downloaded the build. The most direct reading is the device itself. Family phone apps show their marketing version and build number in settings, read from the running app's Info.plist, so "installed" is a number seen on the phone, not a conclusion drawn from a green pipeline. The TestFlight app on the device can install updates automatically when the tester has that turned on, and until it does, the old build keeps running.

Installed is delivery of the app. It is not always delivery of the change. When a client change depends on a new engine route, the engine at home has to be restarted as well, or the newly installed app meets an older engine, which is exactly how a correct capture came to be parked with "Method Not Allowed".

Writing the Report

A delivery report lists the four facts with evidence for each and a status line that names the highest fact actually verified. It does not say "shipped" when it means uploaded, and it does not say "on the phone" when it means assigned. A build becomes untestable 90 days after upload, so a long-running tester needs a fresh upload before then, even when nothing in the app has changed.

Code

Show the installed version and build in the app, so fact four is read rather than inferred·swift
import Foundation
import SwiftUI

/// What is installed, read from the running app. "Installed" is checked here, never inferred.
struct BuildIdentity: Equatable, Sendable {
    let version: String   // CFBundleShortVersionString, e.g. 1.4.0
    let build: String     // CFBundleVersion, e.g. 42: the number the pipeline committed

    init(info: [String: Any]) {
        version = info["CFBundleShortVersionString"] as? String ?? "unknown"
        build = info["CFBundleVersion"] as? String ?? "unknown"
    }

    init(bundle: Bundle = .main) {
        self.init(info: bundle.infoDictionary ?? [:])
    }

    var label: String { "\(version) (\(build))" }
}

struct AboutSection: View {
    private let identity = BuildIdentity()

    var body: some View {
        Section("About") {
            LabeledContent("Version", value: identity.label)
        }
    }
}
A delivery report that names the highest verified fact·text
Spark iOS, build 42 (source 3f2c9e1)

  1 uploaded    yes   SPARK_MOBILE_UPLOAD_OK at 14:02, export gate passed
  2 processed   yes   App Store Connect email at 14:19, no ITMS notice so far
  3 assigned    yes   internal group "Family" lists build 42 (automatic distribution on)
  4 installed   no    iPhone About still shows 1.4.0 (41); iPad not checked

Status: processed and assigned, NOT delivered. Next check: the iPhone's About row.

External links

Exercise

Add BuildIdentity and an About section to SparkMobile, then upload one build and follow it through all four facts, writing the report as you go with a time and a piece of evidence for each line. Stop at the first fact you cannot verify and write the status line for that moment. Then, when the device updates, finish the report with the About row's reading.
Hint
Keep BuildIdentity(info:) separate from Bundle.main so a unit test can pass a dictionary in. If fact three never arrives, open the internal group and check whether automatic distribution is on before suspecting the upload.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.