how can I run tests on codemagic for native ios app? - ios

I am trying to build a CI/CD flow for my app, but I got a problem with the yaml.
I am not getting a good response of codemagic, this is the error:
I have a target in my project named PortfolioTests and my yaml code is this one:
workflows:
develop:
instance_type: mac_mini_m1
environment:
xcode: 14.2
vars:
#BUNDLE_ID: "io.codemagic.sample.iosnative"
XCODE_WORKSPACE: "Portfolio.xcodeproj" # <-- Name of your Xcode workspace
XCODE_SCHEME: "PortfolioTests" # <-- Name of your Xcode scheme
scripts:
- name: say hello
script: echo "Hello Codemagician!"
- name: Run iOS tests
script: |
set -e # exit on first failed command
xcode-project run-tests \
--workspace ${XCODE_WORKSPACE?} \
--scheme ${XCODE_SCHEME?} \
--device "iPhone 12"
#test_report: build/ios/test/*.xml

Can you update your command to
xcode-project run-tests \
--project ${XCODE_WORKSPACE?} \
--scheme ${XCODE_SCHEME?} \
--device "iPhone 12"
instead? As it is a project and not a workspace.

Related

Firebase iOS TestLab failed during validation: The XCTest zip file was malformed

I have created iOS Lane for uploading Flutter integration tests to Firebase TestLab and it fails when trying to run the test. When I upload manually ios_tests.zip file which contains Runner_iphoneos folder and Release_iphoneos15.2-arm64.xctestrun, it pass on TestLab, but when using workflow .yml file in github action, TestLab fails to execute the tests.
Here is the error log for specific failing part:
Uploading [build/ios_integ/Build/Products/ios_tests.zip] to Firebase Test Lab...
Test [matrix-1aenoclku3vww] has been created in the Google Cloud.
Firebase Test Lab will execute your xctest test on 1 device(s).
Creating individual test executions...................failed.
ERROR: (gcloud.firebase.test.ios.run)
Matrix [matrix-1aenoclku3vww] failed during validation: The XCTest zip file was malformed. The zip did not contain a single .xctestrun file and the contents of the DerivedData/Build/Products directory..
So the ios_tests.zip file is uploaded and I can find it in GCS bucket. When I extract it I can find all the files. But when I try to manually upload this file to TestLab it gives the same error. Seems like it is somehow changed in the build or upload process.
Also it is strange that logs say that Matrix [matrix-1aenoclku3vww] is created, but I cannot see it in firebase console in TestLab. Like its not run at all.
This is the .yml script I use, it fails only at "Run Instrumentation Tests in Firebase Test Lab":
name: Firebase_test
on: [workflow_dispatch]
jobs:
iOS_Lane:
name: iOS Lane
runs-on: macos-latest
env:
PROJECT_DIRECTORY: cicd
defaults:
run:
working-directory: ./${{ env.PROJECT_DIRECTORY }}
steps:
- uses: actions/checkout#v3
- uses: actions/setup-java#v2
with:
distribution: "zulu"
java-version: "11"
- uses: subosito/flutter-action#v2
with:
flutter-version: "3.0.2"
- name: Fetching Flutter dependencies
run: flutter pub get
- name: Install the Apple certificate and provisioning profile
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_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 --output $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $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 list-keychain -d user -s $KEYCHAIN_PATH
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- name: Build Firebase debug
run: flutter build ios integration_test/smoke_test.dart --release
- name: Build Firebase build
env:
OUTPUT_PATH: ../build/ios_integ
run: |
pushd ios
xcodebuild clean build -workspace Runner.xcworkspace -scheme Runner -config Flutter/Release.xcconfig -derivedDataPath $OUTPUT_PATH -sdk iphoneos build-for-testing
popd
- name: Zip Firebase build
env:
PRODUCT_PATH: build/ios_integ/Build/Products
DEV_TARGET: 15.2
run: |
pushd $PRODUCT_PATH
zip -r "ios_tests.zip" "Release-iphoneos" "Runner_iphoneos$DEV_TARGET-arm64.xctestrun"
popd
- id: "auth"
uses: "google-github-actions/auth#v0"
with:
credentials_json: "${{ secrets.FIREBASE_SERVICE_JSON }}"
- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud#v0"
- name: "Use gcloud CLI"
run: "gcloud info"
- name: Set current project
run: gcloud config set project ${{ secrets.GCP_PROJECT_ID }}
- name: Run Instrumentation Tests in Firebase Test Lab
env:
ZIP_LOCATION: build/ios_integ/Build/Products/ios_tests.zip
DEVICE_MODEL: iphone13pro,version=15.2,locale=en_US,orientation=portrait
run: gcloud firebase test ios run --test $ZIP_LOCATION --device model=$DEVICE_MODEL --timeout 3m
Thanks in advance!

