Skip to content

Commit 12be867

Browse files
authored
Changes in provisioning to fix fails installing Appium on Linux (dotnet#29105)
* Changes in provisioning to fix fails installing Appium on Linux * Fix mistake * More changes, try to install appium drivers with elevated privileges (if normal install fails) * More changes * Display the installed drivers
1 parent acdb6f2 commit 12be867

1 file changed

Lines changed: 171 additions & 68 deletions

File tree

src/Provisioning/Provisioning.csproj

Lines changed: 171 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.Build.NoTargets">
1+
<Project Sdk="Microsoft.Build.NoTargets">
22

33
<!-- Imports all the Provisioning versions -->
44
<Import Project="../../eng/Versions.props" />
@@ -116,78 +116,181 @@
116116
<!-- * Appium Provisioning -->
117117
<!-- ******************************************** -->
118118

119-
<Target Name="ProvisionAppiumDrivers" DependsOnTargets="InstallAppium">
120-
121-
<!-- Get a json output list of the installed appium drivers with their version info -->
122-
<Exec Command="appium driver list --installed --json" ConsoleToMSBuild="True" IgnoreExitCode="True">
123-
<Output TaskParameter="ConsoleOutput" ItemName="_AppiumDriverListInstalledJsonLines" />
124-
</Exec>
125-
126-
<!-- Concatenate the item group console output lines into one single property string -->
127-
<PropertyGroup>
128-
<_AppiumDriverListInstalledJson>@(_AppiumDriverListInstalledJsonLines->'%(Identity)', ' ')</_AppiumDriverListInstalledJson>
129-
</PropertyGroup>
130-
131-
<!-- Get the version of each driver from the JSON output and put it in a property -->
132-
<JsonPeek Content="$(_AppiumDriverListInstalledJson)" Query="$.%(AppiumDrivers.Identity).version">
133-
<Output TaskParameter="Result" PropertyName="_AppiumVersion_%(AppiumDrivers.Identity)" />
134-
</JsonPeek>
135-
136-
<!-- Get the groups of drivers to install vs update based on the versions resolved and expected -->
137-
<ItemGroup>
138-
<AppiumDriversToInstall Include="@(AppiumDrivers)" KeepMetadata="Version" Condition=" '$(_AppiumVersion_%(AppiumDrivers.Identity))' == '' " />
139-
<AppiumDriversToUpdate Include="@(AppiumDrivers)" KeepMetadata="Version" Condition=" '$(_AppiumVersion_%(AppiumDrivers.Identity))' != '' AND '$(_AppiumVersion_%(AppiumDrivers.Identity))' != '%(AppiumDrivers.Version)' " />
140-
</ItemGroup>
141-
142-
143-
<!-- Update any drivers needing an update (if any) -->
144-
<Exec Command="appium driver update %(AppiumDriversToUpdate.Identity)" Condition=" '@(AppiumDriversToUpdate)' != '' " />
145-
146-
<!-- Install any drivers not yet installed (if any) -->
147-
<Exec Command="appium driver install %(AppiumDriversToInstall.Identity)@%(AppiumDriversToInstall.Version)" Condition=" '@(AppiumDriversToInstall)' != '' " />
148-
149-
<!-- Run doctor command just so we have some output -->
150-
<Exec Command="appium driver doctor %(AppiumDrivers.Identity)" ContinueOnError="true" Condition=" '$(SkipAppiumDoctor)' != 'True' " />
151-
152-
<!-- Run driver list again for our records -->
153-
<Exec Command="appium driver list --installed" ContinueOnError="true" />
154-
</Target>
155-
156-
<Target Name="InstallAppium">
157-
<!-- Get the NPM package version for appium if installed -->
158-
<!-- this uses loglevel error to prevent extra noise in the console output that isn't json -->
159-
<Exec Command="npm list -g appium --json --depth 1 --loglevel error" ConsoleToMSBuild="True" IgnoreExitCode="True">
160-
<Output TaskParameter="ConsoleOutput" ItemName="_AppiumNpmListOutputLines" />
161-
</Exec>
162-
163-
<!-- Concat the console output lines into a single property -->
164-
<PropertyGroup>
165-
<_AppiumNpmListOutput>@(_AppiumNpmListOutputLines->'%(Identity)', ' ')</_AppiumNpmListOutput>
166-
</PropertyGroup>
167-
168-
<!-- Check if the output contains an error -->
169-
<PropertyGroup>
170-
<_AppiumNpmListHasError Condition="$(_AppiumNpmListOutput.Contains('error'))">True</_AppiumNpmListHasError>
171-
</PropertyGroup>
172-
173-
<!-- Peek the appium version info from the json output (only if no error) -->
174-
<JsonPeek Content="$(_AppiumNpmListOutput)" Query="$.dependencies.appium.version" Condition="'$(_AppiumNpmListHasError)' != 'True'">
175-
<Output TaskParameter="Result" PropertyName="_AppiumNpmListVersion" />
176-
</JsonPeek>
177-
178-
<!-- Set the version to empty if there was an error, which will force installation -->
179-
<PropertyGroup Condition="'$(_AppiumNpmListHasError)' == 'True'">
180-
<_AppiumNpmListVersion></_AppiumNpmListVersion>
181-
</PropertyGroup>
182-
183-
<!-- Install appium at the specified version if necessary -->
184-
<Exec Command="npm i --location=global appium@$(AppiumVersion)" Condition=" '$(_AppiumNpmListVersion)' != '$(AppiumVersion)' " />
185-
</Target>
119+
<Target Name="ProvisionAppiumDrivers" DependsOnTargets="InstallAppium">
120+
<!-- Create a temp file for JSON output to avoid string concatenation issues -->
121+
<PropertyGroup>
122+
<AppiumDriverListJsonFile>$(MSBuildThisFileDirectory)obj\appium-drivers.json</AppiumDriverListJsonFile>
123+
</PropertyGroup>
124+
125+
<!-- Ensure output directory exists -->
126+
<MakeDir Directories="$(MSBuildThisFileDirectory)obj" Condition="!Exists('$(MSBuildThisFileDirectory)obj')" />
127+
128+
<!-- Get JSON output list of installed appium drivers with their version info -->
129+
<Exec
130+
Command="appium driver list --installed --json > &quot;$(AppiumDriverListJsonFile)&quot;" StandardOutputImportance="low" StandardErrorImportance="high" ContinueOnError="true">
131+
<Output TaskParameter="ExitCode" PropertyName="AppiumDriverListExitCode" />
132+
</Exec>
133+
134+
<!-- Alert if driver list command failed -->
135+
<Warning
136+
Text="Failed to get Appium driver list (exit code: $(AppiumDriverListExitCode)). Will try to install all drivers."
137+
Condition="'$(AppiumDriverListExitCode)' != '0'" />
138+
139+
<!-- Read the JSON file content if it exists -->
140+
<ReadLinesFromFile File="$(AppiumDriverListJsonFile)" Condition="Exists('$(AppiumDriverListJsonFile)')">
141+
<Output TaskParameter="Lines" ItemName="_AppiumDriverListJsonLines" />
142+
</ReadLinesFromFile>
143+
144+
<!-- Join lines properly to create valid JSON -->
145+
<PropertyGroup>
146+
<_AppiumDriverListJson>@(_AppiumDriverListJsonLines, '')</_AppiumDriverListJson>
147+
</PropertyGroup>
148+
149+
<!-- Get the version of each driver from the JSON output and put it in a property -->
150+
<JsonPeek
151+
Content="$(_AppiumDriverListJson)" Query="$.%(AppiumDrivers.Identity).version" Condition="'$(_AppiumDriverListJson)' != ''">
152+
<Output TaskParameter="Result" PropertyName="_AppiumVersion_%(AppiumDrivers.Identity)" />
153+
</JsonPeek>
154+
155+
<!-- Get the groups of drivers to install vs update based on the versions resolved and expected -->
156+
<ItemGroup>
157+
<AppiumDriversToInstall Include="@(AppiumDrivers)" KeepMetadata="Version"
158+
Condition=" '$(_AppiumVersion_%(AppiumDrivers.Identity))' == '' " />
159+
<AppiumDriversToUpdate Include="@(AppiumDrivers)" KeepMetadata="Version"
160+
Condition=" '$(_AppiumVersion_%(AppiumDrivers.Identity))' != '' AND
161+
'$(_AppiumVersion_%(AppiumDrivers.Identity))' != '%(AppiumDrivers.Version)' " />
162+
</ItemGroup>
163+
164+
<!-- Log what we're going to do -->
165+
<Message Text="Appium drivers to update: @(AppiumDriversToUpdate->'%(Identity) ($(AppiumVersion_%(Identity)) → %(Version))', ', ')"
166+
Importance="high"
167+
Condition="'@(AppiumDriversToUpdate)' != ''" />
168+
<Message Text="Appium drivers to install: @(AppiumDriversToInstall->'%(Identity)@%(Version)', ', ')"
169+
Importance="high"
170+
Condition="'@(AppiumDriversToInstall)' != ''" />
171+
<Message Text="All Appium drivers are up-to-date."
172+
Importance="normal"
173+
Condition="'@(AppiumDriversToUpdate)' == '' AND '@(AppiumDriversToInstall)' == ''" />
174+
175+
<!-- Update any drivers needing an update (if any) with timeout -->
176+
<Exec
177+
Command="appium driver update %(AppiumDriversToUpdate.Identity)"
178+
Condition="'@(AppiumDriversToUpdate)' != ''"
179+
Timeout="300000"
180+
StandardOutputImportance="normal"
181+
StandardErrorImportance="high">
182+
<Output TaskParameter="ExitCode" PropertyName="_UpdateExitCode_%(AppiumDriversToUpdate.Identity)" />
183+
</Exec>
184+
185+
<!-- Install any drivers not yet installed (if any) with timeout -->
186+
<Exec
187+
Command="appium driver install %(AppiumDriversToInstall.Identity)@%(AppiumDriversToInstall.Version)"
188+
Condition="'@(AppiumDriversToInstall)' != ''"
189+
Timeout="300000"
190+
StandardOutputImportance="normal"
191+
StandardErrorImportance="high">
192+
<Output TaskParameter="ExitCode" PropertyName="_InstallExitCode_%(AppiumDriversToInstall.Identity)" />
193+
</Exec>
194+
195+
<!-- Run doctor command just as a batch for all drivers rather than one by one -->
196+
<PropertyGroup>
197+
<_AppiumDriversString>@(AppiumDrivers->'%(Identity)', ' ')</_AppiumDriversString>
198+
</PropertyGroup>
199+
200+
<Exec
201+
Command="appium driver doctor $(_AppiumDriversString)"
202+
ContinueOnError="true"
203+
Condition="'$(SkipAppiumDoctor)' != 'True'"
204+
StandardOutputImportance="normal"
205+
StandardErrorImportance="high"
206+
Timeout="120000" />
207+
208+
<!-- Run driver list again for our records -->
209+
<Exec Command="appium driver list --installed" ContinueOnError="true" StandardOutputImportance="normal" />
210+
</Target>
211+
212+
<Target Name="InstallAppium">
213+
<!-- Get the NPM package version for appium if installed -->
214+
<!-- this uses loglevel error to prevent extra noise in the console output that isn't json -->
215+
<Exec Command="npm list -g appium --json --depth 1 --loglevel error" ConsoleToMSBuild="True" IgnoreExitCode="True">
216+
<Output TaskParameter="ConsoleOutput" ItemName="_AppiumNpmListOutputLines" />
217+
</Exec>
218+
219+
<!-- Concat the console output lines into a single property -->
220+
<PropertyGroup>
221+
<_AppiumNpmListOutput>@(_AppiumNpmListOutputLines->'%(Identity)', '')</_AppiumNpmListOutput>
222+
</PropertyGroup>
223+
224+
<!-- Check if the output contains an error -->
225+
<PropertyGroup>
226+
<_AppiumNpmListHasError Condition="'$(_AppiumNpmListOutput)' == '' OR $(_AppiumNpmListOutput.Contains('error')) OR $(_AppiumNpmListOutput.Contains('ERR!'))">True</_AppiumNpmListHasError>
227+
</PropertyGroup>
228+
229+
<!-- Peek the appium version info from the json output (only if no error) -->
230+
<JsonPeek Content="$(_AppiumNpmListOutput)" Query="$.dependencies.appium.version" Condition="'$(_AppiumNpmListHasError)' != 'True'">
231+
<Output TaskParameter="Result" PropertyName="_AppiumNpmListVersion" />
232+
</JsonPeek>
233+
234+
<!-- Set the version to empty if there was an error, which will force installation -->
235+
<PropertyGroup Condition="'$(_AppiumNpmListHasError)' == 'True'">
236+
<_AppiumNpmListVersion></_AppiumNpmListVersion>
237+
</PropertyGroup>
238+
239+
<!-- Define privilege escalation commands -->
240+
<PropertyGroup Condition=" '$(IsMacOS)' == 'True' OR '$(IsLinux)' == 'True' ">
241+
<!-- macOS/Linux privilege elevation -->
242+
<ElevatedNpmCommand>sudo -E npm i --location=global appium@$(AppiumVersion)</ElevatedNpmCommand>
243+
</PropertyGroup>
244+
245+
<PropertyGroup Condition=" '$(IsWindows)' == 'True' ">
246+
<!-- Windows privilege elevation -->
247+
<ElevatedNpmCommand>powershell -ExecutionPolicy Bypass -Command "Start-Process -FilePath 'cmd.exe' -ArgumentList '/c npm i --location=global appium@$(AppiumVersion)' -Verb RunAs -Wait"</ElevatedNpmCommand>
248+
</PropertyGroup>
249+
250+
<!-- Try normal install first -->
251+
<Exec
252+
Command="npm i --location=global appium@$(AppiumVersion)"
253+
Condition="'$(_AppiumNpmListVersion)' != '$(AppiumVersion)'"
254+
Timeout="600000"
255+
StandardOutputImportance="normal"
256+
StandardErrorImportance="high"
257+
ContinueOnError="true"
258+
IgnoreExitCode="true">
259+
<Output TaskParameter="ExitCode" PropertyName="NpmExitCode" />
260+
</Exec>
261+
262+
<!-- If normal install fails, try with elevated privileges -->
263+
<Exec
264+
Command="$(ElevatedNpmCommand)"
265+
Condition="'$(_AppiumNpmListVersion)' != '$(AppiumVersion)' AND '$(NpmExitCode)' != '0' AND '$(ElevatedNpmCommand)' != ''"
266+
Timeout="600000"
267+
StandardOutputImportance="normal"
268+
StandardErrorImportance="high"
269+
ContinueOnError="true" />
270+
</Target>
186271

187272
<Target Name="ProvisionAppium" DependsOnTargets="InstallAppium;ProvisionAppiumDrivers">
188273
<Error
189274
Condition=" '$(MSBuildRuntimeType)' != 'Core' "
190275
Text="You should only run this target with 'dotnet build'." />
276+
277+
<!-- Final validation to confirm all drivers are installed correctly -->
278+
<Exec
279+
Command="appium driver list --installed --json > &quot;$(MSBuildThisFileDirectory)obj\final-appium-drivers.json&quot;"
280+
ContinueOnError="true"
281+
StandardOutputImportance="low"
282+
StandardErrorImportance="high" />
283+
284+
<!-- Read the content from the saved file -->
285+
<ReadLinesFromFile
286+
File="$(MSBuildThisFileDirectory)obj\final-appium-drivers.json">
287+
<Output TaskParameter="Lines" PropertyName="AppiumDriverOutput" />
288+
</ReadLinesFromFile>
289+
290+
<!-- Display the driver list result -->
291+
<Message Text="Appium driver list result: $(AppiumDriverOutput)" Importance="high" />
292+
293+
<Message Text="Appium provisioning completed successfully." Importance="high" />
191294
</Target>
192295

193296
<!-- ******************************************** -->

0 commit comments

Comments
 (0)