parent
7f023b3830
commit
32f23ff295
|
@ -0,0 +1,70 @@
|
|||
name: "TestFlight ⚙️"
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [testflight]
|
||||
|
||||
jobs:
|
||||
test_build:
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: git Checkout
|
||||
if: ${{ github.event.client_payload.hasCheckoutCommit }}
|
||||
run: |
|
||||
git checkout ${{ github.event.client_payload.commitSHA }}
|
||||
|
||||
- run: 'echo "$SSH_KEY" > key'
|
||||
shell: bash
|
||||
env:
|
||||
SSH_KEY: ${{secrets.P12_PASSWORD}}
|
||||
|
||||
- name: Install the Apple certificate and provisioning profile
|
||||
env:
|
||||
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
|
||||
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
|
||||
KEYCHAIN_PASSWORD: "CI_PASSWORD"
|
||||
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
# import certificate and provisioning profile from secrets
|
||||
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
|
||||
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
|
||||
|
||||
# create temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
|
||||
# import certificate to keychain
|
||||
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
# apply provisioning profile
|
||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||
sudo mkdir -p /Library/MobileDevice/Provisioning\ Profiles
|
||||
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
|
||||
sudo cp $PP_PATH /Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
- name: Build and Upload to TestFlight
|
||||
run: sudo fastlane testFlightLane \
|
||||
keyID:${{ secrets.APP_STORE_KEY_ID }} \
|
||||
issuerID:${{ secrets.APP_STORE_ISSUER_ID }} \
|
||||
keyContents:${{ secrets.APP_STORE_KEY_CONTENTS }} \
|
||||
scheme:${{ github.event.client_payload.scheme }} \
|
||||
codeSign64:${{ secrets.CODE_SIGN_64 }} \
|
||||
profileName64:${{ secrets.PROFILE_NAME_64 }} \
|
||||
xcodeVersion:${{ github.event.client_payload.xcodeVersion }} \
|
||||
build:${{ github.event.client_payload.build }} \
|
||||
version:${{ github.event.client_payload.version }}
|
|
@ -63,6 +63,82 @@ class Fastfile: LaneFile {
|
|||
)
|
||||
}
|
||||
|
||||
// MARK: TestFlight
|
||||
|
||||
// TODO: verify tvOS
|
||||
func testFlightLane(withOptions options: [String: String]?) {
|
||||
|
||||
guard let options,
|
||||
let keyID = options["keyID"],
|
||||
let issuerID = options["issuerID"],
|
||||
let keyContents = options["keyContents"],
|
||||
let scheme = options["scheme"],
|
||||
let codeSign64 = options["codeSign64"],
|
||||
let profileName64 = options["profileName64"]
|
||||
else {
|
||||
puts(message: "ERROR: missing or incorrect options")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
guard let decodedCodeSignIdentity = decodeBase64(encoded: codeSign64) else {
|
||||
puts(message: "ERROR: code sign identity not valid base 64")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
guard let profileName = decodeBase64(encoded: profileName64) else {
|
||||
puts(message: "ERROR: profile name not valid base 64")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
if let xcodeVersion = options["xcodeVersion"] {
|
||||
xcodes(version: xcodeVersion)
|
||||
}
|
||||
|
||||
appStoreConnectApiKey(
|
||||
keyId: keyID,
|
||||
issuerId: .userDefined(issuerID),
|
||||
keyContent: .userDefined(keyContents),
|
||||
isKeyContentBase64: true,
|
||||
duration: 1200,
|
||||
inHouse: false
|
||||
)
|
||||
|
||||
updateCodeSigningSettings(
|
||||
path: "Swiftfin.xcodeproj",
|
||||
useAutomaticSigning: false,
|
||||
codeSignIdentity: .userDefined(decodedCodeSignIdentity),
|
||||
profileName: .userDefined(profileName)
|
||||
)
|
||||
|
||||
if let version = options["version"] {
|
||||
incrementVersionNumber(
|
||||
versionNumber: .userDefined(version),
|
||||
xcodeproj: "Swiftfin.xcodeproj"
|
||||
)
|
||||
}
|
||||
|
||||
if let build = options["build"] {
|
||||
incrementBuildNumber(
|
||||
buildNumber: .userDefined(build),
|
||||
xcodeproj: "Swiftfin.xcodeproj"
|
||||
)
|
||||
} else {
|
||||
incrementBuildNumber(
|
||||
xcodeproj: "Swiftfin.xcodeproj"
|
||||
)
|
||||
}
|
||||
|
||||
buildApp(
|
||||
scheme: .userDefined(scheme),
|
||||
skipArchive: .userDefined(false),
|
||||
skipProfileDetection: false
|
||||
)
|
||||
|
||||
uploadToTestflight(
|
||||
ipa: "Swiftfin.ipa"
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: Utilities
|
||||
|
||||
private func decodeBase64(encoded: String) -> String? {
|
||||
|
|
|
@ -95,7 +95,7 @@ public protocol DeliverfileProtocol: AnyObject {
|
|||
/// Path to the app rating's config
|
||||
var appRatingConfigPath: String? { get }
|
||||
|
||||
/// Extra information for the submission (e.g. compliance specifications, IDFA settings)
|
||||
/// Extra information for the submission (e.g. compliance specifications)
|
||||
var submissionInformation: [String: Any]? { get }
|
||||
|
||||
/// The ID of your App Store Connect team if you're in multiple teams
|
||||
|
@ -272,4 +272,4 @@ public extension DeliverfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.124]
|
||||
// FastlaneRunnerAPIVersion [0.9.127]
|
||||
|
|
|
@ -190,7 +190,7 @@ public func appStoreBuildNumber(apiKeyPath: OptionalConfigValue<String?> = .fast
|
|||
|
||||
- parameters:
|
||||
- keyId: The key ID
|
||||
- issuerId: The issuer ID
|
||||
- issuerId: The issuer ID. It can be nil if the key is individual API key
|
||||
- keyFilepath: The path to the key p8 file
|
||||
- keyContent: The content of the key p8 file
|
||||
- isKeyContentBase64: Whether :key_content is Base64 encoded or not
|
||||
|
@ -201,7 +201,7 @@ public func appStoreBuildNumber(apiKeyPath: OptionalConfigValue<String?> = .fast
|
|||
Load the App Store Connect API token to use in other fastlane tools and actions
|
||||
*/
|
||||
public func appStoreConnectApiKey(keyId: String,
|
||||
issuerId: String,
|
||||
issuerId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
keyFilepath: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
keyContent: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
isKeyContentBase64: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
||||
|
@ -210,7 +210,7 @@ public func appStoreConnectApiKey(keyId: String,
|
|||
setSpaceshipToken: OptionalConfigValue<Bool> = .fastlaneDefault(true))
|
||||
{
|
||||
let keyIdArg = RubyCommand.Argument(name: "key_id", value: keyId, type: nil)
|
||||
let issuerIdArg = RubyCommand.Argument(name: "issuer_id", value: issuerId, type: nil)
|
||||
let issuerIdArg = issuerId.asRubyArgument(name: "issuer_id", type: nil)
|
||||
let keyFilepathArg = keyFilepath.asRubyArgument(name: "key_filepath", type: nil)
|
||||
let keyContentArg = keyContent.asRubyArgument(name: "key_content", type: nil)
|
||||
let isKeyContentBase64Arg = isKeyContentBase64.asRubyArgument(name: "is_key_content_base64", type: nil)
|
||||
|
@ -674,7 +674,7 @@ public func appledoc(input: [String],
|
|||
- resetRatings: Reset the summary rating when you release a new version of the application
|
||||
- priceTier: The price tier of this application
|
||||
- appRatingConfigPath: Path to the app rating's config
|
||||
- submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings)
|
||||
- submissionInformation: Extra information for the submission (e.g. compliance specifications)
|
||||
- teamId: The ID of your App Store Connect team if you're in multiple teams
|
||||
- teamName: The name of your App Store Connect team if you're in multiple teams
|
||||
- devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID!
|
||||
|
@ -3714,7 +3714,7 @@ public func deleteKeychain(name: OptionalConfigValue<String?> = .fastlaneDefault
|
|||
- resetRatings: Reset the summary rating when you release a new version of the application
|
||||
- priceTier: The price tier of this application
|
||||
- appRatingConfigPath: Path to the app rating's config
|
||||
- submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings)
|
||||
- submissionInformation: Extra information for the submission (e.g. compliance specifications)
|
||||
- teamId: The ID of your App Store Connect team if you're in multiple teams
|
||||
- teamName: The name of your App Store Connect team if you're in multiple teams
|
||||
- devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID!
|
||||
|
@ -4096,7 +4096,7 @@ public func downloadAppPrivacyDetailsFromAppStore(username: String,
|
|||
- appIdentifier: The bundle identifier of your app
|
||||
- teamId: The ID of your App Store Connect team if you're in multiple teams
|
||||
- teamName: The name of your App Store Connect team if you're in multiple teams
|
||||
- platform: The app platform for dSYMs you wish to download (ios, appletvos)
|
||||
- platform: The app platform for dSYMs you wish to download (ios, xros, appletvos)
|
||||
- version: The app version for dSYMs you wish to download, pass in 'latest' to download only the latest build's dSYMs or 'live' to download only the live version dSYMs
|
||||
- buildNumber: The app build_number for dSYMs you wish to download
|
||||
- minVersion: The minimum app version for dSYMs you wish to download
|
||||
|
@ -9707,7 +9707,7 @@ public func setBuildNumberRepository(useHgRevisionNumber: OptionalConfigValue<Bo
|
|||
- changelog: Changelog text that should be uploaded to App Store Connect
|
||||
- teamId: The ID of your App Store Connect team if you're in multiple teams
|
||||
- teamName: The name of your App Store Connect team if you're in multiple teams
|
||||
- platform: The platform of the app (ios, appletvos, mac)
|
||||
- platform: The platform of the app (ios, appletvos, xros, mac)
|
||||
|
||||
This is useful if you have only one changelog for all languages.
|
||||
You can store the changelog in `./changelog.txt` and it will automatically get loaded from there. This integration is useful if you support e.g. 10 languages and want to use the same "What's new"-text for all languages.
|
||||
|
@ -10938,6 +10938,7 @@ public func splunkmint(dsym: OptionalConfigValue<String?> = .fastlaneDefault(nil
|
|||
- xcprettyOutput: Specifies the output type for xcpretty. eg. 'test', or 'simple'
|
||||
- xcprettyArgs: Pass in xcpretty additional command line arguments (e.g. '--test --no-color' or '--tap --no-utf'), requires xcpretty_output to be specified also
|
||||
- verbose: Increase verbosity of informational output
|
||||
- veryVerbose: Increase verbosity to include debug output
|
||||
- simulator: Specifies the simulator to pass for Swift Compiler (one of: iphonesimulator, macosx)
|
||||
- simulatorArch: Specifies the architecture of the simulator to pass for Swift Compiler (one of: x86_64, arm64). Requires the simulator option to be specified also, otherwise, it's ignored
|
||||
*/
|
||||
|
@ -10953,6 +10954,7 @@ public func spm(command: String = "build",
|
|||
xcprettyOutput: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
xcprettyArgs: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
verbose: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
||||
veryVerbose: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
||||
simulator: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
simulatorArch: String = "arm64")
|
||||
{
|
||||
|
@ -10968,6 +10970,7 @@ public func spm(command: String = "build",
|
|||
let xcprettyOutputArg = xcprettyOutput.asRubyArgument(name: "xcpretty_output", type: nil)
|
||||
let xcprettyArgsArg = xcprettyArgs.asRubyArgument(name: "xcpretty_args", type: nil)
|
||||
let verboseArg = verbose.asRubyArgument(name: "verbose", type: nil)
|
||||
let veryVerboseArg = veryVerbose.asRubyArgument(name: "very_verbose", type: nil)
|
||||
let simulatorArg = simulator.asRubyArgument(name: "simulator", type: nil)
|
||||
let simulatorArchArg = RubyCommand.Argument(name: "simulator_arch", value: simulatorArch, type: nil)
|
||||
let array: [RubyCommand.Argument?] = [commandArg,
|
||||
|
@ -10982,6 +10985,7 @@ public func spm(command: String = "build",
|
|||
xcprettyOutputArg,
|
||||
xcprettyArgsArg,
|
||||
verboseArg,
|
||||
veryVerboseArg,
|
||||
simulatorArg,
|
||||
simulatorArchArg]
|
||||
let args: [RubyCommand.Argument] = array
|
||||
|
@ -12536,7 +12540,7 @@ public func uploadSymbolsToSentry(apiHost: String = "https://app.getsentry.com/a
|
|||
- resetRatings: Reset the summary rating when you release a new version of the application
|
||||
- priceTier: The price tier of this application
|
||||
- appRatingConfigPath: Path to the app rating's config
|
||||
- submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings)
|
||||
- submissionInformation: Extra information for the submission (e.g. compliance specifications)
|
||||
- teamId: The ID of your App Store Connect team if you're in multiple teams
|
||||
- teamName: The name of your App Store Connect team if you're in multiple teams
|
||||
- devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID!
|
||||
|
@ -13594,7 +13598,7 @@ public func xcov(workspace: OptionalConfigValue<String?> = .fastlaneDefault(nil)
|
|||
coverallsServiceJobId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
coverallsRepoToken: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
xcconfig: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
||||
ideFoundationPath: String = "/Applications/Xcode-15.3.0.app/Contents/Developer/../Frameworks/IDEFoundation.framework/Versions/A/IDEFoundation",
|
||||
ideFoundationPath: String = "/Applications/Xcode_15.4.app/Contents/Developer/../Frameworks/IDEFoundation.framework/Versions/A/IDEFoundation",
|
||||
legacySupport: OptionalConfigValue<Bool> = .fastlaneDefault(false))
|
||||
{
|
||||
let workspaceArg = workspace.asRubyArgument(name: "workspace", type: nil)
|
||||
|
@ -13797,4 +13801,4 @@ public let snapshotfile: Snapshotfile = .init()
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.177]
|
||||
// FastlaneRunnerAPIVersion [0.9.180]
|
||||
|
|
|
@ -404,6 +404,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.0;
|
||||
|
@ -416,6 +417,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
|
|
|
@ -208,4 +208,4 @@ public extension GymfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.127]
|
||||
// FastlaneRunnerAPIVersion [0.9.130]
|
||||
|
|
|
@ -228,4 +228,4 @@ public extension MatchfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.121]
|
||||
// FastlaneRunnerAPIVersion [0.9.124]
|
||||
|
|
|
@ -52,4 +52,4 @@ public extension PrecheckfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.120]
|
||||
// FastlaneRunnerAPIVersion [0.9.123]
|
||||
|
|
|
@ -320,4 +320,4 @@ public extension ScanfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.132]
|
||||
// FastlaneRunnerAPIVersion [0.9.135]
|
||||
|
|
|
@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.122]
|
||||
// FastlaneRunnerAPIVersion [0.9.125]
|
||||
|
|
|
@ -204,4 +204,4 @@ public extension SnapshotfileProtocol {
|
|||
|
||||
// Please don't remove the lines below
|
||||
// They are used to detect outdated files
|
||||
// FastlaneRunnerAPIVersion [0.9.116]
|
||||
// FastlaneRunnerAPIVersion [0.9.119]
|
||||
|
|
Loading…
Reference in New Issue