The following build commands failed: PhaseScriptExecution Run Script in fastlane

when I build the ios project using this command in Flutter in github actions(by the way, using the same command in my local macOS catalina 10.15.7 and xcode 12.3 works fine):
./ios && bundle exec fastlane beta
shows this error:
** ARCHIVE FAILED **
The following build commands failed:
PhaseScriptExecution Run\ Script /Users/runner/Library/Developer/Xcode/DerivedData/Runner-gzzbtgmsqethlzedjqlbspydxjjv/Build/Intermediates.noindex/ArchiveIntermediates/Runner/IntermediateBuildFilesPath/Runner.build/Release-iphoneos/Runner.build/Script-9740EEB61CF901F6004384FC.sh
(1 failure)
[05:17:23]: Exit status: 65
[05:17:23]:
[05:17:23]: Maybe the error shown is caused by using the wrong version of Xcode
[05:17:23]: Found multiple versions of Xcode in '/Applications/'
[05:17:23]: Make sure you selected the right version for your project
[05:17:23]: This build process was executed using '/Applications/Xcode_12.3.app'
[05:17:23]: If you want to update your Xcode path, either
[05:17:23]:
[05:17:23]: - Specify the Xcode version in your Fastfile
[05:17:23]: ▸ xcversion(version: "8.1") # Selects Xcode 8.1.0
[05:17:23]:
[05:17:23]: - Specify an absolute path to your Xcode installation in your Fastfile
[05:17:23]: ▸ xcode_select "/Applications/Xcode8.app"
[05:17:23]:
[05:17:23]: - Manually update the path using
[05:17:23]: ▸ sudo xcode-select -s /Applications/Xcode.app
[05:17:23]:
this is the fastlane, in this script, I specify the xcode version 12.3 :
xcversion(version: "12.3")
xcode_select("/Applications/Xcode_12.3.app")
if is_ci
create_keychain(
name: ENV['MATCH_KEYCHAIN_NAME'],
password: ENV["MATCH_KEYCHAIN_PASSWORD"],
default_keychain: true,
unlock: true,
timeout: 3600,
lock_when_sleeps: false
)
end
where is going wrong and what should I do to fix it? I have tried to execute the commad in github actions, this is my config:
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout#v2
- uses: actions/setup-java#v1
with:
java-version: '12.x'
- uses: subosito/flutter-action#v1
with:
flutter-version: '1.22.5'
- name: Select Xcode version
run: sudo xcode-select -s '/Applications/Xcode_12.3.app/Contents/Developer'
- name: Bundle install
run: cd ./ios && bundle install && bundle update fastlane
- name: Install tools
run: |
flutter precache
flutter pub get
cd ./ios && pod repo update && pod install
#- run: flutter pub get
#- run: flutter build apk
#- run: flutter build ios --release --no-codesign
- name: Setup SSH Keys and known_hosts for fastlane match
run: |
SSH_PATH="$HOME/.ssh"
mkdir -p "$SSH_PATH"
touch "$SSH_PATH/known_hosts"
echo "$PRIVATE_KEY" > "$SSH_PATH/id_rsa"
chmod 700 "$SSH_PATH"
ssh-keyscan github.com >> ~/.ssh/known_hosts
chmod 600 "$SSH_PATH/known_hosts"
chmod 600 "$SSH_PATH/id_rsa"
eval $(ssh-agent)
ssh-add "$SSH_PATH/id_rsa"
env:
PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy to TestFlight/PGY
run: |
cd ./ios && bundle exec fastlane beta
I tried to install new version(1.10.0) of cocopods(the same verion of my local Macbook Pro):
- name: Bundle install
run: cd ./ios && gem install cocoapods -v 1.10.0 && bundle install && bundle update fastlane
and tried to tweak the build type of xcode:
still not work.
Your build log shows the following error:
[05:32:01]: ▸ ../../../hostedtoolcache/flutter/1.22.5-stable/x64/packages/flutter/lib/src/widgets/scroll_view.dart:588:9: Context: Found this candidate, but the arguments don't match.
[05:32:01]: ▸ const CustomScrollView({
[05:32:01]: ▸ ^^^^^^^^^^^^^^^^
[05:32:01]: ▸ Command PhaseScriptExecution failed with a nonzero exit code
[05:32:01]:
Could you check this? It might be possible that the error is not due to any xcode version.

iOS build fails on GitHub Actions (without fastlane), but it works intermittently

I have slightly different approach for building iOS apps. Instead of putting a bunch of code in the .yaml file, I prefer to put most stuff in a shell script and have a simpler .yaml file... is there any problem in this approach?
My build gets stuck in the "Build app" step. The other steps work fine.
Intermittently, like once every 15 times it just magically works, but most of the time it fails. It gets stuck and I can't see the log, until I cancel the job, but the log doesn't say anything useful. Running the scripts in my local machine works 100% of time. It seems to be something very particular to GitHub actions.
Is there any problem, limitation on using this approach (bash script) in GitHub actions?
Why would this fail?
I am not using using fastlane.
Here is my YAML file:
name: Build iOS
on:
push:
branches:
- master
jobs:
build:
runs-on: macOS-latest
steps:
- uses: actions/checkout#v2
- name: Switch XCode Version
run: sudo xcode-select -s /Applications/Xcode_11.2.app
- name: Get dependencies
run: source .github/ios/build.sh && get_dependencies
- name: Decrypt secrets
run: source .github/ios/build.sh && decrypt_secrets ${{ secrets.SECRET_KEY }}
env:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
- name: Set up code signing
run: source .github/ios/build.sh && setup_code_signing
- name: Build app
run: source .github/ios/build.sh && build_app
- name: Upload artifacts
run: source .github/ios/build.sh && upload_artifacts
and the script
#!/bin/bash
PROVISIONING_PROFILE="MyApp"
CODE_SIGN_IDENTITY="Apple Development: MyApp (XXXXXXXXXX)"
DOMAIN="MyApp.com"
PRODUCT_BUNDLE_IDENTIFIER="com.MyApp.app"
# Get dependencies
function get_dependencies()
{
yarn
cd ios
pod install
cd ..
}
function decrypt
{
INPUT=$1
OUTPUT="${1%.*}"
openssl aes-256-cbc -salt -a -d -in $INPUT -out $OUTPUT -pass pass:$SECRET_KEY
}
# Decrypt secrets
function decrypt_secrets
{
export SECRET_KEY=$1
decrypt .github/ios/secrets/MyApp.mobileprovision.encrypted
decrypt .github/ios/secrets/MyApp.p12.encrypted
decrypt .github/ssh/id_rsa.encrypted
}
# Set up code signing
function setup_code_signing()
{
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
# provisioning
cp .github/ios/secrets/MyApp.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/$PROVISIONING_PROFILE.mobileprovision
# keychain
security create-keychain -p "MyApp" build.keychain
security import ./.github/ios/secrets/MyApp.p12 -t agg -k ~/Library/Keychains/build.keychain -P "" -A
security list-keychains -s ~/Library/Keychains/build.keychain
security default-keychain -s ~/Library/Keychains/build.keychain
security unlock-keychain -p "MyApp" ~/Library/Keychains/build.keychain
security set-key-partition-list -S apple-tool:,apple: -s -k "MyApp" ~/Library/Keychains/build.keychain
}
# Build
function build_app()
{
# dev environment
echo "API_URL=https://backend.$DOMAIN/" > .env
# build number
BUILD_NUMBER=${GITHUB_RUN_NUMBER:-1}
# ExportOptions.plist
sed -e "s/__BUILD_NUMBER__/$BUILD_NUMBER/g" \
-e "s/__PRODUCT_BUNDLE_IDENTIFIER__/$PRODUCT_BUNDLE_IDENTIFIER/g" \
-e "s/__CODE_SIGN_IDENTITY__/$CODE_SIGN_IDENTITY/g" \
.github/ios/ExportOptions.plist > ios/ExportOptions.plist
cd ios
set -e
set -o pipefail
# archive
xcodebuild archive \
-workspace MyApp.xcworkspace \
-scheme MyApp \
-sdk iphoneos13.2 \
-configuration Release \
-archivePath "$PWD/build/MyApp.xcarchive" \
PRODUCT_BUNDLE_IDENTIFIER="$PRODUCT_BUNDLE_IDENTIFIER" \
PROVISIONING_PROFILE="$PROVISIONING_PROFILE" \
CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" \
CURRENT_PROJECT_VERSION="$BUILD_NUMBER"
# export
xcodebuild \
-exportArchive \
-archivePath "$PWD/build/MyApp.xcarchive" \
-exportOptionsPlist "$PWD/ExportOptions.plist" \
-exportPath "$PWD/build"
}
# Upload artifacts
function upload_artifacts()
{
chmod 600 .github/ssh/id_rsa
BUILD_PATH="www/app/builds/$GITHUB_RUN_NUMBER"
ssh -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' ubuntu#MyApp.dev "mkdir -p $BUILD_PATH"
scp -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -r ios/build/Apps/* ubuntu#MyApp.dev:$BUILD_PATH
scp -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -r ios/build/manifest.plist ubuntu#MyApp.dev:$BUILD_PATH
}
Most of the time, the log gets stuck on this line:
/usr/bin/codesign --force --sign F4D55F28BEBE840ADF175A67B471FFBF2E27B222 --entitlements /Users/runner/Library/Developer/Xcode/DerivedData/MyApp-fhnolcbrhrsoglcxtgrffszyvmwz/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/IntermediateBuildFilesPath/MyApp.build/Release-iphoneos/MyApp.build/MyApp.app.xcent --timestamp=none /Users/runner/Library/Developer/Xcode/DerivedData/MyApp-fhnolcbrhrsoglcxtgrffszyvmwz/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/InstallationBuildProductsLocation/Applications/MyApp.app
Kudos to the answers from here:
Jenkins - Xcode build works codesign fails
The problem that happened to me is that I was trying to follow the first only the first answer from Jamieson (the accepted one), but maybe it is not up to date anymore.
I used the answer from Stephen Quan and it worked perfectly!
My final keychain part now is:
# Create temporary keychain
KEYCHAIN="MyApp$$.keychain"
KEYCHAIN_PASSWORD="MyApp"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
# Append keychain to the search list
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | sed s/\"//g)
security list-keychains
# Unlock the keychain
security set-keychain-settings "$KEYCHAIN"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
# Import certificate
security import .github/ios/secrets/MyApp.p12 -k "$KEYCHAIN" -P "" -T "/usr/bin/codesign"
# Detect the iOS identity
IOS_IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN" | head -1 | grep '"' | sed -e 's/[^"]*"//' -e 's/".*//')
IOS_UUID=$(security find-identity -v -p codesigning "$KEYCHAIN" | head -1 | grep '"' | awk '{print $2}')
# New requirement for MacOS 10.12+
security set-key-partition-list -S apple-tool:,apple: -s -k $KEYCHAIN_PASSWORD $KEYCHAIN

Gitlab CI/CD Runner error: " unrecognized import path" GOLANG

I'm trying to implement CI/CD for a GO project
This is my gitlab-ci.yml file:
image: golang:latest
variables:
REPO_NAME: gitlab.com/thomasaudo/website
before_script:
- cd $GOPATH/src
- mkdir -p gitlab.com/$CI_PROJECT_NAMESPACE
- cd gitlab.com/$CI_PROJECT_NAMESPACE
- ln -s $CI_PROJECT_DIR
- cd $CI_PROJECT_NAME
stages:
- test
format:
stage: test
script:
- go get ./...
- go fmt $(go list ./... | grep -v /vendor/)
- go vet $(go list ./... | grep -v /vendor/)
- go test -race $(go list ./... | grep -v /vendor/)
However, my runner stopped with the following error: package website/src/routes: unrecognized import path "website/src/routes" (import path does not begin with hostname)
Thanks for your help
You should use full paths in your import statements, e.g
website/src/routes
should become
gitlab.com/thomasaudo/website/src/routes
Also, it looks like you use govendor, so you are probably missing govendor sync command in one of your build steps.

GitLab CI with Docker, Fastlane and Cocoapods not working

Desperate help needed:
Already asked for the case with gitlab-runner register as "shell", I try to ask a very similar question here with gitlab-runner register as "docker".
Since 3 days I try to get Gitlab CI running (using docker, fastlane - all for an iOS-app having Cocoapods dependencies).
Here is the error message that the GitLab CI spits out:
I did the following steps:
install fastlane (link to fastlane page)
create a GitLab project and upload your project repository (link to GitLab)
install gitlab-runner on MacOS, following these steps...
install Docker (for desktop), registering here and downloading the app
register gitlab-runner (i.e. open terminal and type the following):
(your Token can be found under GitLab-->Settings-->CI/CD)
sudo gitlab-runner register \
--non-interactive \
--url "https://gitlab.com/" \
--registration-token "TOKENABCDEFG" \
--description "MyApp runner with ruby-2.6" \
--tag-list ios \
--executor "docker" \
--docker-image ruby:2.6
start docker application on your Mac
run docker image (by typing the following in your terminal:)
docker run -d --name gitlab-runner --restart always \
-v /Users/Shared/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
After all that, any git push to your GitLab project repo will automatically start a Pipeline.
I also tried using a local shell (instead of docker) - but no success either as documented here.
No matter what I try, I always end up with the same error message:
[08:48:04]: Driving the lane 'ios tests' 🚀
[08:48:04]: -----------------------
[08:48:04]: --- Step: cocoapods ---
[08:48:04]: -----------------------
[08:48:04]: Using deprecated option: '--clean' (true)
[08:48:04]: $ cd '.' && bundle exec pod install
[08:48:04]: ▸ WARNING: CocoaPods requires your terminal to be using UTF-8 encoding.
[08:48:04]: ▸ Consider adding the following to ~/.profile:
[08:48:04]: ▸ export LANG=en_US.UTF-8
[08:48:04]: ▸
[08:48:04]: ▸ bundler: failed to load command: pod (/usr/local/bundle/bin/pod)
[08:48:04]: ▸ CLAide::Help: [!] You cannot run CocoaPods as root.
Here is my .gitlab-ci.yml file:
stages:
- unit_tests
variables:
LC_ALL: "en_US.UTF-8"
LANG: "en_US.UTF-8"
before_script:
- gem install bundler
- bundle install
unit_tests:
dependencies: []
stage: unit_tests
artifacts:
paths:
- fastlane/screenshots
- fastlane/logs
script:
- bundle exec fastlane tests
tags:
- ios
And here the Fastfile:
update_fastlane
default_platform(:ios)
platform :ios do
def install_pods
cocoapods(
clean: true,
podfile: "./Podfile",
try_repo_update_on_error: true
)
end
lane :tests do
install_pods()
gym(configuration: "Release",
workspace: "MyApp.xcworkspace",
scheme: "MyApp",
clean: true,
output_name: "MyApp.ipa")
# increment_build_number
scan(workspace: "MyApp.xcworkspace",
devices: ["iPhone SE", "iPhone XS"],
scheme: "MyAppTests")
end
I finally found the solution:
Your gitlab-runner register is not allowed to have sudo.
For some reason there are many tutorials out there that show differently (i.e. with sudo) - such as this video or others...
Anyway, on a Mac you absolutely need to leave sudo out and absolutely register as "shell" executor for GitLab (i.e. not "docker")
Here is the best tutorial I have found on how to Gitlab CI an iOS project.

Resources