diff --git a/DeviceTests/DeviceTests.Android/MainActivity.cs b/DeviceTests/DeviceTests.Android/MainActivity.cs index 4a0908899..5e176fe81 100644 --- a/DeviceTests/DeviceTests.Android/MainActivity.cs +++ b/DeviceTests/DeviceTests.Android/MainActivity.cs @@ -18,7 +18,7 @@ protected override void OnCreate(Bundle bundle) Xamarin.Essentials.Platform.Init(this, bundle); var hostIp = Intent.Extras?.GetString("HOST_IP", null); - var hostPort = Intent.Extras?.GetInt("HOST_PORT", 10578) ?? 10578; + var hostPort = Intent.Extras?.GetInt("HOST_PORT", 63559) ?? 63559; if (!string.IsNullOrEmpty(hostIp)) { diff --git a/DeviceTests/build.cake b/DeviceTests/build.cake index f0d304342..53fbac817 100644 --- a/DeviceTests/build.cake +++ b/DeviceTests/build.cake @@ -1,38 +1,55 @@ #addin nuget:?package=Cake.AppleSimulator&version=0.2.0 #addin nuget:?package=Cake.Android.Adb&version=3.2.0 #addin nuget:?package=Cake.Android.AvdManager&version=2.2.0 -#addin nuget:?package=Cake.FileHelpers +#addin nuget:?package=Cake.FileHelpers&version=3.3.0 var TARGET = Argument("target", "Default"); -var IOS_SIM_NAME = EnvironmentVariable("IOS_SIM_NAME") ?? "iPhone 11"; -var IOS_SIM_RUNTIME = EnvironmentVariable("IOS_SIM_RUNTIME") ?? "com.apple.CoreSimulator.SimRuntime.iOS-13-1"; +var IOS_SIM_NAME = Argument("ios-device", EnvironmentVariable("IOS_SIM_NAME") ?? "iPhone 11"); +var IOS_SIM_RUNTIME = Argument("ios-runtime", EnvironmentVariable("IOS_SIM_RUNTIME") ?? "com.apple.CoreSimulator.SimRuntime.iOS-13-6"); var IOS_PROJ = "./DeviceTests.iOS/DeviceTests.iOS.csproj"; var IOS_BUNDLE_ID = "com.xamarin.essentials.devicetests"; var IOS_IPA_PATH = "./DeviceTests.iOS/bin/iPhoneSimulator/Release/XamarinEssentialsDeviceTestsiOS.app"; -var IOS_TEST_RESULTS_PATH = "./xunit-ios.xml"; +var IOS_TEST_RESULTS_PATH = MakeAbsolute((FilePath)"../output/test-results/ios/TestResults.xml"); var ANDROID_PROJ = "./DeviceTests.Android/DeviceTests.Android.csproj"; var ANDROID_APK_PATH = "./DeviceTests.Android/bin/Release/com.xamarin.essentials.devicetests-Signed.apk"; -var ANDROID_TEST_RESULTS_PATH = "./xunit-android.xml"; +var ANDROID_TEST_RESULTS_PATH = MakeAbsolute((FilePath)"../output/test-results/android/TestResults.xml"); +var ANDROID_SCREENSHOT_PATH = MakeAbsolute((DirectoryPath)"../output/test-results/android"); var ANDROID_AVD = EnvironmentVariable("ANDROID_AVD") ?? "CABOODLE"; var ANDROID_PKG_NAME = "com.xamarin.essentials.devicetests"; -var ANDROID_EMU_TARGET = EnvironmentVariable("ANDROID_EMU_TARGET") ?? "system-images;android-29;google_apis_playstore;x86_64"; -var ANDROID_EMU_DEVICE = EnvironmentVariable("ANDROID_EMU_DEVICE") ?? "pixel"; +var ANDROID_EMU_TARGET = Argument("avd-target", EnvironmentVariable("ANDROID_EMU_TARGET") ?? "system-images;android-29;google_apis_playstore;x86"); +var ANDROID_EMU_DEVICE = Argument("avd-device", EnvironmentVariable("ANDROID_EMU_DEVICE") ?? "Nexus 5X"); var UWP_PROJ = "./DeviceTests.UWP/DeviceTests.UWP.csproj"; -var UWP_TEST_RESULTS_PATH = "./xunit-uwp.xml"; +var UWP_TEST_RESULTS_PATH = MakeAbsolute((FilePath)"../output/test-results/uwp/TestResults.xml"); var UWP_PACKAGE_ID = "ec0cc741-fd3e-485c-81be-68815c480690"; var TCP_LISTEN_TIMEOUT = 240; -var TCP_LISTEN_PORT = 10578; +var TCP_LISTEN_PORT = 63559; var TCP_LISTEN_HOST = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()) - .AddressList.First(f => f.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString(); + .AddressList.First(f => f.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) + .ToString(); + +var OUTPUT_PATH = MakeAbsolute((DirectoryPath)"../output/"); var ANDROID_HOME = EnvironmentVariable("ANDROID_HOME"); -Func DownloadTcpTextAsync = (int port, FilePath filename) => - System.Threading.Tasks.Task.Run (() => { +System.Environment.SetEnvironmentVariable("PATH", + $"{ANDROID_HOME}/tools/bin" + System.IO.Path.PathSeparator + + $"{ANDROID_HOME}/platform-tools" + System.IO.Path.PathSeparator + + $"{ANDROID_HOME}/emulator" + System.IO.Path.PathSeparator + + EnvironmentVariable("PATH")); + + +// utils + +Task DownloadTcpTextAsync(int port, FilePath filename, Action waitAction = null) +{ + filename = MakeAbsolute(filename); + EnsureDirectoryExists(filename.GetDirectory()); + + return System.Threading.Tasks.Task.Run(() => { var tcpListener = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, port); tcpListener.Start(); var listening = true; @@ -40,9 +57,11 @@ Func DownloadTcpTextAsync = (int port, FilePath filename) = System.Threading.Tasks.Task.Run(() => { // Sleep until timeout elapses or tcp listener stopped after a successful connection var elapsed = 0; - while (elapsed <= TCP_LISTEN_TIMEOUT && listening) { + while(elapsed <= TCP_LISTEN_TIMEOUT && listening) { System.Threading.Thread.Sleep(1000); elapsed++; + Information($"Still waiting for tests... {elapsed}/{TCP_LISTEN_TIMEOUT}"); + waitAction?.Invoke(); } // If still listening, timeout elapsed, stop the listener @@ -54,76 +73,76 @@ Func DownloadTcpTextAsync = (int port, FilePath filename) = try { var tcpClient = tcpListener.AcceptTcpClient(); - var fileName = MakeAbsolute (filename).FullPath; - using (var file = System.IO.File.Open(fileName, System.IO.FileMode.Create)) + using (var file = System.IO.File.Open(filename.FullPath, System.IO.FileMode.Create)) using (var stream = tcpClient.GetStream()) stream.CopyTo(file); tcpClient.Close(); tcpListener.Stop(); - listening = false; + listening = false; } catch { throw new Exception("Test results listener failed or timed out."); } }); +} -Action AddPlatformToTestResults = (FilePath testResultsFile, string platformName) => { +void AddPlatformToTestResults(FilePath testResultsFile, string platformName) +{ if (FileExists(testResultsFile)) { var txt = FileReadText(testResultsFile); txt = txt.Replace(" + +// iOS tasks + +Task("build-ios") + .Does(() => { // Setup the test listener config to be built into the app FileWriteText((new FilePath(IOS_PROJ)).GetDirectory().CombineWithFilePath("tests.cfg"), $"{TCP_LISTEN_HOST}:{TCP_LISTEN_PORT}"); - // Nuget restore - MSBuild (IOS_PROJ, c => { - c.Configuration = "Release"; - c.Targets.Clear(); - c.Targets.Add("Restore"); - }); - - // Build the project (with ipa) - MSBuild (IOS_PROJ, c => { + MSBuild(IOS_PROJ, c => { c.Configuration = "Release"; + c.Restore = true; c.Properties["Platform"] = new List { "iPhoneSimulator" }; c.Properties["BuildIpa"] = new List { "true" }; c.Properties["ContinuousIntegrationBuild"] = new List { "false" }; c.Targets.Clear(); c.Targets.Add("Rebuild"); + c.BinaryLogger = new MSBuildBinaryLogSettings { + Enabled = true, + FileName = OUTPUT_PATH.CombineWithFilePath("binlogs/device-tests-ios-build.binlog").FullPath, + }; }); }); -Task ("test-ios-emu") - .IsDependentOn ("build-ios") - .Does (() => +Task("test-ios-emu") + .IsDependentOn("build-ios") + .Does(() => { - var sims = ListAppleSimulators (); - foreach (var s in sims) - { - Information("Info: {0} ({1} - {2} - {3})", s.Name, s.Runtime, s.UDID, s.Availability); + var sims = ListAppleSimulators(); + foreach (var s in sims) { + Information("Info: {0}({1} - {2} - {3})", s.Name, s.Runtime, s.UDID, s.Availability); } // Look for a matching simulator on the system - var sim = sims.First (s => s.Name == IOS_SIM_NAME && s.Runtime == IOS_SIM_RUNTIME); + var sim = sims.First(s => s.Name == IOS_SIM_NAME && s.Runtime == IOS_SIM_RUNTIME); // Boot the simulator - Information("Booting: {0} ({1} - {2})", sim.Name, sim.Runtime, sim.UDID); - if (!sim.State.ToLower().Contains ("booted")) - BootAppleSimulator (sim.UDID); + Information("Booting: {0}({1} - {2})", sim.Name, sim.Runtime, sim.UDID); + if (!sim.State.ToLower().Contains("booted")) + BootAppleSimulator(sim.UDID); // Wait for it to be booted var booted = false; for (int i = 0; i < 100; i++) { - if (ListAppleSimulators().Any (s => s.UDID == sim.UDID && s.State.ToLower().Contains("booted"))) { + if (ListAppleSimulators().Any(s => s.UDID == sim.UDID && s.State.ToLower().Contains("booted"))) { booted = true; break; } @@ -132,12 +151,12 @@ Task ("test-ios-emu") // Install the IPA that was previously built var ipaPath = new FilePath(IOS_IPA_PATH); - Information ("Installing: {0}", ipaPath); + Information("Installing: {0}", ipaPath); InstalliOSApplication(sim.UDID, MakeAbsolute(ipaPath).FullPath); // Start our Test Results TCP listener Information("Started TCP Test Results Listener on port: {0}", TCP_LISTEN_PORT); - var tcpListenerTask = DownloadTcpTextAsync (TCP_LISTEN_PORT, IOS_TEST_RESULTS_PATH); + var tcpListenerTask = DownloadTcpTextAsync(TCP_LISTEN_PORT, IOS_TEST_RESULTS_PATH); // Launch the IPA Information("Launching: {0}", IOS_BUNDLE_ID); @@ -145,53 +164,53 @@ Task ("test-ios-emu") // Wait for the TCP listener to get results Information("Waiting for tests..."); - tcpListenerTask.Wait (); + tcpListenerTask.Wait(); AddPlatformToTestResults(IOS_TEST_RESULTS_PATH, "iOS"); // Close up simulators Information("Closing Simulator"); - ShutdownAllAppleSimulators (); + ShutdownAllAppleSimulators(); }); -Task ("build-android") - .Does (() => -{ - // Nuget restore - MSBuild (ANDROID_PROJ, c => { - c.Configuration = "Debug"; - c.Targets.Clear(); - c.Targets.Add("Restore"); - }); +// Android tasks +Task("build-android") + .Does(() => +{ // Build the app in debug mode // needs to be debug so unit tests get discovered - MSBuild (ANDROID_PROJ, c => { + MSBuild(ANDROID_PROJ, c => { c.Configuration = "Debug"; + c.Restore = true; c.Properties["ContinuousIntegrationBuild"] = new List { "false" }; c.Targets.Clear(); c.Targets.Add("Rebuild"); + c.BinaryLogger = new MSBuildBinaryLogSettings { + Enabled = true, + FileName = OUTPUT_PATH.CombineWithFilePath("binlogs/device-tests-android-build.binlog").FullPath, + }; }); }); -Task ("test-android-emu") - .IsDependentOn ("build-android") - .Does (() => +Task("test-android-emu") + .IsDependentOn("build-android") + .Does(() => { - var avdSettings = new AndroidAvdManagerToolSettings { SdkRoot = ANDROID_HOME }; - var emuSettings = new AndroidEmulatorToolSettings { SdkRoot = ANDROID_HOME }; + var avdSettings = new AndroidAvdManagerToolSettings { SdkRoot = ANDROID_HOME }; // Delete AVD first, if it exists - Information ("Deleting AVD if exists: {0}...", ANDROID_AVD); + Information("Deleting AVD if exists: {0}...", ANDROID_AVD); try { AndroidAvdDelete(ANDROID_AVD, avdSettings); } catch { } // Create the AVD - Information ("Creating AVD: {0}...", ANDROID_AVD); - AndroidAvdCreate (ANDROID_AVD, ANDROID_EMU_TARGET, ANDROID_EMU_DEVICE, force: true, settings: avdSettings); - - Information ("Starting Emulator: {0}...", ANDROID_AVD); + Information("Creating AVD: {0}...", ANDROID_AVD); + AndroidAvdCreate(ANDROID_AVD, ANDROID_EMU_TARGET, ANDROID_EMU_DEVICE, force: true, settings: avdSettings); + + Information("Starting Emulator: {0}...", ANDROID_AVD); + var emuSettings = new AndroidEmulatorToolSettings { SdkRoot = ANDROID_HOME, ArgumentCustomization = args => args.Append("-no-window") }; var emulatorProcess = AndroidEmulatorStart(ANDROID_AVD, emuSettings); var adbSettings = new AdbToolSettings { SdkRoot = ANDROID_HOME }; @@ -212,38 +231,54 @@ Task ("test-android-emu") System.Threading.Thread.Sleep(1000); } - Information ("Matched ADB Serial: {0}", emuSerial); + Information("Matched ADB Serial: {0}", emuSerial); adbSettings = new AdbToolSettings { SdkRoot = ANDROID_HOME, Serial = emuSerial }; // Wait for the emulator to enter a 'booted' state AdbWaitForEmulatorToBoot(TimeSpan.FromSeconds(100), adbSettings); - Information ("Emulator finished booting."); + Information("Emulator finished booting."); + + // Read the logcat + AdbLogcat(new AdbLogcatOptions { Clear = true }, settings: adbSettings); + AdbLogcat(settings: adbSettings); - // Try uninstalling the existing package (if installed) - try { - AdbUninstall (ANDROID_PKG_NAME, false, adbSettings); - Information ("Uninstalled old: {0}", ANDROID_PKG_NAME); + // Try uninstalling the existing package(if installed) + try { + AdbUninstall(ANDROID_PKG_NAME, false, adbSettings); + Information("Uninstalled old: {0}", ANDROID_PKG_NAME); } catch { } // Use the Install target to push the app onto emulator - MSBuild (ANDROID_PROJ, c => { + MSBuild(ANDROID_PROJ, c => { c.Configuration = "Debug"; c.Properties["ContinuousIntegrationBuild"] = new List { "false" }; c.Properties["AdbTarget"] = new List { "-s " + emuSerial }; c.Targets.Clear(); c.Targets.Add("Install"); + c.BinaryLogger = new MSBuildBinaryLogSettings { + Enabled = true, + FileName = OUTPUT_PATH.CombineWithFilePath("binlogs/device-tests-android-install.binlog").FullPath, + }; }); // Start the TCP Test results listener Information("Started TCP Test Results Listener on port: {0}:{1}", TCP_LISTEN_HOST, TCP_LISTEN_PORT); - var tcpListenerTask = DownloadTcpTextAsync (TCP_LISTEN_PORT, ANDROID_TEST_RESULTS_PATH); + // var printed = false; + var tcpListenerTask = DownloadTcpTextAsync(TCP_LISTEN_PORT, ANDROID_TEST_RESULTS_PATH, () => { + // if (!printed) { + // AdbScreenCapture(ANDROID_SCREENSHOT_PATH.CombineWithFilePath($"screenshot.png"), adbSettings); + // AdbLogcat(settings: adbSettings); + // printed = true; + // } + }); // Launch the app on the emulator - AdbShell ($"am start -n {ANDROID_PKG_NAME}/{ANDROID_PKG_NAME}.MainActivity --es HOST_IP {TCP_LISTEN_HOST} --ei HOST_PORT {TCP_LISTEN_PORT}", adbSettings); + AdbShell($"am start -n {ANDROID_PKG_NAME}/{ANDROID_PKG_NAME}.MainActivity --es HOST_IP {TCP_LISTEN_HOST} --ei HOST_PORT {TCP_LISTEN_PORT}", adbSettings); + AdbLogcat(settings: adbSettings); // Wait for the test results to come back Information("Waiting for tests..."); - tcpListenerTask.Wait (); + tcpListenerTask.Wait(); AddPlatformToTestResults(ANDROID_TEST_RESULTS_PATH, "Android"); @@ -260,55 +295,54 @@ Task ("test-android-emu") }); -Task ("build-uwp") - .Does (() => -{ - // Nuget restore - MSBuild (UWP_PROJ, c => { - c.Targets.Clear(); - c.Targets.Add("Restore"); - }); +// UWP tasks - // Build the project (with ipa) - MSBuild (UWP_PROJ, c => { +Task("build-uwp") + .Does(() => +{ + MSBuild(UWP_PROJ, c => { c.Configuration = "Debug"; + c.Restore = true; c.Properties["ContinuousIntegrationBuild"] = new List { "false" }; c.Properties["AppxBundlePlatforms"] = new List { "x86" }; c.Properties["AppxBundle"] = new List { "Always" }; c.Targets.Clear(); c.Targets.Add("Rebuild"); + c.BinaryLogger = new MSBuildBinaryLogSettings { + Enabled = true, + FileName = OUTPUT_PATH.CombineWithFilePath("binlogs/device-tests-uwp-build.binlog").FullPath, + }; }); }); - -Task ("test-uwp-emu") - .IsDependentOn ("build-uwp") +Task("test-uwp-emu") + .IsDependentOn("build-uwp") .WithCriteria(IsRunningOnWindows()) - .Does (() => + .Does(() => { - var uninstallPS = new Action (() => { + var uninstallPS = new Action(() => { try { - StartProcess ("powershell", + StartProcess("powershell", "$app = Get-AppxPackage -Name " + UWP_PACKAGE_ID + "; if ($app) { Remove-AppxPackage -Package $app.PackageFullName }"); } catch { } }); // Try to uninstall the app if it exists from before uninstallPS(); - + // Install the appx var dependencies = GetFiles("./**/AppPackages/**/Dependencies/x86/*.appx"); foreach (var dep in dependencies) { Information("Installing Dependency appx: {0}", dep); StartProcess("powershell", "Add-AppxPackage -Path \"" + MakeAbsolute(dep).FullPath + "\""); } - var appxBundlePath = GetFiles("./**/AppPackages/**/*.appxbundle").First (); + var appxBundlePath = GetFiles("./**/AppPackages/**/*.appxbundle").First(); Information("Installing appx: {0}", appxBundlePath); - StartProcess ("powershell", "Add-AppxPackage -Path \"" + MakeAbsolute(appxBundlePath).FullPath + "\""); + StartProcess("powershell", "Add-AppxPackage -Path \"" + MakeAbsolute(appxBundlePath).FullPath + "\""); // Start the TCP Test results listener Information("Started TCP Test Results Listener on port: {0}:{1}", TCP_LISTEN_HOST, TCP_LISTEN_PORT); - var tcpListenerTask = DownloadTcpTextAsync (TCP_LISTEN_PORT, UWP_TEST_RESULTS_PATH); + var tcpListenerTask = DownloadTcpTextAsync(TCP_LISTEN_PORT, UWP_TEST_RESULTS_PATH); // Launch the app Information("Running appx: {0}", appxBundlePath); @@ -317,12 +351,13 @@ Task ("test-uwp-emu") // Wait for the test results to come back Information("Waiting for tests..."); - tcpListenerTask.Wait (); + tcpListenerTask.Wait(); AddPlatformToTestResults(UWP_TEST_RESULTS_PATH, "UWP"); - // Uninstall the app (this will terminate it too) + // Uninstall the app(this will terminate it too) uninstallPS(); }); + RunTarget(TARGET); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 06123ac5a..4b89bfe8f 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.1 false XamarinEssentialsTests portable diff --git a/Xamarin.Essentials/Xamarin.Essentials.csproj b/Xamarin.Essentials/Xamarin.Essentials.csproj index bf7773b48..badb4d87f 100644 --- a/Xamarin.Essentials/Xamarin.Essentials.csproj +++ b/Xamarin.Essentials/Xamarin.Essentials.csproj @@ -15,7 +15,7 @@ 1.0.0.0 1.0.0.0 1.0.0 - $(Version)$(VersionSuffix) + 1.0.0 Microsoft microsoft,Xamarin,XamarinNuGet en diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 79f7bc85c..ea55d104d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,272 +1,151 @@ +trigger: + - main + - develop + - refs/tags/* + +pr: + - main + - develop variables: - CurrentSemanticVersionBase: '1.6.0' - PreviewNumber: $[counter(variables['CurrentSemanticVersionBase'], 1001)] - CurrentSemanticVersion: '$(CurrentSemanticVersionBase)-preview$(PreviewNumber)' - NugetPackageVersion: '$(CurrentSemanticVersion)' - MONO_VERSION: 6_8_0 - XCODE_VERSION: 11.3 - NETCORE_VERSION: '3.1.x' - NETCORE_TEST_VERSION: '2.2.x' - IOS_SIM_NAME: 'iPhone 11' - IOS_SIM_RUNTIME: 'com.apple.CoreSimulator.SimRuntime.iOS-13-3' - ANDROID_EMU_TARGET: 'system-images;android-26;google_apis;x86' - ANDROID_EMU_DEVICE: 'Nexus 5X' - RunPoliCheck: 'false' + BASE_VERSION: 1.6.0 + PREVIEW_LABEL: 'ci' + BUILD_NUMBER: $[counter(format('{0}_{1}_{2}', variables['BASE_VERSION'], variables['PREVIEW_LABEL'], variables['Build.SourceBranch']), 1)] + NUGET_VERSION: $[format('{0}-{1}.{2}', variables['BASE_VERSION'], variables['PREVIEW_LABEL'], variables['BUILD_NUMBER'])] + GIT_SHA: $(Build.SourceVersion) + GIT_BRANCH_NAME: $(Build.SourceBranchName) resources: repositories: - - repository: xamarin-templates + - repository: internal-templates type: github name: xamarin/yaml-templates endpoint: xamarin + - repository: components + type: github + name: xamarin/XamarinComponents + endpoint: xamarin -jobs: +stages: + - stage: prepare + displayName: Prepare Variables + jobs: + - job: prepare + displayName: Prepare Build + pool: + vmImage: ubuntu-latest + steps: + - checkout: none + - pwsh: | + $pr = "pr." + $env:SYSTEM_PULLREQUEST_PULLREQUESTNUMBER + $nuget = $env:BASE_VERSION + "-" + $pr + "." + $env:BUILD_NUMBER + Write-Host "Preview label: $pr" + Write-Host "NuGet version: $nuget" + Write-Host "##vso[task.setvariable variable=PREVIEW_LABEL]$pr" + Write-Host "##vso[task.setvariable variable=NUGET_VERSION]$nuget" + displayName: Use a special preview label for PRs + condition: eq(variables['Build.Reason'], 'PullRequest') + - pwsh: | + $tagVersion = $env:BUILD_SOURCEBRANCHNAME + Write-Host "Tag version: $tagVersion" + Write-Host "##vso[task.setvariable variable=NUGET_VERSION]$tagVersion" + displayName: Override version for tags + condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') + - pwsh: | + Write-Host "##vso[build.updatebuildnumber]$env:NUGET_VERSION" + displayName: Update the build number with a more readable one - - job: build_windows - displayName: Build Windows Library - pool: - vmImage: windows-2019 - steps: - # if this is a tagged build, then update the version number - - powershell: | - $buildSourceBranch = "$(Build.SourceBranch)" - $tagVersion = $buildSourceBranch.Substring($buildSourceBranch.LastIndexOf("/") + 1) - Write-Host("Branch = $buildSourceBranch, Version = $tagVersion"); - Write-Host ("##vso[task.setvariable variable=NugetPackageVersion;]$tagVersion") - displayName: Set NuGet Version to Tag Number - condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') - # restore, build and pack the packages - - task: MSBuild@1 - displayName: Build Solution - inputs: - solution: Xamarin.Essentials/Xamarin.Essentials.csproj - configuration: Release - msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false' - - task: MSBuild@1 - displayName: Pack NuGets - inputs: - solution: Xamarin.Essentials/Xamarin.Essentials.csproj - configuration: Release - msbuildArguments: '/t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"' -# - task: DotNetCoreCLI@2 -# displayName: Publish to GitHub NuGet Packages -# condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/master')) -# inputs: -# command: 'custom' -# custom: 'nuget' -# arguments: 'push --source https://nuget.pkg.github.com/xamarin/index.json --api-key $(GitHub.NuGet.Token) "$(Build.ArtifactStagingDirectory)\nuget\*.nupkg"' - - task: DotNetCoreCLI@2 - displayName: Run Tests - inputs: - command: test - projects: 'Tests/Tests.csproj' - arguments: '--configuration Release' - # publish the packages - - task: PublishBuildArtifacts@1 - displayName: 'Publish Unsigned NuGets' - inputs: - artifactName: nuget - pathToPublish: '$(Build.ArtifactStagingDirectory)/nuget' - # make sure we are following the rules, but only on the main build + - stage: build + displayName: Build Library + dependsOn: [ 'prepare' ] + jobs: + - template: .ci/build.yml@components + parameters: + areaPath: 'DevDiv\Xamarin SDK\Build and Tools' - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - condition: not(startsWith(variables['Build.SourceBranch'], 'refs/tags/')) - displayName: Component Detection - Log - inputs: - scanType: LogOnly - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') - displayName: Component Detection - Report - - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@1 - condition: eq(variables['RunPoliCheck'], 'true') - displayName: 'PoliCheck' - inputs: - targetType: F - - - job: build_macos - displayName: Build macOS Library - pool: - vmImage: macos-10.14 - steps: - # if this is a tagged build, then update the version number - - powershell: | - $buildSourceBranch = "$(Build.SourceBranch)" - $tagVersion = $buildSourceBranch.Substring($buildSourceBranch.LastIndexOf("/") + 1) - Write-Host("Branch = $buildSourceBranch, Version = $tagVersion"); - Write-Host ("##vso[task.setvariable variable=NugetPackageVersion;]$tagVersion") - displayName: Set NuGet Version to Tag Number - condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') - # make sure to select the correct Xamarin and mono - - bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MONO_VERSION) - displayName: Switch to the latest Xamarin SDK - - bash: echo '##vso[task.setvariable variable=MD_APPLE_SDK_ROOT;]'/Applications/Xcode_$(XCODE_VERSION).app;sudo xcode-select --switch /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer - displayName: Switch to the latest Xcode - # restore, build and pack the packages - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' - inputs: - version: $(NETCORE_VERSION) - includePreviewVersions: false - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' - inputs: - version: $(NETCORE_TEST_VERSION) - includePreviewVersions: false - - task: MSBuild@1 - displayName: Build Solution - inputs: - solution: Xamarin.Essentials/Xamarin.Essentials.csproj - configuration: Release - msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false' - - task: MSBuild@1 - displayName: Pack NuGets - inputs: - solution: Xamarin.Essentials/Xamarin.Essentials.csproj - configuration: Release - msbuildArguments: '/t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"' - - task: DotNetCoreCLI@2 - displayName: Run Tests - inputs: - command: test - projects: 'Tests/Tests.csproj' - arguments: '--configuration Release' + - template: sign-artifacts/jobs/v1.yml@internal-templates + parameters: + additionalConditions: eq(variables['Build.SourceBranch'], 'refs/heads/main') - - job: build_samples - displayName: Build Samples - pool: - vmImage: windows-2019 - steps: - # restore, build and pack the packages - - task: MSBuild@1 - displayName: Build Solution - inputs: - solution: Xamarin.Essentials.sln - configuration: Release - msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false' + - stage: devicetests + displayName: Device Tests + dependsOn: [ 'prepare' ] + jobs: + - job: devicetests_uwp + displayName: UWP + # skip for now + condition: and(succeeded(), not(succeeded())) + pool: + vmImage: windows-2019 + steps: + - script: 'certutil -importpfx $(Build.SourcesDirectory)\DeviceTests\DeviceTests.UWP\DeviceTests.UWP_TemporaryKey.pfx' + displayName: 'Run certutil' + - powershell: | + cd DeviceTests + .\build.ps1 --target=test-uwp-emu --settings_skipverification=true --verbosity=diagnostic + displayName: 'Run Device Tests - UWP' + - task: PublishTestResults@2 + displayName: 'Publish Test Results' + inputs: + testResultsFormat: XUnit + testResultsFiles: '**/xunit-*.xml' + testRunTitle: 'Device Tests - UWP' - - job: devicetests_uwp - displayName: Run UWP Device Tests - dependsOn: - - build_windows - - build_macos - # skip for now - condition: and(succeeded(), not(succeeded())) - pool: - vmImage: windows-2019 - steps: - - script: 'certutil -importpfx $(Build.SourcesDirectory)\DeviceTests\DeviceTests.UWP\DeviceTests.UWP_TemporaryKey.pfx' - displayName: 'Run certutil' - - powershell: | - cd DeviceTests - .\build.ps1 --target=test-uwp-emu --settings_skipverification=true --verbosity=diagnostic - displayName: 'Run Device Tests - UWP' - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFormat: XUnit - testResultsFiles: '**/xunit-*.xml' - testRunTitle: 'Device Tests - UWP' + - template: .ci/build.yml@components + parameters: + name: devicetests_ios + runChecks: false + displayName: iOS + windowsImage: '' + areaPath: 'DevDiv\Xamarin SDK\Build and Tools' + verbosity: diagnostic + cakeFile: DeviceTests/build.cake + cakeTarget: test-ios-emu - - job: devicetests_ios - displayName: Run iOS Device Tests - dependsOn: - - build_windows - - build_macos - pool: - vmImage: macos-10.14 - steps: - - bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MONO_VERSION) - displayName: Switch to the latest Xamarin SDK - - bash: echo '##vso[task.setvariable variable=MD_APPLE_SDK_ROOT;]'/Applications/Xcode_$(XCODE_VERSION).app;sudo xcode-select --switch /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer - displayName: Switch to the latest Xcode - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' - inputs: - version: $(NETCORE_VERSION) - includePreviewVersions: false - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' - inputs: - version: $(NETCORE_TEST_VERSION) - includePreviewVersions: false - - task: InstallAppleCertificate@2 - displayName: 'Install an Apple certificate' - inputs: - certSecureFile: 'Components iOS Certificate.p12' - - task: InstallAppleProvisioningProfile@1 - displayName: 'Install an Apple provisioning profile' - inputs: - provProfileSecureFile: 'Components iOS Provisioning.mobileprovision' - - bash: | - cd DeviceTests - dotnet tool install -g cake.tool --version 0.36.0 - dotnet cake --target=test-ios-emu --settings_skipverification=true --verbosity=diagnostic - displayName: 'Run Device Tests - iOS' - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFormat: XUnit - testResultsFiles: '**/xunit-*.xml' - testRunTitle: 'Device Tests - iOS' + - template: .ci/build.yml@components + parameters: + name: devicetests_android_api_23 + runChecks: false + displayName: Android API 23 + windowsImage: '' + macosImage: 'macos-10.14' + areaPath: 'DevDiv\Xamarin SDK\Build and Tools' + verbosity: diagnostic + cakeFile: DeviceTests/build.cake + cakeTarget: test-android-emu + cakeExtraArgs: --avd-target="`"system-images;android-23;google_apis;x86`"" + preBuildSteps: + - bash: sh -c "echo \"y\" | $ANDROID_HOME/tools/bin/sdkmanager \"system-images;android-23;google_apis;x86\"" + displayName: Install the Android emulators - - job: devicetests_android - displayName: Run Android Device Tests - dependsOn: - - build_windows - - build_macos - pool: - vmImage: macos-10.14 - steps: - - bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MONO_VERSION) - displayName: Switch to the latest Xamarin SDK - - bash: echo '##vso[task.setvariable variable=MD_APPLE_SDK_ROOT;]'/Applications/Xcode_$(XCODE_VERSION).app;sudo xcode-select --switch /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer - displayName: Switch to the latest Xcode - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' - inputs: - version: $(NETCORE_VERSION) - includePreviewVersions: false - - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' - inputs: - version: $(NETCORE_TEST_VERSION) - includePreviewVersions: false - - bash: sh -c "echo \"y\" | $ANDROID_HOME/tools/bin/sdkmanager \"$ANDROID_EMU_TARGET\"" - displayName: Install the Android emulators - - bash: | - PATH="$ANDROID_HOME/tools/bin:$PATH" - PATH="$ANDROID_HOME/emulator:$PATH" - cd DeviceTests - dotnet tool install -g cake.tool --version 0.36.0 - dotnet cake --target=test-android-emu --settings_skipverification=true --verbosity=diagnostic - displayName: 'Run Device Tests - Android' - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFormat: XUnit - testResultsFiles: '**/xunit-*.xml' - testRunTitle: 'Device Tests - Android' + - template: .ci/build.yml@components + parameters: + name: devicetests_android_api_26 + runChecks: false + displayName: Android API 26 + windowsImage: '' + macosImage: 'macos-10.14' + areaPath: 'DevDiv\Xamarin SDK\Build and Tools' + verbosity: diagnostic + cakeFile: DeviceTests/build.cake + cakeTarget: test-android-emu + cakeExtraArgs: --avd-target="`"system-images;android-26;google_apis;x86`"" + preBuildSteps: + - bash: sh -c "echo \"y\" | $ANDROID_HOME/tools/bin/sdkmanager \"system-images;android-26;google_apis;x86\"" + displayName: Install the Android emulators - # only sign the packages when running on Windows, and using the private server which has the certificates - - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: - - job: signing - displayName: Signing NuGets - dependsOn: build_windows - pool: - name: VSEng-XamarinCustom - demands: - - corpnet - condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/')) - steps: - # don't checkout code and sign the packages - - checkout: none - - template: sign-artifacts.yml@xamarin-templates - parameters: - targetFolder: '$(Build.ArtifactStagingDirectory)/signed' - # publish the signed packages - - task: PublishBuildArtifacts@1 - displayName: 'Publish Signed NuGets' - inputs: - artifactName: nuget-signed - pathToPublish: '$(Build.ArtifactStagingDirectory)/signed' + - template: .ci/build.yml@components + parameters: + name: devicetests_android_api_29 + runChecks: false + displayName: Android API 29 + windowsImage: '' + macosImage: 'macos-10.14' + areaPath: 'DevDiv\Xamarin SDK\Build and Tools' + verbosity: diagnostic + cakeFile: DeviceTests/build.cake + cakeTarget: test-android-emu + cakeExtraArgs: --avd-target="`"system-images;android-29;google_apis_playstore;x86`"" + preBuildSteps: + - bash: sh -c "echo \"y\" | $ANDROID_HOME/tools/bin/sdkmanager \"system-images;android-29;google_apis_playstore;x86\"" + displayName: Install the Android emulators diff --git a/build.cake b/build.cake new file mode 100644 index 000000000..05692910e --- /dev/null +++ b/build.cake @@ -0,0 +1,91 @@ +var TARGET = Argument("t", Argument("target", "ci")); + +var NUGET_VERSION = EnvironmentVariable("NUGET_VERSION") ?? "1.0.0"; +var GIT_SHA = Argument("gitSha", EnvironmentVariable("GIT_SHA") ?? ""); +var GIT_BRANCH_NAME = Argument("gitBranch", EnvironmentVariable("GIT_BRANCH_NAME") ?? ""); + +Task("prepare") + .Does(() => +{ + // Update .csproj nuget versions + XmlPoke("./Xamarin.Essentials/Xamarin.Essentials.csproj", "/Project/PropertyGroup/PackageVersion", NUGET_VERSION); +}); + +Task("libs") + .IsDependentOn("prepare") + .Does(() => +{ + MSBuild("./Xamarin.Essentials/Xamarin.Essentials.csproj", new MSBuildSettings() + .EnableBinaryLogger("./output/binlogs/libs.binlog") + .SetConfiguration("Release") + .WithRestore()); +}); + +Task("nugets") + .IsDependentOn("prepare") + .IsDependentOn("libs") + .IsDependentOn("docs") + .Does(() => +{ + MSBuild("./Xamarin.Essentials/Xamarin.Essentials.csproj", new MSBuildSettings() + .EnableBinaryLogger("./output/binlogs/nugets.binlog") + .SetConfiguration("Release") + .WithRestore() + .WithProperty("PackageOutputPath", MakeAbsolute(new FilePath("./output/")).FullPath) + .WithTarget("Pack")); +}); + +Task("tests") + .IsDependentOn("libs") + .Does(() => +{ + var failed = 0; + + foreach (var csproj in GetFiles("./Tests/**/*.csproj")) { + try { + DotNetCoreTest(csproj.FullPath, new DotNetCoreTestSettings { + Configuration = "Release", + Logger = $"trx;LogFileName={csproj.GetFilenameWithoutExtension()}.trx", + }); + } catch (Exception) { + failed++; + } + } + + var output = $"./output/test-results/"; + EnsureDirectoryExists(output); + CopyFiles($"./tests/**/TestResults/*.trx", output); + + if (failed > 0) + throw new Exception($"{failed} tests have failed."); +}); + +Task("samples") + .IsDependentOn("nugets") + .Does(() => +{ + MSBuild("./Xamarin.Essentials.sln", new MSBuildSettings() + .EnableBinaryLogger("./output/binlogs/samples.binlog") + .SetConfiguration("Release") + .WithRestore()); +}); + +Task("docs") + .IsDependentOn("libs") + .WithCriteria(IsRunningOnWindows()) + .Does(() => +{ + MSBuild("./Xamarin.Essentials/Xamarin.Essentials.csproj", new MSBuildSettings() + .EnableBinaryLogger("./output/binlogs/nugets.binlog") + .SetConfiguration("Release") + .WithRestore() + .WithTarget("mdocupdatedocs")); +}); + +Task("ci") + .IsDependentOn("libs") + .IsDependentOn("nugets") + .IsDependentOn("tests") + .IsDependentOn("samples"); + +RunTarget(TARGET); diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index 689fa87e2..000000000 --- a/build.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -$ErrorActionPreference = "Stop" - -$cibuild = "false" - -# Make sure that we have something on non-bots -if (!$env:BUILD_NUMBER) { - $env:BUILD_NUMBER = "0" -} - -# Find MSBuild on this machine -if ($IsMacOS) { - $msbuild = "msbuild" -} else { - $vswhere = 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' - $msbuild = & $vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath - $msbuild = join-path $msbuild 'MSBuild\Current\Bin\MSBuild.exe' - $cibuild = "true" -} - -Write-Output "Using MSBuild from: $msbuild" - -# Build the projects -& $msbuild "./Xamarin.Essentials.sln" /restore /t:Build /p:Configuration=Release /p:ContinuousIntegrationBuild=$ciBuild /p:Deterministic=false -if ($lastexitcode -ne 0) { exit $lastexitcode; } - -# Create the stable NuGet package -& $msbuild "./Xamarin.Essentials/Xamarin.Essentials.csproj" /t:Pack /p:Configuration=Release /p:ContinuousIntegrationBuild=$cibuild /p:Deterministic=false /p:VersionSuffix=".$env:BUILD_NUMBER" -if ($lastexitcode -ne 0) { exit $lastexitcode; } - -# Create the beta NuGet package -& $msbuild "./Xamarin.Essentials/Xamarin.Essentials.csproj" /t:Pack /p:Configuration=Release /p:ContinuousIntegrationBuild=$cibuild /p:Deterministic=false /p:VersionSuffix=".$env:BUILD_NUMBER-beta" -if ($lastexitcode -ne 0) { exit $lastexitcode; } - -# Copy everything into the output folder -Copy-Item "./Xamarin.Essentials/bin/Release" "./Output" -Recurse -Force - -exit $lastexitcode; diff --git a/generate-docs.cmd b/generate-docs.cmd deleted file mode 100644 index 1314487e3..000000000 --- a/generate-docs.cmd +++ /dev/null @@ -1 +0,0 @@ -msbuild /r /v:m /t:rebuild;mdocupdatedocs /p:Configuration=Release /p:ContinuousIntegrationBuild=false Xamarin.Essentials/Xamarin.Essentials.csproj \ No newline at end of file