Information and motivation
I am working right now on a migration from a Jenkins build pipeline to an Azure DevOps pipeline.
Some details on the environment:
- On premise Azure DevOps Server 2020 bundled with on premise Azure Pipeline agents are used
- Azure Pipeline agents were already used in the past for build of non-C++ and rather small projects
- Existing Azure Pipeline agents are Linux or Docker based only
The product to be migrated is a big C++ project.
Some details on the project:
- Commercial product
- private git repository hosted in Azure DevOps Server
- Pull requests with quality gates to multiple production branches
- Dedicated builds for Windows, Debian, RedHat EL/Oracle Linux, Android, iOS
- Distributed object cache (sccache stored into redis in memory db) is enabled to have reasonable build times
iOS has maybe caught the eye. To migrate this pipeline an Azure Pipeline agent for MacOS is required.
I came up with a rather small commandset to download and manually run the agent and a first test was successful (build and sign the iOS app):
Unattended startup
When working with Jenkins, Jenkins started it´s agent by opening an SSH session to the MacOS host and Jenkins took care to start the agent via that SSH connection.
With Azure Pipeline agents this is not possible and one needs to start those agents somehow yourself, but I have not seen a good example on Microsoft documentation about it, just some hint about Launch Agents.
Upon taking a deeper look at that, I noticed, that Launch Agents are only started once a user logs in. This is not suitable as direct/graphical access to those machines is not desired.
The alternative are LaunchDaemons so after googling around I created my first launch daemon plist file and saved it to /Library/LaunchDaemons/com.microsoft.azagent.plist:
By running
the daemon started and connection was successful, also after a reboot.
It does not work
After running a build some problems were observed in comparison to manually running the agent.
Unlock keychain
In general, to sign an iOS app a certificate needs to be available in a keychain, this is done by the following command before signing:
When running the agent via daemon, an error was thrown during above command:
To solve this error the a property was added to the plist file:
Certificate access
With access to the keychain the build presented and error during signing which is widely known:
MacOS has some additional check enabled for command line access to those signing certificates.
This error message is typically mitigated by login into the GUI session and sign something in that session via command line. A popup asks for permission which you "Always allow":
After that, at least for the Jenkins agent or a remote SSH connection, signing from the command line works after unlocking the keychain.
But this was not the case for the Azure Pipeline agent started via LaunchDaemon.
Tests using custom keychains did not work either resulted in the same error message or others like:
But this was not the case for the Azure Pipeline agent started via LaunchDaemon.
A different approach (which works)
During my research and tests I came across a post suggesting to let the LaunchDaemon run an SSH connection to localhost to get a proper session. I knew already that it works when running the agent manually via SSH, but how to automate that?
The idea is to have a password-less SSH connection to localhost and automatically run the agent. This can be achieved by the following commands:
Also the plist file needs to be adapted slightly
With those adaptations finally everything worked on MacOS build agents. Hooray!
You can use all main cryptos like BTC, BCH, ETH, and LTC, but additionally lower-cap cash. Crypto transactions have zero charges hooked up and require 48 hours for handling. You will not 1xbet discover more fee choices anywhere else than on Super Slots. The platform helps 17 cryptocurrencies and 8 fiat banking strategies. a hundred and fifty video games is a decent collection, particularly since they all come from one developer - RealTime Gaming.
ReplyDelete