More bootstrapped build-and-run and test reporting in CI
This commit is contained in:
parent
9cb0c52315
commit
f450668b53
16
.github/workflows/main.yml
vendored
16
.github/workflows/main.yml
vendored
@ -62,26 +62,14 @@ jobs:
|
||||
bundler-cache: true
|
||||
|
||||
- name: Build and Test
|
||||
run: |
|
||||
function formatFailures() {
|
||||
grep '<failure message' fastlane/test_output/report.junit | sed -E "s/^.*<failure message='(.*)'>(.*):([0-9]+)<\/failure>/::error file=\2,line=\3::\1/" | sed -E 's/"/"/g'
|
||||
exit 1
|
||||
}
|
||||
|
||||
bundle exec fastlane scan \
|
||||
--scheme Signal \
|
||||
--output_types junit \
|
||||
--skip_package_dependencies_resolution \
|
||||
--disable_package_automatic_updates \
|
||||
--xcargs '-test-timeouts-enabled YES -maximum-test-execution-time-allowance 300 -default-test-execution-time-allowance 60' \
|
||||
|| formatFailures
|
||||
run: Scripts/build-and-test.sh
|
||||
|
||||
- name: Upload build logs
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: Logs
|
||||
path: ~/Library/Logs/scan
|
||||
path: ~/Library/Logs/Signal-CI
|
||||
|
||||
check_autogenstrings:
|
||||
name: Check if strings file is outdated
|
||||
|
||||
62
Scripts/build-and-test.sh
Executable file
62
Scripts/build-and-test.sh
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
LOG_DIR="$HOME/Library/Logs/Signal-CI"
|
||||
rm -rf "$LOG_DIR"
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
echo
|
||||
echo "Available iOS Simulator runtimes:"
|
||||
xcrun simctl list runtimes
|
||||
|
||||
echo
|
||||
echo "Available iOS Simulators:"
|
||||
xcrun simctl list devices
|
||||
|
||||
LATEST_IOS_RUNTIME=$(
|
||||
xcrun simctl list runtimes -j \
|
||||
| jq -r '.runtimes | map(select(.name | startswith("iOS"))) | sort_by(.version) | last | .identifier'
|
||||
)
|
||||
echo
|
||||
echo "Using latest iOS runtime: $LATEST_IOS_RUNTIME"
|
||||
|
||||
LATEST_IOS_SIM_ID=$(
|
||||
xcrun simctl list devices -j \
|
||||
| jq -r --arg runtime "$LATEST_IOS_RUNTIME" '.devices[$runtime] | first | .udid'
|
||||
)
|
||||
echo
|
||||
echo "Using simulator: $LATEST_IOS_SIM_ID"
|
||||
|
||||
echo
|
||||
set -o pipefail \
|
||||
&& NSUnbufferedIO=YES xcodebuild \
|
||||
-workspace Signal.xcworkspace \
|
||||
-scheme Signal \
|
||||
-destination "platform=iOS Simulator,id=$LATEST_IOS_SIM_ID" \
|
||||
-disableAutomaticPackageResolution \
|
||||
-test-timeouts-enabled YES \
|
||||
-maximum-test-execution-time-allowance 300 \
|
||||
-default-test-execution-time-allowance 60 \
|
||||
-resultBundlePath "$LOG_DIR/TestResult.xcresult" \
|
||||
build test \
|
||||
2>&1 \
|
||||
| tee "$LOG_DIR/Signal-CI.log" \
|
||||
| xcbeautify \
|
||||
--renderer github-actions \
|
||||
--disable-logging \
|
||||
| while IFS= read -r line; do
|
||||
printf '[%s] %s\n' "$(date +%H:%M:%S)" "$line"
|
||||
done
|
||||
|
||||
XCODEBUILD_RESULT_CODE=$?
|
||||
|
||||
xcrun \
|
||||
xcresulttool \
|
||||
get \
|
||||
test-results \
|
||||
summary \
|
||||
--path "$LOG_DIR/TestResult.xcresult" \
|
||||
> "$LOG_DIR/TestResultSummary.json"
|
||||
|
||||
Scripts/parse-xcresult.py "$LOG_DIR/TestResultSummary.json"
|
||||
|
||||
exit $XCODEBUILD_RESULT_CODE
|
||||
56
Scripts/parse-xcresult.py
Executable file
56
Scripts/parse-xcresult.py
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse_xcresult(data):
|
||||
# Calculate duration
|
||||
start_time = data.get("startTime")
|
||||
finish_time = data.get("finishTime")
|
||||
duration = finish_time - start_time if start_time and finish_time else 0
|
||||
|
||||
# Get test counts
|
||||
total = data.get("totalTestCount", 0)
|
||||
passed = data.get("passedTests", 0)
|
||||
failed = data.get("failedTests", 0)
|
||||
|
||||
# Print summary
|
||||
print()
|
||||
print("********")
|
||||
print(f"Ran {total} tests in {duration:.0f} seconds.")
|
||||
print(f"{passed} tests passed.")
|
||||
print(f"{failed} tests failed.")
|
||||
print("********")
|
||||
|
||||
# Print failures if any
|
||||
failures = data.get("testFailures", [])
|
||||
if failures:
|
||||
for failure in failures:
|
||||
print()
|
||||
test_id = failure.get("testIdentifierString", "N/A")
|
||||
error = failure.get("failureText", "N/A")
|
||||
print("Test failed:")
|
||||
print(f" {test_id}")
|
||||
print(f" {error}")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: parse_xcresult.py <path_to_json_file>")
|
||||
sys.exit(1)
|
||||
|
||||
json_file = Path(sys.argv[1])
|
||||
|
||||
try:
|
||||
with open(json_file, "r") as f:
|
||||
data = json.load(f)
|
||||
parse_xcresult(data)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -260,7 +260,6 @@
|
||||
3444E6BB264EDFF300B32E3B /* CVColorOrGradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3444E6BA264EDFF200B32E3B /* CVColorOrGradientView.swift */; };
|
||||
344A761124B366F4009D69A5 /* FlagsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344A761024B366F4009D69A5 /* FlagsViewController.swift */; };
|
||||
344A761324B36C8C009D69A5 /* TestingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344A761224B36C8C009D69A5 /* TestingViewController.swift */; };
|
||||
3452851D26DFD12300824983 /* PaymentsFormatTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3452851C26DFD12300824983 /* PaymentsFormatTest.swift */; };
|
||||
34546F502649989D007C4958 /* ChatColorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34546F4F2649989C007C4958 /* ChatColorViewController.swift */; };
|
||||
345772B6257E4E01001D7D44 /* CVViewStateSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345772B5257E4E01001D7D44 /* CVViewStateSnapshot.swift */; };
|
||||
3457794326828A9A00732869 /* ConversationCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3457794226828A9A00732869 /* ConversationCollectionView.swift */; };
|
||||
@ -4241,7 +4240,6 @@
|
||||
344A761024B366F4009D69A5 /* FlagsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlagsViewController.swift; sourceTree = "<group>"; };
|
||||
344A761224B36C8C009D69A5 /* TestingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestingViewController.swift; sourceTree = "<group>"; };
|
||||
3452851A26DE890300824983 /* DateUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateUtil.swift; sourceTree = "<group>"; };
|
||||
3452851C26DFD12300824983 /* PaymentsFormatTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentsFormatTest.swift; sourceTree = "<group>"; };
|
||||
34546F4F2649989C007C4958 /* ChatColorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatColorViewController.swift; sourceTree = "<group>"; };
|
||||
3456A73123D63EBE00947219 /* GroupsV2Protos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupsV2Protos.swift; sourceTree = "<group>"; };
|
||||
345772B5257E4E01001D7D44 /* CVViewStateSnapshot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CVViewStateSnapshot.swift; sourceTree = "<group>"; };
|
||||
@ -8643,7 +8641,6 @@
|
||||
3471210D25ED5F850037CD1F /* Payments */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3452851C26DFD12300824983 /* PaymentsFormatTest.swift */,
|
||||
3471210E25ED5F850037CD1F /* PaymentsReconciliationTest.swift */,
|
||||
346EFC3025FD050F00F493C7 /* PaymentsTest.swift */,
|
||||
);
|
||||
@ -18403,7 +18400,6 @@
|
||||
4C2A538C23C5462300D28CD8 /* MessageLoaderTest.swift in Sources */,
|
||||
45D062F527D7F49800BD505E /* OWSContactsManagerTest.swift in Sources */,
|
||||
F93461BB291ED2B000366682 /* PaymentDetailsValidityTest.swift in Sources */,
|
||||
3452851D26DFD12300824983 /* PaymentsFormatTest.swift in Sources */,
|
||||
3471211025ED5F910037CD1F /* PaymentsReconciliationTest.swift in Sources */,
|
||||
346EFC3225FD051400F493C7 /* PaymentsTest.swift in Sources */,
|
||||
50791B1D2D037A9800D747F8 /* PhoneNumberCountryTest.swift in Sources */,
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
//
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable import SignalServiceKit
|
||||
@testable import SignalUI
|
||||
|
||||
class PaymentsFormatTest: XCTestCase {
|
||||
|
||||
func test_formatAsFiatCurrency() {
|
||||
let paymentAmount = TSPaymentAmount(currency: .mobileCoin, picoMob: 12345 * PaymentsConstants.picoMobPerMob)
|
||||
let conversionSingle = CurrencyConversionInfo(currencyCode: "ZQ",
|
||||
name: "Fake currency",
|
||||
conversionRate: 1,
|
||||
conversionDate: Date())
|
||||
let conversionDouble = CurrencyConversionInfo(currencyCode: "ZQ",
|
||||
name: "Fake currency",
|
||||
conversionRate: 2,
|
||||
conversionDate: Date())
|
||||
|
||||
do {
|
||||
// USA
|
||||
let locale: Locale = Locale(identifier: "en_US")
|
||||
XCTAssertEqual("12,345.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24,690.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
|
||||
do {
|
||||
// UK
|
||||
//
|
||||
// From: https://en.wikipedia.org/wiki/Decimal_separator#Hindu.E2.80.93Arabic_numeral_system
|
||||
// 1,234,567.89 United Kingdom
|
||||
//
|
||||
// NOTE: The United Kingdom supports multiple ways of formatting currency.
|
||||
let locale: Locale = Locale(identifier: "en_GB")
|
||||
XCTAssertEqual("12,345.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24,690.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
|
||||
do {
|
||||
// France
|
||||
//
|
||||
// From: https://en.wikipedia.org/wiki/Decimal_separator#Hindu.E2.80.93Arabic_numeral_system
|
||||
// 1234567,89 SI style (French version), France
|
||||
//
|
||||
// NOTE: NumberFormatter uses a 'NARROW NO-BREAK SPACE' (U+202F) as a grouping separator.
|
||||
// https://www.fileformat.info/info/unicode/char/202f/index.htm
|
||||
let locale: Locale = Locale(identifier: "fr_FR")
|
||||
XCTAssertEqual("12 345,00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24 690,00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
|
||||
do {
|
||||
// Switzerland (French)
|
||||
//
|
||||
// From: https://en.wikipedia.org/wiki/Decimal_separator#Hindu.E2.80.93Arabic_numeral_system
|
||||
// 1'234'567.89 Switzerland (computing), Liechtenstein.
|
||||
// 1'234'567,89 Switzerland (handwriting), Italy (handwriting).
|
||||
//
|
||||
// NOTE: Swiss formatting depends on the language used.
|
||||
// NOTE: NumberFormatter uses a 'NARROW NO-BREAK SPACE' (U+202F) as a grouping separator.
|
||||
// https://www.fileformat.info/info/unicode/char/202f/index.htm
|
||||
let locale: Locale = Locale(identifier: "fr_CH")
|
||||
XCTAssertEqual("12 345,00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24 690,00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
|
||||
do {
|
||||
// Switzerland (German)
|
||||
//
|
||||
// From: https://en.wikipedia.org/wiki/Decimal_separator#Hindu.E2.80.93Arabic_numeral_system
|
||||
// 1'234'567.89 Switzerland (computing), Liechtenstein.
|
||||
// 1'234'567,89 Switzerland (handwriting), Italy (handwriting).
|
||||
//
|
||||
// NOTE: Swiss formatting depends on the language used.
|
||||
let locale: Locale = Locale(identifier: "de_CH")
|
||||
XCTAssertEqual("12’345.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24’690.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
|
||||
do {
|
||||
// Switzerland (Swiss German)
|
||||
//
|
||||
// From: https://en.wikipedia.org/wiki/Decimal_separator#Hindu.E2.80.93Arabic_numeral_system
|
||||
// 1'234'567.89 Switzerland (computing), Liechtenstein.
|
||||
// 1'234'567,89 Switzerland (handwriting), Italy (handwriting).
|
||||
//
|
||||
// NOTE: Swiss formatting depends on the language used.
|
||||
let locale: Locale = Locale(identifier: "gsw_CH")
|
||||
XCTAssertEqual("12’345.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24’690.00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
|
||||
do {
|
||||
// Germany
|
||||
//
|
||||
// From: https://en.wikipedia.org/wiki/Decimal_separator#Hindu.E2.80.93Arabic_numeral_system
|
||||
// 1.234.567,89 Germany
|
||||
let locale: Locale = Locale(identifier: "de_DE")
|
||||
XCTAssertEqual("12.345,00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionSingle,
|
||||
locale: locale)!)
|
||||
XCTAssertEqual("24.690,00", PaymentsFormat.formatAsFiatCurrency(paymentAmount: paymentAmount,
|
||||
currencyConversionInfo: conversionDouble,
|
||||
locale: locale)!)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user