Compare commits

...
Author SHA1 Message Date
buzzertandClaude Fable 5 e7b81f24bd ci: put CI keychain first in codesign search list
TestFlight / testflight (push) Failing after 19s
codesign resolves signing identities through the user keychain search
list (first match wins) and ignores --keychain for the lookup. This
runner hosts another project whose keychain holds the same Apple
Distribution identity, so when that keychain is locked, codesign fails
with errSecInternalComponent no matter how correctly our own keychain
is set up. Prepend the fresh CI keychain to the search list for the
build and always delete it afterward, which restores the original list.

Also drop the runner-diagnostics step, the GitHub-hosted Ruby PATH
export, and the duplicate CODE_SIGN_IDENTITY param.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 13:01:42 -07:00
buzzert 20a310a4b1 ci: use Ruby 3.1 for TestFlight upload
TestFlight / testflight (push) Failing after 46s
2026-07-11 12:01:27 -07:00
buzzert b6859706db ios: simplify CI signing keychain setup
TestFlight / testflight (push) Failing after 25s
2026-07-11 11:55:04 -07:00
buzzert ea148839d3 Revert "ios: pass match keychain to codesign"
This reverts commit a0e410155d.
2026-07-11 11:32:00 -07:00
buzzert a0e410155d ios: pass match keychain to codesign
TestFlight / testflight (push) Failing after 55s
2026-07-11 11:29:10 -07:00
buzzert b5a5d21767 docs: document iOS release workflow 2026-07-11 11:17:05 -07:00
buzzert 0ad96f4f99 ios: center transcript content on iPad
TestFlight / testflight (push) Failing after 52s
2026-07-11 11:15:01 -07:00
6 changed files with 33 additions and 23 deletions
+3 -16
View File
@@ -8,16 +8,11 @@ on:
jobs: jobs:
testflight: testflight:
runs-on: xcode runs-on: macos-arm64
defaults:
run:
shell: bash
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Ruby - name: Setup Ruby
uses: ruby/setup-ruby@v1 uses: ruby/setup-ruby@v1
@@ -27,16 +22,11 @@ jobs:
working-directory: ios working-directory: ios
- name: Install XcodeGen - name: Install XcodeGen
run: | run: command -v xcodegen >/dev/null 2>&1 || brew install xcodegen
set -euo pipefail
if ! command -v xcodegen >/dev/null 2>&1; then
brew install xcodegen
fi
- name: Upload to TestFlight - name: Upload to TestFlight
working-directory: ios working-directory: ios
env: env:
HOME: /var/lib/act_runner
APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }} APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}
@@ -46,7 +36,4 @@ jobs:
SYBIL_BUILD_NUMBER: ${{ github.run_number }} SYBIL_BUILD_NUMBER: ${{ github.run_number }}
FASTLANE_SKIP_UPDATE_CHECK: "1" FASTLANE_SKIP_UPDATE_CHECK: "1"
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: "120" FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: "120"
run: | run: bundle exec fastlane ios beta
export PATH="/Users/runner/hostedtoolcache/Ruby/3.1.7/arm64/bin:${PATH}"
ruby --version
bundle exec fastlane ios beta
+6
View File
@@ -21,6 +21,12 @@ Instructions for work under `/Users/buzzert/src/sybil-2/ios`.
- To choose a screenshot path, run `just screenshot path=build/name.png`. - To choose a screenshot path, run `just screenshot path=build/name.png`.
- The underlying screenshot command is `xcrun simctl io booted screenshot <path>` and requires a booted simulator. - The underlying screenshot command is `xcrun simctl io booted screenshot <path>` and requires a booted simulator.
## Release Workflow
- iOS release tags use the annotated tag namespace `release/ios/vX.Y.Z`; increment from the latest existing `release/ios/v*` tag.
- Tag message convention is `ios: X.Y.Z`, for example `git tag -a release/ios/v1.13.5 -m "ios: 1.13.5"`.
- Push the release commit and tag together with `git push origin <branch> release/ios/vX.Y.Z`.
- Fastlane derives the marketing version from the release tag and stamps `ios/Apps/Sybil/project.yml` during CI, so do not manually bump `MARKETING_VERSION` for normal tagged releases unless explicitly requested.
## App Structure ## App Structure
- App target entry: `/Users/buzzert/src/sybil-2/ios/Apps/Sybil/Sources/SybilApp.swift` - App target entry: `/Users/buzzert/src/sybil-2/ios/Apps/Sybil/Sources/SybilApp.swift`
- Shared iOS app code lives in Swift package: - Shared iOS app code lives in Swift package:
@@ -58,7 +58,8 @@ struct SybilChatTranscriptView: View {
.frame(height: 18 + bottomContentInset) .frame(height: 18 + bottomContentInset)
.id(bottomAnchorID) .id(bottomAnchorID)
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: SybilLayout.webContentMaxWidth, alignment: .leading)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.horizontal, 14) .padding(.horizontal, 14)
.padding(.top, 18 + topContentInset) .padding(.top, 18 + topContentInset)
} }
@@ -98,7 +98,8 @@ struct SybilSearchResultsView: View {
.foregroundStyle(SybilTheme.danger) .foregroundStyle(SybilTheme.danger)
} }
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: SybilLayout.webContentMaxWidth, alignment: .leading)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.horizontal, 14) .padding(.horizontal, 14)
.padding(.top, 20 + topContentInset) .padding(.top, 20 + topContentInset)
.padding(.bottom, 20 + bottomContentInset) .padding(.bottom, 20 + bottomContentInset)
@@ -64,6 +64,10 @@ extension Font {
} }
} }
enum SybilLayout {
static let webContentMaxWidth: CGFloat = 896
}
enum SybilTheme { enum SybilTheme {
static let background = Color(red: 0.02, green: 0.02, blue: 0.05) static let background = Color(red: 0.02, green: 0.02, blue: 0.05)
static let surface = Color(red: 0.05, green: 0.04, blue: 0.10) static let surface = Color(red: 0.05, green: 0.04, blue: 0.10)
+16 -5
View File
@@ -71,9 +71,13 @@ platform :ios do
) )
end end
# CI has no login keychain, so create a dedicated throwaway one for match to # CI signs headlessly, so match needs a fresh unlocked keychain to import
# import the distribution cert into. The runner's launchd job sets # into. codesign resolves identities through the user keychain *search list*
# SessionCreate, so add_to_search_list actually makes it visible to xcodebuild. # (first match wins; the --keychain flag does not restrict the lookup), and
# other projects' keychains on this runner hold the same identity but are
# usually locked — so ours must come first. delete_keychain in the beta
# lane's ensure removes both the keychain and its search-list entry, which
# also keeps our (later locked) copy from shadowing those other projects.
private_lane :prepare_ci_keychain do private_lane :prepare_ci_keychain do
next unless ci? next unless ci?
@@ -83,9 +87,15 @@ platform :ios do
password: CI_KEYCHAIN_PASSWORD, password: CI_KEYCHAIN_PASSWORD,
unlock: true, unlock: true,
timeout: 3600, timeout: 3600,
add_to_search_list: true add_to_search_list: false
) )
others = sh("security list-keychains -d user", log: false)
.scan(/"([^"]+)"/)
.flatten
.reject { |path| path.include?(CI_KEYCHAIN_NAME) }
sh("security list-keychains -d user -s #{([CI_KEYCHAIN_DB_PATH] + others).shelljoin}")
ENV["MATCH_KEYCHAIN_NAME"] = CI_KEYCHAIN_NAME ENV["MATCH_KEYCHAIN_NAME"] = CI_KEYCHAIN_NAME
ENV["MATCH_KEYCHAIN_PASSWORD"] = CI_KEYCHAIN_PASSWORD ENV["MATCH_KEYCHAIN_PASSWORD"] = CI_KEYCHAIN_PASSWORD
end end
@@ -129,7 +139,6 @@ platform :ios do
project: PROJECT_FILE, project: PROJECT_FILE,
scheme: SCHEME, scheme: SCHEME,
export_method: "app-store", export_method: "app-store",
codesigning_identity: "Apple Distribution",
xcargs: [ xcargs: [
"DEVELOPMENT_TEAM=#{TEAM_ID.shellescape}", "DEVELOPMENT_TEAM=#{TEAM_ID.shellescape}",
"CODE_SIGN_STYLE=Manual", "CODE_SIGN_STYLE=Manual",
@@ -149,5 +158,7 @@ platform :ios do
api_key: api_key, api_key: api_key,
skip_waiting_for_build_processing: true skip_waiting_for_build_processing: true
) )
ensure
delete_keychain(name: CI_KEYCHAIN_NAME) if ci? && File.file?(CI_KEYCHAIN_DB_PATH)
end end
end end