Skip to content

implement rotateBy by specifying an angle in degree #11925

implement rotateBy by specifying an angle in degree

implement rotateBy by specifying an angle in degree #11925

Workflow file for this run

name: ios-ci
on:
workflow_dispatch:
push:
branches:
- main
- ios-*.*.x
tags:
- 'ios-*'
pull_request:
branches:
- '*'
permissions:
id-token: write # needed for AWS
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files-yaml.outputs.ios_any_modified != 'true' }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
submodules: recursive
persist-credentials: false
- name: Get all iOS files that have changed
if: github.event_name != 'workflow_dispatch'
id: changed-files-yaml
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files_yaml_from_source_file: .github/changed-files.yml
- name: Run step if test file(s) change
if: steps.changed-files-yaml.outputs.ios_any_modified == 'true'
run: |
echo "One or more iOS file(s) has changed."
echo "List of changes: ${{ steps.changed-files-yaml.outputs.ios_all_changed_files }}"
ios-build:
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: macos-26
concurrency:
# cancel jobs on PRs only
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
env:
BUILDTYPE: Debug
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
IOS_BUNDLE_ID_PREFIX: org.maplibre
defaults:
run:
working-directory: platform/ios
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
submodules: false
persist-credentials: false
- name: Remove stale git lock files
run: find .git -type f -name "*.lock" -delete 2>/dev/null || true
working-directory: .
- name: Update submodules
run: git submodule update --init --recursive
working-directory: .
- name: Install Apple signing assets
# Run platform/ios/scripts/ios-ci-create-signing-assets.sh to regenerate these values.
run: scripts/ios-ci-install-signing-assets.sh
env:
BUILD_CERTIFICATE_BASE64: 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
P12_PASSWORD: HmSQyXesip4O/YK+g30foy+dMYdBSam7xvWWsBeDrKM=
BUILD_PROVISION_PROFILE_BASE64: MIIwkgYJKoZIhvcNAQcCoIIwgzCCMH8CAQExCzAJBgUrDgMCGgUAMIIgnwYJKoZIhvcNAQcBoIIgkASCIIw8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8IURPQ1RZUEUgcGxpc3QgUFVCTElDICItLy9BcHBsZS8vRFREIFBMSVNUIDEuMC8vRU4iICJodHRwOi8vd3d3LmFwcGxlLmNvbS9EVERzL1Byb3BlcnR5TGlzdC0xLjAuZHRkIj4KPHBsaXN0IHZlcnNpb249IjEuMCI+CjxkaWN0PgoJPGtleT5BcHBJRE5hbWU8L2tleT4KCTxzdHJpbmc+TWFwTGlicmUgaU9TIENJIFdpbGRjYXJkIERldmVsb3BtZW50PC9zdHJpbmc+Cgk8a2V5PkFwcGxpY2F0aW9uSWRlbnRpZmllclByZWZpeDwva2V5PgoJPGFycmF5PgoJPHN0cmluZz5RTUM3TjRCRFZaPC9zdHJpbmc+Cgk8L2FycmF5PgoJPGtleT5DcmVhdGlvbkRhdGU8L2tleT4KCTxkYXRlPjIwMjYtMDYtMjNUMTY6MTQ6MjlaPC9kYXRlPgoJPGtleT5QbGF0Zm9ybTwva2V5PgoJPGFycmF5PgoJCTxzdHJpbmc+aU9TPC9zdHJpbmc+CgkJPHN0cmluZz54ck9TPC9zdHJpbmc+CgkJPHN0cmluZz52aXNpb25PUzwvc3RyaW5nPgoJPC9hcnJheT4KCTxrZXk+SXNYY29kZU1hbmFnZWQ8L2tleT4KCTxmYWxzZS8+Cgk8a2V5PkRldmVsb3BlckNlcnRpZmljYXRlczwva2V5PgoJPGFycmF5PgoJCTxkYXRhPk1JSUZzekNDQkp1Z0F3SUJBZ0lRRlp5eFBncE9KTzZ1dmU5YnAreHRmakFOQmdrcWhraUc5dzBCQVFzRkFEQjFNVVF3UWdZRFZRUURERHRCY0hCc1pTQlhiM0pzWkhkcFpHVWdSR1YyWld4dmNHVnlJRkpsYkdGMGFXOXVjeUJEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURUxNQWtHQTFVRUN3d0NSek14RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRJMk1EWXlNekUyTURReU4xb1hEVEkzTURZeU16RTJNRFF5Tmxvd2dZNHhHakFZQmdvSmtpYUprL0lzWkFFQkRBbzFWMFpVV1ZOR1NqTTFNVGN3TlFZRFZRUUREQzVwVUdodmJtVWdSR1YyWld4dmNHVnlPaUJEY21WaGRHVmtJSFpwWVNCQlVFa2dLRFZYUmxSWlUwWktNelVwTVJNd0VRWURWUVFMREFwUlRVTTNUalJDUkZaYU1SVXdFd1lEVlFRS0RBeENZWEowSUV4dmRYZGxjbk14Q3pBSkJnTlZCQVlUQWxWVE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeEZVR3BMRUdmZU5DMU1kcmlRcDB4MGVSNDdJd3o1OUdoNjZZYkVuSnFLSUZDMkdYdkd4WDN4ZkRBS0lHaThueVRMVVhSUDBqY2VCL1VoNE50djZqSFFlTURRVitRRlNiU1RLOU15KytXajNOc0VteFpTZ25qakRTb09ISE5uMW5LakRMdFUrNVB4WmlheUJVSkJqQVJ3U21USFNuZVM0WUJHcjRscjRtZGhoYlhBbXZBVEtvYUxFUEVhZnJheThSNFFZN3NSSEtXWEtFd3dPQjNXVmsxSG4wUi9pc2hBeHI1UkZrL2RyOGNjNVBDRHNIRmwwTE1MNE5lZ0JuaEpXWEVtSzJZdmhhRDBoeTIvRHhZMTM2M3JWaURJU1hWWnFJTURGTkRDOVhUcU4wUTNvLzVvVTJwdGh0QndyaTZlcysrRStrM0RKVmR6MFV4cC9pdEtvLzFRSURBUUFCbzRJQ0l6Q0NBaDh3REFZRFZSMFRBUUgvQkFJd0FEQWZCZ05WSFNNRUdEQVdnQlFKL3NBVmtQbXZaQXFTRXJrbUtHTU1sK3luc2pCd0JnZ3JCZ0VGQlFjQkFRUmtNR0l3TFFZSUt3WUJCUVVITUFLR0lXaDBkSEE2THk5alpYSjBjeTVoY0hCc1pTNWpiMjB2ZDNka2NtY3pMbVJsY2pBeEJnZ3JCZ0VGQlFjd0FZWWxhSFIwY0RvdkwyOWpjM0F1WVhCd2JHVXVZMjl0TDI5amMzQXdNeTEzZDJSeVp6TXdNekNDQVI0R0ExVWRJQVNDQVJVd2dnRVJNSUlCRFFZSktvWklodmRqWkFVQk1JSC9NSUhEQmdnckJnRUZCUWNDQWpDQnRneUJzMUpsYkdsaGJtTmxJRzl1SUhSb2FYTWdZMlZ5ZEdsbWFXTmhkR1VnWW5rZ1lXNTVJSEJoY25SNUlHRnpjM1Z0WlhNZ1lXTmpaWEIwWVc1alpTQnZaaUIwYUdVZ2RHaGxiaUJoY0hCc2FXTmhZbXhsSUhOMFlXNWtZWEprSUhSbGNtMXpJR0Z1WkNCamIyNWthWFJwYjI1eklHOW1JSFZ6WlN3Z1kyVnlkR2xtYVdOaGRHVWdjRzlzYVdONUlHRnVaQ0JqWlhKMGFXWnBZMkYwYVc5dUlIQnlZV04wYVdObElITjBZWFJsYldWdWRITXVNRGNHQ0NzR0FRVUZCd0lCRml0b2RIUndjem92TDNkM2R5NWhjSEJzWlM1amIyMHZZMlZ5ZEdsbWFXTmhkR1ZoZFhSb2IzSnBkSGt2TUJZR0ExVWRKUUVCL3dRTU1Bb0dDQ3NHQVFVRkJ3TURNQjBHQTFVZERnUVdCQlRldkdna2JxcDNuSTk1cDFPY204RzIzZlVGTVRBT0JnTlZIUThCQWY4RUJBTUNCNEF3RXdZS0tvWklodmRqWkFZQkFnRUIvd1FDQlFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFEUklmeHUyankwbUpCTnZEL2FPYVI1UGhvMGdIWWZCOURiaWJqcUltU1pTemxrVzlyK2FFcCtQaXc4R0hKcXIyZWM5UUsxQm94KzNyMEs0MDZacWJxU29uRVRVeEtLTm93WnRWb3N3WWV0ZVd6dWl5d1BQalRHOUZ3dENkb1lGZnFaUWlJNXNwYWh0b0l5TmVOS2NyR0IvVWZwWnhXbXp0eDJhYitoSUVRMG9GTDhhMVhLUWNmR1dzZ01LdktsRHBJdko5cXl1VEt6ZkExRjVrTEtjeWkxYmhJMTFoZHNVUFdjMFArWGlGL1lxc0dhTVZkaGdjaWo4YnJOSnBiMnlTUi9ITVZZWmFYKzk4WHZqUSs2VFFTQThQMk8zMEhzU3Q2Ym5kUU0vWkdXYy9pT25oUnZOeGdwOVRzWFlYSUlBVVZBeGdiWU5kNnhWNnZybjJjc2lOWXM9PC9kYXRhPgoJPC9hcnJheT4KCgk8a2V5PkRFUi1FbmNvZGVkLVByb2ZpbGU8L2tleT4KCTxkYXRhPk1JSU5vQVlKS29aSWh2Y05BUWNDb0lJTmtUQ0NEWTBDQVFFeERUQUxCZ2xnaGtnQlpRTUVBZ0V3Z2dOZkJna3Foa2lHOXcwQkJ3R2dnZ05RQklJRFRER0NBMGd3REF3SFZtVnljMmx2YmdJQkFUQU5EQWhRVUZGRGFHVmphd0VCL3pBUURBcFVhVzFsVkc5TWFYWmxBZ0lCYlRBVERBNUpjMWhqYjJSbFRXRnVZV2RsWkFFQkFEQVlEQWhVWldGdFRtRnRaUXdNUW1GeWRDQk1iM1YzWlhKek1CME1ERU55WldGMGFXOXVSR0YwWlJjTk1qWXdOakl6TVRZeE5ESTVXakFlREE1VVpXRnRTV1JsYm5ScFptbGxjakFNREFwUlRVTTNUalJDUkZaYU1COE1Ea1Y0Y0dseVlYUnBiMjVFWVhSbEZ3MHlOekEyTWpNeE5qRTBNamxhTUNFTUNGQnNZWFJtYjNKdE1CVU1BMmxQVXd3RWVISlBVd3dJZG1semFXOXVUMU13SWd3WFVISnZabWxzWlVScGMzUnlhV0oxZEdsdmJsUjVjR1VNQjB4SlRVbFVSVVF3S3d3YlFYQndiR2xqWVhScGIyNUpaR1Z1ZEdsbWFXVnlVSEpsWm1sNE1Bd01DbEZOUXpkT05FSkVWbG93TEF3RVRtRnRaUXdrVFdGd1RHbGljbVVnYVU5VElFTkpJRmRwYkdSallYSmtJRVJsZG1Wc2IzQnRaVzUwTUN3TUJGVlZTVVFNSkRFek9XWXlZV1V4TFRkalpXUXRORGRrTlMwNFpHSXhMV013WkRWa09XTmpNVEF3WkRBeERBbEJjSEJKUkU1aGJXVU1KRTFoY0V4cFluSmxJR2xQVXlCRFNTQlhhV3hrWTJGeVpDQkVaWFpsYkc5d2JXVnVkREE3REJWRVpYWmxiRzl3WlhKRFpYSjBhV1pwWTJGMFpYTXdJZ1FnU2JjRy90dkdScjlSdEVEY3hWODh3S0hJVTJLSkJ2SEdUb1lkZFUyZTNBd3dkZ3dTVUhKdmRtbHphVzl1WldSRVpYWnBZMlZ6TUdBTUdUQXdNREE0TVRFd0xUQXdNRVV4UkRVeE16WkdPVGd3TVVVTUtHRmhaVFkyTkdFNU1UTTBZVGRrTkRFd1pETXlPVEF5TVdJNFlXTTRNak0yWkRobVlUQm1NVElNR1RBd01EQTRNVEV5TFRBd01ESXlPRUU0TUVWRE16WXdNVVV3Z2M4TURFVnVkR2wwYkdWdFpXNTBjM0NCdmdJQkFiQ0J1REF6REJaaGNIQnNhV05oZEdsdmJpMXBaR1Z1ZEdsbWFXVnlEQmxSVFVNM1RqUkNSRlphTG05eVp5NXRZWEJzYVdKeVpTNHFNREVNSTJOdmJTNWhjSEJzWlM1a1pYWmxiRzl3WlhJdWRHVmhiUzFwWkdWdWRHbG1hV1Z5REFwUlRVTTNUalJDUkZaYU1CTU1EbWRsZEMxMFlYTnJMV0ZzYkc5M0FRSC9NRGtNRm10bGVXTm9ZV2x1TFdGalkyVnpjeTFuY205MWNITXdId3dNVVUxRE4wNDBRa1JXV2k0cURBOWpiMjB1WVhCd2JHVXVkRzlyWlc2Z2dnZzlNSUlDUXpDQ0FjbWdBd0lCQWdJSUxjWDhpTkxGUzVVd0NnWUlLb1pJemowRUF3TXdaekViTUJrR0ExVUVBd3dTUVhCd2JHVWdVbTl2ZENCRFFTQXRJRWN6TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd0hoY05NVFF3TkRNd01UZ3hPVEEyV2hjTk16a3dORE13TVRneE9UQTJXakJuTVJzd0dRWURWUVFEREJKQmNIQnNaU0JTYjI5MElFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkpqcEx6MUFjcVR0a3lKeWdSTWMzUkNWOGNXalRuSGNGQmJaRHVXbUJTcDNaSHRmVGpqVHV4eEV0WC8xSDdZeVlsM0o2WVJiVHpCUEVWb0EvVmhZREtYMUR5eE5CMGNUZGRxWGw1ZHZNVnp0SzUxN0lEdll1VlRaWHBta09sRUtNYU5DTUVBd0hRWURWUjBPQkJZRUZMdXczcUZZTTRpYXBJcVozcjY5NjYvYXl5U3JNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEZ1lEVlIwUEFRSC9CQVFEQWdFR01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RQ0Q2Y0hFRmw0YVhUUVkyZTN2OUd3T0FFWkx1Tit5UmhIRkQvM21lb3locG12T3dnUFVuUFdUeG5TNGF0K3FJeFVDTUcxbWloREsxQTNVVDgyTlF6NjBpbU9sTTI3amJkb1h0MlFmeUZNbStZaGlkRGtMRjF2TFVhZ002QmdENTZLeUtEQ0NBdVl3Z2dKdG9BTUNBUUlDQ0RNTjd2aS9UR2d1TUFvR0NDcUdTTTQ5QkFNRE1HY3hHekFaQmdOVkJBTU1Fa0Z3Y0d4bElGSnZiM1FnUTBFZ0xTQkhNekVtTUNRR0ExVUVDd3dkUVhCd2JHVWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhreEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUI0WERURTNNREl5TWpJeU1qTXlNbG9YRFRNeU1ESXhPREF3TURBd01Gb3djakVtTUNRR0ExVUVBd3dkUVhCd2JHVWdVM2x6ZEdWdElFbHVkR1ZuY21GMGFXOXVJRU5CSURReEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJBWnJwRlp2Zlo4bjBjNDJqcEliVnMxVU5tUkt5WlJvbWZySklIN2k5VmdQM09KcTZ4bEhMeTd2TzZRQnRBRVRSSHhhSnEyZ25Da2xpdVhtQm05UGZGcWpnZmN3Z2ZRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZkJnTlZIU01FR0RBV2dCUzdzTjZoV0RPSW1xU0ttZDYrdmV1djJzc2txekJHQmdnckJnRUZCUWNCQVFRNk1EZ3dOZ1lJS3dZQkJRVUhNQUdHS21oMGRIQTZMeTl2WTNOd0xtRndjR3hsTG1OdmJTOXZZM053TURNdFlYQndiR1Z5YjI5MFkyRm5NekEzQmdOVkhSOEVNREF1TUN5Z0txQW9oaVpvZEhSd09pOHZZM0pzTG1Gd2NHeGxMbU52YlM5aGNIQnNaWEp2YjNSallXY3pMbU55YkRBZEJnTlZIUTRFRmdRVWVrZTZPSW9WSkVnaVJzMitqeG9rZXpRREtta3dEZ1lEVlIwUEFRSC9CQVFEQWdFR01CQUdDaXFHU0liM1kyUUdBaEVFQWdVQU1Bb0dDQ3FHU000OUJBTURBMmNBTUdRQ01CVU1xWTdHcjVacGE2ZWYzVnpVQTFsc3JsTFVZTWFMZHVDM3hhTHhDWHpnbXVOcnNlTjhNY1FuZXFlT2lmMnJkd0l3WVRNZzhTbi8rWWN5cmluSVpEMTJlMUdrMGdJdmRyNWdJcEh4MVRwMTNMVGl4aXFXL3NZSjNFcFAxU1R3L01xeU1JSURDRENDQXEyZ0F3SUJBZ0lJZEF3K09lV1NxbUF3Q2dZSUtvWkl6ajBFQXdJd2NqRW1NQ1FHQTFVRUF3d2RRWEJ3YkdVZ1UzbHpkR1Z0SUVsdWRHVm5jbUYwYVc5dUlFTkJJRFF4SmpBa0JnTlZCQXNNSFVGd2NHeGxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1STXdFUVlEVlFRS0RBcEJjSEJzWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpBZUZ3MHlOakF4TWpFeE9USTNNakJhRncwek1EQXlNVGt4T1RJM01UbGFNRTR4S2pBb0JnTlZCQU1NSVZkWFJGSWdVSEp2ZG1semFXOXVhVzVuSUZCeWIyWnBiR1VnVTJsbmJtbHVaekVUTUJFR0ExVUVDZ3dLUVhCd2JHVWdTVzVqTGpFTE1Ba0dBMVVFQmhNQ1ZWTXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU1FDbStKejlPQmdEQlV0YnM2cHd1cHJ5bTJFZEZ2aysyKzgwbmFlWEh1YXAyYmg4RlIvaVR5RFhqUU5idEtJV09PQk5HL3BycU9yNXY0MElRT2ZWRTRvNElCVHpDQ0FVc3dEQVlEVlIwVEFRSC9CQUl3QURBZkJnTlZIU01FR0RBV2dCUjZSN280aWhVa1NDSkd6YjZQR2lSN05BTXFhVEJCQmdnckJnRUZCUWNCQVFRMU1ETXdNUVlJS3dZQkJRVUhNQUdHSldoMGRIQTZMeTl2WTNOd0xtRndjR3hsTG1OdmJTOXZZM053TURNdFlYTnBZMkUwTURNd2daWUdBMVVkSUFTQmpqQ0JpekNCaUFZSktvWklodmRqWkFVQk1Ic3dlUVlJS3dZQkJRVUhBZ0l3YlF4clZHaHBjeUJqWlhKMGFXWnBZMkYwWlNCcGN5QjBieUJpWlNCMWMyVmtJR1Y0WTJ4MWMybDJaV3g1SUdadmNpQm1kVzVqZEdsdmJuTWdhVzUwWlhKdVlXd2dkRzhnUVhCd2JHVWdVSEp2WkhWamRITWdZVzVrTDI5eUlFRndjR3hsSUhCeWIyTmxjM05sY3k0d0hRWURWUjBPQkJZRUZPT1I0WWwwQVdha2grNy9zMVNMM1RGTHhWL1FNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVBCZ2txaGtpRzkyTmtEQk1FQWdVQU1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQ0tMQW40bmtrUk5DZnJldUJDQitOaE1uL3loUnFQbkZBcTJGMkIzQjBzVlFJaEFPRlZuYno2ZjNhVGljN0RNNkRERHlrNjlaendrQy9aWDA5NFFuajFNZHpVTVlJQjB6Q0NBYzhDQVFFd2ZqQnlNU1l3SkFZRFZRUUREQjFCY0hCc1pTQlRlWE4wWlcwZ1NXNTBaV2R5WVhScGIyNGdRMEVnTkRFbU1DUUdBMVVFQ3d3ZFFYQndiR1VnUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3hFekFSQmdOVkJBb01Da0Z3Y0d4bElFbHVZeTR4Q3pBSkJnTlZCQVlUQWxWVEFnaDBERDQ1NVpLcVlEQUxCZ2xnaGtnQlpRTUVBZ0dnZ2Vjd0dBWUpLb1pJaHZjTkFRa0RNUXNHQ1NxR1NJYjNEUUVIQVRBY0Jna3Foa2lHOXcwQkNRVXhEeGNOTWpZd05qSXpNVFl4TkRJNVdqQW9CZ2txaGtpRzl3MEJDVFF4R3pBWk1Bc0dDV0NHU0FGbEF3UUNBYUVLQmdncWhrak9QUVFEQWpBdkJna3Foa2lHOXcwQkNRUXhJZ1FnUk4rWHZPOVZvSnFlbmFvaEN1VmFISVYrUWRFNUk1T0tMSjFRdTdya2EwMHdVZ1lKS29aSWh2Y05BUWtQTVVVd1F6QUtCZ2dxaGtpRzl3MERCekFPQmdncWhraUc5dzBEQWdJQ0FJQXdEUVlJS29aSWh2Y05Bd0lDQVVBd0J3WUZLdzREQWdjd0RRWUlLb1pJaHZjTkF3SUNBU2d3Q2dZSUtvWkl6ajBFQXdJRVJ6QkZBaUIwRTk5UEhidm9GcDhnbm5iZElwYU9mL2dCS3VyK0lnM0dXc29Fa2JoeFVBSWhBTk1nc01ULy81Y2VxTWhrV0dVWnc5MzFXOEFKeTF1UFZCMGJEdlZoVTg1QjwvZGF0YT4KCQkJCQkJCQkJCQk8a2V5PlBQUUNoZWNrPC9rZXk+Cgk8dHJ1ZS8+CgoJPGtleT5FbnRpdGxlbWVudHM8L2tleT4KCTxkaWN0PgoJCQkJPGtleT5hcHBsaWNhdGlvbi1pZGVudGlmaWVyPC9rZXk+CgkJPHN0cmluZz5RTUM3TjRCRFZaLm9yZy5tYXBsaWJyZS4qPC9zdHJpbmc+CgkJCQk8a2V5PmtleWNoYWluLWFjY2Vzcy1ncm91cHM8L2tleT4KCQk8YXJyYXk+CgkJCQk8c3RyaW5nPlFNQzdONEJEVlouKjwvc3RyaW5nPgoJCQkJPHN0cmluZz5jb20uYXBwbGUudG9rZW48L3N0cmluZz4KCQk8L2FycmF5PgoJCQkJPGtleT5nZXQtdGFzay1hbGxvdzwva2V5PgoJCTx0cnVlLz4KCQkJCTxrZXk+Y29tLmFwcGxlLmRldmVsb3Blci50ZWFtLWlkZW50aWZpZXI8L2tleT4KCQk8c3RyaW5nPlFNQzdONEJEVlo8L3N0cmluZz4KCQkKCTwvZGljdD4KCTxrZXk+RXhwaXJhdGlvbkRhdGU8L2tleT4KCTxkYXRlPjIwMjctMDYtMjNUMTY6MTQ6MjlaPC9kYXRlPgoJPGtleT5OYW1lPC9rZXk+Cgk8c3RyaW5nPk1hcExpYnJlIGlPUyBDSSBXaWxkY2FyZCBEZXZlbG9wbWVudDwvc3RyaW5nPgoJPGtleT5Qcm92aXNpb25lZERldmljZXM8L2tleT4KCTxhcnJheT4KCQk8c3RyaW5nPjAwMDA4MTEwLTAwMEUxRDUxMzZGOTgwMUU8L3N0cmluZz4KCQk8c3RyaW5nPmFhZTY2NGE5MTM0YTdkNDEwZDMyOTAyMWI4YWM4MjM2ZDhmYTBmMTI8L3N0cmluZz4KCQk8c3RyaW5nPjAwMDA4MTEyLTAwMDIyOEE4MEVDMzYwMUU8L3N0cmluZz4KCTwvYXJyYXk+Cgk8a2V5PlRlYW1J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
KEYCHAIN_PASSWORD: h39tdjPQyknPcjqrR5oGN1tWuq9hsvKWn2ngnHY2nDk=
- name: Set up Bazel
uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}
repository-cache: true
cache-save: ${{ github.event_name != 'pull_request' }}
# render test
- name: Build RenderTest .ipa and .xctest for AWS Device Farm
run: |
set -e
bazel run //platform/ios:xcodeproj --@rules_xcodeproj//xcodeproj:extra_common_flags="--//:renderer=metal"
build_dir="$(mktemp -d)"
xcodebuild build-for-testing -scheme RenderTest -project MapLibre.xcodeproj -derivedDataPath "$build_dir"
render_test_app_dir="$(dirname "$(find "$build_dir" -name RenderTestApp.app)")"
cd "$render_test_app_dir"
mkdir -p Payload
ditto RenderTestApp.app Payload/RenderTestApp.app
iphoneos_developer_dir="$(xcode-select -p)/Platforms/iPhoneOS.platform/Developer"
ditto "$iphoneos_developer_dir/Library/Frameworks/Testing.framework" Payload/RenderTestApp.app/Frameworks/Testing.framework
ditto "$iphoneos_developer_dir/usr/lib/lib_TestingInterop.dylib" Payload/RenderTestApp.app/Frameworks/lib_TestingInterop.dylib
chmod -R u+w Payload/RenderTestApp.app
zip -r RenderTestApp.zip Payload
mv RenderTestApp.zip RenderTestApp.ipa
cd Payload/RenderTestApp.app/PlugIns
zip -r "$render_test_app_dir"/RenderTest.xctest.zip RenderTest.xctest
echo render_test_artifacts_dir="$render_test_app_dir" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ios-render-test
retention-days: 3
if-no-files-found: error
path: |
${{ env.render_test_artifacts_dir }}/RenderTest.xctest.zip
${{ env.render_test_artifacts_dir }}/RenderTestApp.ipa
- name: Build Example (Swift) App
run: bazel build //platform/ios/app-swift:MapLibreApp --//:renderer=metal
- name: Check debug symbols
run: bazel run //platform:check-public-symbols --//:renderer=metal
- name: Lint plist files
run: bazel run //platform/ios:lint-plists --//:renderer=metal
- name: Running iOS tests
run: bazel test //platform/ios/test:ios_test --test_output=errors --//:renderer=metal
# tsan run fails with 'Interceptors are not working. This may be because ThreadSanitizer is loaded too late...'
#- name: Running iOS UI tests (Thread Sanitizer)
# run: bazel test //platform/ios/iosapp-UITests:uitest --test_output=errors --//:renderer=metal --features=tsan
# https://github.com/maplibre/maplibre-native/issues/3642
# - name: Running iOS UI tests (Address+UB Sanitizer)
# run: |
# retry_count=0
# max_retries=5
# while [ $retry_count -le $max_retries ]; do
# bazel test //platform/ios/iosapp-UITests:uitest \
# --test_output=errors \
# --//:renderer=metal \
# --features=include_clang_rt \
# --copt=-fsanitize=undefined \
# --linkopt=-fsanitize=undefined \
# --copt=-fsanitize-recover=null \
# --linkopt=-fsanitize-recover=null && break
# retry_count=$((retry_count+1))
# if [ $retry_count -eq $max_retries ]; then
# echo "::error::Failed to run iOS UI tests after $max_retries attempts"
# exit 1
# fi
# echo "Attempt $retry_count failed. Retrying..."
# done
# C++ unit tests
- name: Build CppUnitTests .ipa and .xctest for AWS Device Farm
run: |
set -e
bazel run //platform/ios:xcodeproj --@rules_xcodeproj//xcodeproj:extra_common_flags="--//:renderer=metal"
build_dir="$(mktemp -d)"
xcodebuild build-for-testing -scheme CppUnitTests -project MapLibre.xcodeproj -derivedDataPath "$build_dir"
ios_cpp_test_app_dir="$(dirname "$(find "$build_dir" -name CppUnitTestsApp.app)")"
cd "$ios_cpp_test_app_dir"
mkdir -p Payload
ditto CppUnitTestsApp.app Payload/CppUnitTestsApp.app
iphoneos_developer_dir="$(xcode-select -p)/Platforms/iPhoneOS.platform/Developer"
ditto "$iphoneos_developer_dir/Library/Frameworks/Testing.framework" Payload/CppUnitTestsApp.app/Frameworks/Testing.framework
ditto "$iphoneos_developer_dir/usr/lib/lib_TestingInterop.dylib" Payload/CppUnitTestsApp.app/Frameworks/lib_TestingInterop.dylib
chmod -R u+w Payload/CppUnitTestsApp.app
zip -r CppUnitTestsApp.zip Payload
mv CppUnitTestsApp.zip CppUnitTestsApp.ipa
cd Payload/CppUnitTestsApp.app/PlugIns
zip -r "$ios_cpp_test_app_dir"/CppUnitTests.xctest.zip CppUnitTests.xctest
echo ios_cpp_test_artifacts_dir="$ios_cpp_test_app_dir" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ios-cpp-unit-tests
retention-days: 3
if-no-files-found: error
path: |
${{ env.ios_cpp_test_artifacts_dir }}/CppUnitTests.xctest.zip
${{ env.ios_cpp_test_artifacts_dir }}/CppUnitTestsApp.ipa
# Size test (Bloaty)
- name: Build dynamic library for size test (Bloaty)
run: |
bazel build //platform/ios:MapLibre.dynamic --//:renderer=metal --compilation_mode="opt" --copt -g --copt="-Oz" --strip never --output_groups=+dsyms --apple_generate_dsym
bazel_bin="$(bazel info --compilation_mode="opt" bazel-bin)"
unzip "$bazel_bin"/platform/ios/MapLibre.dynamic.xcframework.zip
cp "$bazel_bin"/platform/ios/MapLibre.dynamic_dsyms/MapLibre_ios_device.framework.dSYM/Contents/Resources/DWARF/MapLibre_ios_device MapLibre_DWARF
cp MapLibre.xcframework/ios-arm64/MapLibre.framework/MapLibre MapLibre_dynamic
- name: Upload size test as artifact (Bloaty)
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ios-size-test-files
retention-days: 3
if-no-files-found: error
path: |
platform/ios/MapLibre_DWARF
platform/ios/MapLibre_dynamic
- name: Configure AWS Credentials
if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}
role-session-name: ${{ github.run_id }}
- name: Upload MapLibre_DWARF & MapLibre_dynamic to S3
if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME
run: |
aws s3 cp MapLibre_DWARF s3://maplibre-native/size-test-ios/MapLibre_DWARF-main
aws s3 cp MapLibre_dynamic s3://maplibre-native/size-test-ios/MapLibre_dynamic-main
- if: github.event_name == 'pull_request'
uses: ./.github/actions/save-pr-number
- name: Build DocC documentation
working-directory: .
run: |
HOSTING_BASE_PATH="maplibre-native/ios/latest" platform/ios/scripts/docc.sh
ios-build-cmake:
needs: pre_job
runs-on: macos-14
if: needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
submodules: recursive
- name: Configure sccache
uses: ./.github/actions/configure-sccache-s3
with:
vars: ${{ toJSON(vars) }}
- name: Initialize sccache
run: |
sccache --start-server
sccache --zero-stats
- name: Configure build with CMake
run: |
cmake --preset ios-metal \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build mbgl-core
run: cmake --build build-ios --target mbgl-core ios-sdk-static app
- name: Show sccache stats
if: always()
run: |
sccache --show-stats
ios-build-webgpu-dawn:
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: macos-26
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
submodules: recursive
persist-credentials: false
- name: Configure sccache
uses: ./.github/actions/configure-sccache-s3
with:
vars: ${{ toJSON(vars) }}
- name: Initialize sccache
run: |
sccache --start-server
sccache --zero-stats
- name: Configure build with CMake
run: |
cmake --preset ios-webgpu-dawn \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build mbgl-core and iOS SDK
continue-on-error: true
run: cmake --build build-ios-webgpu-dawn --target mbgl-core ios-sdk-static
- name: Show sccache stats
if: always()
run: |
sccache --show-stats
ios-build-webgpu-wgpu:
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: macos-26
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
submodules: recursive
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- name: Ensure iOS Rust targets are installed for active toolchain
working-directory: vendor/wgpu-native
run: |
# vendor/wgpu-native pins its own rust toolchain; install targets for that active toolchain
ACTIVE_TOOLCHAIN=$(rustup show active-toolchain | awk '{print $1}')
rustup target add aarch64-apple-ios --toolchain "$ACTIVE_TOOLCHAIN"
rustup target list --toolchain "$ACTIVE_TOOLCHAIN" --installed | grep -x 'aarch64-apple-ios'
- name: Configure sccache
uses: ./.github/actions/configure-sccache-s3
with:
vars: ${{ toJSON(vars) }}
- name: Initialize sccache
run: |
sccache --start-server
sccache --zero-stats
- name: Configure build with CMake
run: |
RUSTC_WRAPPER=sccache cmake --preset ios-webgpu-wgpu \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build mbgl-core and iOS SDK
continue-on-error: true
run: RUSTC_WRAPPER=sccache cmake --build build-ios-webgpu-wgpu --target mbgl-core ios-sdk-static
- name: Show sccache stats
if: always()
run: |
sccache --show-stats
ios-ci-result:
runs-on: ubuntu-latest
if: needs.pre_job.outputs.should_skip != 'true' && always()
needs:
- pre_job
- ios-build
- ios-build-cmake
- ios-build-webgpu-dawn
- ios-build-webgpu-wgpu
steps:
- name: Mark result as failed
if: needs.ios-build.result != 'success' || needs.ios-build-cmake.result != 'success'
run: exit 1
# Trigger release on main if VERSION file changed
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
if: github.ref == 'refs/heads/main'
with:
persist-credentials: false
- name: VERSION file changed
if: github.ref == 'refs/heads/main'
id: version-file-ios-changed
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files: platform/ios/VERSION
- name: Run release
if: github.ref == 'refs/heads/main' && steps.version-file-ios-changed.outputs.any_changed == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: gh workflow run ios-release.yml --ref ${{ github.ref }}