Loadbudget

SIGNING

Who signs a build, and why not Release on a laptop?

Binds: code::ios-app-signing

docs/IDENTITY.md holds the registry: the teams, the identifiers, and the identifiers that this product lost. This file points at that one, and it does not repeat it.

Set up a machine

The team comes from one file per machine, which git ignores. Do this once:

  1. Run cp ios-app/Config/Local.xcconfig.example ios-app/Config/Local.xcconfig.
  2. Run just ios-app team. It prints your team identifier.
  3. Write that identifier into ios-app/Config/Local.xcconfig, as DEVELOPMENT_TEAM.
  4. Write your initials into the same file, as DEV_SUFFIX, with a leading dot. Chris uses .kw.
  5. Run just ios-app generate.

Both app targets read both values. A device build of either app signs under an identifier that names you.

Step 4 matters only for a device build. Without your own DEV_SUFFIX, the first developer to build takes com.loadbudget.application.dev, and the second is refused. docs/IDENTITY.md holds the rule that causes this, in section “The suffix per configuration”.

Iwona signs nothing on a laptop

Iwona holds the Apple Developer Program team, and Xcode Cloud signs Release with it. She runs no build herself, and she installs no build from Xcode. Every build reaches her through TestFlight, and ios-app/docs/operations/CD.md states how.

So a Debug build reaches her never. Anything that only a Debug build can do, she cannot do. The export on the About screen ships for that reason: a file of her workouts has no other route off her phone.

When just ios-app team finds no profile

just ios-app team reads the provisioning profiles that Xcode stores, so it fails until Xcode has provisioned once. If it reports no profile, do this:

  1. Run just ios-app open, with the phone connected.
  2. Select the Loadbudget target, tab Signing & Capabilities, and select your Apple Account team.
  3. Xcode creates the certificate and the profile.
  4. Run just ios-app team again.

Settings > Accounts does not show the identifier.

Do not select the team in the target editor

XcodeGen writes the Xcode project from ios-app/project.yml, and .gitignore excludes it. So every just ios-app generate discards a selection made there. It does not touch ios-app/Config/Local.xcconfig.

ios-app/Config/Base.xcconfig holds the default, and it ends with an optional include of ios-app/Config/Local.xcconfig. The include is last, so a local value wins. A build with no local file signs with no team, which is what a simulator build and CI need.

The team reaches Debug only

ios-app/project.yml lists ios-app/Config/Local.xcconfig under configFiles for Debug, and it lists nothing for Release. So xcodebuild -showBuildSettings -configuration Release prints no DEVELOPMENT_TEAM, and Xcode cannot provision Release on a laptop.

That is the point. Automatic signing registers an identifier against whatever team it holds, and a free Personal Team can never release a claim. This product lost three identifiers that way.

Xcode Cloud is unaffected. It passes DEVELOPMENT_TEAM on the xcodebuild command line, so Release signs there and nowhere else.

A paid membership is not needed to run on your own device

Xcode needs a team, and a free Apple Account is one. Xcode calls it a Personal Team.

The profile that a Personal Team issues expires after 7 days. The app then stops opening until you run it from Xcode again.

A device build needs a team that supports HealthKit

ios-app/project.yml writes ios-app/Apps/Loadbudget/Loadbudget.entitlements during just ios-app generate, and .gitignore excludes that file. A simulator build needs no team, and it needs no capability on the identifier.

A device build does. Whether a Personal Team signs a HealthKit app is not established here. Apple lists the capabilities that each membership supports, at Supported capabilities. Read that page before you add another one. When a device build fails to provision, read the build from TestFlight instead.

Xcode lists both teams on a laptop

Xcode signs in with an Apple Account, and not with a role. Xcode on the laptop of Chris signs in as Iwona, the Account Holder, so it lists her team beside the Personal Team.

The key IDEProvisioningTeamByIdentifier in the Xcode preferences holds both, and 5RNUV38S95 reads isFreeProvisioningTeam = 0. That value marks the paid team, and not a free one.

The configuration keeps Release off a laptop, and the team list does not. Section “The team reaches Debug only” holds the mechanism. ios-app/project.yml gives Release no configuration file, so a Release build on a laptop carries no team.

Xcode Cloud signs Release inside the account of the Account Holder.

A device build here still uses a Personal Team and the .dev identifier, because ios-app/Config/Local.xcconfig names that team.

Sources