From f396818e23ecba9f79322615a55d190765a5fab5 Mon Sep 17 00:00:00 2001 From: Shady Ibraheem Date: Fri, 15 Nov 2019 15:23:41 -0500 Subject: [PATCH] Inital commit. --- .gitattributes | 2 + .github/ISSUE_TEMPLATE/bug-report.md | 56 +- .github/ISSUE_TEMPLATE/tool-request.md | 60 +- .gitignore | 390 +++++++++ .vscode/settings.json | 4 + .vscode/tasks.json | 42 + CONTRIBUTING.md | 32 + LICENSE | 21 + README.md | 73 +- SECURITY.md | 3 + _config.yml | 1 + help/debuggingFailedBuilds.md | 27 + help/resources/askOnError.png | Bin 0 -> 21961 bytes help/resources/packerResourceGroup.png | Bin 0 -> 71149 bytes help/resources/resourceGroupName.png | Bin 0 -> 208502 bytes help/resources/vmCredentials.png | Bin 0 -> 142298 bytes helpers/CreateAzureVMFromPackerTemplate.ps1 | 72 ++ helpers/GenerateResourcesAndImage.ps1 | 155 ++++ images/linux/Ubuntu1604-README.md | 260 ++++++ images/linux/Ubuntu1804-README.md | 250 ++++++ images/linux/config/ubuntu1604.conf | 2 + images/linux/config/ubuntu1804.conf | 2 + images/linux/scripts/base/repos.sh | 15 + images/linux/scripts/helpers/apt.sh | 23 + .../linux/scripts/helpers/containercache.sh | 31 + images/linux/scripts/helpers/document.sh | 30 + .../linux/scripts/installers/1604/android.sh | 145 ++++ .../scripts/installers/1604/azpowershell.sh | 46 ++ images/linux/scripts/installers/1604/basic.sh | 88 ++ .../scripts/installers/1604/dotnetcore-sdk.sh | 94 +++ images/linux/scripts/installers/1604/go.sh | 36 + .../installers/1604/hosted-tool-cache.sh | 40 + .../installers/1604/kubernetes-tools.sh | 40 + .../scripts/installers/1604/mercurial.sh | 25 + images/linux/scripts/installers/1604/php.sh | 268 ++++++ .../scripts/installers/1604/powershellcore.sh | 28 + .../installers/1604/preparemetadata.sh | 12 + .../linux/scripts/installers/1804/android.sh | 133 +++ .../scripts/installers/1804/azpowershell.sh | 46 ++ images/linux/scripts/installers/1804/basic.sh | 154 ++++ .../scripts/installers/1804/dotnetcore-sdk.sh | 95 +++ images/linux/scripts/installers/1804/go.sh | 34 + .../installers/1804/hosted-tool-cache.sh | 40 + .../installers/1804/kubernetes-tools.sh | 42 + .../scripts/installers/1804/mercurial.sh | 21 + images/linux/scripts/installers/1804/php.sh | 181 ++++ .../scripts/installers/1804/powershellcore.sh | 31 + .../installers/1804/preparemetadata.sh | 12 + images/linux/scripts/installers/7-zip.sh | 23 + images/linux/scripts/installers/ansible.sh | 25 + images/linux/scripts/installers/aws.sh | 26 + images/linux/scripts/installers/azcopy.sh | 25 + images/linux/scripts/installers/azure-cli.sh | 26 + .../scripts/installers/azure-devops-cli.sh | 23 + images/linux/scripts/installers/boost.sh | 31 + .../scripts/installers/build-essential.sh | 24 + images/linux/scripts/installers/clang.sh | 31 + images/linux/scripts/installers/cmake.sh | 30 + .../scripts/installers/docker-compose.sh | 26 + .../linux/scripts/installers/docker-moby.sh | 43 + images/linux/scripts/installers/docker.sh | 34 + images/linux/scripts/installers/erlang.sh | 39 + images/linux/scripts/installers/example.sh | 31 + images/linux/scripts/installers/firefox.sh | 25 + images/linux/scripts/installers/gcc.sh | 25 + images/linux/scripts/installers/git.sh | 37 + .../linux/scripts/installers/google-chrome.sh | 27 + .../scripts/installers/google-cloud-sdk.sh | 25 + images/linux/scripts/installers/haskell.sh | 64 ++ images/linux/scripts/installers/heroku.sh | 22 + images/linux/scripts/installers/hhvm.sh | 37 + .../linux/scripts/installers/image-magick.sh | 20 + images/linux/scripts/installers/java-tools.sh | 78 ++ images/linux/scripts/installers/kind.sh | 26 + images/linux/scripts/installers/leiningen.sh | 35 + images/linux/scripts/installers/miniconda.sh | 23 + images/linux/scripts/installers/mono.sh | 29 + images/linux/scripts/installers/mysql.sh | 43 + images/linux/scripts/installers/nodejs.sh | 47 ++ images/linux/scripts/installers/phantomjs.sh | 29 + images/linux/scripts/installers/pollinate.sh | 22 + images/linux/scripts/installers/python.sh | 67 ++ images/linux/scripts/installers/ruby.sh | 11 + images/linux/scripts/installers/rust.sh | 54 ++ images/linux/scripts/installers/sbt.sh | 20 + images/linux/scripts/installers/sphinx.sh | 15 + images/linux/scripts/installers/subversion.sh | 22 + images/linux/scripts/installers/terraform.sh | 26 + .../scripts/installers/test-toolcache.sh | 70 ++ images/linux/scripts/installers/vcpkg.sh | 30 + images/linux/scripts/installers/zeit-now.sh | 22 + images/linux/ubuntu1604.json | 236 ++++++ images/linux/ubuntu1804.json | 239 ++++++ images/macos/macos-10.13-Readme.md | 395 +++++++++ images/macos/macos-10.14-Readme.md | 390 +++++++++ images/win/Windows2019-Azure.json | 782 ++++++++++++++++++ .../scripts/ImageHelpers/ImageHelpers.psd1 | 124 +++ .../scripts/ImageHelpers/ImageHelpers.psm1 | 19 + .../scripts/ImageHelpers/InstallHelpers.ps1 | 83 ++ .../scripts/ImageHelpers/MarkdownHelpers.ps1 | 25 + .../win/scripts/ImageHelpers/PathHelpers.ps1 | 68 ++ .../ImageHelpers/test/ImageHelpers.Tests.ps1 | 13 + .../ImageHelpers/test/PathHelpers.Tests.ps1 | 34 + .../scripts/Installers/Download-ToolCache.ps1 | 51 ++ .../Installers/Enable-DeveloperMode.ps1 | 13 + images/win/scripts/Installers/Finalize-VM.ps1 | 34 + .../win/scripts/Installers/Install-7zip.ps1 | 6 + .../scripts/Installers/Install-AzureCli.ps1 | 12 + .../Install-AzureCosmosDbEmulator.ps1 | 8 + .../Installers/Install-AzureDevOpsCli.ps1 | 6 + .../Installers/Install-AzureModules.ps1 | 197 +++++ .../win/scripts/Installers/Install-Boost.ps1 | 45 + .../win/scripts/Installers/Install-Chrome.ps1 | 26 + .../Installers/Install-CloudFoundryCli.ps1 | 24 + .../win/scripts/Installers/Install-Cmake.ps1 | 6 + .../Installers/Install-ContainersFeature.ps1 | 16 + .../win/scripts/Installers/Install-DACFx.ps1 | 10 + .../win/scripts/Installers/Install-Docker.ps1 | 16 + .../scripts/Installers/Install-DotnetSDK.ps1 | 113 +++ .../scripts/Installers/Install-Firefox.ps1 | 20 + images/win/scripts/Installers/Install-Git.ps1 | 18 + .../scripts/Installers/Install-GitVersion.ps1 | 6 + images/win/scripts/Installers/Install-Go.ps1 | 71 ++ .../scripts/Installers/Install-InnoSetup.ps1 | 6 + .../scripts/Installers/Install-JavaTools.ps1 | 98 +++ images/win/scripts/Installers/Install-Jq.ps1 | 6 + .../win/scripts/Installers/Install-Kind.ps1 | 40 + .../Installers/Install-KubernetesCli.ps1 | 6 + .../scripts/Installers/Install-Mercurial.ps1 | 10 + .../win/scripts/Installers/Install-MinGW.ps1 | 13 + .../scripts/Installers/Install-Miniconda.ps1 | 16 + .../scripts/Installers/Install-MysqlCli.ps1 | 39 + .../win/scripts/Installers/Install-NET48.ps1 | 13 + .../win/scripts/Installers/Install-NSIS.ps1 | 10 + .../scripts/Installers/Install-NodeLts.ps1 | 34 + .../scripts/Installers/Install-OpenSSL.ps1 | 6 + images/win/scripts/Installers/Install-PHP.ps1 | 20 + .../win/scripts/Installers/Install-Perl.ps1 | 6 + .../Installers/Install-PowershellCore.ps1 | 6 + .../win/scripts/Installers/Install-Ruby.ps1 | 20 + .../win/scripts/Installers/Install-Rust.ps1 | 53 ++ .../Installers/Install-SQLPowerShellTools.ps1 | 61 ++ images/win/scripts/Installers/Install-Sbt.ps1 | 21 + .../Installers/Install-SeleniumWebDrivers.ps1 | 17 + .../Installers/Install-ServiceFabricSDK.ps1 | 13 + images/win/scripts/Installers/Install-Svn.ps1 | 6 + .../scripts/Installers/Install-TypeScript.ps1 | 7 + .../win/scripts/Installers/Install-Vcpkg.ps1 | 21 + .../Installers/Install-WinAppDriver.ps1 | 8 + .../Installers/Install-WindowsUpdates.ps1 | 10 + .../scripts/Installers/Update-AndroidSDK.ps1 | 156 ++++ .../scripts/Installers/Update-DotnetTLS.ps1 | 18 + .../win/scripts/Installers/Validate-7zip.ps1 | 25 + .../scripts/Installers/Validate-AzureCli.ps1 | 28 + .../Validate-AzureCosmosDbEmulator.ps1 | 47 ++ .../Installers/Validate-AzureDevOpsCli.ps1 | 24 + .../Installers/Validate-AzureModules.ps1 | 71 ++ .../win/scripts/Installers/Validate-Boost.ps1 | 75 ++ .../scripts/Installers/Validate-Chrome.ps1 | 25 + .../Installers/Validate-CloudFoundryCli.ps1 | 28 + .../win/scripts/Installers/Validate-Cmake.ps1 | 31 + .../win/scripts/Installers/Validate-DACFx.ps1 | 33 + .../scripts/Installers/Validate-Docker.ps1 | 46 ++ .../scripts/Installers/Validate-DotnetSDK.ps1 | 46 ++ .../scripts/Installers/Validate-DotnetTLS.ps1 | 28 + .../scripts/Installers/Validate-Firefox.ps1 | 25 + .../win/scripts/Installers/Validate-Git.ps1 | 49 ++ .../Installers/Validate-GitVersion.ps1 | 25 + images/win/scripts/Installers/Validate-Go.ps1 | 70 ++ .../scripts/Installers/Validate-InnoSetup.ps1 | 27 + .../scripts/Installers/Validate-JavaTools.ps1 | 113 +++ images/win/scripts/Installers/Validate-Jq.ps1 | 23 + .../win/scripts/Installers/Validate-Kind.ps1 | 28 + .../Installers/Validate-KubernetesCli.ps1 | 28 + .../scripts/Installers/Validate-Mercurial.ps1 | 25 + .../win/scripts/Installers/Validate-MinGW.ps1 | 57 ++ .../scripts/Installers/Validate-Miniconda.ps1 | 36 + .../scripts/Installers/Validate-MysqlCli.ps1 | 27 + .../scripts/Installers/Validate-NET472.ps1 | 27 + .../win/scripts/Installers/Validate-NET48.ps1 | 27 + .../win/scripts/Installers/Validate-NSIS.ps1 | 32 + .../scripts/Installers/Validate-NodeLts.ps1 | 71 ++ .../scripts/Installers/Validate-OpenSSL.ps1 | 29 + .../win/scripts/Installers/Validate-PHP.ps1 | 49 ++ .../win/scripts/Installers/Validate-Perl.ps1 | 23 + .../Installers/Validate-PowershellCore.ps1 | 28 + .../scripts/Installers/Validate-Python.ps1 | 45 + .../win/scripts/Installers/Validate-Ruby.ps1 | 53 ++ .../win/scripts/Installers/Validate-Rust.ps1 | 34 + .../Validate-SQLPowerShellTools.ps1 | 37 + .../win/scripts/Installers/Validate-Sbt.ps1 | 18 + .../Validate-SeleniumWebDrivers.ps1 | 67 ++ .../Installers/Validate-ServiceFabricSDK.ps1 | 44 + .../win/scripts/Installers/Validate-Svn.ps1 | 28 + .../scripts/Installers/Validate-ToolCache.ps1 | 94 +++ .../Installers/Validate-TypeScript.ps1 | 27 + .../win/scripts/Installers/Validate-Vcpkg.ps1 | 46 ++ .../Installers/Validate-WinAppDriver.ps1 | 45 + .../Installers/Windows2019/Initialize-VM.ps1 | 145 ++++ .../Installers/Windows2019/Install-Python.ps1 | 28 + .../Installers/Windows2019/Install-VS2019.ps1 | 188 +++++ .../Installers/Windows2019/Install-WDK.ps1 | 53 ++ .../Installers/Windows2019/Install-Wix.ps1 | 53 ++ .../Installers/Windows2019/Run-Antivirus.ps1 | 27 + .../Windows2019/Update-DockerImages.ps1 | 36 + .../Installers/Windows2019/Validate-WDK.ps1 | 13 + .../Installers/Windows2019/Validate-Wix.ps1 | 61 ++ images/win/scripts/README.md | 1 + 208 files changed, 10770 insertions(+), 95 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 SECURITY.md create mode 100644 _config.yml create mode 100644 help/debuggingFailedBuilds.md create mode 100644 help/resources/askOnError.png create mode 100644 help/resources/packerResourceGroup.png create mode 100644 help/resources/resourceGroupName.png create mode 100644 help/resources/vmCredentials.png create mode 100644 helpers/CreateAzureVMFromPackerTemplate.ps1 create mode 100644 helpers/GenerateResourcesAndImage.ps1 create mode 100644 images/linux/Ubuntu1604-README.md create mode 100644 images/linux/Ubuntu1804-README.md create mode 100644 images/linux/config/ubuntu1604.conf create mode 100644 images/linux/config/ubuntu1804.conf create mode 100644 images/linux/scripts/base/repos.sh create mode 100644 images/linux/scripts/helpers/apt.sh create mode 100644 images/linux/scripts/helpers/containercache.sh create mode 100644 images/linux/scripts/helpers/document.sh create mode 100644 images/linux/scripts/installers/1604/android.sh create mode 100644 images/linux/scripts/installers/1604/azpowershell.sh create mode 100644 images/linux/scripts/installers/1604/basic.sh create mode 100644 images/linux/scripts/installers/1604/dotnetcore-sdk.sh create mode 100644 images/linux/scripts/installers/1604/go.sh create mode 100644 images/linux/scripts/installers/1604/hosted-tool-cache.sh create mode 100644 images/linux/scripts/installers/1604/kubernetes-tools.sh create mode 100644 images/linux/scripts/installers/1604/mercurial.sh create mode 100644 images/linux/scripts/installers/1604/php.sh create mode 100644 images/linux/scripts/installers/1604/powershellcore.sh create mode 100644 images/linux/scripts/installers/1604/preparemetadata.sh create mode 100644 images/linux/scripts/installers/1804/android.sh create mode 100644 images/linux/scripts/installers/1804/azpowershell.sh create mode 100644 images/linux/scripts/installers/1804/basic.sh create mode 100644 images/linux/scripts/installers/1804/dotnetcore-sdk.sh create mode 100644 images/linux/scripts/installers/1804/go.sh create mode 100644 images/linux/scripts/installers/1804/hosted-tool-cache.sh create mode 100644 images/linux/scripts/installers/1804/kubernetes-tools.sh create mode 100644 images/linux/scripts/installers/1804/mercurial.sh create mode 100644 images/linux/scripts/installers/1804/php.sh create mode 100644 images/linux/scripts/installers/1804/powershellcore.sh create mode 100644 images/linux/scripts/installers/1804/preparemetadata.sh create mode 100644 images/linux/scripts/installers/7-zip.sh create mode 100644 images/linux/scripts/installers/ansible.sh create mode 100644 images/linux/scripts/installers/aws.sh create mode 100644 images/linux/scripts/installers/azcopy.sh create mode 100644 images/linux/scripts/installers/azure-cli.sh create mode 100644 images/linux/scripts/installers/azure-devops-cli.sh create mode 100644 images/linux/scripts/installers/boost.sh create mode 100644 images/linux/scripts/installers/build-essential.sh create mode 100644 images/linux/scripts/installers/clang.sh create mode 100644 images/linux/scripts/installers/cmake.sh create mode 100644 images/linux/scripts/installers/docker-compose.sh create mode 100644 images/linux/scripts/installers/docker-moby.sh create mode 100644 images/linux/scripts/installers/docker.sh create mode 100644 images/linux/scripts/installers/erlang.sh create mode 100644 images/linux/scripts/installers/example.sh create mode 100644 images/linux/scripts/installers/firefox.sh create mode 100644 images/linux/scripts/installers/gcc.sh create mode 100644 images/linux/scripts/installers/git.sh create mode 100644 images/linux/scripts/installers/google-chrome.sh create mode 100644 images/linux/scripts/installers/google-cloud-sdk.sh create mode 100644 images/linux/scripts/installers/haskell.sh create mode 100644 images/linux/scripts/installers/heroku.sh create mode 100644 images/linux/scripts/installers/hhvm.sh create mode 100644 images/linux/scripts/installers/image-magick.sh create mode 100644 images/linux/scripts/installers/java-tools.sh create mode 100644 images/linux/scripts/installers/kind.sh create mode 100644 images/linux/scripts/installers/leiningen.sh create mode 100644 images/linux/scripts/installers/miniconda.sh create mode 100644 images/linux/scripts/installers/mono.sh create mode 100644 images/linux/scripts/installers/mysql.sh create mode 100644 images/linux/scripts/installers/nodejs.sh create mode 100644 images/linux/scripts/installers/phantomjs.sh create mode 100644 images/linux/scripts/installers/pollinate.sh create mode 100644 images/linux/scripts/installers/python.sh create mode 100644 images/linux/scripts/installers/ruby.sh create mode 100644 images/linux/scripts/installers/rust.sh create mode 100644 images/linux/scripts/installers/sbt.sh create mode 100644 images/linux/scripts/installers/sphinx.sh create mode 100644 images/linux/scripts/installers/subversion.sh create mode 100644 images/linux/scripts/installers/terraform.sh create mode 100644 images/linux/scripts/installers/test-toolcache.sh create mode 100644 images/linux/scripts/installers/vcpkg.sh create mode 100644 images/linux/scripts/installers/zeit-now.sh create mode 100644 images/linux/ubuntu1604.json create mode 100644 images/linux/ubuntu1804.json create mode 100644 images/macos/macos-10.13-Readme.md create mode 100644 images/macos/macos-10.14-Readme.md create mode 100644 images/win/Windows2019-Azure.json create mode 100644 images/win/scripts/ImageHelpers/ImageHelpers.psd1 create mode 100644 images/win/scripts/ImageHelpers/ImageHelpers.psm1 create mode 100644 images/win/scripts/ImageHelpers/InstallHelpers.ps1 create mode 100644 images/win/scripts/ImageHelpers/MarkdownHelpers.ps1 create mode 100644 images/win/scripts/ImageHelpers/PathHelpers.ps1 create mode 100644 images/win/scripts/ImageHelpers/test/ImageHelpers.Tests.ps1 create mode 100644 images/win/scripts/ImageHelpers/test/PathHelpers.Tests.ps1 create mode 100644 images/win/scripts/Installers/Download-ToolCache.ps1 create mode 100644 images/win/scripts/Installers/Enable-DeveloperMode.ps1 create mode 100644 images/win/scripts/Installers/Finalize-VM.ps1 create mode 100644 images/win/scripts/Installers/Install-7zip.ps1 create mode 100644 images/win/scripts/Installers/Install-AzureCli.ps1 create mode 100644 images/win/scripts/Installers/Install-AzureCosmosDbEmulator.ps1 create mode 100644 images/win/scripts/Installers/Install-AzureDevOpsCli.ps1 create mode 100644 images/win/scripts/Installers/Install-AzureModules.ps1 create mode 100644 images/win/scripts/Installers/Install-Boost.ps1 create mode 100644 images/win/scripts/Installers/Install-Chrome.ps1 create mode 100644 images/win/scripts/Installers/Install-CloudFoundryCli.ps1 create mode 100644 images/win/scripts/Installers/Install-Cmake.ps1 create mode 100644 images/win/scripts/Installers/Install-ContainersFeature.ps1 create mode 100644 images/win/scripts/Installers/Install-DACFx.ps1 create mode 100644 images/win/scripts/Installers/Install-Docker.ps1 create mode 100644 images/win/scripts/Installers/Install-DotnetSDK.ps1 create mode 100644 images/win/scripts/Installers/Install-Firefox.ps1 create mode 100644 images/win/scripts/Installers/Install-Git.ps1 create mode 100644 images/win/scripts/Installers/Install-GitVersion.ps1 create mode 100644 images/win/scripts/Installers/Install-Go.ps1 create mode 100644 images/win/scripts/Installers/Install-InnoSetup.ps1 create mode 100644 images/win/scripts/Installers/Install-JavaTools.ps1 create mode 100644 images/win/scripts/Installers/Install-Jq.ps1 create mode 100644 images/win/scripts/Installers/Install-Kind.ps1 create mode 100644 images/win/scripts/Installers/Install-KubernetesCli.ps1 create mode 100644 images/win/scripts/Installers/Install-Mercurial.ps1 create mode 100644 images/win/scripts/Installers/Install-MinGW.ps1 create mode 100644 images/win/scripts/Installers/Install-Miniconda.ps1 create mode 100644 images/win/scripts/Installers/Install-MysqlCli.ps1 create mode 100644 images/win/scripts/Installers/Install-NET48.ps1 create mode 100644 images/win/scripts/Installers/Install-NSIS.ps1 create mode 100644 images/win/scripts/Installers/Install-NodeLts.ps1 create mode 100644 images/win/scripts/Installers/Install-OpenSSL.ps1 create mode 100644 images/win/scripts/Installers/Install-PHP.ps1 create mode 100644 images/win/scripts/Installers/Install-Perl.ps1 create mode 100644 images/win/scripts/Installers/Install-PowershellCore.ps1 create mode 100644 images/win/scripts/Installers/Install-Ruby.ps1 create mode 100644 images/win/scripts/Installers/Install-Rust.ps1 create mode 100644 images/win/scripts/Installers/Install-SQLPowerShellTools.ps1 create mode 100644 images/win/scripts/Installers/Install-Sbt.ps1 create mode 100644 images/win/scripts/Installers/Install-SeleniumWebDrivers.ps1 create mode 100644 images/win/scripts/Installers/Install-ServiceFabricSDK.ps1 create mode 100644 images/win/scripts/Installers/Install-Svn.ps1 create mode 100644 images/win/scripts/Installers/Install-TypeScript.ps1 create mode 100644 images/win/scripts/Installers/Install-Vcpkg.ps1 create mode 100644 images/win/scripts/Installers/Install-WinAppDriver.ps1 create mode 100644 images/win/scripts/Installers/Install-WindowsUpdates.ps1 create mode 100644 images/win/scripts/Installers/Update-AndroidSDK.ps1 create mode 100644 images/win/scripts/Installers/Update-DotnetTLS.ps1 create mode 100644 images/win/scripts/Installers/Validate-7zip.ps1 create mode 100644 images/win/scripts/Installers/Validate-AzureCli.ps1 create mode 100644 images/win/scripts/Installers/Validate-AzureCosmosDbEmulator.ps1 create mode 100644 images/win/scripts/Installers/Validate-AzureDevOpsCli.ps1 create mode 100644 images/win/scripts/Installers/Validate-AzureModules.ps1 create mode 100644 images/win/scripts/Installers/Validate-Boost.ps1 create mode 100644 images/win/scripts/Installers/Validate-Chrome.ps1 create mode 100644 images/win/scripts/Installers/Validate-CloudFoundryCli.ps1 create mode 100644 images/win/scripts/Installers/Validate-Cmake.ps1 create mode 100644 images/win/scripts/Installers/Validate-DACFx.ps1 create mode 100644 images/win/scripts/Installers/Validate-Docker.ps1 create mode 100644 images/win/scripts/Installers/Validate-DotnetSDK.ps1 create mode 100644 images/win/scripts/Installers/Validate-DotnetTLS.ps1 create mode 100644 images/win/scripts/Installers/Validate-Firefox.ps1 create mode 100644 images/win/scripts/Installers/Validate-Git.ps1 create mode 100644 images/win/scripts/Installers/Validate-GitVersion.ps1 create mode 100644 images/win/scripts/Installers/Validate-Go.ps1 create mode 100644 images/win/scripts/Installers/Validate-InnoSetup.ps1 create mode 100644 images/win/scripts/Installers/Validate-JavaTools.ps1 create mode 100644 images/win/scripts/Installers/Validate-Jq.ps1 create mode 100644 images/win/scripts/Installers/Validate-Kind.ps1 create mode 100644 images/win/scripts/Installers/Validate-KubernetesCli.ps1 create mode 100644 images/win/scripts/Installers/Validate-Mercurial.ps1 create mode 100644 images/win/scripts/Installers/Validate-MinGW.ps1 create mode 100644 images/win/scripts/Installers/Validate-Miniconda.ps1 create mode 100644 images/win/scripts/Installers/Validate-MysqlCli.ps1 create mode 100644 images/win/scripts/Installers/Validate-NET472.ps1 create mode 100644 images/win/scripts/Installers/Validate-NET48.ps1 create mode 100644 images/win/scripts/Installers/Validate-NSIS.ps1 create mode 100644 images/win/scripts/Installers/Validate-NodeLts.ps1 create mode 100644 images/win/scripts/Installers/Validate-OpenSSL.ps1 create mode 100644 images/win/scripts/Installers/Validate-PHP.ps1 create mode 100644 images/win/scripts/Installers/Validate-Perl.ps1 create mode 100644 images/win/scripts/Installers/Validate-PowershellCore.ps1 create mode 100644 images/win/scripts/Installers/Validate-Python.ps1 create mode 100644 images/win/scripts/Installers/Validate-Ruby.ps1 create mode 100644 images/win/scripts/Installers/Validate-Rust.ps1 create mode 100644 images/win/scripts/Installers/Validate-SQLPowerShellTools.ps1 create mode 100644 images/win/scripts/Installers/Validate-Sbt.ps1 create mode 100644 images/win/scripts/Installers/Validate-SeleniumWebDrivers.ps1 create mode 100644 images/win/scripts/Installers/Validate-ServiceFabricSDK.ps1 create mode 100644 images/win/scripts/Installers/Validate-Svn.ps1 create mode 100644 images/win/scripts/Installers/Validate-ToolCache.ps1 create mode 100644 images/win/scripts/Installers/Validate-TypeScript.ps1 create mode 100644 images/win/scripts/Installers/Validate-Vcpkg.ps1 create mode 100644 images/win/scripts/Installers/Validate-WinAppDriver.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Install-Python.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Install-VS2019.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Install-WDK.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Install-Wix.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Run-Antivirus.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Update-DockerImages.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Validate-WDK.ps1 create mode 100644 images/win/scripts/Installers/Windows2019/Validate-Wix.ps1 create mode 100644 images/win/scripts/README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..957a75d0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Do not normalize line endings +* -text \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index b43b1e71..0694dbab 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,28 +1,28 @@ ---- -name: Bug report -about: Submit a bug report -title: '' -labels: t:Bug report -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is, and why you consider it to be a bug. - -**Virtual environments affected** -- [ ] macOS 10.15 -- [ ] Ubuntu 16.04 LTS -- [ ] Ubuntu 18.04 LTS -- [ ] Windows Server 2016 R2 -- [ ] Windows Server 2019 - -**Expected behavior** -A description of what you expected to happen. - -**Actual behavior** -A description with steps to reproduce the issue. If your have a public example or repo to share, -please provide the link. - -1. Step 1 -2. Step 2 +--- +name: Bug report +about: Submit a bug report +title: '' +labels: t:Bug report +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is, and why you consider it to be a bug. + +**Virtual environments affected** +- [ ] macOS 10.15 +- [ ] Ubuntu 16.04 LTS +- [ ] Ubuntu 18.04 LTS +- [ ] Windows Server 2016 R2 +- [ ] Windows Server 2019 + +**Expected behavior** +A description of what you expected to happen. + +**Actual behavior** +A description with steps to reproduce the issue. If your have a public example or repo to share, +please provide the link. + +1. Step 1 +2. Step 2 diff --git a/.github/ISSUE_TEMPLATE/tool-request.md b/.github/ISSUE_TEMPLATE/tool-request.md index ba9140bd..fcf42b2b 100644 --- a/.github/ISSUE_TEMPLATE/tool-request.md +++ b/.github/ISSUE_TEMPLATE/tool-request.md @@ -1,30 +1,30 @@ ---- -name: Tool request -about: Request a new tool or update to a tool -title: Update/Add [tool name] -labels: t:Enhancement -assignees: '' - ---- - -**Tool information** -- Tool name: -- Add or update? -- Desired version: -- Approximate size: -- If this is an add request: - - Brief description of tool: - - URL for tool's homepage: - -**Virtual environments affected** -- [ ] macOS 10.15 -- [ ] Ubuntu 16.04 LTS -- [ ] Ubuntu 18.04 LTS -- [ ] Windows Server 2016 R2 -- [ ] Windows Server 2019 - -**Can this tool be installed during the build?** - - -**Are you willing to submit a PR?** - +--- +name: Tool request +about: Request a new tool or update to a tool +title: Update/Add [tool name] +labels: t:Enhancement +assignees: '' + +--- + +**Tool information** +- Tool name: +- Add or update? +- Desired version: +- Approximate size: +- If this is an add request: + - Brief description of tool: + - URL for tool's homepage: + +**Virtual environments affected** +- [ ] macOS 10.15 +- [ ] Ubuntu 16.04 LTS +- [ ] Ubuntu 18.04 LTS +- [ ] Windows Server 2016 R2 +- [ ] Windows Server 2019 + +**Can this tool be installed during the build?** + + +**Are you willing to submit a PR?** + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a327f456 --- /dev/null +++ b/.gitignore @@ -0,0 +1,390 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# Ignore files generated by packer +InstalledSoftware.md + +# Desktop Service Store +.DS_Store + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# gatsby files +.cache/ +public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# visual studio code launch configuration +launch.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..470eddc0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + // When enabled, will trim trailing whitespace when you save a file. + "files.trimTrailingWhitespace": true +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..da6002dd --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,42 @@ +// Available variables which can be used inside of strings. +// ${workspaceRoot}: the root folder of the team +// ${file}: the current opened file +// ${relativeFile}: the current opened file relative to workspaceRoot +// ${fileBasename}: the current opened file's basename +// ${fileDirname}: the current opened file's dirname +// ${fileExtname}: the current opened file's extension +// ${cwd}: the current working directory of the spawned process +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + + // Start PowerShell + "windows": { + "command": "${env:windir}/System32/WindowsPowerShell/v1.0/powershell.exe", + //"command": "${env:ProgramFiles}/PowerShell/6.0.0/powershell.exe", + "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass" ] + }, + "linux": { + "command": "/usr/bin/powershell", + "args": [ "-NoProfile" ] + }, + "osx": { + "command": "/usr/local/bin/powershell", + "args": [ "-NoProfile" ] + }, + + // Associate with test task runner + "tasks": [ + { + "taskName": "Test", + "suppressTaskName": true, + "isTestCommand": true, + "args": [ + "Write-Host 'Invoking Pester...'; $ProgressPreference = 'SilentlyContinue'; Invoke-Pester -Script test -PesterOption @{IncludeVSCodeMarker=$true};", + "Invoke-Command { Write-Host 'Completed Test task in task runner.' }" + ], + "problemMatcher": "$pester" + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..2e287d1b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,32 @@ +## Contributing + +[fork]: https://github.com/actions/virtual-environments/fork +[pr]: https://github.com//actions/virtual-environments/compare +[code-of-conduct]: CODE_OF_CONDUCT.md + +Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. + +Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [MIT](LICENSE.md). + +Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. + +## Submitting a pull request + +1. [Fork][fork] and clone the repository +1. Create a new branch: `git checkout -b my-branch-name` +1. Make your changes, ensure that they include steps to install and validate post-install (e.g. [kind.sh](images/linux/scripts/installers/kind.sh)). +1. Test your changes by [creating VHD and deploying a VM](help/CreateImageAndAzureResources.md). +1. Push to your fork and [submit a pull request][pr] + +Here are a few things you can do that will increase the likelihood of your pull request being accepted: + +- Follow the style guide for [Powershell](https://github.com/PoshCode/PowerShellPracticeAndStyle) when writing Windows scripts. There is currently no set style for the Shell scripts that run Linux installs :soon:. +- Include complete details of why this is needed in the PR description. If it's a new piece tool being installed, consider cross-platform. If the tool is available in other platforms (MacOS, Windows, Linux), make sure you include it in as many as possible. +- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. +- Write [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). + +## Resources + +- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) +- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) +- [GitHub Help](https://help.github.com) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..331b241b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 95949233..3e43177e 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,36 @@ -# GitHub Actions Virtual Environments -This repository will contain the code that we use to create the GitHub Actions [virtual environments](https://help.github.com/en/articles/software-in-virtual-environments-for-github-actions). -We're not quite ready to share the code and accept contributions yet. However, we want to gather your software requests and bug reports. -Please use the issue templates to submit requests and bug reports related to the installed software. - -If you need help with how to set up your workflow file or use a specific tool, -check out the [GitHub Actions Community Forum](https://github.community/t5/GitHub-Actions/bd-p/actions). - -## OS's offered -We currently offer Linux, macOS, and Windows virtual environments: - -- **Linux**. We offer Ubuntu 16.04 and Ubuntu 18.04. We do not plan to offer other Linux distributions. If you want to build using other distributions with the hosted virtual environments, we suggest you use Docker. Alternatively, you can host your own VMs and make use of self-hosted runners. -- **macOS**. We offer macOS Catalina 10.15. -- **Windows**. We offer Windows Server 2016 and Windows Server 2019. However, we plan to offer only Windows Server 2019 starting on November 7, 2019. We plan to add Visual Studio 2017 to the Windows Server 2019 virtual environment, but do not yet have a firm ETA. - -## Guidelines for what's installed -We follow these rough guidelines when deciding what to pre-install: - -- Tools and ecosystems that are more popular and widely-used will be given priority. -- More recent versions of tools will be given priority over older versions. -- Tools and versions that are deprecated or have reached end-of-life will not be added. -- Tools and versions will be removed 6 months after they are deprecated or have reached end-of-life. -- If a tool can be installed during the build, we will evaluate how much time is saved -and how much space is used by having the tool pre-installed. - -## Updates to the virtual environments -_Cadence_ - -You can expect approximately weekly updates to the software on the virtual environments. -For some tools, we always install the latest at the time of the deployment; for others, -we pin the tool to specific version(s). - -_Notifications_ - -Right now, we don't have a great way for you to know when updates to the images are coming. -When we have the code available here, you can watch the Releases for when we generate -candidate environments, and when we deploy new ones. +# GitHub Actions Virtual Environments +This repository contains the code that we use to create the GitHub Actions [virtual environments](https://help.github.com/en/articles/software-in-virtual-environments-for-github-actions). +Please use the issue templates to submit requests and bug reports related to the installed software. + +If you need help with how to set up your workflow file or use a specific tool, +check out the [GitHub Actions Community Forum](https://github.community/t5/GitHub-Actions/bd-p/actions). + +## OS's offered +We currently offer Linux, macOS, and Windows virtual environments: + +- **Linux**. We offer Ubuntu 16.04 and Ubuntu 18.04. We do not plan to offer other Linux distributions. If you want to build using other distributions with the hosted virtual environments, we suggest you use Docker. Alternatively, you can host your own VMs and make use of self-hosted runners. +- **macOS**. We offer macOS Catalina 10.15. +- **Windows**. We offer Windows Server 2019. + +## Guidelines for what's installed +We follow these rough guidelines when deciding what to pre-install: + +- Tools and ecosystems that are more popular and widely-used will be given priority. +- More recent versions of tools will be given priority over older versions. +- Tools and versions that are deprecated or have reached end-of-life will not be added. +- Tools and versions will be removed 6 months after they are deprecated or have reached end-of-life. +- If a tool can be installed during the build, we will evaluate how much time is saved +and how much space is used by having the tool pre-installed. + +## Updates to the virtual environments +_Cadence_ + +You can expect approximately weekly updates to the software on the virtual environments. +For some tools, we always install the latest at the time of the deployment; for others, +we pin the tool to specific version(s). + +_Notifications_ + +Right now, we don't have a great way for you to know when updates to the images are coming. +When we have the code available here, you can watch the Releases for when we generate +candidate environments, and when we deploy new ones. \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..f0b196fb --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,3 @@ +If you discover a security issue in this repo, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github) + +Thanks for helping make GitHub Actions safe for everyone. diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..c7418817 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file diff --git a/help/debuggingFailedBuilds.md b/help/debuggingFailedBuilds.md new file mode 100644 index 00000000..756531d2 --- /dev/null +++ b/help/debuggingFailedBuilds.md @@ -0,0 +1,27 @@ +# Debugging Failed Packer Builds + +## Step 1: Run packer build `-on-error=ask` +When you run the `packer build` command, give it the `-on-error=ask` flag. +By default, `packer build` will delete the resource group as soon as the build fails. +`-on-error=ask` will pause it and wait for your input so you have time to remote in to the VM and diagnose the failure. + +When the build fails, you will see this: + +![Ask on error screenshot](/help/resources/askOnError.png "Ask on error screenshot") + +## Step 2: Find the resource group name in the build log +At the beginning of the build log (written to console), find the resource group name for the VM: + +![Resource group from log screenshot](/help/resources/resourceGroupName.png "Resource group from log screenshot") + +Log into the Azure Portal. Find that resource group under `Resource groups`. You should see the resources for the Packer build: + +![Packer resource group in Azure screenshot](/help/resources/packerResourceGroup.png "Packer resource group in Azure screenshot") + +## Step 3: Connect to the VM +Select the VM in the resource group. Click `Connect:` + +This will download an RDP file. Open that and enter the credentials found in the JSON file you pass to `packer build`: + +![VM credentials screenshot](/help/resources/vmCredentials.png "VM credentials screenshot") + diff --git a/help/resources/askOnError.png b/help/resources/askOnError.png new file mode 100644 index 0000000000000000000000000000000000000000..fff463b4967a81edc7bf07fdb63b785c258d641f GIT binary patch literal 21961 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 LSQ=Luy5Ii~gBQ$% literal 0 HcmV?d00001 diff --git a/help/resources/packerResourceGroup.png b/help/resources/packerResourceGroup.png new file mode 100644 index 0000000000000000000000000000000000000000..e06c535174a70d4eed2b1e3af8a1825ec9d24f56 GIT binary patch literal 71149 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

asB<{y?;QogsQ2S#tqJnjec)lHn8#A#3$Wp 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 dK%5@`)JCLa?5 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

@Y4}$X#dawLonlPzdHpcy`A%H2GL}!g^p`zM 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 literal 0 HcmV?d00001 diff --git a/help/resources/resourceGroupName.png b/help/resources/resourceGroupName.png new file mode 100644 index 0000000000000000000000000000000000000000..366f0dcad78fd58ff5f75e37de5e997e0c67230e GIT binary patch literal 208502 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%0D;ymY7G7xmAR9^ys1Qs}h)~2BzmTAI5Kzqb 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 literal 0 HcmV?d00001 diff --git a/help/resources/vmCredentials.png b/help/resources/vmCredentials.png new file mode 100644 index 0000000000000000000000000000000000000000..8ede9bdafdb6bfd61adf388e0891e1ba37666e80 GIT binary patch literal 142298 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

bh?cb)?Kx6fG|o{nt)S40)i zxwLR7UfbcwjX&|#mOOPlBWRvLM_~K93{w}ll+0nbsY_~tJTgY;;m|>nssGIU2WoiS zq^qmDzDhJ=%setOLLw3}ZdyGsFaR*8vFOx|jg7++=i~|}gfqV|GDdhz%~TpmkVVcf zKT#cKR(hj9by(d+S~a=4u}=`H+(%+vLHPgOwJsgmFw}Q)a&mcj`TX2IbEHQR7Y7H> zXBQ5^i;syhWWbK%e4{9rI~I)3#R`!A$jF3&bC8E)`^mND6s85&33)u4o;wWa65M$J z*{V{tFgG_hGc)`4tsMw!3&H1dygpuuh(L=LWpO<>u2GmIVZ=t-+1UYr6Cm2I$kyo| zb-5vWlC8Yd)3Y5y^{-y@+ko|;T{#1=;S_+lP#Kx@D1ee3Cr(y4u}e+yOI$+(zc4a3 z)(POU1Hn3zlZy3E&&1PqJ4Qq{_RlyD{`Jw2f!4@#Ba@88&Te}`jE%f%kxMT9^qqsXNKV?*S`PWMt%uDqNgkG9XNUXy|Bvrjmdw;}b7$3Vw?EM^Ry(n?UKtVrSt3|1Q;b#sxsR*jOb1IRxs`rQ16+M5s7Mfn+u2c}gFdd0+i75=p3WGEJfK zMCt~%juCAXh2x70ptci`8~BDW;9?Dp0nDTh^r%ymenX~0lggR(1_bO1fe#g$x1|b^ z_j{p5550kI1~OQ}JeQYTcF{!v*c1OsV`y?2whv;^cfaax(7=ig3RIOSbB2FD=C#sG z5;EGDVPFol^PZ;5r|o~A@ctc# lNmKh5(**qcmF@Qf-wtROP0&H=X*mY-Lr7AvgkRg|{{XUHNo4>4 literal 0 HcmV?d00001 diff --git a/helpers/CreateAzureVMFromPackerTemplate.ps1 b/helpers/CreateAzureVMFromPackerTemplate.ps1 new file mode 100644 index 00000000..5abd5742 --- /dev/null +++ b/helpers/CreateAzureVMFromPackerTemplate.ps1 @@ -0,0 +1,72 @@ +Function CreateAzureVMFromPackerTemplate { + <# + .SYNOPSIS + Creates an Azure VM from a template. Also generates network resources in Azure to make the VM accessible. + + .DESCRIPTION + Creates Azure resources and kicks off a packer image generation for the selected image type. + + .PARAMETER SubscriptionId + The Azure subscription Id where resources will be created. + + .PARAMETER ResourceGroupName + The Azure resource group name where the Azure virtual machine will be created. + + .PARAMETER TemplatFilePath + The path for the json template generated by packer during image generation locally. + + .PARAMETER VirtualMachineName + The name of the virtual machine to be generated. + + .PARAMETER AdminUserName + The administrator username for the virtual machine to be created. + + .PARAMETER AdminPassword + The administrator password for the virtual machine to be created. + + .PARAMETER AzureLocation + The location where the Azure virtual machine will be provisioned. Example: "eastus" + + .EXAMPLE + CreateAzureVMFromPackerTemplate -SubscriptionId {YourSubscriptionId} -ResourceGroupName {ResourceGroupName} -TemplateFile "C:\BuildVmImages\temporaryTemplate.json" -VirtualMachineName "testvm1" -AdminUsername "shady1" -AdminPassword "SomeSecurePassword1" -AzureLocation "eastus" + #> + param ( + [Parameter(Mandatory = $True)] + [string] $SubscriptionId, + [Parameter(Mandatory = $True)] + [string] $ResourceGroupName, + [Parameter(Mandatory = $True)] + [string] $TemplateFilePath, + [Parameter(Mandatory = $True)] + [string] $VirtualMachineName, + [Parameter(Mandatory = $True)] + [string] $AdminUsername, + [Parameter(Mandatory = $True)] + [string] $AdminPassword, + [Parameter(Mandatory = $True)] + [string] $AzureLocation + ) + + $vmSize = "Standard_DS2_v2" + $vnetName = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper() + $subnetName = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper() + $nicName = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper() + $publicIpName = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper() + + Write-Host "Creating a Vnet and a Subnet" + az network vnet create -g $ResourceGroupName -l $AzureLocation --name $vnetName --address-prefix 10.0.0.0/16 --subscription $subscriptionId + az network vnet subnet create -g $ResourceGroupName --vnet-name $vnetName -n $subnetName --address-prefix 10.0.1.0/24 --subscription $subscriptionId + + Write-Host "Creating a network interface card (NIC)." + $nic = az network nic create -g $ResourceGroupName --vnet-name $vnetName --subnet $subnetName -n $nicName --subscription $subscriptionId + $networkId = ($nic | ConvertFrom-Json).NewNIC.id + + Write-Host "create public IP." + az network public-ip create -g $ResourceGroupName -n $publicIpName --subscription $subscriptionId --allocation-method Static --location $AzureLocation --sku Standard --version IPv4 + + Write-Host "Adding the public IP to the NIC." + az network nic ip-config update --name ipconfig1 --nic-name $nicName --resource-group $ResourceGroupName --subscription $subscriptionId --public-ip-address $publicIpName + + Write-Host "Creating the VM" + az group deployment create --resource-group $ResourceGroupName --subscription $subscriptionId --name $VirtualMachineName --template-file $templateFilePath --parameters vmSize=$vmSize vmName=$VirtualMachineName adminUserName=$AdminUsername adminPassword=$AdminPassword networkInterfaceId=$networkId +} diff --git a/helpers/GenerateResourcesAndImage.ps1 b/helpers/GenerateResourcesAndImage.ps1 new file mode 100644 index 00000000..4dc2ed53 --- /dev/null +++ b/helpers/GenerateResourcesAndImage.ps1 @@ -0,0 +1,155 @@ +$ErrorActionPreference = 'Stop' + +enum ImageType { + Windows2019 = 0 + Ubuntu1604 = 1 + Ubuntu1804 = 2 +} + +Function Get-PackerTemplatePath { + param ( + [Parameter(Mandatory = $True)] + [string] $RepositoryRoot, + [Parameter(Mandatory = $True)] + [ImageType] $ImageType + ) + + $relativePath = "N/A" + + switch ($ImageType) { + ([ImageType]::WindowsLatest) { + $relativePath = "\images\win\Windows2019-Azure.json" + } + ([ImageType]::Ubuntu1604) { + $relativePath = "\images\linux\ubuntu1604.json" + } + ([ImageType]::Ubuntu1804) { + $relativePath = "\images\linux\ubuntu1804.json" + } + } + + return $RepositoryRoot + $relativePath; +} + +Function GenerateResourcesAndImage { + <# + .SYNOPSIS + A helper function to help generate an image. + + .DESCRIPTION + Creates Azure resources and kicks off a packer image generation for the selected image type. + + .PARAMETER SubscriptionId + The Azure subscription Id where resources will be created. + + .PARAMETER ResourceGroupName + The Azure resource group name where the Azure resources will be created. + + .PARAMETER ImageGenerationRepositoryRoot + The root path of the image generation repository source. + + .PARAMETER ImageType + The type of the image being generated. Valid options are: {"WindowsLatest", "Ubuntu1604", "Ubuntu1804"}. + + .PARAMETER AzureLocation + The location of the resources being created in Azure. For example "East US". + + .PARAMETER Force + Delete the resource group if it exists without user confirmation. + + .EXAMPLE + GenerateResourcesAndImage -SubscriptionId {YourSubscriptionId} -ResourceGroupName "shsamytest1" -ImageGenerationRepositoryRoot "C:\azure-pipelines-image-generation" -ImageType Ubuntu1604 -AzureLocation "East US" + #> + param ( + [Parameter(Mandatory = $True)] + [string] $SubscriptionId, + [Parameter(Mandatory = $True)] + [string] $ResourceGroupName, + [Parameter(Mandatory = $True)] + [string] $ImageGenerationRepositoryRoot, + [Parameter(Mandatory = $True)] + [ImageType] $ImageType, + [Parameter(Mandatory = $True)] + [string] $AzureLocation, + [Parameter(Mandatory = $False)] + [int] $SecondsToWaitForServicePrincipalSetup = 30, + [Parameter(Mandatory = $False)] + [Switch] $Force + ) + + $builderScriptPath = Get-PackerTemplatePath -RepositoryRoot $ImageGenerationRepositoryRoot -ImageType $ImageType + $ServicePrincipalClientSecret = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper(); + $InstallPassword = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper(); + + Login-AzureRmAccount + Set-AzureRmContext -SubscriptionId $SubscriptionId + + $alreadyExists = $true; + try { + Get-AzureRmResourceGroup -Name $ResourceGroupName + Write-Verbose "Resource group was found, will delete and recreate it." + } + catch { + Write-Verbose "Resource group was not found, will create it." + $alreadyExists = $false; + } + + if ($alreadyExists) { + if($Force -eq $true) { + # Cleanup the resource group if it already exitsted before + Remove-AzureRmResourceGroup -Name $ResourceGroupName -Force + New-AzureRmResourceGroup -Name $ResourceGroupName -Location $AzureLocation + } else { + $title = "Delete Resource Group" + $message = "The resource group you specified already exists. Do you want to clean it up?" + + $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", ` + "Delete the resource group including all resources." + + $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", ` + "Keep the resource group and continue." + + $stop = New-Object System.Management.Automation.Host.ChoiceDescription "&Stop", ` + "Stop the current action." + + $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no, $stop) + $result = $host.ui.PromptForChoice($title, $message, $options, 0) + + switch ($result) + { + 0 { Remove-AzureRmResourceGroup -Name $ResourceGroupName -Force; New-AzureRmResourceGroup -Name $ResourceGroupName -Location $AzureLocation } + 1 { <# Do nothing #> } + 2 { exit } + } + } + } else { + New-AzureRmResourceGroup -Name $ResourceGroupName -Location $AzureLocation + } + + # This script should follow the recommended naming conventions for azure resources + $storageAccountName = if($ResourceGroupName.EndsWith("-rg")) { + $ResourceGroupName.Substring(0, $ResourceGroupName.Length -3) + } else { $ResourceGroupName } + + # Resource group names may contain special characters, that are not allowed in the storage account name + $storageAccountName = $storageAccountName.Replace("-", "").Replace("_", "").Replace("(", "").Replace(")", "").ToLower() + $storageAccountName += "001" + + New-AzureRmStorageAccount -ResourceGroupName $ResourceGroupName -AccountName $storageAccountName -Location $AzureLocation -SkuName "Standard_LRS" + + $spDisplayName = [System.GUID]::NewGuid().ToString().ToUpper() + $sp = New-AzureRmADServicePrincipal -DisplayName $spDisplayName -Password (ConvertTo-SecureString $ServicePrincipalClientSecret -AsPlainText -Force) + + $spAppId = $sp.ApplicationId + $spClientId = $sp.ApplicationId + $spObjectId = $sp.Id + Start-Sleep -Seconds $SecondsToWaitForServicePrincipalSetup + + New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $spAppId + Start-Sleep -Seconds $SecondsToWaitForServicePrincipalSetup + $sub = Get-AzureRmSubscription -SubscriptionId $SubscriptionId + $tenantId = $sub.TenantId + # "", "Note this variable-setting script for running Packer with these Azure resources in the future:", "==============================================================================================", "`$spClientId = `"$spClientId`"", "`$ServicePrincipalClientSecret = `"$ServicePrincipalClientSecret`"", "`$SubscriptionId = `"$SubscriptionId`"", "`$tenantId = `"$tenantId`"", "`$spObjectId = `"$spObjectId`"", "`$AzureLocation = `"$AzureLocation`"", "`$ResourceGroupName = `"$ResourceGroupName`"", "`$storageAccountName = `"$storageAccountName`"", "`$install_password = `"$install_password`"", "" + + packer.exe build -on-error=ask -var "client_id=$($spClientId)" -var "client_secret=$($ServicePrincipalClientSecret)" -var "subscription_id=$($SubscriptionId)" -var "tenant_id=$($tenantId)" -var "object_id=$($spObjectId)" -var "location=$($AzureLocation)" -var "resource_group=$($ResourceGroupName)" -var "storage_account=$($storageAccountName)" -var "install_password=$($InstallPassword)" $builderScriptPath +} diff --git a/images/linux/Ubuntu1604-README.md b/images/linux/Ubuntu1604-README.md new file mode 100644 index 00000000..3c592fa0 --- /dev/null +++ b/images/linux/Ubuntu1604-README.md @@ -0,0 +1,260 @@ +# Hosted Ubuntu 1604 Image (Ubuntu 16.04.6 LTS) +The following software is installed on machines in the Hosted Ubuntu 1604 (20190930.2) pool +*** +- 7-Zip 9.20 +- Ansible (ansible 2.8.5) +- AzCopy (azcopy 7.3.0-netcore) +- Azure CLI (azure-cli 2.0.74) +- Azure CLI (azure-devops 0.12.0) +- Basic CLI: + - curl + - dnsutils + - file + - ftp + - iproute2 + - iputils-ping + - jq + - libcurl3 + - libicu55 + - libunwind8 + - locales + - netcat + - openssh-client + - rsync + - shellcheck + - sudo + - telnet + - time + - unzip + - wget + - zip + - tzdata +- AWS CLI (aws-cli/1.16.248 Python/2.7.12 Linux/4.15.0-1057-azure botocore/1.12.238) +- build-essential +- Clang 6.0 (clang version 6.0.1-svn334776-1~exp1~20190309042730.123 (branches/release_60)) +- CMake (cmake version 3.12.4) +- Docker Compose (docker-compose version 1.22.0, build f46880fe) +- Docker (Docker version 3.0.6, build a63faebc) +- Docker (Docker version 3.0.6, build a63faebc) +- .NET Core SDK 1.0.1 +- .NET Core SDK 1.0.4 +- .NET Core SDK 1.1.10 +- .NET Core SDK 1.1.11 +- .NET Core SDK 1.1.12 +- .NET Core SDK 1.1.13 +- .NET Core SDK 1.1.4 +- .NET Core SDK 1.1.5 +- .NET Core SDK 1.1.7 +- .NET Core SDK 1.1.8 +- .NET Core SDK 1.1.9 +- .NET Core SDK 2.0.0 +- .NET Core SDK 2.0.3 +- .NET Core SDK 2.1.100 +- .NET Core SDK 2.1.101 +- .NET Core SDK 2.1.102 +- .NET Core SDK 2.1.103 +- .NET Core SDK 2.1.104 +- .NET Core SDK 2.1.105 +- .NET Core SDK 2.1.2 +- .NET Core SDK 2.1.200 +- .NET Core SDK 2.1.201 +- .NET Core SDK 2.1.202 +- .NET Core SDK 2.1.300 +- .NET Core SDK 2.1.301 +- .NET Core SDK 2.1.302 +- .NET Core SDK 2.1.4 +- .NET Core SDK 2.1.400 +- .NET Core SDK 2.1.401 +- .NET Core SDK 2.1.402 +- .NET Core SDK 2.1.403 +- .NET Core SDK 2.1.500 +- .NET Core SDK 2.1.502 +- .NET Core SDK 2.1.503 +- .NET Core SDK 2.1.504 +- .NET Core SDK 2.1.505 +- .NET Core SDK 2.2.100 +- .NET Core SDK 2.2.101 +- .NET Core SDK 2.2.102 +- .NET Core SDK 2.2.103 +- .NET Core SDK 2.2.104 +- .NET Core SDK 2.2.105 +- .NET Core SDK 3.0 +- Erlang (Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 10.5) +- Firefox (Mozilla Firefox 69.0.1) +- GNU C++ 7.4.0 +- Git (2.23.0) +- Git Large File Storage (LFS) (2.8.0) +- Go 1.9 (go version go1.9.7 linux/amd64) +- Go 1.10 (go version go1.10.8 linux/amd64) +- Go 1.11 (go version go1.11.12 linux/amd64) +- Go 1.12 (go version go1.12.7 linux/amd64) +- Go 1.13 (go version go1.13 linux/amd64) +- Google Chrome (Google Chrome 77.0.3865.90 ) +- Google Cloud SDK (264.0.0) +- Haskell Cabal (cabal-install version 2.0.0.1 +compiled using version 2.0.1.1 of the Cabal library ) +- Haskell Cabal (cabal-install version 2.2.0.0 +compiled using version 2.2.0.1 of the Cabal library ) +- Haskell Cabal (cabal-install version 2.4.1.0 +compiled using version 2.4.1.0 of the Cabal library ) +- Haskell Cabal (cabal-install version 3.0.0.0 +compiled using version 3.0.0.0 of the Cabal library ) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.0.2) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.2.2) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.4.4) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.2) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.3) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.4) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.5) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.8.1) +- Haskell Stack (Version 2.1.3, Git revision 636e3a759d51127df2b62f90772def126cdf6d1f (7735 commits) x86_64 hpack-0.31.2) +- Heroku (heroku/7.31.0 linux-x64 node-v11.14.0) +- HHVM (HipHop VM 4.24.0 (rel)) +- ImageMagick +- Azul Zulu OpenJDK (7) (openjdk version "1.7.0_232") +- Azul Zulu OpenJDK (8) (openjdk version "1.8.0_222") +- Azul Zulu OpenJDK (11) (openjdk version "11.0.4" 2019-07-16 LTS) +- Azul Zulu OpenJDK (12) (openjdk version "12.0.2" 2019-07-16) +- Ant (Apache Ant(TM) version 1.9.6 compiled on July 20 2018) +- Gradle 5.6.2 +- Maven (Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T19:00:29Z)) +- kubectl (Client Version: v1.16.0) +- helm (Client: v2.14.3+g0e7f3b6) +- Leiningen (Leiningen 2.9.1 on Java 1.8.0_222 OpenJDK 64-Bit Server VM) +- Mercurial (Mercurial Distributed SCM (version 4.4.1)) +- Miniconda (conda 4.7.10) +- Mono (Mono JIT compiler version 6.4.0.198 (tarball Tue Sep 24 01:20:30 UTC 2019)) +- MySQL (mysql Ver 14.14 Distrib 5.7.27, for Linux (x86_64) using EditLine wrapper) +- MySQL Server (user:root password:root) +- MS SQL Server Client Tools +- Node.js (v10.16.3) +- Bower (1.8.8) +- Grunt (grunt-cli v1.2.0) +- Gulp (CLI version: 2.2.0 +Local version: Unknown) +- n (6.0.1) +- Parcel (1.12.3) +- TypeScript (Version 3.6.3) +- Webpack (4.41.0) +- Webpack CLI (3.3.9) +- Yarn (1.19.0) +- PhantomJS (2.1.1) +- PHP 5.6 (PHP 5.6.40-12+ubuntu16.04.1+deb.sury.org+1 (cli) ) +- PHP 7.0 (PHP 7.0.33-11+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 13:30:45) ( NTS )) +- PHP 7.1 (PHP 7.1.32-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 13:28:17) ( NTS )) +- PHP 7.2 (PHP 7.2.22-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 12:54:12) ( NTS )) +- PHP 7.3 (PHP 7.3.9-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 12:54:04) ( NTS )) +- Composer (Composer version 1.9.0 2019-08-02 20:55:32) +- PHPUnit (PHPUnit 7.5.16 by Sebastian Bergmann and contributors.) +- Pollinate +- Powershell (PowerShell 6.2.3) +- rustup (1.19.0) +- rust (1.38.0) +- cargo (1.38.0) +- rustfmt (1.4.4-stable) +- clippy (0.0.212) +- rustdoc (1.38.0) +- bindgen (execute +the +0.51.1) +- cbindgen (0.9.1) +- Scala +- Sphinx Open Source Search Server +- Subversion (svn, version 1.9.3 (r1718519)) +- Terraform (Terraform v0.12.9) +- Vcpkg 2019.09.12-unknownhash +- Zeit Now CLI (16.3.0) +- Google Repository 58 +- Google Play services 49 +- Google APIs 24 +- Google APIs 23 +- Google APIs 22 +- Google APIs 21 +- CMake 3.6.4111459 +- Android Support Repository 47.0.0 +- Android Solver for ConstraintLayout 1.0.2 +- Android Solver for ConstraintLayout 1.0.1 +- Android SDK Platform-Tools 29.0.4 +- Android SDK Platform 29 +- Android SDK Platform 28 +- Android SDK Platform 27 +- Android SDK Platform 26 +- Android SDK Platform 25 +- Android SDK Platform 24 +- Android SDK Platform 23 +- Android SDK Platform 22 +- Android SDK Platform 21 +- Android SDK Platform 19 +- Android SDK Platform 17 +- Android SDK Platform 15 +- Android SDK Platform 10 +- Android SDK Patch Applier v4 +- Android SDK Build-Tools 29.0.2 +- Android SDK Build-Tools 29.0.0 +- Android SDK Build-Tools 28.0.3 +- Android SDK Build-Tools 28.0.2 +- Android SDK Build-Tools 28.0.1 +- Android SDK Build-Tools 28.0.0 +- Android SDK Build-Tools 27.0.3 +- Android SDK Build-Tools 27.0.2 +- Android SDK Build-Tools 27.0.1 +- Android SDK Build-Tools 27.0.0 +- Android SDK Build-Tools 26.0.3 +- Android SDK Build-Tools 26.0.2 +- Android SDK Build-Tools 26.0.1 +- Android SDK Build-Tools 26.0.0 +- Android SDK Build-Tools 25.0.3 +- Android SDK Build-Tools 25.0.2 +- Android SDK Build-Tools 25.0.1 +- Android SDK Build-Tools 25.0.0 +- Android SDK Build-Tools 24.0.3 +- Android SDK Build-Tools 24.0.2 +- Android SDK Build-Tools 24.0.1 +- Android SDK Build-Tools 24.0.0 +- Android SDK Build-Tools 23.0.3 +- Android SDK Build-Tools 23.0.2 +- Android SDK Build-Tools 23.0.1 +- Android SDK Build-Tools 22.0.1 +- Android SDK Build-Tools 21.1.2 +- Android SDK Build-Tools 20.0.0 +- Android SDK Build-Tools 19.1.0 +- Android SDK Build-Tools 17.0.0 +- Android NDK 20.0.5594570 +- Android ConstraintLayout 1.0.2 +- Android ConstraintLayout 1.0.1 +- Az Module (1.0.0) +- Az Module (1.6.0) +- Az Module (2.3.2) +- Az Module (2.6.0) +- Cached container images + - jekyll/builder:latest (Digest: sha256:9182fe84c46f8c196fc89d5c960839053a31e246c39994f30498fbcf70cd4b04) + - node:10 (Digest: sha256:a2bc0489b71f88b358d2ed66efe0025b1896032ca6fd52df780426ce1acd18be) + - node:12 (Digest: sha256:cda22332e2dd46807a14d3268ee3fb298651386ad1f03cfd58772a7dc65f89c7) + - buildpack-deps:stretch (Digest: sha256:9e704902086098039b91927801b84925fbc29bd79133b582bcbea6a19f0362ca) + - debian:9 (Digest: sha256:5fb93ce7a427b7c1c2374d5c29d68a159de7d5e781deeda422f8d51a1a9b6480) + - debian:8 (Digest: sha256:a97db35fa665312803a229cb97fd921a884d0ef3be8cca008e958a7c936c2e7f) + - node:12-alpine (Digest: sha256:744b156ec2dca0ad8291f80f9093273d45eb85378b6290b2fbbada861cc3ed01) + - alpine:3.10 (Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb) + - node:10-alpine (Digest: sha256:77c898d0da5e7bfb6e05c9a64de136ba4e03889a72f3c298e95df822a38f450d) + - alpine:3.9 (Digest: sha256:7746df395af22f04212cd25a92c1d6dbc5a06a0ca9579a229ef43008d4d1302a) + - alpine:3.7 (Digest: sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10) + - alpine:3.8 (Digest: sha256:04696b491e0cc3c58a75bace8941c14c924b9f313b03ce5029ebbc040ed9dcd9) + - mcr.microsoft.com/azure-pipelines/node8-typescript:latest (Digest: sha256:e52e60b9f71183969830a3664279b5d8c799b4b0ec2c25a0686f7c02f6a9669a) +- Python (available through the [setup-python](https://github.com/actions/setup-python/blob/master/README.md) task) + - Python 2.7.16 + - Python 3.4.10 + - Python 3.5.7 + - Python 3.6.9 + - Python 3.7.4 +- Ruby (available through the [setup-ruby](https://github.com/actions/setup-ruby/blob/master/README.md) task) + - Ruby 2.3.7 + - Ruby 2.4.6 + - Ruby 2.5.5 + - Ruby 2.6.3 +- Python (Python 2.7.12) +- pip (pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7)) +- Python3 (Python 3.5.2) +- pip3 (pip 8.1.1 from /usr/lib/python3/dist-packages (python 3.5)) +- PyPy2 ([PyPy 7.1.0 with GCC 6.2.0 20160901]) +- PyPy3 ([PyPy 7.0.0 with GCC 6.2.0 20160901]) +- Boost C++ Libraries 1.69.0 \ No newline at end of file diff --git a/images/linux/Ubuntu1804-README.md b/images/linux/Ubuntu1804-README.md new file mode 100644 index 00000000..43ad1a00 --- /dev/null +++ b/images/linux/Ubuntu1804-README.md @@ -0,0 +1,250 @@ +# Hosted Ubuntu 1804 Image (Ubuntu 18.04.3 LTS) +The following software is installed on machines in the Hosted Ubuntu 1804 (v20190930.2) pool +*** +- 7-Zip 16.02 +- Ansible (ansible 2.8.5) +- AzCopy (azcopy 7.3.0-netcore) +- Azure CLI (azure-cli 2.0.74) +- Azure CLI (azure-devops 0.12.0) +- Basic CLI: + - curl + - dnsutils + - file + - ftp + - iproute2 + - iputils-ping + - jq + - libcurl3 + - libicu55 + - libunwind8 + - locales + - netcat + - openssh-client + - rsync + - shellcheck + - sudo + - telnet + - time + - unzip + - wget + - zip + - tzdata +- AWS CLI (aws-cli/1.16.248 Python/2.7.15+ Linux/5.0.0-1018-azure botocore/1.12.238) +- build-essential +- Clang 6.0 (clang version 6.0.1-svn334776-1~exp1~20190309042703.125 (branches/release_60)) +- CMake (cmake version 3.12.4) +- Docker Compose (docker-compose version 1.22.0, build f46880fe) +- Docker (Docker version 3.0.6, build a63faebc) +- Docker (Docker version 3.0.6, build a63faebc) +- .NET Core SDK: + - 2.2.402 + - 2.2.401 + - 2.2.301 + - 2.2.300 + - 2.2.206 + - 2.2.205 + - 2.2.204 + - 2.2.203 + - 2.2.202 + - 2.2.109 + - 2.2.108 + - 2.2.107 + - 2.2.106 + - 2.2.105 + - 2.2.104 + - 2.2.103 + - 2.2.102 + - 2.2.101 + - 2.2.100 + - 2.1.802 + - 2.1.801 + - 2.1.701 + - 2.1.700 + - 2.1.606 + - 2.1.605 + - 2.1.604 + - 2.1.603 + - 2.1.602 + - 2.1.509 + - 2.1.508 + - 2.1.507 + - 2.1.506 + - 2.1.505 + - 2.1.504 + - 2.1.503 + - 2.1.502 + - 2.1.500 + - 2.1.403 + - 2.1.402 + - 2.1.401 + - 2.1.302 + - 2.1.301 + - 2.1.300 +- Erlang (Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 10.5) +- Firefox (Mozilla Firefox 69.0.1) +- GNU C++ 7.4.0 +- Git (2.23.0) +- Git Large File Storage (LFS) (2.8.0) +- Go 1.11 (go version go1.11.12 linux/amd64) +- Go 1.12 (go version go1.12.7 linux/amd64) +- Go 1.13 (go version go1.13 linux/amd64) +- Google Chrome (Google Chrome 77.0.3865.90 ) +- Google Cloud SDK (264.0.0) +- Haskell Cabal (cabal-install version 2.0.0.1 +compiled using version 2.0.1.1 of the Cabal library ) +- Haskell Cabal (cabal-install version 2.2.0.0 +compiled using version 2.2.0.1 of the Cabal library ) +- Haskell Cabal (cabal-install version 2.4.1.0 +compiled using version 2.4.1.0 of the Cabal library ) +- Haskell Cabal (cabal-install version 3.0.0.0 +compiled using version 3.0.0.0 of the Cabal library ) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.0.2) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.2.2) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.4.4) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.2) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.3) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.4) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.6.5) +- GHC (The Glorious Glasgow Haskell Compilation System, version 8.8.1) +- Haskell Stack (Version 2.1.3, Git revision 636e3a759d51127df2b62f90772def126cdf6d1f (7735 commits) x86_64 hpack-0.31.2) +- Heroku (heroku/7.31.0 linux-x64 node-v11.14.0) +- HHVM (HipHop VM 4.24.0 (rel)) +- ImageMagick +- Azul Zulu OpenJDK (7) (openjdk version "1.7.0_232") +- Azul Zulu OpenJDK (8) (openjdk version "1.8.0_222") +- Azul Zulu OpenJDK (11) (openjdk version "11.0.4" 2019-07-16 LTS) +- Azul Zulu OpenJDK (12) (openjdk version "12.0.2" 2019-07-16) +- Ant (Apache Ant(TM) version 1.10.5 compiled on March 28 2019) +- Gradle 5.6.2 +- Maven (Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T19:00:29Z)) +- kubectl (Client Version: v1.16.0) +- helm (Client: v2.14.3+g0e7f3b6) +- Leiningen (Leiningen 2.9.1 on Java 1.8.0_222 OpenJDK 64-Bit Server VM) +- Mercurial (Mercurial Distributed SCM (version 4.5.3)) +- Miniconda (conda 4.7.10) +- Mono (Mono JIT compiler version 6.4.0.198 (tarball Tue Sep 24 01:21:28 UTC 2019)) +- MySQL (mysql Ver 14.14 Distrib 5.7.27, for Linux (x86_64) using EditLine wrapper) +- MySQL Server (user:root password:root) +- MS SQL Server Client Tools +- Node.js (v10.16.3) +- Bower (1.8.8) +- Grunt (grunt-cli v1.2.0) +- Gulp (CLI version: 2.2.0 +Local version: Unknown) +- n (6.0.1) +- Parcel (1.12.3) +- TypeScript (Version 3.6.3) +- Webpack (4.41.0) +- Webpack CLI (3.3.9) +- Yarn (1.19.0) +- PhantomJS (2.1.1) +- PHP 7.1 (PHP 7.1.32-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 13:28:37) ( NTS )) +- PHP 7.2 (PHP 7.2.22-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 12:54:33) ( NTS )) +- PHP 7.3 (PHP 7.3.9-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 12:54:24) ( NTS )) +- Composer (Composer version 1.9.0 2019-08-02 20:55:32) +- PHPUnit (PHPUnit 7.5.16 by Sebastian Bergmann and contributors.) +- Pollinate +- Powershell (PowerShell 6.2.3) +- rustup (1.19.0) +- rust (1.38.0) +- cargo (1.38.0) +- rustfmt (1.4.4-stable) +- clippy (0.0.212) +- rustdoc (1.38.0) +- bindgen (execute +the +0.51.1) +- cbindgen (0.9.1) +- Scala +- Sphinx Open Source Search Server +- Subversion (svn, version 1.9.7 (r1800392)) +- Terraform (Terraform v0.12.9) +- Vcpkg 2019.09.12-unknownhash +- Zeit Now CLI (16.3.0) +- Google Repository 58 +- Google Play services 49 +- Google APIs 24 +- Google APIs 23 +- Google APIs 22 +- Google APIs 21 +- CMake 3.6.4111459 +- Android Support Repository 47.0.0 +- Android SDK Platform-Tools 29.0.4 +- Android SDK Platform 29 +- Android SDK Platform 28 +- Android SDK Platform 27 +- Android SDK Platform 26 +- Android SDK Platform 25 +- Android SDK Platform 24 +- Android SDK Platform 23 +- Android SDK Platform 22 +- Android SDK Platform 21 +- Android SDK Platform 19 +- Android SDK Platform 17 +- Android SDK Patch Applier v4 +- Android SDK Build-Tools 29.0.2 +- Android SDK Build-Tools 29.0.0 +- Android SDK Build-Tools 28.0.3 +- Android SDK Build-Tools 28.0.2 +- Android SDK Build-Tools 28.0.1 +- Android SDK Build-Tools 28.0.0 +- Android SDK Build-Tools 27.0.3 +- Android SDK Build-Tools 27.0.2 +- Android SDK Build-Tools 27.0.1 +- Android SDK Build-Tools 27.0.0 +- Android SDK Build-Tools 26.0.3 +- Android SDK Build-Tools 26.0.2 +- Android SDK Build-Tools 26.0.1 +- Android SDK Build-Tools 26.0.0 +- Android SDK Build-Tools 25.0.3 +- Android SDK Build-Tools 25.0.2 +- Android SDK Build-Tools 25.0.1 +- Android SDK Build-Tools 25.0.0 +- Android SDK Build-Tools 24.0.3 +- Android SDK Build-Tools 24.0.2 +- Android SDK Build-Tools 24.0.1 +- Android SDK Build-Tools 24.0.0 +- Android SDK Build-Tools 23.0.3 +- Android SDK Build-Tools 23.0.2 +- Android SDK Build-Tools 23.0.1 +- Android SDK Build-Tools 22.0.1 +- Android SDK Build-Tools 21.1.2 +- Android SDK Build-Tools 20.0.0 +- Android SDK Build-Tools 19.1.0 +- Android SDK Build-Tools 17.0.0 +- Android NDK 20.0.5594570 +- Az Module (1.0.0) +- Az Module (1.6.0) +- Az Module (2.3.2) +- Az Module (2.6.0) +- Cached container images + - jekyll/builder:latest (Digest: sha256:9182fe84c46f8c196fc89d5c960839053a31e246c39994f30498fbcf70cd4b04) + - node:10 (Digest: sha256:a2bc0489b71f88b358d2ed66efe0025b1896032ca6fd52df780426ce1acd18be) + - node:12 (Digest: sha256:cda22332e2dd46807a14d3268ee3fb298651386ad1f03cfd58772a7dc65f89c7) + - buildpack-deps:stretch (Digest: sha256:9e704902086098039b91927801b84925fbc29bd79133b582bcbea6a19f0362ca) + - debian:9 (Digest: sha256:5fb93ce7a427b7c1c2374d5c29d68a159de7d5e781deeda422f8d51a1a9b6480) + - debian:8 (Digest: sha256:a97db35fa665312803a229cb97fd921a884d0ef3be8cca008e958a7c936c2e7f) + - node:12-alpine (Digest: sha256:744b156ec2dca0ad8291f80f9093273d45eb85378b6290b2fbbada861cc3ed01) + - alpine:3.10 (Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb) + - node:10-alpine (Digest: sha256:77c898d0da5e7bfb6e05c9a64de136ba4e03889a72f3c298e95df822a38f450d) + - alpine:3.9 (Digest: sha256:7746df395af22f04212cd25a92c1d6dbc5a06a0ca9579a229ef43008d4d1302a) + - alpine:3.7 (Digest: sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10) + - alpine:3.8 (Digest: sha256:04696b491e0cc3c58a75bace8941c14c924b9f313b03ce5029ebbc040ed9dcd9) + - mcr.microsoft.com/azure-pipelines/node8-typescript:latest (Digest: sha256:e52e60b9f71183969830a3664279b5d8c799b4b0ec2c25a0686f7c02f6a9669a) +- Python (available through the [Use Python Version](https://go.microsoft.com/fwlink/?linkid=871498) task) + - Python 2.7.16 + - Python 3.5.7 + - Python 3.6.9 + - Python 3.7.4 +- Ruby (available through the [Use Ruby Version](https://go.microsoft.com/fwlink/?linkid=2005989) task) + - Ruby 2.3.7 + - Ruby 2.4.6 + - Ruby 2.5.5 + - Ruby 2.6.3 +- Python (Python 2.7.15+) +- pip (pip 9.0.1 from /usr/lib/python2.7/dist-packages (python 2.7)) +- Python3 (Python 3.6.8) +- pip3 (pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)) +- PyPy2 ([PyPy 7.1.0 with GCC 6.2.0 20160901]) +- PyPy3 ([PyPy 7.0.0 with GCC 6.2.0 20160901]) +- Boost C++ Libraries 1.69.0 diff --git a/images/linux/config/ubuntu1604.conf b/images/linux/config/ubuntu1604.conf new file mode 100644 index 00000000..e9fbaed2 --- /dev/null +++ b/images/linux/config/ubuntu1604.conf @@ -0,0 +1,2 @@ +# Name of the hosted pool this image will support +POOL_NAME="Hosted Ubuntu 1604" diff --git a/images/linux/config/ubuntu1804.conf b/images/linux/config/ubuntu1804.conf new file mode 100644 index 00000000..375a9382 --- /dev/null +++ b/images/linux/config/ubuntu1804.conf @@ -0,0 +1,2 @@ +# Name of the hosted pool this image will support +POOL_NAME="Hosted Ubuntu 1804" diff --git a/images/linux/scripts/base/repos.sh b/images/linux/scripts/base/repos.sh new file mode 100644 index 00000000..f8280cc0 --- /dev/null +++ b/images/linux/scripts/base/repos.sh @@ -0,0 +1,15 @@ +#!/bin/bash +################################################################################ +## File: repos.sh +## Desc: Installs official Microsoft package repos for the distribution +################################################################################ + +LSB_RELEASE=$(lsb_release -rs) + +# Install Microsoft repository +wget https://packages.microsoft.com/config/ubuntu/$LSB_RELEASE/packages-microsoft-prod.deb +dpkg -i packages-microsoft-prod.deb +apt-get update + +# Install Microsoft GPG public key +curl -L https://packages.microsoft.com/keys/microsoft.asc | apt-key add - diff --git a/images/linux/scripts/helpers/apt.sh b/images/linux/scripts/helpers/apt.sh new file mode 100644 index 00000000..e95a2160 --- /dev/null +++ b/images/linux/scripts/helpers/apt.sh @@ -0,0 +1,23 @@ +#!/bin/bash +################################################################################ +## File: apt.sh +## Desc: This script contains helper functions for using dpkg and apt +################################################################################ + +## Use dpkg to figure out if a package has already been installed +## Example use: +## if ! IsInstalled packageName; then +## echo "packageName is not installed!" +## fi +function IsInstalled { + dpkg -S $1 &> /dev/null +} + +# Configure apt to always assume Y +echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes + +# Use apt-fast for parallel downloads +apt-get install aria2 +add-apt-repository -y ppa:apt-fast/stable +apt-get update +apt-get -y install apt-fast diff --git a/images/linux/scripts/helpers/containercache.sh b/images/linux/scripts/helpers/containercache.sh new file mode 100644 index 00000000..bdf3a83f --- /dev/null +++ b/images/linux/scripts/helpers/containercache.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +source $HELPER_SCRIPTS/apt.sh +source $HELPER_SCRIPTS/document.sh + +# Check prereqs +echo "Checking prereqs for image pulls" +if ! command -v docker; then + echo "Docker is not installed, cant pull images" + exit 1 +fi + +# Information output +systemctl status docker --no-pager + +# Pull images +images=( + docker.io/jekyll/builder + mcr.microsoft.com/azure-pipelines/node8-typescript +) + +for image in "${images[@]}"; do + docker pull "$image" +done + +## Add container information to the metadata file + DocumentInstalledItem "Cached container images" + +while read -r line; do + DocumentInstalledItemIndent "$line" +done <<< "$(docker images --digests --format '{{.Repository}}:{{.Tag}} (Digest: {{.Digest}})')" diff --git a/images/linux/scripts/helpers/document.sh b/images/linux/scripts/helpers/document.sh new file mode 100644 index 00000000..86217160 --- /dev/null +++ b/images/linux/scripts/helpers/document.sh @@ -0,0 +1,30 @@ +#!/bin/bash +################################################################################ +## File: document.sh +## Desc: Helper functions for writing information to the metadata document +################################################################################ + +function WriteItem { + if [ -z "$METADATA_FILE" ]; then + echo "METADATA_FILE environment variable must be set to output to Metadata Document!" + return 1; + else + echo -e "$1" >> "$METADATA_FILE" + fi +} + +function AddTitle { + WriteItem "# $1" +} + +function AddSubTitle { + WriteItem "## $1" +} + +function DocumentInstalledItem { + WriteItem "- $1" +} + +function DocumentInstalledItemIndent { + WriteItem " - $1" +} diff --git a/images/linux/scripts/installers/1604/android.sh b/images/linux/scripts/installers/1604/android.sh new file mode 100644 index 00000000..a2017cc3 --- /dev/null +++ b/images/linux/scripts/installers/1604/android.sh @@ -0,0 +1,145 @@ +#!/bin/bash +################################################################################ +## File: android.sh +## Desc: Installs Android SDK +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Set env variable for SDK Root (https://developer.android.com/studio/command-line/variables) + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk + echo "ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}" | tee -a /etc/environment + +# ANDROID_HOME is deprecated, but older versions of Gradle rely on it +echo "ANDROID_HOME=${ANDROID_SDK_ROOT}" | tee -a /etc/environment + +# Download the latest command line tools so that we can accept all of the licenses. +# See https://developer.android.com/studio/#command-tools +wget -O android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip +unzip android-sdk.zip -d ${ANDROID_ROOT} +rm -f android-sdk.zip + +# Install the following SDKs and build tools, passing in "y" to accept licenses. +echo "y" | ${ANDROID_ROOT}/tools/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT} \ + "ndk-bundle" \ + "platform-tools" \ + "platforms;android-29" \ + "platforms;android-28" \ + "platforms;android-27" \ + "platforms;android-26" \ + "platforms;android-25" \ + "platforms;android-24" \ + "platforms;android-23" \ + "platforms;android-22" \ + "platforms;android-21" \ + "platforms;android-19" \ + "platforms;android-17" \ + "platforms;android-15" \ + "platforms;android-10" \ + "build-tools;29.0.2" \ + "build-tools;29.0.0" \ + "build-tools;28.0.3" \ + "build-tools;28.0.2" \ + "build-tools;28.0.1" \ + "build-tools;28.0.0" \ + "build-tools;27.0.3" \ + "build-tools;27.0.2" \ + "build-tools;27.0.1" \ + "build-tools;27.0.0" \ + "build-tools;26.0.3" \ + "build-tools;26.0.2" \ + "build-tools;26.0.1" \ + "build-tools;26.0.0" \ + "build-tools;25.0.3" \ + "build-tools;25.0.2" \ + "build-tools;25.0.1" \ + "build-tools;25.0.0" \ + "build-tools;24.0.3" \ + "build-tools;24.0.2" \ + "build-tools;24.0.1" \ + "build-tools;24.0.0" \ + "build-tools;23.0.3" \ + "build-tools;23.0.2" \ + "build-tools;23.0.1" \ + "build-tools;22.0.1" \ + "build-tools;21.1.2" \ + "build-tools;20.0.0" \ + "build-tools;19.1.0" \ + "build-tools;17.0.0" \ + "extras;android;m2repository" \ + "extras;google;m2repository" \ + "extras;google;google_play_services" \ + "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.2" \ + "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.1" \ + "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2" \ + "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.1" \ + "add-ons;addon-google_apis-google-24" \ + "add-ons;addon-google_apis-google-23" \ + "add-ons;addon-google_apis-google-22" \ + "add-ons;addon-google_apis-google-21" \ + "cmake;3.6.4111459" \ + "patcher;v4" + +# Document what was added to the image +echo "Lastly, document what was added to the metadata file" +DocumentInstalledItem "Google Repository $(cat ${ANDROID_SDK_ROOT}/extras/google/m2repository/source.properties 2>&1 | grep Pkg.Revision | cut -d '=' -f 2)" +DocumentInstalledItem "Google Play services $(cat ${ANDROID_SDK_ROOT}/extras/google/google_play_services/source.properties 2>&1 | grep Pkg.Revision | cut -d '=' -f 2)" +DocumentInstalledItem "Google APIs 24" +DocumentInstalledItem "Google APIs 23" +DocumentInstalledItem "Google APIs 22" +DocumentInstalledItem "Google APIs 21" +DocumentInstalledItem "CMake $(ls ${ANDROID_SDK_ROOT}/cmake 2>&1)" +DocumentInstalledItem "Android Support Repository 47.0.0" +DocumentInstalledItem "Android Solver for ConstraintLayout 1.0.2" +DocumentInstalledItem "Android Solver for ConstraintLayout 1.0.1" +DocumentInstalledItem "Android SDK Platform-Tools $(cat ${ANDROID_SDK_ROOT}/platform-tools/source.properties 2>&1 | grep Pkg.Revision | cut -d '=' -f 2)" +DocumentInstalledItem "Android SDK Platform 29" +DocumentInstalledItem "Android SDK Platform 28" +DocumentInstalledItem "Android SDK Platform 27" +DocumentInstalledItem "Android SDK Platform 26" +DocumentInstalledItem "Android SDK Platform 25" +DocumentInstalledItem "Android SDK Platform 24" +DocumentInstalledItem "Android SDK Platform 23" +DocumentInstalledItem "Android SDK Platform 22" +DocumentInstalledItem "Android SDK Platform 21" +DocumentInstalledItem "Android SDK Platform 19" +DocumentInstalledItem "Android SDK Platform 17" +DocumentInstalledItem "Android SDK Platform 15" +DocumentInstalledItem "Android SDK Platform 10" +DocumentInstalledItem "Android SDK Patch Applier v4" +DocumentInstalledItem "Android SDK Build-Tools 29.0.2" +DocumentInstalledItem "Android SDK Build-Tools 29.0.0" +DocumentInstalledItem "Android SDK Build-Tools 28.0.3" +DocumentInstalledItem "Android SDK Build-Tools 28.0.2" +DocumentInstalledItem "Android SDK Build-Tools 28.0.1" +DocumentInstalledItem "Android SDK Build-Tools 28.0.0" +DocumentInstalledItem "Android SDK Build-Tools 27.0.3" +DocumentInstalledItem "Android SDK Build-Tools 27.0.2" +DocumentInstalledItem "Android SDK Build-Tools 27.0.1" +DocumentInstalledItem "Android SDK Build-Tools 27.0.0" +DocumentInstalledItem "Android SDK Build-Tools 26.0.3" +DocumentInstalledItem "Android SDK Build-Tools 26.0.2" +DocumentInstalledItem "Android SDK Build-Tools 26.0.1" +DocumentInstalledItem "Android SDK Build-Tools 26.0.0" +DocumentInstalledItem "Android SDK Build-Tools 25.0.3" +DocumentInstalledItem "Android SDK Build-Tools 25.0.2" +DocumentInstalledItem "Android SDK Build-Tools 25.0.1" +DocumentInstalledItem "Android SDK Build-Tools 25.0.0" +DocumentInstalledItem "Android SDK Build-Tools 24.0.3" +DocumentInstalledItem "Android SDK Build-Tools 24.0.2" +DocumentInstalledItem "Android SDK Build-Tools 24.0.1" +DocumentInstalledItem "Android SDK Build-Tools 24.0.0" +DocumentInstalledItem "Android SDK Build-Tools 23.0.3" +DocumentInstalledItem "Android SDK Build-Tools 23.0.2" +DocumentInstalledItem "Android SDK Build-Tools 23.0.1" +DocumentInstalledItem "Android SDK Build-Tools 22.0.1" +DocumentInstalledItem "Android SDK Build-Tools 21.1.2" +DocumentInstalledItem "Android SDK Build-Tools 20.0.0" +DocumentInstalledItem "Android SDK Build-Tools 19.1.0" +DocumentInstalledItem "Android SDK Build-Tools 17.0.0" +DocumentInstalledItem "Android NDK $(cat ${ANDROID_SDK_ROOT}/ndk-bundle/source.properties 2>&1 | grep Pkg.Revision | cut -d ' ' -f 3)" +DocumentInstalledItem "Android ConstraintLayout 1.0.2" +DocumentInstalledItem "Android ConstraintLayout 1.0.1" diff --git a/images/linux/scripts/installers/1604/azpowershell.sh b/images/linux/scripts/installers/1604/azpowershell.sh new file mode 100644 index 00000000..1886e8de --- /dev/null +++ b/images/linux/scripts/installers/1604/azpowershell.sh @@ -0,0 +1,46 @@ +#!/bin/bash +################################################################################ +## File: azpowershell.sh +## Desc: Installed Azure PowerShell +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Azure CLI (instructions taken from https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_1.0.0 -RequiredVersion 1.0.0 -Force' +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_1.6.0 -RequiredVersion 1.6.0 -Force' +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_2.3.2 -RequiredVersion 2.3.2 -Force' +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_2.6.0 -RequiredVersion 2.6.0 -Force' + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! pwsh -Command '$actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_1.0.0:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath + $actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_1.6.0:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath + $actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_2.3.2:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath + $actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_2.6.0:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath'; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Az Module (1.0.0)" +DocumentInstalledItem "Az Module (1.6.0)" +DocumentInstalledItem "Az Module (2.3.2)" +DocumentInstalledItem "Az Module (2.6.0)" \ No newline at end of file diff --git a/images/linux/scripts/installers/1604/basic.sh b/images/linux/scripts/installers/1604/basic.sh new file mode 100644 index 00000000..b437f048 --- /dev/null +++ b/images/linux/scripts/installers/1604/basic.sh @@ -0,0 +1,88 @@ +#!/bin/bash +################################################################################ +## File: basic.sh +## Desc: Installs basic command line utilities and dev packages +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +set -e + +# Install basic command-line utilities +apt-fast install -y --no-install-recommends \ + curl \ + dnsutils \ + file \ + ftp \ + iproute2 \ + iputils-ping \ + jq \ + libcurl3 \ + libicu55 \ + libunwind8 \ + locales \ + netcat \ + openssh-client \ + rsync \ + shellcheck \ + sudo \ + telnet \ + time \ + unzip \ + wget \ + zip \ + tzdata + +# Electron / VSCode / GitHub Desktop prereqs +apt-fast install -y --no-install-recommends \ + libxkbfile-dev \ + pkg-config \ + libsecret-1-dev \ + libxss1 \ + libgconf-2-4 \ + dbus \ + xvfb \ + libgtk-3-0 \ + fakeroot \ + dpkg \ + rpm \ + xz-utils \ + xorriso \ + zsync + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in curl file ftp jq netcat ssh rsync shellcheck sudo telnet time unzip wget zip; do + if ! command -v $cmd; then + echo "$cmd was not installed" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Basic CLI:" +DocumentInstalledItemIndent "curl" +DocumentInstalledItemIndent "dnsutils" +DocumentInstalledItemIndent "file" +DocumentInstalledItemIndent "ftp" +DocumentInstalledItemIndent "iproute2" +DocumentInstalledItemIndent "iputils-ping" +DocumentInstalledItemIndent "jq" +DocumentInstalledItemIndent "libcurl3" +DocumentInstalledItemIndent "libicu55" +DocumentInstalledItemIndent "libunwind8" +DocumentInstalledItemIndent "locales" +DocumentInstalledItemIndent "netcat" +DocumentInstalledItemIndent "openssh-client" +DocumentInstalledItemIndent "rsync" +DocumentInstalledItemIndent "shellcheck" +DocumentInstalledItemIndent "sudo" +DocumentInstalledItemIndent "telnet" +DocumentInstalledItemIndent "time" +DocumentInstalledItemIndent "unzip" +DocumentInstalledItemIndent "wget" +DocumentInstalledItemIndent "zip" +DocumentInstalledItemIndent "tzdata" \ No newline at end of file diff --git a/images/linux/scripts/installers/1604/dotnetcore-sdk.sh b/images/linux/scripts/installers/1604/dotnetcore-sdk.sh new file mode 100644 index 00000000..b2f1bc0d --- /dev/null +++ b/images/linux/scripts/installers/1604/dotnetcore-sdk.sh @@ -0,0 +1,94 @@ +#!/bin/bash +################################################################################ +## File: dotnetcore-sdk.sh +## Desc: Installs .NET Core SDK +################################################################################ + +source $HELPER_SCRIPTS/apt.sh +source $HELPER_SCRIPTS/document.sh + +LATEST_DOTNET_PACKAGE=dotnet-sdk-3.0 + +LSB_RELEASE=$(lsb_release -rs) + +mksamples() +{ + sdk=$1 + sample=$2 + mkdir "$sdk" + cd "$sdk" || exit + set -e + dotnet help + dotnet new globaljson --sdk-version "$sdk" + dotnet new "$sample" + dotnet restore + dotnet build + set +e + cd .. || exit + rm -rf "$sdk" +} + +set -e + +echo "Determing if .NET Core ($LATEST_DOTNET_PACKAGE) is installed" +if ! IsInstalled $LATEST_DOTNET_PACKAGE; then + echo "Could not find .NET Core ($LATEST_DOTNET_PACKAGE), installing..." + wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb + dpkg -i packages-microsoft-prod.deb + apt-get update + apt-get install apt-transport-https + apt-get update + apt-get install $LATEST_DOTNET_PACKAGE +else + echo ".NET Core ($LATEST_DOTNET_PACKAGE) is already installed" +fi + +# Get list of all released SDKs from channels which are not end-of-life or preview +release_urls=("https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.1/releases.json" "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json" "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.1/releases.json") +sdks=() +for release_url in ${release_urls[@]}; do + echo "${release_url}" + releases=$(curl "${release_url}") + sdks=("${sdks[@]}" $(echo "${releases}" | jq '.releases[]' | jq '.sdk.version')) + sdks=("${sdks[@]}" $(echo "${releases}" | jq '.releases[]' | jq '.sdks[]?' | jq '.version')) +done + +sortedSdks=$(echo ${sdks[@]} | tr ' ' '\n' | grep -v preview | grep -v rc | grep -v display | cut -d\" -f2 | sort -u -r) + +for sdk in $sortedSdks; do + url="https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$sdk/dotnet-sdk-$sdk-linux-x64.tar.gz" + echo "$url" >> urls + echo "Adding $url to list to download later" +done + +# Download additional SDKs +echo "Downloading release tarballs..." +cat urls | xargs -n 1 -P 16 wget -q +for tarball in *.tar.gz; do + dest="./tmp-$(basename -s .tar.gz $tarball)" + echo "Extracting $tarball to $dest" + mkdir "$dest" && tar -C "$dest" -xzf "$tarball" + rsync -qav "$dest/shared/" /usr/share/dotnet/shared/ + rsync -qav "$dest/host/" /usr/share/dotnet/host/ + rsync -qav "$dest/sdk/" /usr/share/dotnet/sdk/ + rm -rf "$dest" + rm "$tarball" +done +rm urls + +DocumentInstalledItem ".NET Core SDK:" +# Smoke test each SDK +for sdk in $sortedSdks; do + mksamples "$sdk" "console" + mksamples "$sdk" "mstest" + mksamples "$sdk" "xunit" + mksamples "$sdk" "web" + mksamples "$sdk" "mvc" + mksamples "$sdk" "webapi" + DocumentInstalledItemIndent "$sdk" +done + +# NuGetFallbackFolder at /usr/share/dotnet/sdk/NuGetFallbackFolder is warmed up by smoke test +# Additional FTE will just copy to ~/.dotnet/NuGet which provides no benefit on a fungible machine +echo "DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1" | tee -a /etc/environment +echo "PATH=\"\$HOME/.dotnet/tools:\$PATH\"" | tee -a /etc/skel/.profile diff --git a/images/linux/scripts/installers/1604/go.sh b/images/linux/scripts/installers/1604/go.sh new file mode 100644 index 00000000..69c7afbe --- /dev/null +++ b/images/linux/scripts/installers/1604/go.sh @@ -0,0 +1,36 @@ +#!/bin/bash +################################################################################ +## File: go.sh +## Desc: Installs go, configures GOROOT, and adds go to the path +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# This function installs Go using the specified arguments: +# $1=MajorVersion (1.11) +# $2=MajorAndMinorVersion (1.11.1) +# $3=IsDefaultVersion (true or false) +function InstallGo () { + curl -sL https://dl.google.com/go/go$2.linux-amd64.tar.gz -o go$2.linux-amd64.tar.gz + mkdir -p /usr/local/go$1 + tar -C /usr/local/go$1 -xzf go$2.linux-amd64.tar.gz --strip-components=1 go + rm go$2.linux-amd64.tar.gz + echo "GOROOT_${1//./_}_X64=/usr/local/go$1" | tee -a /etc/environment + DocumentInstalledItem "Go $1 ($(/usr/local/go$1/bin/go version))" + + # If this version of Go is to be the default version, + # symlink it into the path and point GOROOT to it. + if [ $3 = true ] + then + ln -s /usr/local/go$1/bin/* /usr/bin/ + echo "GOROOT=/usr/local/go$1" | tee -a /etc/environment + fi +} + +# Install Go versions +InstallGo 1.9 1.9.7 false +InstallGo 1.10 1.10.8 false +InstallGo 1.11 1.11.12 false +InstallGo 1.12 1.12.7 true +InstallGo 1.13 1.13 false diff --git a/images/linux/scripts/installers/1604/hosted-tool-cache.sh b/images/linux/scripts/installers/1604/hosted-tool-cache.sh new file mode 100644 index 00000000..f49cffd6 --- /dev/null +++ b/images/linux/scripts/installers/1604/hosted-tool-cache.sh @@ -0,0 +1,40 @@ +#!/bin/bash +################################################################################ +## File: hosted-tool-cache.sh +## Desc: Downloads and installs hosted tools cache +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Fail out if any setups fail +set -e + +# Download hosted tool cache +AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache +echo "AGENT_TOOLSDIRECTORY=$AGENT_TOOLSDIRECTORY" | tee -a /etc/environment +azcopy --recursive \ + --source https://vstsagenttools.blob.core.windows.net/tools/hostedtoolcache/linux \ + --destination $AGENT_TOOLSDIRECTORY + +# Install tools from hosted tool cache +original_directory=$PWD +setups=$(find $AGENT_TOOLSDIRECTORY -name setup.sh) +for setup in $setups; do + chmod +x $setup; + cd $(dirname $setup); + ./$(basename $setup); + cd $original_directory; +done; + +DocumentInstalledItem "Python (available through the [setup-python](https://github.com/actions/setup-python/blob/master/README.md) task)" +pythons=$(ls $AGENT_TOOLSDIRECTORY/Python) +for python in $pythons; do + DocumentInstalledItemIndent "Python $python" +done; + +DocumentInstalledItem "Ruby (available through the [setup-ruby](https://github.com/actions/setup-ruby/blob/master/README.md) task)" +rubys=$(ls $AGENT_TOOLSDIRECTORY/Ruby) +for ruby in $rubys; do + DocumentInstalledItemIndent "Ruby $ruby" +done; diff --git a/images/linux/scripts/installers/1604/kubernetes-tools.sh b/images/linux/scripts/installers/1604/kubernetes-tools.sh new file mode 100644 index 00000000..e4b8fd25 --- /dev/null +++ b/images/linux/scripts/installers/1604/kubernetes-tools.sh @@ -0,0 +1,40 @@ +#!/bin/bash +################################################################################ +## File: kubernetes-tools.sh +## Desc: Installs kubectl, helm +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +## Install kubectl +apt-get install -y apt-transport-https +curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - +touch /etc/apt/sources.list.d/kubernetes.list +echo "deb http://apt.kubernetes.io/ kubernetes-$(lsb_release -cs) main" | tee -a /etc/apt/sources.list.d/kubernetes.list +apt-get update +apt-get install -y kubectl + +# Install Helm +curl -L https://git.io/get_helm.sh | bash + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v kubectl; then + echo "kubectl was not installed" + exit 1 +fi + +if ! command -v helm; then + echo "helm was not installed" + exit 1 +fi + +echo "Initializing helm" +helm init --client-only + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "kubectl ($(kubectl version --short |& head -n 1))" +DocumentInstalledItem "helm ($(helm version --short |& head -n 1))" diff --git a/images/linux/scripts/installers/1604/mercurial.sh b/images/linux/scripts/installers/1604/mercurial.sh new file mode 100644 index 00000000..5c45a95c --- /dev/null +++ b/images/linux/scripts/installers/1604/mercurial.sh @@ -0,0 +1,25 @@ +#!/bin/bash +################################################################################ +## File: mercurial.sh +## Desc: Installs Mercurial +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install Mercurial from the mercurial-ppa/releases repository for the latest version. +# https://www.mercurial-scm.org/wiki/Download +add-apt-repository ppa:mercurial-ppa/releases -y +apt-get update +apt-get install -y --no-install-recommends mercurial + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v hg; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Mercurial ($(hg --version | head -n 1))" diff --git a/images/linux/scripts/installers/1604/php.sh b/images/linux/scripts/installers/1604/php.sh new file mode 100644 index 00000000..45c5fe03 --- /dev/null +++ b/images/linux/scripts/installers/1604/php.sh @@ -0,0 +1,268 @@ +#!/bin/bash +################################################################################ +## File: php.sh +## Desc: Installs php +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_RELEASE=$(lsb_release -rs) + +set -e + +apt-add-repository ppa:ondrej/php -y + +# Install php5.6 +apt-get update +apt-fast install -y --no-install-recommends \ + php5.6 \ + php5.6-amqp \ + php5.6-bcmath \ + php5.6-bz2 \ + php5.6-cgi \ + php5.6-cli \ + php5.6-common \ + php5.6-curl \ + php5.6-dba \ + php5.6-dev \ + php5.6-enchant \ + php5.6-fpm \ + php5.6-gd \ + php5.6-gmp \ + php5.6-imap \ + php5.6-interbase \ + php5.6-intl \ + php5.6-json \ + php5.6-ldap \ + php5.6-mbstring \ + php5.6-mcrypt \ + php5.6-mysql \ + php5.6-odbc \ + php5.6-opcache \ + php5.6-pgsql \ + php5.6-phpdbg \ + php5.6-pspell \ + php5.6-readline \ + php5.6-recode \ + php5.6-snmp \ + php5.6-soap \ + php5.6-sqlite3 \ + php5.6-sybase \ + php5.6-tidy \ + php5.6-xml \ + php5.6-xmlrpc \ + php5.6-xsl \ + php5.6-zip +apt-get remove --purge -yq php5.6-dev + +# Install php7.0 +apt-fast install -y --no-install-recommends \ + php7.0 \ + php7.0-amqp \ + php7.0-bcmath \ + php7.0-bz2 \ + php7.0-cgi \ + php7.0-cli \ + php7.0-common \ + php7.0-curl \ + php7.0-dba \ + php7.0-dev \ + php7.0-enchant \ + php7.0-fpm \ + php7.0-gd \ + php7.0-gmp \ + php7.0-imap \ + php7.0-interbase \ + php7.0-intl \ + php7.0-json \ + php7.0-ldap \ + php7.0-mbstring \ + php7.0-mcrypt \ + php7.0-mysql \ + php7.0-odbc \ + php7.0-opcache \ + php7.0-pgsql \ + php7.0-phpdbg \ + php7.0-pspell \ + php7.0-readline \ + php7.0-recode \ + php7.0-snmp \ + php7.0-soap \ + php7.0-sqlite3 \ + php7.0-sybase \ + php7.0-tidy \ + php7.0-xml \ + php7.0-xmlrpc \ + php7.0-xsl \ + php7.0-zip +apt-get remove --purge -yq php7.0-dev + +# Install php7.1 +apt-fast install -y --no-install-recommends \ + php7.1 \ + php7.1-amqp \ + php7.1-bcmath \ + php7.1-bz2 \ + php7.1-cgi \ + php7.1-cli \ + php7.1-common \ + php7.1-curl \ + php7.1-dba \ + php7.1-dev \ + php7.1-enchant \ + php7.1-fpm \ + php7.1-gd \ + php7.1-gmp \ + php7.1-imap \ + php7.1-interbase \ + php7.1-intl \ + php7.1-json \ + php7.1-ldap \ + php7.1-mbstring \ + php7.1-mcrypt \ + php7.1-mysql \ + php7.1-odbc \ + php7.1-opcache \ + php7.1-pgsql \ + php7.1-phpdbg \ + php7.1-pspell \ + php7.1-readline \ + php7.1-recode \ + php7.1-snmp \ + php7.1-soap \ + php7.1-sqlite3 \ + php7.1-sybase \ + php7.1-tidy \ + php7.1-xml \ + php7.1-xmlrpc \ + php7.1-xsl \ + php7.1-zip +apt-get remove --purge -yq php7.1-dev + +# Install php7.2 +apt-fast install -y --no-install-recommends \ + php7.2 \ + php7.2-apcu \ + php7.2-amqp \ + php7.2-bcmath \ + php7.2-bz2 \ + php7.2-cgi \ + php7.2-cli \ + php7.2-common \ + php7.2-curl \ + php7.2-dba \ + php7.2-dev \ + php7.2-enchant \ + php7.2-fpm \ + php7.2-gd \ + php7.2-gmp \ + php7.2-imap \ + php7.2-interbase \ + php7.2-intl \ + php7.2-json \ + php7.2-ldap \ + php7.2-mbstring \ + php7.2-mysql \ + php7.2-odbc \ + php7.2-opcache \ + php7.2-pgsql \ + php7.2-phpdbg \ + php7.2-pspell \ + php7.2-readline \ + php7.2-recode \ + php7.2-snmp \ + php7.2-soap \ + php7.2-sqlite3 \ + php7.2-sybase \ + php7.2-tidy \ + php7.2-xml \ + php7.2-xmlrpc \ + php7.2-xsl \ + php7.2-zip + +# Install php7.3 +apt-fast install -y --no-install-recommends \ + php7.3 \ + php7.3-apcu \ + php7.3-amqp \ + php7.3-bcmath \ + php7.3-bz2 \ + php7.3-cgi \ + php7.3-cli \ + php7.3-common \ + php7.3-curl \ + php7.3-dba \ + php7.3-dev \ + php7.3-enchant \ + php7.3-fpm \ + php7.3-gd \ + php7.3-gmp \ + php7.3-imap \ + php7.3-interbase \ + php7.3-intl \ + php7.3-json \ + php7.3-ldap \ + php7.3-mbstring \ + php7.3-mysql \ + php7.3-odbc \ + php7.3-opcache \ + php7.3-pgsql \ + php7.3-phpdbg \ + php7.3-pspell \ + php7.3-readline \ + php7.3-recode \ + php7.3-snmp \ + php7.3-soap \ + php7.3-sqlite3 \ + php7.3-sybase \ + php7.3-tidy \ + php7.3-xml \ + php7.3-xmlrpc \ + php7.3-xsl \ + php7.3-zip + +apt-fast install -y --no-install-recommends \ + php-igbinary \ + php-memcache \ + php-memcached \ + php-mongodb \ + php-redis \ + php-xdebug \ + php-yaml \ + php-zmq + +apt-get remove --purge -yq php7.2-dev + +apt-fast install -y --no-install-recommends snmp + +# Install composer +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" +php composer-setup.php +sudo mv composer.phar /usr/bin/composer +php -r "unlink('composer-setup.php');" + +# Install phpunit (for PHP) +wget -q -O phpunit https://phar.phpunit.de/phpunit-7.phar +chmod +x phpunit +mv phpunit /usr/local/bin/phpunit + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in php php5.6 php7.0 php7.1 php7.2 php7.3 composer phpunit; do + if ! command -v $cmd; then + echo "$cmd was not installed" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "PHP 5.6 ($(php5.6 --version | head -n 1))" +DocumentInstalledItem "PHP 7.0 ($(php7.0 --version | head -n 1))" +DocumentInstalledItem "PHP 7.1 ($(php7.1 --version | head -n 1))" +DocumentInstalledItem "PHP 7.2 ($(php7.2 --version | head -n 1))" +DocumentInstalledItem "PHP 7.3 ($(php7.3 --version | head -n 1))" +DocumentInstalledItem "Composer ($(composer --version))" +DocumentInstalledItem "PHPUnit ($(phpunit --version))" diff --git a/images/linux/scripts/installers/1604/powershellcore.sh b/images/linux/scripts/installers/1604/powershellcore.sh new file mode 100644 index 00000000..8b827815 --- /dev/null +++ b/images/linux/scripts/installers/1604/powershellcore.sh @@ -0,0 +1,28 @@ +#!/bin/bash +################################################################################ +## File: powershellcore.sh +## Desc: Installs powershellcore +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_RELEASE=$(lsb_release -rs) + +# Install Powershell +apt-get install -y powershell + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v pwsh; then + echo "pwsh was not installed" + exit 1 +fi +if ! pwsh -c 'Write-Host Hello world'; then + echo "pwsh failed to run" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Powershell ($(pwsh --version))" diff --git a/images/linux/scripts/installers/1604/preparemetadata.sh b/images/linux/scripts/installers/1604/preparemetadata.sh new file mode 100644 index 00000000..be102d83 --- /dev/null +++ b/images/linux/scripts/installers/1604/preparemetadata.sh @@ -0,0 +1,12 @@ +#!/bin/bash +################################################################################ +## File: preparemetadata.sh +## Desc: This script adds a image title information to the metadata +## document +################################################################################ + +source $HELPER_SCRIPTS/document.sh + +AddTitle "Hosted Ubuntu 1604 Image ($(lsb_release -ds))" +WriteItem "The following software is installed on machines in the Hosted Ubuntu 1604 ($IMAGE_VERSION) pool" +WriteItem "***" diff --git a/images/linux/scripts/installers/1804/android.sh b/images/linux/scripts/installers/1804/android.sh new file mode 100644 index 00000000..df83a73e --- /dev/null +++ b/images/linux/scripts/installers/1804/android.sh @@ -0,0 +1,133 @@ +#!/bin/bash +################################################################################ +## File: android.sh +## Desc: Installs Android SDK +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Set env variable for SDK Root (https://developer.android.com/studio/command-line/variables) +ANDROID_ROOT=/usr/local/lib/android +ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk +echo "ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}" | tee -a /etc/environment + +# ANDROID_HOME is deprecated, but older versions of Gradle rely on it +echo "ANDROID_HOME=${ANDROID_SDK_ROOT}" | tee -a /etc/environment + +# Download the latest command line tools so that we can accept all of the licenses. +# See https://developer.android.com/studio/#command-tools +wget -O android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip +unzip android-sdk.zip -d ${ANDROID_ROOT} +rm -f android-sdk.zip + +# Install the following SDKs and build tools, passing in "y" to accept licenses. +echo "y" | ${ANDROID_ROOT}/tools/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT} \ + "ndk-bundle" \ + "platform-tools" \ + "platforms;android-29" \ + "platforms;android-28" \ + "platforms;android-27" \ + "platforms;android-26" \ + "platforms;android-25" \ + "platforms;android-24" \ + "platforms;android-23" \ + "platforms;android-22" \ + "platforms;android-21" \ + "platforms;android-19" \ + "platforms;android-17" \ + "build-tools;29.0.2" \ + "build-tools;29.0.0" \ + "build-tools;28.0.3" \ + "build-tools;28.0.2" \ + "build-tools;28.0.1" \ + "build-tools;28.0.0" \ + "build-tools;27.0.3" \ + "build-tools;27.0.2" \ + "build-tools;27.0.1" \ + "build-tools;27.0.0" \ + "build-tools;26.0.3" \ + "build-tools;26.0.2" \ + "build-tools;26.0.1" \ + "build-tools;26.0.0" \ + "build-tools;25.0.3" \ + "build-tools;25.0.2" \ + "build-tools;25.0.1" \ + "build-tools;25.0.0" \ + "build-tools;24.0.3" \ + "build-tools;24.0.2" \ + "build-tools;24.0.1" \ + "build-tools;24.0.0" \ + "build-tools;23.0.3" \ + "build-tools;23.0.2" \ + "build-tools;23.0.1" \ + "build-tools;22.0.1" \ + "build-tools;21.1.2" \ + "build-tools;20.0.0" \ + "build-tools;19.1.0" \ + "build-tools;17.0.0" \ + "extras;android;m2repository" \ + "extras;google;m2repository" \ + "extras;google;google_play_services" \ + "add-ons;addon-google_apis-google-24" \ + "add-ons;addon-google_apis-google-23" \ + "add-ons;addon-google_apis-google-22" \ + "add-ons;addon-google_apis-google-21" \ + "cmake;3.6.4111459" \ + "patcher;v4" + +# Document what was added to the image +echo "Lastly, document what was added to the metadata file" +DocumentInstalledItem "Google Repository $(cat ${ANDROID_SDK_ROOT}/extras/google/m2repository/source.properties 2>&1 | grep Pkg.Revision | cut -d '=' -f 2)" +DocumentInstalledItem "Google Play services $(cat ${ANDROID_SDK_ROOT}/extras/google/google_play_services/source.properties 2>&1 | grep Pkg.Revision | cut -d '=' -f 2)" +DocumentInstalledItem "Google APIs 24" +DocumentInstalledItem "Google APIs 23" +DocumentInstalledItem "Google APIs 22" +DocumentInstalledItem "Google APIs 21" +DocumentInstalledItem "CMake $(ls ${ANDROID_SDK_ROOT}/cmake 2>&1)" +DocumentInstalledItem "Android Support Repository 47.0.0" +DocumentInstalledItem "Android SDK Platform-Tools $(cat ${ANDROID_SDK_ROOT}/platform-tools/source.properties 2>&1 | grep Pkg.Revision | cut -d '=' -f 2)" +DocumentInstalledItem "Android SDK Platform 29" +DocumentInstalledItem "Android SDK Platform 28" +DocumentInstalledItem "Android SDK Platform 27" +DocumentInstalledItem "Android SDK Platform 26" +DocumentInstalledItem "Android SDK Platform 25" +DocumentInstalledItem "Android SDK Platform 24" +DocumentInstalledItem "Android SDK Platform 23" +DocumentInstalledItem "Android SDK Platform 22" +DocumentInstalledItem "Android SDK Platform 21" +DocumentInstalledItem "Android SDK Platform 19" +DocumentInstalledItem "Android SDK Platform 17" +DocumentInstalledItem "Android SDK Patch Applier v4" +DocumentInstalledItem "Android SDK Build-Tools 29.0.2" +DocumentInstalledItem "Android SDK Build-Tools 29.0.0" +DocumentInstalledItem "Android SDK Build-Tools 28.0.3" +DocumentInstalledItem "Android SDK Build-Tools 28.0.2" +DocumentInstalledItem "Android SDK Build-Tools 28.0.1" +DocumentInstalledItem "Android SDK Build-Tools 28.0.0" +DocumentInstalledItem "Android SDK Build-Tools 27.0.3" +DocumentInstalledItem "Android SDK Build-Tools 27.0.2" +DocumentInstalledItem "Android SDK Build-Tools 27.0.1" +DocumentInstalledItem "Android SDK Build-Tools 27.0.0" +DocumentInstalledItem "Android SDK Build-Tools 26.0.3" +DocumentInstalledItem "Android SDK Build-Tools 26.0.2" +DocumentInstalledItem "Android SDK Build-Tools 26.0.1" +DocumentInstalledItem "Android SDK Build-Tools 26.0.0" +DocumentInstalledItem "Android SDK Build-Tools 25.0.3" +DocumentInstalledItem "Android SDK Build-Tools 25.0.2" +DocumentInstalledItem "Android SDK Build-Tools 25.0.1" +DocumentInstalledItem "Android SDK Build-Tools 25.0.0" +DocumentInstalledItem "Android SDK Build-Tools 24.0.3" +DocumentInstalledItem "Android SDK Build-Tools 24.0.2" +DocumentInstalledItem "Android SDK Build-Tools 24.0.1" +DocumentInstalledItem "Android SDK Build-Tools 24.0.0" +DocumentInstalledItem "Android SDK Build-Tools 23.0.3" +DocumentInstalledItem "Android SDK Build-Tools 23.0.2" +DocumentInstalledItem "Android SDK Build-Tools 23.0.1" +DocumentInstalledItem "Android SDK Build-Tools 22.0.1" +DocumentInstalledItem "Android SDK Build-Tools 21.1.2" +DocumentInstalledItem "Android SDK Build-Tools 20.0.0" +DocumentInstalledItem "Android SDK Build-Tools 19.1.0" +DocumentInstalledItem "Android SDK Build-Tools 17.0.0" +DocumentInstalledItem "Android NDK $(cat ${ANDROID_SDK_ROOT}/ndk-bundle/source.properties 2>&1 | grep Pkg.Revision | cut -d ' ' -f 3)" diff --git a/images/linux/scripts/installers/1804/azpowershell.sh b/images/linux/scripts/installers/1804/azpowershell.sh new file mode 100644 index 00000000..c843aa58 --- /dev/null +++ b/images/linux/scripts/installers/1804/azpowershell.sh @@ -0,0 +1,46 @@ +#!/bin/bash +################################################################################ +## File: azpowershell.sh +## Desc: Installed Azure PowerShell +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Azure CLI (instructions taken from https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_1.0.0 -RequiredVersion 1.0.0 -Force' +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_1.6.0 -RequiredVersion 1.6.0 -Force' +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_2.3.2 -RequiredVersion 2.3.2 -Force' +sudo pwsh -Command 'Save-Module -Name Az -LiteralPath /usr/share/az_2.6.0 -RequiredVersion 2.6.0 -Force' + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! pwsh -Command '$actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_1.0.0:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath + $actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_1.6.0:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath + $actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_2.3.2:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath + $actualPSModulePath = $env:PSModulePath ; $env:PSModulePath = "/usr/share/az_2.6.0:" + $env:PSModulePath; + if (!(get-module -listavailable -name Az.accounts)) { + Write-Host "Az Module was not installed"; $env:PSModulePath = $actualPSModulePath; exit 1 + } + $env:PSModulePath = $actualPSModulePath'; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Az Module (1.0.0)" +DocumentInstalledItem "Az Module (1.6.0)" +DocumentInstalledItem "Az Module (2.3.2)" +DocumentInstalledItem "Az Module (2.6.0)" diff --git a/images/linux/scripts/installers/1804/basic.sh b/images/linux/scripts/installers/1804/basic.sh new file mode 100644 index 00000000..baf3eea4 --- /dev/null +++ b/images/linux/scripts/installers/1804/basic.sh @@ -0,0 +1,154 @@ +#!/bin/bash +################################################################################ +## File: basic.sh +## Desc: Installs basic command line utilities and dev packages +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +set -e + +echo "Install curl" +apt-get install -y --no-install-recommends curl + +echo "Install dnsutils" +apt-get install -y --no-install-recommends dnsutils + +echo "Install file" +apt-get install -y --no-install-recommends file + +echo "Install ftp" +apt-get install -y --no-install-recommends ftp + +echo "Install iproute2" +apt-get install -y --no-install-recommends iproute2 + +echo "Install iputils-ping" +apt-get install -y --no-install-recommends iputils-ping + +echo "Install jq" +apt-get install -y --no-install-recommends jq + +echo "Install libcurl3" +apt-get install -y --no-install-recommends libcurl3 + +echo "Install libunwind8" +apt-get install -y --no-install-recommends libunwind8 + +echo "Install locales" +apt-get install -y --no-install-recommends locales + +echo "Install netcat" +apt-get install -y --no-install-recommends netcat + +echo "Install openssh-client" +apt-get install -y --no-install-recommends openssh-client + +echo "Install rsync" +apt-get install -y --no-install-recommends rsync + +echo "Install shellcheck" +apt-get install -y --no-install-recommends shellcheck + +echo "Install sudo" +apt-get install -y --no-install-recommends sudo + +echo "Install telnet" +apt-get install -y --no-install-recommends telnet + +echo "Install time" +apt-get install -y --no-install-recommends time + +echo "Install unzip" +apt-get install -y --no-install-recommends unzip + +echo "Install wget" +apt-get install -y --no-install-recommends wget + +echo "Install zip" +apt-get install -y --no-install-recommends zip + +echo "Install tzdata" +apt-get install -y --no-install-recommends tzdata + +echo "Install libxkbfile" +apt-get install -y --no-install-recommends libxkbfile-dev + +echo "Install pkg-config" +apt-get install -y --no-install-recommends pkg-config + +echo "Install libsecret-1-dev" +apt-get install -y --no-install-recommends libsecret-1-dev + +echo "Install libxss1" +apt-get install -y --no-install-recommends libxss1 + +echo "Install libgconf-2-4" +apt-get install -y --no-install-recommends libgconf-2-4 + +echo "Install dbus" +apt-get install -y --no-install-recommends dbus + +echo "Install xvfb" +apt-get install -y --no-install-recommends xvfb + +echo "Install libgtk" +apt-get install -y --no-install-recommends libgtk-3-0 + +echo "Install fakeroot" +apt-get install -y --no-install-recommends fakeroot + +echo "Install dpkg" +apt-get install -y --no-install-recommends dpkg + +echo "Install rpm" +apt-get install -y --no-install-recommends rpm + +echo "Install xz-utils" +apt-get install -y --no-install-recommends xz-utils + +echo "Install xorriso" +apt-get install -y --no-install-recommends xorriso + +echo "Install zsync" +apt-get install -y --no-install-recommends zsync + +echo "Install curl" +apt-get install -y --no-install-recommends curl + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in curl file ftp jq netcat ssh rsync shellcheck sudo telnet time unzip wget zip; do + if ! command -v $cmd; then + echo "$cmd was not installed" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Basic CLI:" +DocumentInstalledItemIndent "curl" +DocumentInstalledItemIndent "dnsutils" +DocumentInstalledItemIndent "file" +DocumentInstalledItemIndent "ftp" +DocumentInstalledItemIndent "iproute2" +DocumentInstalledItemIndent "iputils-ping" +DocumentInstalledItemIndent "jq" +DocumentInstalledItemIndent "libcurl3" +DocumentInstalledItemIndent "libicu55" +DocumentInstalledItemIndent "libunwind8" +DocumentInstalledItemIndent "locales" +DocumentInstalledItemIndent "netcat" +DocumentInstalledItemIndent "openssh-client" +DocumentInstalledItemIndent "rsync" +DocumentInstalledItemIndent "shellcheck" +DocumentInstalledItemIndent "sudo" +DocumentInstalledItemIndent "telnet" +DocumentInstalledItemIndent "time" +DocumentInstalledItemIndent "unzip" +DocumentInstalledItemIndent "wget" +DocumentInstalledItemIndent "zip" +DocumentInstalledItemIndent "tzdata" diff --git a/images/linux/scripts/installers/1804/dotnetcore-sdk.sh b/images/linux/scripts/installers/1804/dotnetcore-sdk.sh new file mode 100644 index 00000000..f779ff5c --- /dev/null +++ b/images/linux/scripts/installers/1804/dotnetcore-sdk.sh @@ -0,0 +1,95 @@ +#!/bin/bash +################################################################################ +## File: dotnetcore-sdk.sh +## Team: CI-Platform +## Desc: Installs .NET Core SDK +################################################################################ + +source $HELPER_SCRIPTS/apt.sh +source $HELPER_SCRIPTS/document.sh + +LATEST_DOTNET_PACKAGE=dotnet-sdk-3.0 + +LSB_RELEASE=$(lsb_release -rs) + +mksamples() +{ + sdk=$1 + sample=$2 + mkdir "$sdk" + cd "$sdk" || exit + set -e + dotnet help + dotnet new globaljson --sdk-version "$sdk" + dotnet new "$sample" + dotnet restore + dotnet build + set +e + cd .. || exit + rm -rf "$sdk" +} + +set -e + +echo "Determing if .NET Core ($LATEST_DOTNET_PACKAGE) is installed" +if ! IsInstalled $LATEST_DOTNET_PACKAGE; then + echo "Could not find .NET Core ($LATEST_DOTNET_PACKAGE), installing..." + curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg + mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg + sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-bionic-prod bionic main" > /etc/apt/sources.list.d/dotnetdev.list' + apt-get install apt-transport-https + apt-get update + apt-get install $LATEST_DOTNET_PACKAGE -y +else + echo ".NET Core ($LATEST_DOTNET_PACKAGE) is already installed" +fi + +# Get list of all released SDKs from channels which are not end-of-life or preview +release_urls=("https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.1/releases.json" "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/2.2/releases.json" "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/3.0/releases.json") +sdks=() +for release_url in ${release_urls[@]}; do + echo "${release_url}" + releases=$(curl "${release_url}") + sdks=("${sdks[@]}" $(echo "${releases}" | jq '.releases[]' | jq '.sdk.version')) + sdks=("${sdks[@]}" $(echo "${releases}" | jq '.releases[]' | jq '.sdks[]?' | jq '.version')) +done + +sortedSdks=$(echo ${sdks[@]} | tr ' ' '\n' | grep -v preview | grep -v rc | grep -v display | cut -d\" -f2 | sort -u -r) + +for sdk in $sortedSdks; do + url="https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$sdk/dotnet-sdk-$sdk-linux-x64.tar.gz" + echo "$url" >> urls + echo "Adding $url to list to download later" +done + +# Download additional SDKs +echo "Downloading release tarballs..." +cat urls | xargs -n 1 -P 16 wget -q +for tarball in *.tar.gz; do + dest="./tmp-$(basename -s .tar.gz $tarball)" + echo "Extracting $tarball to $dest" + mkdir "$dest" && tar -C "$dest" -xzf "$tarball" + rsync -qav "$dest/shared/" /usr/share/dotnet/shared/ + rsync -qav "$dest/host/" /usr/share/dotnet/host/ + rsync -qav "$dest/sdk/" /usr/share/dotnet/sdk/ + rm -rf "$dest" + rm "$tarball" +done +rm urls + +DocumentInstalledItem ".NET Core SDK:" +# Smoke test each SDK +for sdk in $sortedSdks; do + mksamples "$sdk" "console" + mksamples "$sdk" "mstest" + mksamples "$sdk" "xunit" + mksamples "$sdk" "web" + mksamples "$sdk" "mvc" + mksamples "$sdk" "webapi" + DocumentInstalledItemIndent "$sdk" +done + +# NuGetFallbackFolder at /usr/share/dotnet/sdk/NuGetFallbackFolder is warmed up by smoke test +# Additional FTE will just copy to ~/.dotnet/NuGet which provides no benefit on a fungible machine +echo "DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1" | tee -a /etc/environment +echo "PATH=\"\$HOME/.dotnet/tools:\$PATH\"" | tee -a /etc/skel/.profile diff --git a/images/linux/scripts/installers/1804/go.sh b/images/linux/scripts/installers/1804/go.sh new file mode 100644 index 00000000..2b1dde0b --- /dev/null +++ b/images/linux/scripts/installers/1804/go.sh @@ -0,0 +1,34 @@ +#!/bin/bash +################################################################################ +## File: go.sh +## Desc: Installs go, configures GOROOT, and adds go to the path +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# This function installs Go using the specified arguments: +# $1=MajorVersion (1.11) +# $2=MajorAndMinorVersion (1.11.1) +# $3=IsDefaultVersion (true or false) +function InstallGo () { + curl -sL https://dl.google.com/go/go$2.linux-amd64.tar.gz -o go$2.linux-amd64.tar.gz + mkdir -p /usr/local/go$1 + tar -C /usr/local/go$1 -xzf go$2.linux-amd64.tar.gz --strip-components=1 go + rm go$2.linux-amd64.tar.gz + echo "GOROOT_${1//./_}_X64=/usr/local/go$1" | tee -a /etc/environment + DocumentInstalledItem "Go $1 ($(/usr/local/go$1/bin/go version))" + + # If this version of Go is to be the default version, + # symlink it into the path and point GOROOT to it. + if [ $3 = true ] + then + ln -s /usr/local/go$1/bin/* /usr/bin/ + echo "GOROOT=/usr/local/go$1" | tee -a /etc/environment + fi +} + +# Install Go versions +InstallGo 1.11 1.11.12 false +InstallGo 1.12 1.12.7 true +InstallGo 1.13 1.13 false diff --git a/images/linux/scripts/installers/1804/hosted-tool-cache.sh b/images/linux/scripts/installers/1804/hosted-tool-cache.sh new file mode 100644 index 00000000..0fb87013 --- /dev/null +++ b/images/linux/scripts/installers/1804/hosted-tool-cache.sh @@ -0,0 +1,40 @@ +#!/bin/bash +################################################################################ +## File: hosted-tool-cache.sh +## Desc: Downloads and installs hosted tools cache +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Fail out if any setups fail +set -e + +# Download hosted tool cache +AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache +echo "AGENT_TOOLSDIRECTORY=$AGENT_TOOLSDIRECTORY" | tee -a /etc/environment +azcopy --recursive \ + --source https://vstsagenttools.blob.core.windows.net/tools/hostedtoolcache/ubuntu-1804 \ + --destination $AGENT_TOOLSDIRECTORY + +# Install tools from hosted tool cache +original_directory=$PWD +setups=$(find $AGENT_TOOLSDIRECTORY -name setup.sh) +for setup in $setups; do + chmod +x $setup; + cd $(dirname $setup); + ./$(basename $setup); + cd $original_directory; +done; + +DocumentInstalledItem "Python (available through the [setup-python](https://github.com/actions/setup-python/blob/master/README.md) task)" +pythons=$(ls $AGENT_TOOLSDIRECTORY/Python) +for python in $pythons; do + DocumentInstalledItemIndent "Python $python" +done; + +DocumentInstalledItem "Ruby (available through the [setup-ruby](https://github.com/actions/setup-ruby/blob/master/README.md) task)" +rubys=$(ls $AGENT_TOOLSDIRECTORY/Ruby) +for ruby in $rubys; do + DocumentInstalledItemIndent "Ruby $ruby" +done; diff --git a/images/linux/scripts/installers/1804/kubernetes-tools.sh b/images/linux/scripts/installers/1804/kubernetes-tools.sh new file mode 100644 index 00000000..dbc5c9d4 --- /dev/null +++ b/images/linux/scripts/installers/1804/kubernetes-tools.sh @@ -0,0 +1,42 @@ +#!/bin/bash +################################################################################ +## File: kubernetes-tools.sh +## Desc: Installs kubectl, helm +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +## Install kubectl +apt-get install -y apt-transport-https +curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - +touch /etc/apt/sources.list.d/kubernetes.list + +# Based on https://kubernetes.io/docs/tasks/tools/install-kubectl/, package is still called xenial +echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list +apt-get update +apt-get install -y kubectl + +# Install Helm +curl -L https://git.io/get_helm.sh | bash + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v kubectl; then + echo "kubectl was not installed" + exit 1 +fi + +if ! command -v helm; then + echo "helm was not installed" + exit 1 +fi + +echo "Initializing helm" +helm init --client-only + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "kubectl ($(kubectl version --short |& head -n 1))" +DocumentInstalledItem "helm ($(helm version --short |& head -n 1))" diff --git a/images/linux/scripts/installers/1804/mercurial.sh b/images/linux/scripts/installers/1804/mercurial.sh new file mode 100644 index 00000000..a7c048d7 --- /dev/null +++ b/images/linux/scripts/installers/1804/mercurial.sh @@ -0,0 +1,21 @@ +#!/bin/bash +################################################################################ +## File: mercurial.sh +## Desc: Installs Mercurial +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +apt-get install -y --no-install-recommends mercurial + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v hg; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Mercurial ($(hg --version | head -n 1))" diff --git a/images/linux/scripts/installers/1804/php.sh b/images/linux/scripts/installers/1804/php.sh new file mode 100644 index 00000000..7dc872ee --- /dev/null +++ b/images/linux/scripts/installers/1804/php.sh @@ -0,0 +1,181 @@ +#!/bin/bash +################################################################################ +## File: php.sh +## Desc: Installs php +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_RELEASE=$(lsb_release -rs) + +set -e + +apt-add-repository ppa:ondrej/php -y + +# Install php7.1 +apt-fast install -y --no-install-recommends \ + php7.1 \ + php7.1-amqp \ + php7.1-bcmath \ + php7.1-bz2 \ + php7.1-cgi \ + php7.1-cli \ + php7.1-common \ + php7.1-curl \ + php7.1-dba \ + php7.1-dev \ + php7.1-enchant \ + php7.1-fpm \ + php7.1-gd \ + php7.1-gmp \ + php7.1-imap \ + php7.1-interbase \ + php7.1-intl \ + php7.1-json \ + php7.1-ldap \ + php7.1-mbstring \ + php7.1-mcrypt \ + php7.1-mysql \ + php7.1-odbc \ + php7.1-opcache \ + php7.1-pgsql \ + php7.1-phpdbg \ + php7.1-pspell \ + php7.1-readline \ + php7.1-recode \ + php7.1-snmp \ + php7.1-soap \ + php7.1-sqlite3 \ + php7.1-sybase \ + php7.1-tidy \ + php7.1-xml \ + php7.1-xmlrpc \ + php7.1-xsl \ + php7.1-zip +apt-get remove --purge -yq php7.1-dev + +# Install php7.2 +apt-fast install -y --no-install-recommends \ + php7.2 \ + php7.2-apcu \ + php7.2-amqp \ + php7.2-bcmath \ + php7.2-bz2 \ + php7.2-cgi \ + php7.2-cli \ + php7.2-common \ + php7.2-curl \ + php7.2-dba \ + php7.2-dev \ + php7.2-enchant \ + php7.2-fpm \ + php7.2-gd \ + php7.2-gmp \ + php7.2-imap \ + php7.2-interbase \ + php7.2-intl \ + php7.2-json \ + php7.2-ldap \ + php7.2-mbstring \ + php7.2-mysql \ + php7.2-odbc \ + php7.2-opcache \ + php7.2-pgsql \ + php7.2-phpdbg \ + php7.2-pspell \ + php7.2-readline \ + php7.2-recode \ + php7.2-snmp \ + php7.2-soap \ + php7.2-sqlite3 \ + php7.2-sybase \ + php7.2-tidy \ + php7.2-xml \ + php7.2-xmlrpc \ + php7.2-xsl \ + php7.2-zip + +# Install php7.3 +apt-fast install -y --no-install-recommends \ + php7.3 \ + php7.3-apcu \ + php7.3-amqp \ + php7.3-bcmath \ + php7.3-bz2 \ + php7.3-cgi \ + php7.3-cli \ + php7.3-common \ + php7.3-curl \ + php7.3-dba \ + php7.3-dev \ + php7.3-enchant \ + php7.3-fpm \ + php7.3-gd \ + php7.3-gmp \ + php7.3-imap \ + php7.3-interbase \ + php7.3-intl \ + php7.3-json \ + php7.3-ldap \ + php7.3-mbstring \ + php7.3-mysql \ + php7.3-odbc \ + php7.3-opcache \ + php7.3-pgsql \ + php7.3-phpdbg \ + php7.3-pspell \ + php7.3-readline \ + php7.3-recode \ + php7.3-snmp \ + php7.3-soap \ + php7.3-sqlite3 \ + php7.3-sybase \ + php7.3-tidy \ + php7.3-xml \ + php7.3-xmlrpc \ + php7.3-xsl \ + php7.3-zip + +apt-fast install -y --no-install-recommends \ + php-igbinary \ + php-memcache \ + php-memcached \ + php-mongodb \ + php-redis \ + php-xdebug \ + php-yaml \ + php-zmq + +apt-get remove --purge -yq php7.2-dev + +apt-fast install -y --no-install-recommends snmp + +# Install composer +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" +php composer-setup.php +sudo mv composer.phar /usr/bin/composer +php -r "unlink('composer-setup.php');" + +# Install phpunit (for PHP) +wget -q -O phpunit https://phar.phpunit.de/phpunit-7.phar +chmod +x phpunit +mv phpunit /usr/local/bin/phpunit + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in php php7.1 php7.2 php7.3 composer phpunit; do + if ! command -v $cmd; then + echo "$cmd was not installed" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "PHP 7.1 ($(php7.1 --version | head -n 1))" +DocumentInstalledItem "PHP 7.2 ($(php7.2 --version | head -n 1))" +DocumentInstalledItem "PHP 7.3 ($(php7.3 --version | head -n 1))" +DocumentInstalledItem "Composer ($(composer --version))" +DocumentInstalledItem "PHPUnit ($(phpunit --version))" diff --git a/images/linux/scripts/installers/1804/powershellcore.sh b/images/linux/scripts/installers/1804/powershellcore.sh new file mode 100644 index 00000000..c9d0e3c3 --- /dev/null +++ b/images/linux/scripts/installers/1804/powershellcore.sh @@ -0,0 +1,31 @@ +#!/bin/bash +################################################################################ +## File: powershellcore.sh +## Desc: Installs powershellcore +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_RELEASE=$(lsb_release -rs) + +# Install Powershell +apt-get install -y powershell + +# Temp fix based on: https://github.com/PowerShell/PowerShell/issues/9746 +sudo apt remove libicu64 + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v pwsh; then + echo "pwsh was not installed" + exit 1 +fi +if ! pwsh -c 'Write-Host Hello world'; then + echo "pwsh failed to run" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Powershell ($(pwsh --version))" diff --git a/images/linux/scripts/installers/1804/preparemetadata.sh b/images/linux/scripts/installers/1804/preparemetadata.sh new file mode 100644 index 00000000..020a5ef1 --- /dev/null +++ b/images/linux/scripts/installers/1804/preparemetadata.sh @@ -0,0 +1,12 @@ +#!/bin/bash +################################################################################ +## File: preparemetadata.sh +## Desc: This script adds a image title information to the metadata +## document +################################################################################ + +source $HELPER_SCRIPTS/document.sh + +AddTitle "Hosted Ubuntu 1804 Image ($(lsb_release -ds))" +WriteItem "The following software is installed on machines in the Hosted Ubuntu 1804 (v$IMAGE_VERSION) pool" +WriteItem "***" diff --git a/images/linux/scripts/installers/7-zip.sh b/images/linux/scripts/installers/7-zip.sh new file mode 100644 index 00000000..42b6b2ef --- /dev/null +++ b/images/linux/scripts/installers/7-zip.sh @@ -0,0 +1,23 @@ +#!/bin/bash +################################################################################ +## File: 7-zip.sh +## Desc: Installs 7-zip +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install 7-Zip +apt-get update -y +apt-get install -y p7zip p7zip-full p7zip-rar + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v 7z; then + echo "7-Zip was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "7-Zip $(7z i | head --lines=2 | cut -d ' ' -f 3 | tr -d '\n')" diff --git a/images/linux/scripts/installers/ansible.sh b/images/linux/scripts/installers/ansible.sh new file mode 100644 index 00000000..0411a642 --- /dev/null +++ b/images/linux/scripts/installers/ansible.sh @@ -0,0 +1,25 @@ +#!/bin/bash +################################################################################ +## File: ansible.sh +## Desc: Installs Ansible +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install Ansible PPA and latest Ansible +add-apt-repository ppa:ansible/ansible +apt-get update +apt-get install -y --no-install-recommends ansible + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v ansible; then + echo "Ansible was not installed or found on PATH" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Ansible ($(ansible --version |& head -n 1))" diff --git a/images/linux/scripts/installers/aws.sh b/images/linux/scripts/installers/aws.sh new file mode 100644 index 00000000..d2fcaf5d --- /dev/null +++ b/images/linux/scripts/installers/aws.sh @@ -0,0 +1,26 @@ +#!/bin/bash +################################################################################ +## File: aws.sh +## Desc: Installs the AWS CLI +################################################################################ + +# Source the helpers +source $HELPER_SCRIPTS/document.sh + +# Install the AWS CLI +curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip" +unzip awscli-bundle.zip +./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws +rm awscli-bundle.zip +rm -rf awscli-bundle + +# Validate the installation +echo "Validate the installation" +if ! command -v aws; then + echo "aws was not installed" + exit 1 +fi + +# Document the installed version +echo "Document the installed version" +DocumentInstalledItem "AWS CLI ($(aws --version 2>&1))" diff --git a/images/linux/scripts/installers/azcopy.sh b/images/linux/scripts/installers/azcopy.sh new file mode 100644 index 00000000..317a4d84 --- /dev/null +++ b/images/linux/scripts/installers/azcopy.sh @@ -0,0 +1,25 @@ +#!/bin/bash +################################################################################ +## File: azcopy.sh +## Desc: Installs AzCopy +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install AzCopy +wget -O azcopy.tar.gz https://aka.ms/downloadazcopylinux64 +tar -xf azcopy.tar.gz +rm azcopy.tar.gz +./install.sh + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v azcopy; then + echo "azcopy was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "AzCopy ($(azcopy --version))" diff --git a/images/linux/scripts/installers/azure-cli.sh b/images/linux/scripts/installers/azure-cli.sh new file mode 100644 index 00000000..bf9d43ae --- /dev/null +++ b/images/linux/scripts/installers/azure-cli.sh @@ -0,0 +1,26 @@ +#!/bin/bash +################################################################################ +## File: azure-cli.sh +## Desc: Installed Azure CLI (az) +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_CODENAME=$(lsb_release -cs) + +# Install Azure CLI (instructions taken from https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) +echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $LSB_CODENAME main" | tee /etc/apt/sources.list.d/azure-cli.list +apt-key adv --keyserver packages.microsoft.com --recv-keys B02C46DF417A0893 +apt-get update +apt-get install -y --no-install-recommends apt-transport-https azure-cli + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v az; then + echo "azure-cli was not installed" + exit 1 +fi + +# Document what was added to the image +DocumentInstalledItem "Azure CLI ($(az -v | head -n 1))" diff --git a/images/linux/scripts/installers/azure-devops-cli.sh b/images/linux/scripts/installers/azure-devops-cli.sh new file mode 100644 index 00000000..c8ca4671 --- /dev/null +++ b/images/linux/scripts/installers/azure-devops-cli.sh @@ -0,0 +1,23 @@ +#!/bin/bash +################################################################################ +## File: azure-devops-cli.sh +## Desc: Installed Azure DevOps CLI (az devops) +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# install azure devops Cli extension +az extension add -n azure-devops + +# check to determine if extension was installed or not +if [ $? -eq 0 ] +then + echo "azure DevOps Cli extension was installed" +else + echo "azure DevOps Cli extension was not installed" + exit 1 +fi + +# Document what was added to the image +DocumentInstalledItem "Azure CLI ($(az -v | grep azure-devops))" diff --git a/images/linux/scripts/installers/boost.sh b/images/linux/scripts/installers/boost.sh new file mode 100644 index 00000000..be9aa802 --- /dev/null +++ b/images/linux/scripts/installers/boost.sh @@ -0,0 +1,31 @@ +#!/bin/bash +################################################################################ +## File: boost.sh +## Desc: Installs Boost C++ Libraries +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +BOOST_ZIP_PATH=/opt/hostedtoolcache/Boost +BOOST_LIB=/usr/local/share/boost + +# Install Boost +for BOOST_VERSION in ${BOOST_VERSIONS//,/ } +do + BOOST_SYMLINK_VER=`echo "${BOOST_VERSION//[.]/_}"` + BOOST_ROOT="BOOST_ROOT_$BOOST_SYMLINK_VER" + BOOST_ZIP="boost_`echo $BOOST_VERSION`_gcc.zip" + + unzip $BOOST_ZIP_PATH/$BOOST_ZIP -d $BOOST_LIB + + echo "$BOOST_ROOT=$BOOST_LIB/$BOOST_VERSION" | tee -a /etc/environment + if [[ $BOOST_VERSION == $BOOST_DEFAULT ]]; then + echo "BOOST_ROOT=$BOOST_LIB/$BOOST_VERSION" | tee -a /etc/environment + fi + + DocumentInstalledItem "Boost C++ Libraries $BOOST_VERSION" +done + +# Deleting archives with Boost Libraries +rm -rf $BOOST_ZIP_PATH diff --git a/images/linux/scripts/installers/build-essential.sh b/images/linux/scripts/installers/build-essential.sh new file mode 100644 index 00000000..964aa045 --- /dev/null +++ b/images/linux/scripts/installers/build-essential.sh @@ -0,0 +1,24 @@ +#!/bin/bash +################################################################################ +## File: build-essential.sh +## Desc: Installs build-essential package +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +PACKAGE=build-essential + +# Test to see if the software in question is already installed, if not install it +echo "Checking to see if the installer script has already been run" +if ! IsInstalled $PACKAGE; then + echo "Installing $PACKAGE" + apt-get install -y --no-install-recommends $PACKAGE +else + echo "$PACKAGE is already installed" +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "$PACKAGE" diff --git a/images/linux/scripts/installers/clang.sh b/images/linux/scripts/installers/clang.sh new file mode 100644 index 00000000..5b85448a --- /dev/null +++ b/images/linux/scripts/installers/clang.sh @@ -0,0 +1,31 @@ +#!/bin/bash +################################################################################ +## File: example.sh +## Desc: This is an example script that can be copied to add a new software +## installer to the image +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - +apt-add-repository "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-6.0 main" +apt-get update +apt-get install -y clang-6.0 lldb-6.0 lld-6.0 + +update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-6.0 100 +update-alternatives --install /usr/bin/clang clang /usr/bin/clang-6.0 100 + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in clang clang++ clang-6.0 clang++-6.0; do + if ! command -v $cmd; then + echo "$cmd was not installed" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Clang 6.0 ($(clang-6.0 --version | head -n 1))" diff --git a/images/linux/scripts/installers/cmake.sh b/images/linux/scripts/installers/cmake.sh new file mode 100644 index 00000000..7e284c83 --- /dev/null +++ b/images/linux/scripts/installers/cmake.sh @@ -0,0 +1,30 @@ +#!/bin/bash +################################################################################ +## File: cmake.sh +## Desc: Installs CMake +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Test to see if the software in question is already installed, if not install it +echo "Checking to see if the installer script has already been run" +if command -v cmake; then + echo "Example variable already set to $EXAMPLE_VAR" +else + curl -sL https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.sh -o cmakeinstall.sh \ + && chmod +x cmakeinstall.sh \ + && ./cmakeinstall.sh --prefix=/usr/local --exclude-subdir \ + && rm cmakeinstall.sh +fi + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v cmake; then + echo "cmake was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "CMake ($(cmake --version | head -n 1))" diff --git a/images/linux/scripts/installers/docker-compose.sh b/images/linux/scripts/installers/docker-compose.sh new file mode 100644 index 00000000..0ee5f47a --- /dev/null +++ b/images/linux/scripts/installers/docker-compose.sh @@ -0,0 +1,26 @@ +#!/bin/bash +################################################################################ +## File: docker-compose.sh +## Desc: Installs Docker Compose +################################################################################ + +source $HELPER_SCRIPTS/apt.sh +source $HELPER_SCRIPTS/document.sh + +version="1.22.0" + +# Install latest docker-compose from releases +curl -L "https://github.com/docker/compose/releases/download/$version/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose +chmod +x /usr/local/bin/docker-compose + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v docker-compose; then + echo "docker-compose was not installed" + exit 1 +fi + +## Add version information to the metadata file +echo "Documenting Docker Compose version" +docker_compose_version=$(docker-compose -v) +DocumentInstalledItem "Docker Compose (${docker_compose_version})" diff --git a/images/linux/scripts/installers/docker-moby.sh b/images/linux/scripts/installers/docker-moby.sh new file mode 100644 index 00000000..ed181722 --- /dev/null +++ b/images/linux/scripts/installers/docker-moby.sh @@ -0,0 +1,43 @@ +#!/bin/bash +################################################################################ +## File: docker-ce.sh +## Desc: Installs docker onto the image, but does not pre-pull any images +################################################################################ + +source $HELPER_SCRIPTS/apt.sh +source $HELPER_SCRIPTS/document.sh + +docker_package=moby + +## Check to see if docker is already installed +echo "Determing if Docker ($docker_package) is installed" +if ! IsInstalled $docker_package; then + echo "Docker ($docker_package) was not found. Installing..." + apt-get remove -y moby-engine moby-cli + apt-get update + apt-get install -y apt-transport-https ca-certificates curl software-properties-common + curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - + curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/microsoft-prod.list + apt-get update + apt-get install -y moby-engine moby-cli +else + echo "Docker ($docker_package) is already installed" +fi + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v docker; then + echo "docker was not installed" + exit 1 +else + # Docker daemon takes time to come up after installing + sleep 10 + set -e + docker info + set +e +fi + +## Add version information to the metadata file +echo "Documenting Docker version" +docker_version=$(docker -v) +DocumentInstalledItem "Docker ($docker_version)" diff --git a/images/linux/scripts/installers/docker.sh b/images/linux/scripts/installers/docker.sh new file mode 100644 index 00000000..2b9db9b4 --- /dev/null +++ b/images/linux/scripts/installers/docker.sh @@ -0,0 +1,34 @@ +#!/bin/bash +################################################################################ +## File: docker.sh +## Desc: Installs the correct version of docker onto the image, and pulls +## down the default docker image used for building on ubuntu +################################################################################ + +source $HELPER_SCRIPTS/apt.sh +source $HELPER_SCRIPTS/document.sh + +DOCKER_PACKAGE=moby + +apt-get remove -y moby-engine mobi-cli +apt-get update +apt-get install -y apt-transport-https ca-certificates curl software-properties-common +apt-get update +apt-get install -y moby-engine mobi-cli + +docker pull node:10 +docker pull node:12 +docker pull buildpack-deps:stretch +docker pull node:10-alpine +docker pull node:12-alpine +docker pull debian:8 +docker pull debian:9 +docker pull alpine:3.7 +docker pull alpine:3.8 +docker pull alpine:3.9 +docker pull alpine:3.10 + +## Add version information to the metadata file +echo "Documenting Docker version" +DOCKER_VERSION=`docker -v` +DocumentInstalledItem "Docker ($DOCKER_VERSION)" diff --git a/images/linux/scripts/installers/erlang.sh b/images/linux/scripts/installers/erlang.sh new file mode 100644 index 00000000..4ff26d04 --- /dev/null +++ b/images/linux/scripts/installers/erlang.sh @@ -0,0 +1,39 @@ +#!/bin/bash +################################################################################ +## File: erlang.sh +## Desc: Installs erlang +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +source_list=/etc/apt/sources.list.d/eslerlang.list + +# Install Erlang +echo "deb http://binaries.erlang-solutions.com/debian $(lsb_release -cs) contrib" > $source_list +wget -O - http://binaries.erlang-solutions.com/debian/erlang_solutions.asc | apt-key add - +apt-get update +apt-get install -y --no-install-recommends esl-erlang + +# Install rebar3 +wget -q -O rebar3 https://s3.amazonaws.com/rebar3/rebar3 +chmod +x rebar3 +mv rebar3 /usr/local/bin/rebar3 + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in erl erlc rebar3; do + if ! command -v $cmd; then + echo "$cmd was not installed or not found on PATH" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +erlang_version="$(erl -version 2>&1 | tr -d '\n' | tr -d '\r')" +DocumentInstalledItem "Erlang ($erlang_version)" + +# Clean up source list +rm $source_list diff --git a/images/linux/scripts/installers/example.sh b/images/linux/scripts/installers/example.sh new file mode 100644 index 00000000..aeab39f0 --- /dev/null +++ b/images/linux/scripts/installers/example.sh @@ -0,0 +1,31 @@ +#!/bin/bash +################################################################################ +## File: example.sh +## Desc: This is an example script that can be copied to add a new software +## installer to the image +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Test to see if the software in question is already installed, if not install it +echo "Checking to see if the installer script has already been run" +if [ -z $EXAMPLE_VAR ]; then + $EXAMPLE_VAR=1.0.0 +else + echo "Example variable already set to $EXAMPLE_VAR" +fi + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if [ -z $EXAMPLE_VAR ]; then + echo "EXAMPLE_VAR variable was not set as expected" + exit 1 +else + echo "EXAMPLE_VAR was set properly" +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Example Var ($EXAMPLE_VAR)" diff --git a/images/linux/scripts/installers/firefox.sh b/images/linux/scripts/installers/firefox.sh new file mode 100644 index 00000000..3f093c7c --- /dev/null +++ b/images/linux/scripts/installers/firefox.sh @@ -0,0 +1,25 @@ +#!/bin/bash +################################################################################ +## File: firefox.sh +## Desc: Installs Firefox +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install Firefox +apt-get install -y firefox + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v firefox; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +# Resolves: Running Firefox as root in a regular user's session is not supported. +# ($HOME is /home/packer which is owned by packer.) +HOME=/root +DocumentInstalledItem "Firefox ($(firefox --version))" diff --git a/images/linux/scripts/installers/gcc.sh b/images/linux/scripts/installers/gcc.sh new file mode 100644 index 00000000..234353a5 --- /dev/null +++ b/images/linux/scripts/installers/gcc.sh @@ -0,0 +1,25 @@ +#!/bin/bash +################################################################################ +## File: gcc.sh +## Desc: Installs GNU C++ +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install GNU C++ compiler +add-apt-repository ppa:ubuntu-toolchain-r/test -y +apt-get update -y +apt-get install g++-7 -y + + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v g++-7; then + echo "GNU C++ was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "GNU C++ $(g++-7 --version | head -n 1 | cut -d ' ' -f 4)" diff --git a/images/linux/scripts/installers/git.sh b/images/linux/scripts/installers/git.sh new file mode 100644 index 00000000..be1393aa --- /dev/null +++ b/images/linux/scripts/installers/git.sh @@ -0,0 +1,37 @@ +#!/bin/bash +################################################################################ +## File: git.sh +## Desc: Installs Git +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +## Install git +add-apt-repository ppa:git-core/ppa -y +apt-get update +apt-get install git -y +git --version + +# Install git-lfs +curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash +apt-get install -y --no-install-recommends git-lfs + +# Run tests to determine that the software installed as expected +echo "Testing git installation" +if ! command -v git; then + echo "git was not installed" + exit 1 +fi +echo "Testing git-lfs installation" +if ! command -v git-lfs; then + echo "git-lfs was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, document the installed versions" +# git version 2.20.1 +DocumentInstalledItem "Git ($(git --version 2>&1 | cut -d ' ' -f 3))" +# git-lfs/2.6.1 (GitHub; linux amd64; go 1.11.1) +DocumentInstalledItem "Git Large File Storage (LFS) ($(git-lfs --version 2>&1 | cut -d ' ' -f 1 | cut -d '/' -f 2))" diff --git a/images/linux/scripts/installers/google-chrome.sh b/images/linux/scripts/installers/google-chrome.sh new file mode 100644 index 00000000..151d18b0 --- /dev/null +++ b/images/linux/scripts/installers/google-chrome.sh @@ -0,0 +1,27 @@ +#!/bin/bash +################################################################################ +## File: google-chrome.sh +## Desc: Installs google-chrome +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_RELEASE=$(lsb_release -rs) + +wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - +echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list +apt-get update +apt-get install -y google-chrome-stable +echo "CHROME_BIN=/usr/bin/google-chrome" | tee -a /etc/environment + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v google-chrome; then + echo "google-chrome was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Google Chrome ($(google-chrome --version))" diff --git a/images/linux/scripts/installers/google-cloud-sdk.sh b/images/linux/scripts/installers/google-cloud-sdk.sh new file mode 100644 index 00000000..f057d6ab --- /dev/null +++ b/images/linux/scripts/installers/google-cloud-sdk.sh @@ -0,0 +1,25 @@ +#!/bin/bash +################################################################################ +## File: google-cloud-sdk.sh +## Desc: Installs the Google Cloud SDK +################################################################################ + +# Source the helpers +source $HELPER_SCRIPTS/document.sh + +# Install the Google Cloud SDK +echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list +curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - +sudo apt-get update -y +sudo apt-get install -y google-cloud-sdk + +# Validate the installation +echo "Validate the installation" +if ! command -v gcloud; then + echo "gcloud was not installed" + exit 1 +fi + +# Document the installed version +echo "Document the installed version" +DocumentInstalledItem "Google Cloud SDK ($(gcloud --version | head -n 1 | cut -d ' ' -f 4))" diff --git a/images/linux/scripts/installers/haskell.sh b/images/linux/scripts/installers/haskell.sh new file mode 100644 index 00000000..63d3d4c3 --- /dev/null +++ b/images/linux/scripts/installers/haskell.sh @@ -0,0 +1,64 @@ +#!/bin/bash +################################################################################ +## File: haskell.sh +## Desc: Installs Haskell +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install Herbert V. Riedel's PPA for managing multiple version of ghc on ubuntu. +# https://launchpad.net/~hvr/+archive/ubuntu/ghc +apt-get install -y software-properties-common +add-apt-repository -y ppa:hvr/ghc +apt-get update + +# Install various versions of ghc and cabal +apt-get install -y \ + ghc-8.0.2 \ + ghc-8.2.2 \ + ghc-8.4.4 \ + ghc-8.6.2 \ + ghc-8.6.3 \ + ghc-8.6.4 \ + ghc-8.6.5 \ + ghc-8.8.1 \ + cabal-install-2.0 \ + cabal-install-2.2 \ + cabal-install-2.4 \ + cabal-install-3.0 + +# Install haskell stack, pinned to v2.1.3 +curl -sSL https://raw.githubusercontent.com/commercialhaskell/stack/v2.1.3/etc/scripts/get-stack.sh | sh + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +# Check all ghc versions +for version in 8.0.2 8.2.2 8.4.4 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1; do + if ! command -v /opt/ghc/$version/bin/ghc; then + echo "ghc $version was not installed" + exit 1 + fi +done +# Check all cabal versions +for version in 2.0 2.2 2.4 3.0; do + if ! command -v /opt/cabal/$version/bin/cabal; then + echo "cabal $version was not installed" + exit 1 + fi +done +# Check stack +if ! command -v stack; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +for version in 2.0 2.2 2.4 3.0; do + DocumentInstalledItem "Haskell Cabal ($(/opt/cabal/$version/bin/cabal --version))" +done +for version in 8.0.2 8.2.2 8.4.4 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1; do + DocumentInstalledItem "GHC ($(/opt/ghc/$version/bin/ghc --version))" +done +DocumentInstalledItem "Haskell Stack ($(stack --version))" diff --git a/images/linux/scripts/installers/heroku.sh b/images/linux/scripts/installers/heroku.sh new file mode 100644 index 00000000..22d4665f --- /dev/null +++ b/images/linux/scripts/installers/heroku.sh @@ -0,0 +1,22 @@ +#!/bin/bash +################################################################################ +## File: heroku.sh +## Desc: Installs Heroku CLI +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install Heroku CLI +curl https://cli-assets.heroku.com/install-ubuntu.sh | sh + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v heroku; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Heroku ($(heroku version))" diff --git a/images/linux/scripts/installers/hhvm.sh b/images/linux/scripts/installers/hhvm.sh new file mode 100644 index 00000000..c040af3e --- /dev/null +++ b/images/linux/scripts/installers/hhvm.sh @@ -0,0 +1,37 @@ +#!/bin/bash +################################################################################ +## File: hhvm.sh +## Desc: Installs hhvm +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +hhvm_package=hhvm + +# Test to see if the software in question is already installed, if not install it +echo "Checking to see if the installer script has already been run" +if ! IsInstalled ${hhvm_package}; then + apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94 + add-apt-repository https://dl.hhvm.com/ubuntu + apt-get update + apt-get -qq install -y hhvm +else + echo "${hhvm_package} already installed" +fi + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! IsInstalled ${hhvm_package}; then + echo "${hhvm_package} was not installed" + exit 1 +fi + +if ! command -v hhvm; then + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "HHVM ($(hhvm --version | head -n 1))" diff --git a/images/linux/scripts/installers/image-magick.sh b/images/linux/scripts/installers/image-magick.sh new file mode 100644 index 00000000..db186057 --- /dev/null +++ b/images/linux/scripts/installers/image-magick.sh @@ -0,0 +1,20 @@ +#!/bin/bash +################################################################################ +## File: image-magick.sh +## Desc: Installs ImageMagick +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install ImageMagick +apt-get install -y --no-install-recommends --fix-missing \ + imagemagick \ + libmagickcore-dev \ + libmagickwand-dev \ + libmagic-dev + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "ImageMagick" diff --git a/images/linux/scripts/installers/java-tools.sh b/images/linux/scripts/installers/java-tools.sh new file mode 100644 index 00000000..c1c25474 --- /dev/null +++ b/images/linux/scripts/installers/java-tools.sh @@ -0,0 +1,78 @@ +#!/bin/bash +################################################################################ +## File: java-tools.sh +## Team: CI-Platform +## Desc: Installs Java and related tooling (Ant, Gradle, Maven) +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +DEFAULT_JDK_VERSION=8 + +set -e + +# Install the Azul Systems Zulu JDKs +# See https://www.azul.com/downloads/azure-only/zulu/ +apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0xB1998361219BD9C9 +apt-add-repository "deb http://repos.azul.com/azure-only/zulu/apt stable main" +apt-get -q update +apt-get -y install zulu-7-azure-jdk=\* +apt-get -y install zulu-8-azure-jdk=\* +apt-get -y install zulu-11-azure-jdk=\* +apt-get -y install zulu-12-azure-jdk=\* +update-java-alternatives -s /usr/lib/jvm/zulu-8-azure-amd64 +echo "JAVA_HOME_7_X64=/usr/lib/jvm/zulu-7-azure-amd64" | tee -a /etc/environment +echo "JAVA_HOME_8_X64=/usr/lib/jvm/zulu-8-azure-amd64" | tee -a /etc/environment +echo "JAVA_HOME_11_X64=/usr/lib/jvm/zulu-11-azure-amd64" | tee -a /etc/environment +echo "JAVA_HOME_12_X64=/usr/lib/jvm/zulu-12-azure-amd64" | tee -a /etc/environment +echo "JAVA_HOME=/usr/lib/jvm/zulu-${DEFAULT_JDK_VERSION}-azure-amd64" | tee -a /etc/environment +echo "JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8" | tee -a /etc/environment + +# Install Ant +apt-fast install -y --no-install-recommends ant ant-optional +echo "ANT_HOME=/usr/share/ant" | tee -a /etc/environment + +# Install Maven +curl -sL https://www-eu.apache.org/dist/maven/maven-3/3.6.2/binaries/apache-maven-3.6.2-bin.zip -o maven.zip +unzip -d /usr/share maven.zip +rm maven.zip +ln -s /usr/share/apache-maven-3.6.2/bin/mvn /usr/bin/mvn +echo "M2_HOME=/usr/share/apache-maven-3.6.2" | tee -a /etc/environment + +# Install Gradle +# This script downloads the latest HTML list of releases at https://gradle.org/releases/. +# Then, it extracts the top-most release download URL, relying on the top-most URL being for the latest release. +# The release download URL looks like this: https://services.gradle.org/distributions/gradle-5.2.1-bin.zip +# The release version is extracted from the download URL (i.e. 5.2.1). +# After all of this, the release is downloaded, extracted, a symlink is created that points to it, and GRADLE_HOME is set. +wget -O gradleReleases.html https://gradle.org/releases/ +gradleUrl=$(grep -m 1 -o "https:\/\/services.gradle.org\/distributions\/gradle-.*-bin\.zip" gradleReleases.html | head -1) +gradleVersion=$(echo $gradleUrl | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p') +rm gradleReleases.html +echo "gradleUrl=$gradleUrl" +echo "gradleVersion=$gradleVersion" +curl -sL $gradleUrl -o gradleLatest.zip +unzip -d /usr/share gradleLatest.zip +rm gradleLatest.zip +ln -s /usr/share/gradle-"${gradleVersion}"/bin/gradle /usr/bin/gradle +echo "GRADLE_HOME=/usr/share/gradle" | tee -a /etc/environment + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in gradle java javac mvn ant; do + if ! command -v $cmd; then + echo "$cmd was not installed or found on path" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Azul Zulu OpenJDK (7) ($(/usr/lib/jvm/zulu-7-azure-amd64/bin/java -showversion |& head -n 1))" +DocumentInstalledItem "Azul Zulu OpenJDK (8) ($(/usr/lib/jvm/zulu-8-azure-amd64/bin/java -showversion |& head -n 1))" +DocumentInstalledItem "Azul Zulu OpenJDK (11) ($(/usr/lib/jvm/zulu-11-azure-amd64/bin/java -showversion |& head -n 1))" +DocumentInstalledItem "Azul Zulu OpenJDK (12) ($(/usr/lib/jvm/zulu-12-azure-amd64/bin/java -showversion |& head -n 1))" +DocumentInstalledItem "Ant ($(ant -version))" +DocumentInstalledItem "Gradle ${gradleVersion}" +DocumentInstalledItem "Maven ($(mvn -version | head -n 1))" diff --git a/images/linux/scripts/installers/kind.sh b/images/linux/scripts/installers/kind.sh new file mode 100644 index 00000000..8cbd1eeb --- /dev/null +++ b/images/linux/scripts/installers/kind.sh @@ -0,0 +1,26 @@ +#!/bin/bash +################################################################################ +## File: kind.sh +## Desc: Installs kind +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install KIND +KIND_VERSION="v0.5.1" + +curl -L -o /usr/local/bin/kind "https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64" +chmod +x /usr/local/bin/kind + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v kind; then + echo "Kind was not installed or found on PATH" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Kind ($(kind version))" diff --git a/images/linux/scripts/installers/leiningen.sh b/images/linux/scripts/installers/leiningen.sh new file mode 100644 index 00000000..c343fc06 --- /dev/null +++ b/images/linux/scripts/installers/leiningen.sh @@ -0,0 +1,35 @@ +#!/bin/bash +################################################################################ +## File: leiningen.sh +## Desc: Installs Leiningen +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +set -e + +LEIN_BIN=/usr/local/bin/lein +curl -s https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > $LEIN_BIN +chmod 0755 $LEIN_BIN + +# Run lein to trigger self-install +export LEIN_HOME=/usr/local/lib/lein +lein + +LEIN_JAR=$(find $LEIN_HOME -name "leiningen-*-standalone.jar") +echo "LEIN_JAR=$LEIN_JAR" | tee -a /etc/environment +echo "LEIN_HOME=$LEIN_HOME" | tee -a /etc/environment + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v lein; then + echo "lein was not installed" + exit 1 +else + lein new app testapp && rm -rf testapp +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Leiningen ($(lein -v))" diff --git a/images/linux/scripts/installers/miniconda.sh b/images/linux/scripts/installers/miniconda.sh new file mode 100644 index 00000000..e012781f --- /dev/null +++ b/images/linux/scripts/installers/miniconda.sh @@ -0,0 +1,23 @@ +#!/bin/bash +################################################################################ +## File: miniconda.sh +## Desc: Installs miniconda +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Miniconda +curl -sL https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda.sh \ + && chmod +x miniconda.sh \ + && ./miniconda.sh -b -p /usr/share/miniconda \ + && rm miniconda.sh + +CONDA=/usr/share/miniconda +echo "CONDA=$CONDA" | tee -a /etc/environment + +ln -s $CONDA/bin/conda /usr/bin/conda + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Miniconda ($($CONDA/bin/conda --version))" diff --git a/images/linux/scripts/installers/mono.sh b/images/linux/scripts/installers/mono.sh new file mode 100644 index 00000000..c00ca95b --- /dev/null +++ b/images/linux/scripts/installers/mono.sh @@ -0,0 +1,29 @@ +#!/bin/bash +################################################################################ +## File: cmake.sh +## Desc: Installs Mono +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +LSB_CODENAME=$(lsb_release -cs) + +# Test to see if the software in question is already installed, if not install it +# wget "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF" -O out && sudo apt-key add out && rm out + +apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +echo "deb https://download.mono-project.com/repo/ubuntu stable-$LSB_CODENAME main" | tee /etc/apt/sources.list.d/mono-official-stable.list +apt-get update +apt-get install -y --no-install-recommends apt-transport-https mono-complete + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v mono; then + echo "mono was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Mono ($(mono --version | head -n 1))" diff --git a/images/linux/scripts/installers/mysql.sh b/images/linux/scripts/installers/mysql.sh new file mode 100644 index 00000000..fecbc9eb --- /dev/null +++ b/images/linux/scripts/installers/mysql.sh @@ -0,0 +1,43 @@ +#!/bin/bash +################################################################################ +## File: mysql.sh +## Desc: Installs MySQL Client +################################################################################ + +## Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +export ACCEPT_EULA=Y + +# Install MySQL Client +apt-get install mysql-client -y + +# Install MySQL Server +MYSQL_ROOT_PASSWORD=root +echo "mysql-server mysql-server/root_password password $MYSQL_ROOT_PASSWORD" | debconf-set-selections +echo "mysql-server mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD" | debconf-set-selections + +apt-get install -y mysql-server + +# Install MS SQL Server client tools (https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools?view=sql-server-2017) +apt-get install -y mssql-tools unixodbc-dev +apt-get -f install +ln -s /opt/mssql-tools/bin/* /usr/local/bin/ + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v mysql; then + echo "mysql was not installed" + exit 1 +fi + +set -e +mysql -vvv -e 'CREATE DATABASE smoke_test' -uroot -proot +mysql -vvv -e 'DROP DATABASE smoke_test' -uroot -proot +set +e + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "MySQL ($(mysql --version))" +DocumentInstalledItem "MySQL Server (user:root password:root)" +DocumentInstalledItem "MS SQL Server Client Tools" diff --git a/images/linux/scripts/installers/nodejs.sh b/images/linux/scripts/installers/nodejs.sh new file mode 100644 index 00000000..8ad5c457 --- /dev/null +++ b/images/linux/scripts/installers/nodejs.sh @@ -0,0 +1,47 @@ +#!/bin/bash +################################################################################ +## File: nodejs.sh +## Team: CI-Platform +## Desc: Installs Node.js LTS and related tooling (Gulp, Bower, Grunt) +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install LTS Node.js and related build tools +curl -sL https://git.io/n-install | bash -s -- -ny - +~/n/bin/n lts +npm install -g bower grunt gulp n parcel-bundler typescript +npm install -g --save-dev webpack webpack-cli +npm install -g npm +rm -rf ~/n + +# Install Yarn repository and key +curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list +apt-get update + +# Install yarn +apt-get install -y --no-install-recommends yarn + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in node bower grunt gulp webpack parcel yarn; do + if ! command -v $cmd; then + echo "$cmd was not installed" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Node.js ($(node --version))" +DocumentInstalledItem "Bower ($(bower --version))" +DocumentInstalledItem "Grunt ($(grunt --version))" +DocumentInstalledItem "Gulp ($(gulp --version))" +DocumentInstalledItem "n ($(n --version))" +DocumentInstalledItem "Parcel ($(parcel --version))" +DocumentInstalledItem "TypeScript ($(tsc --version))" +DocumentInstalledItem "Webpack ($(webpack --version))" +DocumentInstalledItem "Webpack CLI ($(webpack-cli --version))" +DocumentInstalledItem "Yarn ($(yarn --version))" diff --git a/images/linux/scripts/installers/phantomjs.sh b/images/linux/scripts/installers/phantomjs.sh new file mode 100644 index 00000000..338bed36 --- /dev/null +++ b/images/linux/scripts/installers/phantomjs.sh @@ -0,0 +1,29 @@ +#!/bin/bash +################################################################################ +## File: phantomjs.sh +## Desc: Installs PhantomJS +################################################################################ + +set -e + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install PhantomJS +apt-get install -y chrpath libssl-dev libxft-dev libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev +PHANTOM_JS=phantomjs-2.1.1-linux-x86_64 +wget https://bitbucket.org/ariya/phantomjs/downloads/$PHANTOM_JS.tar.bz2 +tar xvjf $PHANTOM_JS.tar.bz2 +mv $PHANTOM_JS /usr/local/share +ln -sf /usr/local/share/$PHANTOM_JS/bin/phantomjs /usr/local/bin + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v phantomjs; then + echo "phantomjs was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "PhantomJS ($(phantomjs --version))" diff --git a/images/linux/scripts/installers/pollinate.sh b/images/linux/scripts/installers/pollinate.sh new file mode 100644 index 00000000..c1692d43 --- /dev/null +++ b/images/linux/scripts/installers/pollinate.sh @@ -0,0 +1,22 @@ +#!/bin/bash +################################################################################ +## File: pollinate.sh +## Desc: Installs Pollinate +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Pollinate +apt-get install -y --no-install-recommends pollinate + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v pollinate; then + echo "pollinate was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Pollinate" diff --git a/images/linux/scripts/installers/python.sh b/images/linux/scripts/installers/python.sh new file mode 100644 index 00000000..4b56cf15 --- /dev/null +++ b/images/linux/scripts/installers/python.sh @@ -0,0 +1,67 @@ +#!/bin/bash +################################################################################ +## File: python.sh +## Desc: Installs Python 2/3 and related tools (pip, pypy) +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Python, Python 3, pip, pip3 +apt-get install -y --no-install-recommends python python-dev python-pip python3 python3-dev python3-pip + +# Install PyPy 2.7 to $AGENT_TOOLSDIRECTORY +wget -q -P /tmp https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.1.0-linux64.tar.bz2 +tar -x -C /tmp -f /tmp/pypy2.7-v7.1.0-linux64.tar.bz2 +rm /tmp/pypy2.7-v7.1.0-linux64.tar.bz2 +mkdir -p $AGENT_TOOLSDIRECTORY/PyPy/2.7.13 +mv /tmp/pypy2.7-v7.1.0-linux64 $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64 +touch $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64.complete + +# add pypy to PATH by default +ln -s $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/pypy /usr/local/bin/pypy +# pypy will be the python in PATH when its tools cache directory is prepended to PATH +# PEP 394-style symlinking; don't bother with minor version +ln -s $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/pypy $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/python2 +ln -s $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/python2 $AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/python + +# Install latest Pip for PyPy2 +$AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/pypy -m ensurepip +$AGENT_TOOLSDIRECTORY/PyPy/2.7.13/x64/bin/pypy -m pip install --ignore-installed pip + +# Install PyPy 3.5 to $AGENT_TOOLSDIRECTORY +wget -q -P /tmp https://bitbucket.org/pypy/pypy/downloads/pypy3.5-v7.0.0-linux64.tar.bz2 +tar -x -C /tmp -f /tmp/pypy3.5-v7.0.0-linux64.tar.bz2 +rm /tmp/pypy3.5-v7.0.0-linux64.tar.bz2 +mkdir -p $AGENT_TOOLSDIRECTORY/PyPy/3.5.3 +mv /tmp/pypy3.5-v7.0.0-linux64 $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64 +touch $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64.complete + +# add pypy3 to PATH by default +ln -s $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/pypy3 /usr/local/bin/pypy3 +# pypy3 will be the python in PATH when its tools cache directory is prepended to PATH +# PEP 394-style symlinking; don't bother with minor version +ln -s $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/pypy3 $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/python3 +ln -s $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/python3 $AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/python + +# Install latest Pip for PyPy3 +$AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/pypy3 -m ensurepip +$AGENT_TOOLSDIRECTORY/PyPy/3.5.3/x64/bin/pypy3 -m pip install --ignore-installed pip + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +for cmd in python pip pypy python3 pip3 pypy3; do + if ! command -v $cmd; then + echo "$cmd was not installed or not found on PATH" + exit 1 + fi +done + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Python ($(python --version 2>&1))" +DocumentInstalledItem "pip ($(pip --version))" +DocumentInstalledItem "Python3 ($(python3 --version))" +DocumentInstalledItem "pip3 ($(pip3 --version))" +DocumentInstalledItem "PyPy2 ($(pypy --version 2>&1 | grep PyPy))" +DocumentInstalledItem "PyPy3 ($(pypy3 --version 2>&1 | grep PyPy))" diff --git a/images/linux/scripts/installers/ruby.sh b/images/linux/scripts/installers/ruby.sh new file mode 100644 index 00000000..cc2d2970 --- /dev/null +++ b/images/linux/scripts/installers/ruby.sh @@ -0,0 +1,11 @@ +#!/bin/bash +################################################################################ +## File: ruby.sh +## Desc: Installs Ruby requirements +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Ruby requirements +apt-get install -y libz-dev openssl libssl-dev diff --git a/images/linux/scripts/installers/rust.sh b/images/linux/scripts/installers/rust.sh new file mode 100644 index 00000000..35fe66b2 --- /dev/null +++ b/images/linux/scripts/installers/rust.sh @@ -0,0 +1,54 @@ +#!/bin/bash +################################################################################ +## File: rust.sh +## Desc: Installs Rust +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +set -e + +export RUSTUP_HOME=/usr/share/rust/.rustup +export CARGO_HOME=/usr/share/rust/.cargo + +curl https://sh.rustup.rs -sSf | sh -s -- -y + +# Add Cargo and Rust binaries to the machine path +echo "PATH=${CARGO_HOME}/bin:$PATH" | tee -a /etc/environment +source $CARGO_HOME/env + +# Install common tools +rustup component add rustfmt +rustup component add clippy +cargo install bindgen +cargo install cbindgen + +echo "Test installation of the Rust toochain" + +# Permissions +chmod -R 777 $(dirname $RUSTUP_HOME) + +for cmd in rustup rustc rustdoc cargo rustfmt cargo-clippy bindgen cbindgen; do + if ! command -v $cmd --version; then + echo "$cmd was not installed or is not found on the path" + exit 1 + fi +done + +# Rust Symlinks are added to a default profile /etc/skel +pushd /etc/skel +ln -sf $RUSTUP_HOME .rustup +ln -sf $CARGO_HOME .cargo +popd + +# Document what was added to the image +echo "Lastly, document what was added to the metadata file" +DocumentInstalledItem "rustup ($(rustup --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "rust ($(rustc --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "cargo ($(cargo --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "rustfmt ($(rustfmt --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "clippy ($(cargo-clippy --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "rustdoc ($(rustdoc --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "bindgen ($(bindgen --version 2>&1 | cut -d ' ' -f 2))" +DocumentInstalledItem "cbindgen ($(cbindgen --version 2>&1 | cut -d ' ' -f 2))" diff --git a/images/linux/scripts/installers/sbt.sh b/images/linux/scripts/installers/sbt.sh new file mode 100644 index 00000000..148dfe00 --- /dev/null +++ b/images/linux/scripts/installers/sbt.sh @@ -0,0 +1,20 @@ +#!/bin/bash +################################################################################ +## File: scala.sh +## Team: CI-Platform +## Desc: Installs sbt +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install sbt +# https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Linux.html +echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list +curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | apt-key add +apt-get -q update +apt-get -y install sbt + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "sbt ($(sbt --script-version))" diff --git a/images/linux/scripts/installers/sphinx.sh b/images/linux/scripts/installers/sphinx.sh new file mode 100644 index 00000000..707a7cae --- /dev/null +++ b/images/linux/scripts/installers/sphinx.sh @@ -0,0 +1,15 @@ +#!/bin/bash +################################################################################ +## File: sphinx.sh +## Desc: Installs Sphinx +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Sphinx +apt-get install -y sphinxsearch + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Sphinx Open Source Search Server" diff --git a/images/linux/scripts/installers/subversion.sh b/images/linux/scripts/installers/subversion.sh new file mode 100644 index 00000000..16556716 --- /dev/null +++ b/images/linux/scripts/installers/subversion.sh @@ -0,0 +1,22 @@ +#!/bin/bash +################################################################################ +## File: subversion.sh +## Desc: Installs Subversion client +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install Subversion +apt-get install -y --no-install-recommends subversion + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v svn; then + echo "Subversion (svn) was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Subversion ($(svn --version | head -n 1))" diff --git a/images/linux/scripts/installers/terraform.sh b/images/linux/scripts/installers/terraform.sh new file mode 100644 index 00000000..6c7ce09d --- /dev/null +++ b/images/linux/scripts/installers/terraform.sh @@ -0,0 +1,26 @@ +#!/bin/bash +################################################################################ +## File: terraform.sh +## Desc: Installs terraform +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh +source $HELPER_SCRIPTS/apt.sh + +# Install Terraform +TERRAFORM_VERSION=$(curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r .current_version) +curl -LO "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" +unzip "terraform_${TERRAFORM_VERSION}_linux_amd64.zip" -d /usr/local/bin +rm -f "terraform_${TERRAFORM_VERSION}_linux_amd64.zip" + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v terraform; then + echo "Terraform was not installed or found on PATH" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Terraform ($(terraform --version))" diff --git a/images/linux/scripts/installers/test-toolcache.sh b/images/linux/scripts/installers/test-toolcache.sh new file mode 100644 index 00000000..d8aa4424 --- /dev/null +++ b/images/linux/scripts/installers/test-toolcache.sh @@ -0,0 +1,70 @@ +#!/bin/bash +################################################################################ +## File: test-toolcache.sh +## Desc: Test Python and Ruby versions in tools cache +################################################################################ + +# Must be procecessed after tool cache setup(hosted-tool-cache.sh). + +# Fail out if any tests fail +set -e + +AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache + +# Python test +if [ -d "$AGENT_TOOLSDIRECTORY/Python" ]; then + cd $AGENT_TOOLSDIRECTORY/Python + python_dirs=($(find . -mindepth 1 -maxdepth 1 -type d | sed "s|^\./||")) + echo "Python versions folders: ${python_dirs[@]}" + echo "------------------------------------------" + if [ -n "$python_dirs" ]; then + for version_dir in "${python_dirs[@]}" + do + echo "Test $AGENT_TOOLSDIRECTORY/Python/$version_dir:" + expected_ver=$(echo $version_dir | egrep -o '[0-9]+\.[0-9]+') + actual_ver=$($AGENT_TOOLSDIRECTORY/Python/$version_dir/x64/python -c 'import sys;print(sys.version)'| head -1 | egrep -o '[0-9]+\.[0-9]+') + + if [ "$expected_ver" = "$actual_ver" ]; then + echo "Passed!" + else + echo "Expected: $expected_ver; Actual: $actual_ver" + exit 1 + fi + done + else + echo "$AGENT_TOOLSDIRECTORY/Python does not include any folders" + exit 1 + fi +else + echo "$AGENT_TOOLSDIRECTORY/Python does not exist" + exit 1 +fi + +# Ruby test +if [ -d "$AGENT_TOOLSDIRECTORY/Ruby" ]; then + cd $AGENT_TOOLSDIRECTORY/Ruby + ruby_dirs=($(find . -mindepth 1 -maxdepth 1 -type d | sed "s|^\./||")) + echo "Ruby versions folders: ${ruby_dirs[@]}" + echo "--------------------------------------" + if [ -n "$ruby_dirs" ]; then + for version_dir in "${ruby_dirs[@]}" + do + echo "Test $AGENT_TOOLSDIRECTORY/Ruby/$version_dir:" + expected_ver=$(echo $version_dir | egrep -o '[0-9]+\.[0-9]+') + actual_ver=$($AGENT_TOOLSDIRECTORY/Ruby/$version_dir/x64/bin/ruby -e "puts RUBY_VERSION" | egrep -o '[0-9]+\.[0-9]+') + + if [ "$expected_ver" = "$actual_ver" ]; then + echo "Passed!" + else + echo "Expected: $expected_ver; Actual: $actual_ver" + exit 1 + fi + done + else + echo "$AGENT_TOOLSDIRECTORY/Ruby does not include any folders" + exit 1 + fi +else + echo "$AGENT_TOOLSDIRECTORY/Ruby does not exist" + exit 1 +fi diff --git a/images/linux/scripts/installers/vcpkg.sh b/images/linux/scripts/installers/vcpkg.sh new file mode 100644 index 00000000..ec42ec5a --- /dev/null +++ b/images/linux/scripts/installers/vcpkg.sh @@ -0,0 +1,30 @@ +#!/bin/bash +################################################################################ +## File: vcpkg.sh +## Desc: Installs vcpkg +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Set env variable for vcpkg +VCPKG_INSTALLATION_ROOT=/usr/local/share/vcpkg +echo "VCPKG_INSTALLATION_ROOT=${VCPKG_INSTALLATION_ROOT}" | tee -a /etc/environment + +# Install vcpkg +git clone --depth=1 https://github.com/Microsoft/vcpkg $VCPKG_INSTALLATION_ROOT +$VCPKG_INSTALLATION_ROOT/bootstrap-vcpkg.sh +$VCPKG_INSTALLATION_ROOT/vcpkg integrate install +chmod 0777 -R $VCPKG_INSTALLATION_ROOT +ln -sf $VCPKG_INSTALLATION_ROOT/vcpkg /usr/local/bin + +# Run tests to determine that the software installed as expected +echo "Testing to make sure that script performed as expected, and basic scenarios work" +if ! command -v vcpkg; then + echo "vcpkg was not installed" + exit 1 +fi + +# Document what was added to the image +echo "Lastly, documenting what we added to the metadata file" +DocumentInstalledItem "Vcpkg $(vcpkg version | head -n 1 | cut -d ' ' -f 6)" diff --git a/images/linux/scripts/installers/zeit-now.sh b/images/linux/scripts/installers/zeit-now.sh new file mode 100644 index 00000000..eb53f08b --- /dev/null +++ b/images/linux/scripts/installers/zeit-now.sh @@ -0,0 +1,22 @@ +#!/bin/bash +################################################################################ +## File: zeit-now.sh +## Desc: Installs the Zeit Now CLI +################################################################################ + +# Source the helpers for use with the script +source $HELPER_SCRIPTS/document.sh + +# Install the Zeit Now CLI +npm i -g now + +# Validate the installation +echo "Validate the installation" +if ! command -v now; then + echo "Zeit Now CLI was not installed" + exit 1 +fi + +# Document the installed version +echo "Document the installed version" +DocumentInstalledItem "Zeit Now CLI ($(now --version))" diff --git a/images/linux/ubuntu1604.json b/images/linux/ubuntu1604.json new file mode 100644 index 00000000..21bf64f1 --- /dev/null +++ b/images/linux/ubuntu1604.json @@ -0,0 +1,236 @@ +{ + "variables": { + "commit_id": "{{env `COMMIT_ID`}}", + "client_id": "{{env `ARM_CLIENT_ID`}}", + "client_secret": "{{env `ARM_CLIENT_SECRET`}}", + "subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}", + "tenant_id": "{{env `ARM_TENANT_ID`}}", + "resource_group": "{{env `ARM_RESOURCE_GROUP`}}", + "storage_account": "{{env `ARM_STORAGE_ACCOUNT`}}", + "temp_resource_group_name": "{{env `TEMP_RESOURCE_GROUP_NAME`}}", + "location": "{{env `ARM_RESOURCE_LOCATION`}}", + "virtual_network_name": "{{env `VNET_NAME`}}", + "virtual_network_resource_group_name": "{{env `VNET_RESOURCE_GROUP`}}", + "virtual_network_subnet_name": "{{env `VNET_SUBNET`}}", + "private_virtual_network_with_public_ip": "{{env `PRIVATE_VIRTUAL_NETWORK_WITH_PUBLIC_IP`}}", + "image_folder": "/imagegeneration", + "commit_file": "/imagegeneration/commit.txt", + "metadata_file": "/imagegeneration/metadatafile", + "installer_script_folder": "/imagegeneration/installers", + "helper_script_folder": "/imagegeneration/helpers", + "vm_size": "Standard_DS2_v2", + "capture_name_prefix": "packer", + "image_version": "dev" + }, + "builders": [ + { + "type": "azure-arm", + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "subscription_id": "{{user `subscription_id`}}", + "tenant_id": "{{user `tenant_id`}}", + + "location": "{{user `location`}}", + "vm_size": "{{user `vm_size`}}", + "resource_group_name": "{{user `resource_group`}}", + "storage_account": "{{user `storage_account`}}", + "temp_resource_group_name": "{{user `temp_resource_group_name`}}", + "capture_container_name": "images", + "capture_name_prefix": "{{user `capture_name_prefix`}}", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "os_type": "Linux", + "image_publisher": "Canonical", + "image_offer": "UbuntuServer", + "image_sku": "16.04-LTS", + "os_disk_size_gb": "86" + } + ], + "provisioners": [ + { + "type": "shell", + "inline": [ + "mkdir {{user `image_folder`}}", + "chmod 777 {{user `image_folder`}}", + "echo {{user `commit_id`}} > {{user `commit_file`}}", + "chmod +r {{user `commit_file`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/base/repos.sh" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "inline": [ + "apt-get update", + "apt-get dist-upgrade -y", + "systemctl disable apt-daily.service", + "systemctl disable apt-daily.timer", + "systemctl disable apt-daily-upgrade.timer", + "systemctl disable apt-daily-upgrade.service", + "echo '* soft nofile 50000 \n* hard nofile 50000' >> /etc/security/limits.conf", + "echo 'session required pam_limits.so' >> /etc/pam.d/common-session", + "echo 'session required pam_limits.so' >> /etc/pam.d/common-session-noninteractive" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "file", + "source": "{{template_dir}}/scripts/helpers", + "destination": "{{user `helper_script_folder`}}" + }, + { + "type": "file", + "source": "{{template_dir}}/scripts/installers", + "destination": "{{user `installer_script_folder`}}" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/installers/1604/preparemetadata.sh" + ], + "environment_vars": [ + "IMAGE_VERSION={{user `image_version`}}", + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "inline": [ + "echo ImageVersion={{user `image_version`}} | tee -a /etc/environment" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts": [ + "{{template_dir}}/scripts/installers/7-zip.sh", + "{{template_dir}}/scripts/installers/ansible.sh", + "{{template_dir}}/scripts/installers/azcopy.sh", + "{{template_dir}}/scripts/installers/azure-cli.sh", + "{{template_dir}}/scripts/installers/azure-devops-cli.sh", + "{{template_dir}}/scripts/installers/1604/basic.sh", + "{{template_dir}}/scripts/installers/aws.sh", + "{{template_dir}}/scripts/installers/build-essential.sh", + "{{template_dir}}/scripts/installers/clang.sh", + "{{template_dir}}/scripts/installers/cmake.sh", + "{{template_dir}}/scripts/installers/docker-compose.sh", + "{{template_dir}}/scripts/installers/docker-moby.sh", + "{{template_dir}}/scripts/installers/docker.sh", + "{{template_dir}}/scripts/installers/1604/dotnetcore-sdk.sh", + "{{template_dir}}/scripts/installers/erlang.sh", + "{{template_dir}}/scripts/installers/firefox.sh", + "{{template_dir}}/scripts/installers/gcc.sh", + "{{template_dir}}/scripts/installers/git.sh", + "{{template_dir}}/scripts/installers/1604/go.sh", + "{{template_dir}}/scripts/installers/google-chrome.sh", + "{{template_dir}}/scripts/installers/google-cloud-sdk.sh", + "{{template_dir}}/scripts/installers/haskell.sh", + "{{template_dir}}/scripts/installers/heroku.sh", + "{{template_dir}}/scripts/installers/hhvm.sh", + "{{template_dir}}/scripts/installers/image-magick.sh", + "{{template_dir}}/scripts/installers/java-tools.sh", + "{{template_dir}}/scripts/installers/kind.sh", + "{{template_dir}}/scripts/installers/1604/kubernetes-tools.sh", + "{{template_dir}}/scripts/installers/leiningen.sh", + "{{template_dir}}/scripts/installers/1604/mercurial.sh", + "{{template_dir}}/scripts/installers/miniconda.sh", + "{{template_dir}}/scripts/installers/mono.sh", + "{{template_dir}}/scripts/installers/mysql.sh", + "{{template_dir}}/scripts/installers/nodejs.sh", + "{{template_dir}}/scripts/installers/phantomjs.sh", + "{{template_dir}}/scripts/installers/1604/php.sh", + "{{template_dir}}/scripts/installers/pollinate.sh", + "{{template_dir}}/scripts/installers/1604/powershellcore.sh", + "{{template_dir}}/scripts/installers/ruby.sh", + "{{template_dir}}/scripts/installers/rust.sh", + "{{template_dir}}/scripts/installers/sbt.sh", + "{{template_dir}}/scripts/installers/sphinx.sh", + "{{template_dir}}/scripts/installers/subversion.sh", + "{{template_dir}}/scripts/installers/terraform.sh", + "{{template_dir}}/scripts/installers/vcpkg.sh", + "{{template_dir}}/scripts/installers/zeit-now.sh" + ], + "environment_vars": [ + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}", + "DEBIAN_FRONTEND=noninteractive" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/installers/1604/android.sh", + "{{template_dir}}/scripts/installers/1604/azpowershell.sh", + "{{template_dir}}/scripts/helpers/containercache.sh", + "{{template_dir}}/scripts/installers/1604/hosted-tool-cache.sh", + "{{template_dir}}/scripts/installers/python.sh", + "{{template_dir}}/scripts/installers/test-toolcache.sh" + ], + "environment_vars": [ + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/installers/boost.sh" + ], + "environment_vars": [ + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}", + "BOOST_VERSIONS=1.69.0", + "BOOST_DEFAULT=1.69.0" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "file", + "source": "{{user `metadata_file`}}", + "destination": "{{template_dir}}/Ubuntu1604-README.md", + "direction": "download" + }, + { + "type": "shell", + "inline": [ + "rm -rf {{user `helper_script_folder`}}", + "rm -rf {{user `installer_script_folder`}}", + "chmod 755 {{user `image_folder`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "file", + "source": "{{template_dir}}/config/ubuntu1604.conf", + "destination": "/tmp/" + }, + { + "type": "shell", + "inline": [ + "mkdir -p /etc/vsts", + "cp /tmp/ubuntu1604.conf /etc/vsts/machine_instance.conf" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "inline": [ + "sleep 30", + "/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + } + ] +} diff --git a/images/linux/ubuntu1804.json b/images/linux/ubuntu1804.json new file mode 100644 index 00000000..873d7c4a --- /dev/null +++ b/images/linux/ubuntu1804.json @@ -0,0 +1,239 @@ +{ + "variables": { + "commit_id": "{{env `COMMIT_ID`}}", + "client_id": "{{env `ARM_CLIENT_ID`}}", + "client_secret": "{{env `ARM_CLIENT_SECRET`}}", + "subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}", + "tenant_id": "{{env `ARM_TENANT_ID`}}", + "resource_group": "{{env `ARM_RESOURCE_GROUP`}}", + "storage_account": "{{env `ARM_STORAGE_ACCOUNT`}}", + "temp_resource_group_name": "{{env `TEMP_RESOURCE_GROUP_NAME`}}", + "location": "{{env `ARM_RESOURCE_LOCATION`}}", + "virtual_network_name": "{{env `VNET_NAME`}}", + "virtual_network_resource_group_name": "{{env `VNET_RESOURCE_GROUP`}}", + "virtual_network_subnet_name": "{{env `VNET_SUBNET`}}", + "private_virtual_network_with_public_ip": "{{env `PRIVATE_VIRTUAL_NETWORK_WITH_PUBLIC_IP`}}", + "image_folder": "/imagegeneration", + "commit_file": "/imagegeneration/commit.txt", + "metadata_file": "/imagegeneration/metadatafile", + "installer_script_folder": "/imagegeneration/installers", + "helper_script_folder": "/imagegeneration/helpers", + "vm_size": "Standard_DS2_v2", + "capture_name_prefix": "packer", + "image_version": "dev" + }, + "builders": [ + { + "type": "azure-arm", + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "subscription_id": "{{user `subscription_id`}}", + "tenant_id": "{{user `tenant_id`}}", + + "location": "{{user `location`}}", + "vm_size": "{{user `vm_size`}}", + "resource_group_name": "{{user `resource_group`}}", + "storage_account": "{{user `storage_account`}}", + "temp_resource_group_name": "{{user `temp_resource_group_name`}}", + "capture_container_name": "images", + "capture_name_prefix": "{{user `capture_name_prefix`}}", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "os_type": "Linux", + "image_publisher": "Canonical", + "image_offer": "UbuntuServer", + "image_sku": "18.04-LTS", + "os_disk_size_gb": "86" + } + ], + "provisioners": [ + { + "type": "shell", + "inline": [ + "mkdir {{user `image_folder`}}", + "chmod 777 {{user `image_folder`}}", + "echo {{user `commit_id`}} > {{user `commit_file`}}", + "chmod +r {{user `commit_file`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/base/repos.sh" + ], + "environment_vars": [ + "DEBIAN_FRONTEND=noninteractive" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "inline": [ + "apt-get update", + "apt-get dist-upgrade -y", + "systemctl disable apt-daily.service", + "systemctl disable apt-daily.timer", + "systemctl disable apt-daily-upgrade.timer", + "systemctl disable apt-daily-upgrade.service", + "echo '* soft nofile 50000 \n* hard nofile 50000' >> /etc/security/limits.conf", + "echo 'session required pam_limits.so' >> /etc/pam.d/common-session", + "echo 'session required pam_limits.so' >> /etc/pam.d/common-session-noninteractive" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "file", + "source": "{{template_dir}}/scripts/helpers", + "destination": "{{user `helper_script_folder`}}" + }, + { + "type": "file", + "source": "{{template_dir}}/scripts/installers", + "destination": "{{user `installer_script_folder`}}" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/installers/1804/preparemetadata.sh" + ], + "environment_vars": [ + "IMAGE_VERSION={{user `image_version`}}", + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "inline": [ + "echo ImageVersion={{user `image_version`}} | tee -a /etc/environment" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts": [ + "{{template_dir}}/scripts/installers/7-zip.sh", + "{{template_dir}}/scripts/installers/ansible.sh", + "{{template_dir}}/scripts/installers/azcopy.sh", + "{{template_dir}}/scripts/installers/azure-cli.sh", + "{{template_dir}}/scripts/installers/azure-devops-cli.sh", + "{{template_dir}}/scripts/installers/1804/basic.sh", + "{{template_dir}}/scripts/installers/aws.sh", + "{{template_dir}}/scripts/installers/build-essential.sh", + "{{template_dir}}/scripts/installers/clang.sh", + "{{template_dir}}/scripts/installers/cmake.sh", + "{{template_dir}}/scripts/installers/docker-compose.sh", + "{{template_dir}}/scripts/installers/docker-moby.sh", + "{{template_dir}}/scripts/installers/docker.sh", + "{{template_dir}}/scripts/installers/1804/dotnetcore-sdk.sh", + "{{template_dir}}/scripts/installers/erlang.sh", + "{{template_dir}}/scripts/installers/firefox.sh", + "{{template_dir}}/scripts/installers/gcc.sh", + "{{template_dir}}/scripts/installers/git.sh", + "{{template_dir}}/scripts/installers/1804/go.sh", + "{{template_dir}}/scripts/installers/google-chrome.sh", + "{{template_dir}}/scripts/installers/google-cloud-sdk.sh", + "{{template_dir}}/scripts/installers/haskell.sh", + "{{template_dir}}/scripts/installers/heroku.sh", + "{{template_dir}}/scripts/installers/hhvm.sh", + "{{template_dir}}/scripts/installers/image-magick.sh", + "{{template_dir}}/scripts/installers/java-tools.sh", + "{{template_dir}}/scripts/installers/kind.sh", + "{{template_dir}}/scripts/installers/1804/kubernetes-tools.sh", + "{{template_dir}}/scripts/installers/leiningen.sh", + "{{template_dir}}/scripts/installers/1804/mercurial.sh", + "{{template_dir}}/scripts/installers/miniconda.sh", + "{{template_dir}}/scripts/installers/mono.sh", + "{{template_dir}}/scripts/installers/mysql.sh", + "{{template_dir}}/scripts/installers/nodejs.sh", + "{{template_dir}}/scripts/installers/phantomjs.sh", + "{{template_dir}}/scripts/installers/1804/php.sh", + "{{template_dir}}/scripts/installers/pollinate.sh", + "{{template_dir}}/scripts/installers/1804/powershellcore.sh", + "{{template_dir}}/scripts/installers/ruby.sh", + "{{template_dir}}/scripts/installers/rust.sh", + "{{template_dir}}/scripts/installers/sbt.sh", + "{{template_dir}}/scripts/installers/sphinx.sh", + "{{template_dir}}/scripts/installers/subversion.sh", + "{{template_dir}}/scripts/installers/terraform.sh", + "{{template_dir}}/scripts/installers/vcpkg.sh", + "{{template_dir}}/scripts/installers/zeit-now.sh" + ], + "environment_vars": [ + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}", + "DEBIAN_FRONTEND=noninteractive" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/installers/1804/android.sh", + "{{template_dir}}/scripts/installers/1804/azpowershell.sh", + "{{template_dir}}/scripts/helpers/containercache.sh", + "{{template_dir}}/scripts/installers/1804/hosted-tool-cache.sh", + "{{template_dir}}/scripts/installers/python.sh", + "{{template_dir}}/scripts/installers/test-toolcache.sh" + ], + "environment_vars": [ + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "scripts":[ + "{{template_dir}}/scripts/installers/boost.sh" + ], + "environment_vars": [ + "METADATA_FILE={{user `metadata_file`}}", + "HELPER_SCRIPTS={{user `helper_script_folder`}}", + "BOOST_VERSIONS=1.69.0", + "BOOST_DEFAULT=1.69.0" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "file", + "source": "{{user `metadata_file`}}", + "destination": "{{template_dir}}/Ubuntu1804-README.md", + "direction": "download" + }, + { + "type": "shell", + "inline": [ + "rm -rf {{user `helper_script_folder`}}", + "rm -rf {{user `installer_script_folder`}}", + "chmod 755 {{user `image_folder`}}" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "file", + "source": "{{template_dir}}/config/ubuntu1804.conf", + "destination": "/tmp/" + }, + { + "type": "shell", + "inline": [ + "mkdir -p /etc/vsts", + "cp /tmp/ubuntu1804.conf /etc/vsts/machine_instance.conf" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + }, + { + "type": "shell", + "inline": [ + "sleep 30", + "/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync" + ], + "execute_command": "sudo sh -c '{{ .Vars }} {{ .Path }}'" + } + ] +} diff --git a/images/macos/macos-10.13-Readme.md b/images/macos/macos-10.13-Readme.md new file mode 100644 index 00000000..b21f0133 --- /dev/null +++ b/images/macos/macos-10.13-Readme.md @@ -0,0 +1,395 @@ +# Azure Pipelines hosted macOS image + +The following software is installed on machines in the Azure Pipelines **macOS-10.13** VM image ('Hosted macOS High Sierra' pool). + +#### Xcode 10.1 set by default + +## Operating System + +- OS X 10.13.6 (17G8037) **High Sierra** + +## Installed Software + +### Language and Runtime + +- Java 1.7: OpenJDK Runtime Environment (Zulu 7.34.0.5-CA-macosx) (build 1.7.0_242-b7) +- Java 1.8: OpenJDK Runtime Environment (Zulu 8.42.0.21-CA-macosx) (build 1.8.0_232-b18) (default) +- Java 11: OpenJDK Runtime Environment Zulu11.35+13-CA (build 11.0.5+10-LTS) +- Java 12: OpenJDK Runtime Environment Zulu12.3+11-CA (build 12.0.2+3) +- Java 13: OpenJDK Runtime Environment Zulu13.28+11-CA (build 13.0.1+10-MTS) +- Node.js 6.17.0 +- NVM 0.33.11 +- NVM - Installed node versions: + v6.17.1 + v8.16.2 + v10.17.0 + v12.13.0 +- PowerShell 6.2.3 +- Python 2.7.17 +- Python 3.7.4 +- Ruby 2.6.5p114 +- .NET Core SDK 1.0.1, 1.0.4, 1.1.4, 1.1.5, 1.1.7, 1.1.8, 1.1.9, 1.1.10, 1.1.11, 1.1.12, 1.1.13, 2.0.0, 2.0.3, 2.1.100, 2.1.101, 2.1.102, 2.1.103, 2.1.104, 2.1.105, 2.1.503, 2.1.504, 2.1.505, 2.1.2, 2.1.200, 2.1.201, 2.1.300, 2.1.301, 2.1.4, 2.1.400, 2.1.401 2.1.402 2.1.502, 2.1.504, 2.2.101, 2.2.102, 2.2.103, 2.2.104, 2.2.105 +- Go 1.13.3 + +### Package Management + +- Bundler 2.0.2 +- Carthage 0.34.0 +- CocoaPods 1.8.4 +- Homebrew 2.1.15 +- NPM 3.10.10 +- Yarn 1.19.1 +- NuGet 4.7.0.5148 +- pip 19.3.1(python 2.7) +- pip 19.2.3(python 3.7) +- Miniconda 4.7.12 + +### Project Management + +- Apache Maven 3.6.2 +- Gradle 5.6.3 + +### Utilities + +- curl 7.66.0 (x86_64-apple-darwin17.7.0) libcurl/7.66.0 SecureTransport zlib/1.2.11 +- Git 2.23.0 +- Git LFS 2.8.0 +- GNU Wget 1.20.3 +- Subversion (SVN) 1.12.2 +- GNU parallel 20190822 + +### Tools + +- fastlane 2.134.0 +- App Center CLI 1.2.2 +- Azure-CLI 2.0.75 + +### Pre-cached tools +- Python (available through the [setup-python](https://github.com/actions/setup-python/blob/master/README.md) task) + - 2.7.16 + - 3.4.10 + - 3.5.7 + - 3.6.9 + - 3.7.5 + - 3.8.0 + - pypy2 + - pypy3 +- Ruby (available through the [setup-ruby](https://github.com/actions/setup-ruby/blob/master/README.md) task) + - 2.3.8 + - 2.4.6 + - 2.5.5 + - 2.6.3 + +### Xcode +| Version | Build | Path | +|------------------------|---------|-------------------------------| +| 10.1 | 10B61 | /Applications/Xcode_10.1.app | +| 10.0 | 10A255 | /Applications/Xcode_10.app | +| 9.4.1 | 9F2000 | /Applications/Xcode_9.4.1.app | +| 9.4 | 9F1027a | /Applications/Xcode_9.4.app | +| 9.3.1 | 9E501 | /Applications/Xcode_9.3.1.app | +| 9.3 | 9E145 | /Applications/Xcode_9.3.app | +| 9.2 | 9C40b | /Applications/Xcode_9.2.app | +| 9.1 | 9B55 | /Applications/Xcode_9.1.app | +| 9.0.1 | 9A1004 | /Applications/Xcode_9.0.1.app | +| 9.0 | 9A235 | /Applications/Xcode_9.app | +| 8.3.3 | 8E3004b | /Applications/Xcode_8.3.3.app | + +### Xcode Support Tools + +- Nomad CLI 3.0.6 +- Nomad CLI IPA 0.14.3 +- xcpretty 0.3.0 +- xctool 0.3.5 +- xcversion 2.6.1 + +### Installed SDKs +| SDK | SDK name | Xcode Version | +|---------------------------|-------------|---------------| +| macOS 10.12 | macosx10.12 | 8.3.3 | +| macOS 10.13 | macosx10.13 | 9.0, 9.0.1, 9.1, 9.2, 9.3, 9.3.1, 9.4, 9.4.1 | +| macOS 10.14 | macosx10.14 | 10, 10.1 | +| iOS 10.3 | iphoneos10.3 | 8.3.3 | +| iOS 11.0 | iphoneos11.0 | 9.0, 9.0.1 | +| iOS 11.1 | iphoneos11.1 | 9.1 | +| iOS 11.2 | iphoneos11.2 | 9.2 | +| iOS 11.3 | iphoneos11.3 | 9.3, 9.3.1 | +| iOS 11.4 | iphoneos11.4 | 9.4, 9.4.1 | +| iOS 12.0 | iphoneos12.0 | 10 | +| iOS 12.1 | iphoneos12.1 | 10.1 | +| iOS Simulator 10.3 | iphonesimulator10.3 | 8.3.3 | +| iOS Simulator 11.0 | iphonesimulator11.0 | 9.0, 9.0.1 | +| iOS Simulator 11.1 | iphonesimulator11.1 | 9.1 | +| iOS Simulator 11.2 | iphonesimulator11.2 | 9.2 | +| iOS Simulator 11.3 | iphonesimulator11.3 | 9.3, 9.3.1 | +| iOS Simulator 11.4 | iphonesimulator11.4 | 9.4, 9.4.1 | +| iOS Simulator 12.0 | iphonesimulator12.0 | 10 | +| iOS Simulator 12.1 | iphonesimulator12.1 | 10.1 | +| tvOS 10.2 | appletvos10.2 | 8.3.3 | +| tvOS 11.0 | appletvos11.0 | 9.0, 9.0.1 | +| tvOS 11.1 | appletvos11.1 | 9.1 | +| tvOS 11.2 | appletvos11.2 | 9.2 | +| tvOS 11.3 | appletvos11.3 | 9.3, 9.3.1 | +| tvOS 11.4 | appletvos11.4 | 9.4, 9.4.1 | +| tvOS 12.0 | appletvos12.0 | 10 | +| tvOS 12.1 | appletvos12.1 | 10.1 | +| tvOS Simulator 10.2 | appletvsimulator10.2 | 8.3.3 | +| tvOS Simulator 11.0 | appletvsimulator11.0 | 9.0, 9.0.1 | +| tvOS Simulator 11.1 | appletvsimulator11.1 | 9.1 | +| tvOS Simulator 11.2 | appletvsimulator11.2 | 9.2 | +| tvOS Simulator 11.3 | appletvsimulator11.3 | 9.3, 9.3.1 | +| tvOS Simulator 11.4 | appletvsimulator11.4 | 9.4, 9.4.1 | +| tvOS Simulator 12.0 | appletvsimulator12.0 | 10 | +| tvOS Simulator 12.1 | appletvsimulator12.1 | 10.1 | +| watchOS 3.2 | watchos3.2 | 8.3.3 | +| watchOS 4.0 | watchos4.0 | 9.0, 9.0.1 | +| watchOS 4.1 | watchos4.1 | 9.1 | +| watchOS 4.2 | watchos4.2 | 9.2 | +| watchOS 4.3 | watchos4.3 | 9.3, 9.3.1, 9.4, 9.4.1 | +| watchOS 5.0 | watchos5.0 | 10.0 | +| watchOS 5.1 | watchos5.1 | 10.1 | +| watchOS Simulator 3.2 | watchsimulator3.2 | 8.3.3 | +| watchOS Simulator 4.0 | watchsimulator4.0 | 9.0, 9.0.1 | +| watchOS Simulator 4.1 | watchsimulator4.1 | 9.1 | +| watchOS Simulator 4.2 | watchsimulator4.2 | 9.2 | +| watchOS Simulator 4.3 | watchsimulator4.3 | 9.3, 9.3.1, 9.4, 9.4.1 | +| watchOS Simulator 5.0 | watchsimulator5.0 | 10.0 | +| watchOS Simulator 5.1 | watchsimulator5.1 | 10.1 | + +### Installed Simulators + +#### Runtimes + +| OS | Xcode Version | Simulators | +|---------|---------------------------------|------------| +| iOS 8.4 (12H141) | 8.3.3, 9.0, 9.0.1, 9.1, 9.2, 9.3, 9.3.1, 9.4, 9.4.1, 10.0, 10.1 | iPhone 4s
iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPad 2
iPad Retina
iPad Air | +| iOS 9.0 (13A344) | 8.3.3, 9.0, 9.0.1, 9.1, 9.2, 9.3, 9.3.1, 9.4, 9.4.1, 10.0, 10.1 | iPhone 4s
iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPad 2
iPad Retina
iPad Air
iPad Air 2 | +| iOS 9.1 (13B143)
iOS 9.2 (13C75)
iOS 9.3 (13E233) | 8.3.3, 9.0, 9.0.1, 9.1, 9.2, 9.3, 9.3.1, 9.4, 9.4.1, 10.0, 10.1 | iPhone 4s
iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPad 2
iPad Retina
iPad Air
iPad Air 2
iPad Pro | +| iOS 10.0 (14A345) | 8.3.3, 9.0, 9.0.1, 9.1, 9.2, 9.3, 9.3.1, 9.4, 9.4.1, 10.0, 10.1 | iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone SE
iPad Air
iPad Air 2
iPad Pro (9.7 inch)
iPad Pro (12.9 inch) | +| iOS 10.1 (14B72)
iOS 10.2 (14C89) | 8.3.3, 9.0, 9.0.1, 9.1, 9.2, 9.3, 9.3.1, 9.4, 9.4.1, 10.0, 10.1 | iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPad Air
iPad Air 2
iPad Pro (9.7 inch)
iPad Pro (12.9 inch) | +| iOS 10.3 (14E8301) | 8.3.3 | iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPad Air
iPad Air 2
iPad Pro (9.7 inch)
iPad Pro (12.9 inch)
iPad (5th generation)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 11.0 (15A372) | 9.0 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone 8
iPhone 8 Plus
iPhone SE
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 11.0 (15A8401) | 9.0.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone 8
iPhone 8 Plus
iPhone SE
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 11.1 (15B87) | 9.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone 8
iPhone 8 Plus
iPhone SE
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 11.2 (15C107) | 9.2 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone 8
iPhone 8 Plus
iPhone SE
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 11.3 (15E217) | 9.3, 9.3.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone 8
iPhone 8 Plus
iPhone SE
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 11.4 (15F79) | 9.4, 9.4.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone 8
iPhone 8 Plus
iPhone SE
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 12.0 (16A366) | 10.0 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPhone 8
iPhone 8 Plus
iPhone X
iPhone XR
iPhone XS
iPhone XS Max
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (10.5-inch)
iPad Pro (11-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad (6th generation) | +| iOS 12.1 (16B91) | 10.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPhone 8
iPhone 8 Plus
iPhone X
iPhone X
iPhone XS
iPhone XS Max
iPhone XR
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch)
iPad (6th generation)
iPad Pro (11-inch)
iPad Pro (12.9-inch) (3rd generation) | +| tvOS 10.2 (14W260) | 8.3.3 | Apple TV 1080p | +| tvOS 11.0 (15J380) | 9.0, 9.0.1 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| tvOS 11.1 (15J580) | 9.1 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| tvOS 11.2 (15K104) | 9.2 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| tvOS 11.3 (15L211) | 9.3, 9.3.1 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| tvOS 11.4 (15L576) | 9.4, 9.4.1 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| tvOS 12.0 (16J364) | 10.0 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| tvOS 12.1 (16J602) | 10.1 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| watchOS 3.2 (14V243) | 8.3.3 | Apple Watch - 38mm
Apple Watch - 42mm
Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm | +| watchOS 4.0 (15R372) | 9.0, 9.0.1 | Apple Watch - 38mm
Apple Watch - 42mm
Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm
Apple Watch Series 3 - 38mm
Apple Watch Series 3 - 42mm | +| watchOS 4.1 (15R844) | 9.1 | Apple Watch - 38mm
Apple Watch - 42mm
Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm
Apple Watch Series 3 - 38mm
Apple Watch Series 3 - 42mm | +| watchOS 4.2 (15S100) | 9.2 | Apple Watch - 38mm
Apple Watch - 42mm
Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm
Apple Watch Series 3 - 38mm
Apple Watch Series 3 - 42mm | +| watchOS 4.3 (15T212) | 9.3, 9.3.1, 9.4, 9.4.1 | Apple Watch - 38mm
Apple Watch - 42mm
Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm
Apple Watch Series 3 - 38mm
Apple Watch Series 3 - 42mm | +| watchOS 5.0 (16R363) | 10.0 | Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm
Apple Watch Series 3 - 38mm
Apple Watch Series 3 - 42mm
Apple Watch Series 4 - 40mm
Apple Watch Series 4 - 44mm | +| watchOS 5.1 (16R591) | 10.1 | Apple Watch Series 2 - 38mm
Apple Watch Series 2 - 42mm
Apple Watch Series 3 - 38mm
Apple Watch Series 3 - 42mm
Apple Watch Series 4 - 40mm
Apple Watch Series 4 - 44mm | + +#### How to install additional simulators? +Image contains only default simulators for each Xcode version. To install a specific simulator for all Xcode version, use xcversion tool: +``` +xcversion simulators --install='iOS 8.4' +``` +**!** - The installation of some simulators may cause compatibility issues. + +### Device Pairs + +| Watch | Phone | +|-----------------------------|----------------| +| Apple Watch - 38mm | iPhone 6s | +| Apple Watch - 42mm | iPhone 6s Plus | +| Apple Watch Series 2 - 38mm | iPhone 7 | +| Apple Watch Series 2 - 42mm | iPhone 7 Plus | +| Apple Watch Series 3 - 38mm | iPhone 8 | +| Apple Watch Series 3 - 42mm | iPhone 8 Plus | +| Apple Watch Series 4 - 40mm | iPhone XS | +| Apple Watch Series 4 - 44mm | iPhone XS Max | + +## Android + +### Android SDK Tools + +| Package name | Description | +|-----------------------|---------------------------------------------| +| tools | Android SDK Tools, revision 26.1.1 | + +### Android SDK Platform-tools + +| Package name | Description | +|-----------------------|---------------------------------------------| +| platform-tools | Android SDK Platform-tools, revision 29.0.4 | + +### Android SDK Platforms + +| Package name | Description | +|-----------------------|-------------------------------------------| +| android-15 | Android SDK Platform 15, Revision 5 | +| android-16 | Android SDK Platform 16, Revision 5 | +| android-17 | Android SDK Platform 17, Revision 3 | +| android-18 | Android SDK Platform 18, Revision 3 | +| android-19 | Android SDK Platform 19, Revision 4 | +| android-20 | Android SDK Platform 20, Revision 2 | +| android-21 | Android SDK Platform 21, Revision 2 | +| android-22 | Android SDK Platform 22, Revision 2 | +| android-23 | Android SDK Platform 23, Revision 3 | +| android-24 | Android SDK Platform 24, Revision 2 | +| android-25 | Android SDK Platform 25, Revision 3 | +| android-26 | Android SDK Platform 26, Revision 2 | +| android-27 | Android SDK Platform 27, Revision 3 | +| android-28 | Android SDK Platform 28, Revision 6 | +| android-29 | Android SDK Platform 29, Revision 3 | + +### Android SDK Build-tools + +| Package name | Description | +|-----------------------|-------------------------------------------| +| build-tools-19.1.0 | Android SDK Build-tools, Revision 19.1.0 | +| build-tools-20.0.0 | Android SDK Build-tools, Revision 20.0.0 | +| build-tools-21.1.2 | Android SDK Build-tools, Revision 21.1.2 | +| build-tools-22.0.1 | Android SDK Build-tools, Revision 22.0.1 | +| build-tools-23.0.1 | Android SDK Build-tools, Revision 23.0.1 | +| build-tools-23.0.2 | Android SDK Build-tools, Revision 23.0.2 | +| build-tools-23.0.3 | Android SDK Build-tools, Revision 23.0.3 | +| build-tools-24.0.0 | Android SDK Build-tools, Revision 24.0.0 | +| build-tools-24.0.1 | Android SDK Build-tools, Revision 24.0.1 | +| build-tools-24.0.2 | Android SDK Build-tools, Revision 24.0.2 | +| build-tools-24.0.3 | Android SDK Build-tools, Revision 24.0.3 | +| build-tools-25.0.0 | Android SDK Build-tools, Revision 25.0.0 | +| build-tools-25.0.1 | Android SDK Build-tools, Revision 25.0.1 | +| build-tools-25.0.2 | Android SDK Build-tools, Revision 25.0.2 | +| build-tools-25.0.3 | Android SDK Build-tools, Revision 25.0.3 | +| build-tools-26.0.0 | Android SDK Build-tools, Revision 26.0.0 | +| build-tools-26.0.1 | Android SDK Build-tools, Revision 26.0.1 | +| build-tools-26.0.2 | Android SDK Build-tools, Revision 26.0.2 | +| build-tools-26.0.3 | Android SDK Build-tools, Revision 26.0.3 | +| build-tools-27.0.0 | Android SDK Build-tools, Revision 27.0.0 | +| build-tools-27.0.1 | Android SDK Build-tools, Revision 27.0.1 | +| build-tools-27.0.2 | Android SDK Build-tools, Revision 27.0.2 | +| build-tools-27.0.3 | Android SDK Build-tools, Revision 27.0.3 | +| build-tools-28.0.0 | Android SDK Build-tools, Revision 28.0.0 | +| build-tools-28.0.1 | Android SDK Build-tools, Revision 28.0.1 | +| build-tools-28.0.2 | Android SDK Build-tools, Revision 28.0.2 | +| build-tools-28.0.3 | Android SDK Build-tools, Revision 28.0.3 | +| build-tools-29.0.0 | Android SDK Build-tools, Revision 29.0.0 | +| build-tools-29.0.1 | Android SDK Build-tools, Revision 29.0.1 | +| build-tools-29.0.2 | Android SDK Build-tools, Revision 29.0.2 | + +### Utils + +| Package name | Description | +|-----------------------|-------------------------------------------| +| cmake | 3.6.4111459 | +| lldb | 3.1.4508709 | +| ndk-bundle | 18.1.5063045 | +| ProGuard | 5.3.3 | +| Android Emulator | 29.2.1 | + +### Google APIs + +| Package name | Description | +|-----------------------|-------------------------------------------| +| google_apis-google-21 | Google APIs, Android API 21, revision 1 | +| google_apis-google-22 | Google APIs, Android API 22, revision 1 | +| google_apis-google-23 | Google APIs, Android API 23, revision 1 | +| google_apis-google-24 | Google APIs, Android API 24, revision 1 | + +### Extra packages + +| Package name | Description | +|-----------------------------------|------------------------------------------| +| extra-android-m2repository | Android Support Repository, revision 47 | +| extra-google-google_play_services | Google Play services, revision 49 | +| extra-google-m2repository | Google Repository, revision 58 | +| Hardware_Accelerated_Execution_Manager | Intel x86 Emulator Accelerator 7.5.1 | + +## Xamarin + +### Visual Studio for Mac + +- 8.3.4.8 + +### Mono + +- 6.4.0 +- 6.0.0 +- 5.18.1 +- 5.16.1 +- 5.12.0 +- 5.10.1 +- 5.8.1 +- 5.8.0 +- 5.4.1.7 +- 5.4.0.201 +- 5.2.0.224 +- 5.0.1.1 +- 4.8.1.0 + +### Xamarin.iOS SDK + +- 13.4.0.2 +- 13.2.0.47 +- 12.14.0.114 +- 12.8.0.2 +- 12.6.0.25 +- 12.2.1.16 +- 12.2.1.11 +- 12.0.0.15 +- 11.14.0.13 +- 11.12.0.4 +- 11.9.1.24 +- 11.8.0.20 +- 11.6.1.4 +- 11.2.0.11 +- 11.0.0.0 +- 10.10.0.36 +- 10.6.0.10 + + +### Xamarin.Android SDK + +- 10.0.3.0 +- 9.4.1.0 +- 9.3.0-23 +- 9.2.3-0 +- 9.1.8-0 +- 9.0.0-20 +- 9.0.0-18 +- 8.3.3-2 +- 8.2.0-16 +- 8.2.0-15 +- 8.1.5-0 +- 8.0.0-33 +- 7.4.5-1 +- 7.3.1-2 +- 7.1.0-43 + +### Xamarin.Mac SDK + +- 6.4.0.2 +- 6.2.0.47 +- 5.16.1.24 +- 5.8.0.0 +- 5.6.0.25 +- 5.3.1.28 +- 5.2.1.16 +- 5.2.1.9 +- 4.6.0.13 +- 4.4.1.193 +- 4.2.1.28 +- 4.2.0.20 +- 4.0.0.216 +- 3.8.0.49 +- 3.6.3.3 +- 3.4.0.36 +- 3.0.0.398 + +### Unit Test Framework + +- NUnit: 3.6.1 diff --git a/images/macos/macos-10.14-Readme.md b/images/macos/macos-10.14-Readme.md new file mode 100644 index 00000000..d4f08c07 --- /dev/null +++ b/images/macos/macos-10.14-Readme.md @@ -0,0 +1,390 @@ +# Azure Pipelines hosted macOS image + +The following software is installed on machines in the Azure Pipelines **macOS-10.14** VM image ('Hosted macOS' pool). + +#### Xcode 11.1 set by default + +## Operating System + +- OS X 10.14.6 (18G103) **Mojave** + +## Installed Software + +### Language and Runtime + +- Java 1.7: OpenJDK Runtime Environment (Zulu 7.34.0.5-CA-macosx) (build 1.7.0_242-b7) +- Java 1.8: OpenJDK Runtime Environment (Zulu 8.42.0.21-CA-macosx) (build 1.8.0_232-b18) (default) +- Java 11: OpenJDK Runtime Environment Zulu11.35+13-CA (build 11.0.5+10-LTS) +- Java 12: OpenJDK Runtime Environment Zulu12.3+11-CA (build 12.0.2+3) +- Java 13: OpenJDK Runtime Environment Zulu13.28+11-CA (build 13.0.1+10-MTS) +- Node.js 6.17.0 +- NVM 0.33.11 +- NVM - Installed node versions: + v6.17.1 + v8.16.2 + v10.17.0 + v12.13.0 +- PowerShell 6.2.3 +- Python 2.7.16 +- Python 3.7.4 +- Ruby 2.6.5p114 +- .NET Core SDK 1.0.1 1.0.4 1.1.10 1.1.11 1.1.12 1.1.13 1.1.4 1.1.5 1.1.7 1.1.8 1.1.9 2.0.0 2.0.3 2.1.100 2.1.101 2.1.102 2.1.103 2.1.104 2.1.105 2.1.2 2.1.200 2.1.201 2.1.202 2.1.300 2.1.301 2.1.302 2.1.4 2.1.400 2.1.401 2.1.402 2.1.403 2.1.500 2.1.502 2.1.503 2.1.504 2.1.505 2.2.100 2.2.101 2.2.102 2.2.103 2.2.104 2.2.105 +- Go 1.13.3 + + +### Package Management + +- Bundler 2.0.2 +- Carthage 0.34.0 +- CocoaPods 1.8.4 +- Homebrew 2.1.15 +- NPM 3.10.10 +- Yarn 1.19.1 +- NuGet 4.7.0.5148 +- pip 19.1.1(python 2.7) +- pip 19.2.3(python 3.7) +- Miniconda 4.7.12 + +### Project Management + +- Apache Maven 3.6.2 +- Gradle 5.6.3 + +### Utilities + +- curl 7.66.0 (libcurl/7.66.0 SecureTransport zlib/1.2.11) +- Git 2.23.0 +- Git LFS 2.8.0 +- GNU Wget 1.20.3 +- Subversion (SVN) 1.12.2 +- GNU parallel 20190922 + +### Tools + +- fastlane 2.134.0 +- App Center CLI 1.2.2 +- Azure-CLI 2.0.75 + +### Pre-cached tools + +- Python (available through the [setup-python](https://github.com/actions/setup-python/blob/master/README.md) task) + - 2.7.16 + - 3.4.10 + - 3.5.7 + - 3.6.9 + - 3.7.5 + - 3.8.0 + - pypy2 + - pypy3 +- Ruby (available through the [setup-ruby](https://github.com/actions/setup-ruby/blob/master/README.md) task) + - 2.3.8 + - 2.4.6 + - 2.5.5 + - 2.6.3 + +### Xcode + +| Version | Build | Path | +|------------------------|---------|---------------------------------| +| 11.2_beta 2 | 11B44 | /Applications/Xcode_11.2.app | +| 11.1 | 11A1027 | /Applications/Xcode_11.1.app | +| 11.0 | 11A420a | /Applications/Xcode_11.app | +| 10.3 | 10G8 | /Applications/Xcode_10.3.app | +| 10.2.1 | 10E1001 | /Applications/Xcode_10.2.1.app | +| 10.2 | 10E125 | /Applications/Xcode_10.2.app | +| 10.1 | 10B61 | /Applications/Xcode_10.1.app | +| 10.0 | 10A255 | /Applications/Xcode_10.app | +| 9.4.1 | 9F2000 | /Applications/Xcode_9.4.1.app | + +### Xcode Support Tools + +- Nomad CLI 3.0.6 +- Nomad CLI IPA 0.14.3 +- xcpretty 0.3.0 +- xctool 0.3.6 +- xcversion 2.6.1 + +### Installed SDKs + +| SDK | SDK name |Xcode Version | +|---------------------------|-------------|--------------| +| macOS 10.13 | macosx10.13 | 9.4.1 | +| macOS 10.14 | macosx10.14 | 10.0, 10.1, 10.2, 10.2.1, 10.3 | +| macOS 10.15 | macosx10.15 | 11.0, 11.1, 11.2_beta 2 | +| iOS 11.4 | iphoneos11.4 | 9.4.1 | +| iOS 12.0 | iphoneos12.0 | 10.0 | +| iOS 12.1 | iphoneos12.1 | 10.1 | +| iOS 12.2 | iphoneos12.2 | 10.2, 10.2.1| +| iOS 12.4 | iphoneos12.4 | 10.3 | +| iOS 13.0 | iphoneos13.0 | 11.0 | +| iOS 13.1 | iphoneos13.1 | 11.1 | +| iOS 13.2 | iphoneos13.2 | 11.2_beta 2 | +| iOS Simulator 11.4 | iphonesimulator11.4 | 9.4.1 | +| iOS Simulator 12.0 | iphonesimulator12.0 | 10.0 | +| iOS Simulator 12.1 | iphonesimulator12.1 | 10.1 | +| iOS Simulator 12.2 | iphonesimulator12.2 | 10.2, 10.2.1 | +| iOS Simulator 12.4 | iphonesimulator12.4 | 10.3 | +| iOS Simulator 13.0 | iphonesimulator13.0 | 11.0 | +| iOS Simulator 13.1 | iphonesimulator13.1 | 11.1 | +| iOS Simulator 13.2 | iphonesimulator13.2 | 11.2_beta 2 | +| tvOS 11.4 | appletvos11.4 | 9.4.1 | +| tvOS 12.0 | appletvos12.0 | 10.0 | +| tvOS 12.1 | appletvos12.1 | 10.1 | +| tvOS 12.2 | appletvos12.2 | 10.2, 10.2.1 | +| tvOS 12.4 | appletvos12.4 | 10.3 | +| tvOS 13.0 | appletvos13.0 | 11.0, 11.1 | +| tvOS 13.2 | appletvos13.2 | 11.2_beta 2 | +| tvOS Simulator 11.4 | appletvsimulator11.4 | 9.4.1 | +| tvOS Simulator 12.0 | appletvsimulator12.0 | 10.0 | +| tvOS Simulator 12.1 | appletvsimulator12.1 | 10.1 | +| tvOS Simulator 12.2 | appletvsimulator12.2 | 10.2, 10.2.1 | +| tvOS Simulator 12.4 | appletvsimulator12.4 | 10.3 | +| tvOS Simulator 13.0 | appletvsimulator13.0 | 11.0, 11.1 | +| tvOS Simulator 13.2 | appletvsimulator13.2 | 11.2_beta 2 | +| watchOS 4.3 | watchos4.3 | 9.4.1 | +| watchOS 5.0 | watchos5.0 | 10.0 | +| watchOS 5.1 | watchos5.1 | 10.1 | +| watchOS 5.2 | watchos5.2 | 10.2, 10.2.1 | +| watchOS 5.3 | watchos5.3 | 10.3 | +| watchOS 6.0 | watchos6.0 | 11.0, 11.1 | +| watchOS 6.1 | watchos6.1 | 11.2_beta 2 | +| watchOS Simulator 4.3 | watchsimulator4.3 | 9.4.1 | +| watchOS Simulator 5.0 | watchsimulator5.0 | 10.0 | +| watchOS Simulator 5.1 | watchsimulator5.1 | 10.1 | +| watchOS Simulator 5.2 | watchsimulator5.2 | 10.2, 10.2.1 | +| watchOS Simulator 5.3 | watchsimulator5.3 | 10.3 | +| watchOS Simulator 6.0 | watchsimulator6.0 | 11.0, 11.1 | +| watchOS Simulator 6.1 | watchsimulator6.1 | 11.2_beta 2 | +| DriverKit 19.0 | driverkit.macosx19.0 | 11.0, 11.1, 11.2_beta 2 | + + +### Installed Simulators + +#### Runtimes + +| OS | Xcode Version | Simulators | +|---------|---------------------------------|------------| +| iOS 8.4 (12H141) | 9.4.1, 10.0, 10.1, 10.2, 10.2.1, 11, 11.1, 11.2_beta 2 | iPhone 4s
iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPad 2
iPad Retina
iPad Air | +| iOS 9.0 (13A344) | 9.4.1, 10.0, 10.1, 10.2, 10.2.1, 11, 11.1, 11.2_beta 2 | iPhone 4s
iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPad 2
iPad Retina
iPad Air
iPad Air 2 | +| iOS 9.1 (13B143)
iOS 9.2 (13C75)
iOS 9.3 (13E233) | 9.4.1, 10.0, 10.1, 10.2, 10.2.1, 11, 11.1, 11.2_beta 2 | iPhone 4s
iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPad 2
iPad Retina
iPad Air
iPad Air 2
iPad Pro | +| iOS 10.0 (14A345) | 9.4.1, 10.0, 10.1, 10.2, 10.2.1, 11, 11.1, 11.2_beta 2 | iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone SE
iPad Air
iPad Air 2
iPad Pro (9.7 inch)
iPad Pro (12.9 inch) | +| iOS 10.1 (14B72)
iOS 10.2 (14C89) | 9.4.1, 10.0, 10.1, 10.2, 10.2.1, 11, 11.1, 11.2_beta 2 | iPhone 5
iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPad Air
iPad Air 2
iPad Pro (9.7 inch)
iPad Pro (12.9 inch) | +| iOS 11.4 (15F79) | 9.4.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPhone 8
iPhone 8 Plus
iPhone X
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch) | +| iOS 12.0 (16A5288q) | 10.0 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPhone 8
iPhone 8 Plus
iPhone X
iPhone XR
iPhone XS
iPhone XS Max
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (10.5-inch)
iPad Pro (11-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad (6th generation) | +| iOS 12.1 (16B91) | 10.1 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPhone 8
iPhone 8 Plus
iPhone X
iPhone X
iPhone XS
iPhone XS Max
iPhone XR
iPad Air
iPad Air 2
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch)
iPad (6th generation)
iPad Pro (11-inch)
iPad Pro (12.9-inch) (3rd generation) | +| iOS 12.2 (16E226)
iOS 12.4 (16G73) | 10.2, 10.2.1
10.3 | iPhone 5s
iPhone 6
iPhone 6 Plus
iPhone 6s
iPhone 6s Plus
iPhone 7
iPhone 7 Plus
iPhone SE
iPhone 8
iPhone 8 Plus
iPhone X
iPhone X
iPhone XS
iPhone XS Max
iPhone XR
iPad Air
iPad Air 2
iPad Air (3rd generation)
iPad mini 2
iPad mini 3
iPad mini 4
iPad mini (5th generation)
iPad (5th generation)
iPad Pro (9.7-inch)
iPad Pro (12.9-inch)
iPad Pro (12.9-inch) (2nd generation)
iPad Pro (10.5-inch)
iPad (6th generation)
iPad Pro (11-inch)
iPad Pro (12.9-inch) (3rd generation) | +| iOS 13.0 (17A577a) | 11 | iPhone 8
iPhone 8 Plus
iPhone 11
iPhone 11 Pro
iPhone 11 Pro Max
iPad Pro (9.7-inch)
iPad Pro
iPad Pro (12.9-inch) (3rd generation)
iPad Air (3rd generation) | +| iOS 13.1 (17A844) | 11.1 | iPhone 8
iPhone 8 Plus
iPhone 11
iPhone 11 Pro
iPhone 11 Pro Max
iPad Pro (9.7-inch)
iPad Pro
iPad Pro (12.9-inch) (3rd generation)
iPad Air (3rd generation) | +| iOS 13.2 (17B5068e) | 11.2_beta 2 | iPhone 8
iPhone 8 Plus
iPhone 11
iPhone 11 Pro
iPhone 11 Pro Max
iPad Pro (9.7-inch)
iPad Pro
iPad Pro (12.9-inch) (3rd generation)
iPad Air (3rd generation) | +| tvOS 11.4 (15L576)
tvOS 12.0 (16J5283n)
tvOS 12.1 (16J602)
tvOS 12.2 (16L225)
tvOS 12.4 (16M567)
tvOS 13.0 (17J559)
tvOS 13.2 (17K5068b) | 9.4.1
10.0
10.1
10.2, 10.2.1
10.3
11.0
11.1 | Apple TV
Apple TV 4K
Apple TV 4K (at 1080p) | +| watchOS 4.3 (15T212) | 9.4.1 | Apple Watch 38mm
Apple Watch 42mm
Apple Watch Series 2 38mm
Apple Watch Series 2 42mm
Apple Watch Series 3 38mm
Apple Watch Series 3 42mm | +| watchOS 5.0 (16R5283q)
watchOS 5.1 (16R591)
watchOS 5.2 (16T224)
watchOS 5.3 (16U567) | 10.0
10.1
10.2, 10.2.1
10.3 | Apple Watch Series 2 38mm
Apple Watch Series 2 42mm
Apple Watch Series 3 38mm
Apple Watch Series 3 42mm
Apple Watch Series 4 40mm
Apple Watch Series 4 44mm | +| watchOS 6.0 (17R566)

watchOS 6.1 (17S5068e) | 11.0
11.1
11.2_beta 2 | Apple Watch Series 4 40mm
Apple Watch Series 4 44mm
Apple Watch Series 5 40mm
Apple Watch Series 5 44mm | + + +#### How to install additional simulators? +Image contains only default simulators for each Xcode version. To install a specific simulator for all Xcode version, use xcversion tool: +``` +xcversion simulators --install='iOS 8.4' +``` +**!** - The installation of some simulators may cause compatibility issues. + +### Device Pairs + +| Watch | Phone | +|-----------------------------|-------------------| +| Apple Watch - 38mm | iPhone 6s | +| Apple Watch - 42mm | iPhone 6s Plus | +| Apple Watch Series 2 - 38mm | iPhone 7 | +| Apple Watch Series 2 - 42mm | iPhone 7 Plus | +| Apple Watch Series 3 - 38mm | iPhone 8 | +| Apple Watch Series 3 - 42mm | iPhone 8 Plus | +| Apple Watch Series 4 - 40mm | iPhone XS | +| Apple Watch Series 4 - 44mm | iPhone XS Max | +| Apple Watch Series 5 - 40mm | iPhone 11 Pro | +| Apple Watch Series 5 - 44mm | iPhone 11 Pro Max | + +## Android + +### Android SDK Tools + +| Package name | Description | +|-----------------------|---------------------------------------------| +| tools | Android SDK Tools, revision 26.1.1 | + +### Android SDK Platform-tools + +| Package name | Description | +|-----------------------|---------------------------------------------| +| platform-tools | Android SDK Platform-tools, revision 29.0.4 | + +### Android SDK Platforms + +| Package name | Description | +|-----------------------|-------------------------------------------| +| android-15 | Android SDK Platform 15, Revision 5 | +| android-16 | Android SDK Platform 16, Revision 5 | +| android-17 | Android SDK Platform 17, Revision 3 | +| android-18 | Android SDK Platform 18, Revision 3 | +| android-19 | Android SDK Platform 19, Revision 4 | +| android-20 | Android SDK Platform 20, Revision 2 | +| android-21 | Android SDK Platform 21, Revision 2 | +| android-22 | Android SDK Platform 22, Revision 2 | +| android-23 | Android SDK Platform 23, Revision 3 | +| android-24 | Android SDK Platform 24, Revision 2 | +| android-25 | Android SDK Platform 25, Revision 3 | +| android-26 | Android SDK Platform 26, Revision 2 | +| android-27 | Android SDK Platform 27, Revision 3 | +| android-28 | Android SDK Platform 28, Revision 6 | +| android-29 | Android SDK Platform 29, Revision 3 | + +### Android SDK Build-tools + +| Package name | Description | +|-----------------------|-------------------------------------------| +| build-tools-19.1.0 | Android SDK Build-tools, Revision 19.1.0 | +| build-tools-20.0.0 | Android SDK Build-tools, Revision 20.0.0 | +| build-tools-21.1.2 | Android SDK Build-tools, Revision 21.1.2 | +| build-tools-22.0.1 | Android SDK Build-tools, Revision 22.0.1 | +| build-tools-23.0.1 | Android SDK Build-tools, Revision 23.0.1 | +| build-tools-23.0.2 | Android SDK Build-tools, Revision 23.0.2 | +| build-tools-23.0.3 | Android SDK Build-tools, Revision 23.0.3 | +| build-tools-24.0.0 | Android SDK Build-tools, Revision 24.0.0 | +| build-tools-24.0.1 | Android SDK Build-tools, Revision 24.0.1 | +| build-tools-24.0.2 | Android SDK Build-tools, Revision 24.0.2 | +| build-tools-24.0.3 | Android SDK Build-tools, Revision 24.0.3 | +| build-tools-25.0.0 | Android SDK Build-tools, Revision 25.0.0 | +| build-tools-25.0.1 | Android SDK Build-tools, Revision 25.0.1 | +| build-tools-25.0.2 | Android SDK Build-tools, Revision 25.0.2 | +| build-tools-25.0.3 | Android SDK Build-tools, Revision 25.0.3 | +| build-tools-26.0.0 | Android SDK Build-tools, Revision 26.0.0 | +| build-tools-26.0.1 | Android SDK Build-tools, Revision 26.0.1 | +| build-tools-26.0.2 | Android SDK Build-tools, Revision 26.0.2 | +| build-tools-26.0.3 | Android SDK Build-tools, Revision 26.0.3 | +| build-tools-27.0.0 | Android SDK Build-tools, Revision 27.0.0 | +| build-tools-27.0.1 | Android SDK Build-tools, Revision 27.0.1 | +| build-tools-27.0.2 | Android SDK Build-tools, Revision 27.0.2 | +| build-tools-27.0.3 | Android SDK Build-tools, Revision 27.0.3 | +| build-tools-28.0.0 | Android SDK Build-tools, Revision 28.0.0 | +| build-tools-28.0.1 | Android SDK Build-tools, Revision 28.0.1 | +| build-tools-28.0.2 | Android SDK Build-tools, Revision 28.0.2 | +| build-tools-28.0.3 | Android SDK Build-tools, Revision 28.0.3 | +| build-tools-29.0.0 | Android SDK Build-tools, Revision 29.0.0 | +| build-tools-29.0.1 | Android SDK Build-tools, Revision 29.0.1 | +| build-tools-29.0.2 | Android SDK Build-tools, Revision 29.0.2 | + +### Utils + +| Package name | Description | +|-----------------------|-------------------------------------------| +| cmake | 3.6.4111459 | +| lldb | 2.3.3614996 | +| ndk-bundle | 18.1.5063045 | +| ProGuard | 5.3.3 | +| Android Emulator | 29.2.1 | + +### Google APIs + +| Package name | Description | +|-----------------------|-------------------------------------------| +| google_apis-google-21 | Google APIs, Android API 21, revision 1 | +| google_apis-google-22 | Google APIs, Android API 22, revision 1 | +| google_apis-google-23 | Google APIs, Android API 23, revision 1 | +| google_apis-google-24 | Google APIs, Android API 24, revision 1 | + +### Extra packages + +| Package name | Description | +|-----------------------------------|------------------------------------------| +| extra-android-m2repository | Android Support Repository, revision 47 | +| extra-google-google_play_services | Google Play services, revision 49 | +| extra-google-m2repository | Google Repository, revision 58 | +| Hardware_Accelerated_Execution_Manager | Intel x86 Emulator Accelerator 7.3.2 | + +## Xamarin + +### Visual Studio for Mac + +- 8.3.4.8 + + +### Mono + +- 6.4.0 +- 6.0.0 +- 5.18.1 +- 5.16.1 +- 5.12.0 +- 5.10.1 +- 5.8.1 +- 5.8.0 +- 5.4.1.7 +- 5.4.0.201 +- 5.2.0.224 +- 5.0.1.1 +- 4.8.1.0 + +### Xamarin.iOS SDK + +- 13.4.0.2 +- 13.2.0.47 +- 12.14.0.114 +- 12.10.0.157 +- 12.8.0.2 +- 12.6.0.25 +- 12.2.1.16 +- 12.2.1.11 +- 12.0.0.15 +- 11.14.0.13 +- 11.12.0.4 +- 11.9.1.24 +- 11.8.0.20 +- 11.6.1.4 +- 11.2.0.11 +- 11.0.0.0 +- 10.10.0.36 +- 10.6.0.10 + + +### Xamarin.Android SDK + +- 10.0.3.0 +- 9.4.1.0 +- 9.3.0-23 +- 9.2.3-0 +- 9.1.8-0 +- 9.0.0-20 +- 9.0.0-18 +- 8.3.3-2 +- 8.2.0-16 +- 8.2.0-15 +- 8.1.5-0 +- 8.0.0-33 +- 7.4.5-1 +- 7.3.1-2 +- 7.1.0-43 + +### Xamarin.Mac SDK + +- 6.4.0.2 +- 6.2.0.47 +- 5.16.1.24 +- 5.10.0.157 +- 5.8.0.0 +- 5.6.0.25 +- 5.3.1.28 +- 5.2.1.16 +- 5.2.1.9 +- 4.6.0.13 +- 4.4.1.193 +- 4.2.1.28 +- 4.2.0.20 +- 4.0.0.216 +- 3.8.0.49 +- 3.6.3.3 +- 3.4.0.36 +- 3.0.0.398 + +### Unit Test Framework + +- NUnit: 3.6.1 diff --git a/images/win/Windows2019-Azure.json b/images/win/Windows2019-Azure.json new file mode 100644 index 00000000..902f0791 --- /dev/null +++ b/images/win/Windows2019-Azure.json @@ -0,0 +1,782 @@ +{ + "variables": { + "client_id": "{{env `ARM_CLIENT_ID`}}", + "client_secret": "{{env `ARM_CLIENT_SECRET`}}", + "subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}", + "tenant_id": "{{env `ARM_TENANT_ID`}}", + "object_id": "{{env `ARM_OBJECT_ID`}}", + "resource_group": "{{env `ARM_RESOURCE_GROUP`}}", + "storage_account": "{{env `ARM_STORAGE_ACCOUNT`}}", + "temp_resource_group_name": "{{env `TEMP_RESOURCE_GROUP_NAME`}}", + "location": "{{env `ARM_RESOURCE_LOCATION`}}", + "ssh_password": "{{env `SSH_PASSWORD`}}", + "virtual_network_name": "{{env `VNET_NAME`}}", + "virtual_network_resource_group_name": "{{env `VNET_RESOURCE_GROUP`}}", + "virtual_network_subnet_name": "{{env `VNET_SUBNET`}}", + "private_virtual_network_with_public_ip": "{{env `PRIVATE_VIRTUAL_NETWORK_WITH_PUBLIC_IP`}}", + "vm_size": "Standard_DS4_v2", + + "image_folder": "C:\\image", + "commit_file": "C:\\image\\commit.txt", + "metadata_file": "C:\\image\\metadata.txt", + "helper_script_folder": "C:\\Program Files\\WindowsPowerShell\\Modules\\", + "commit_id": "LATEST", + "install_user": "installer", + "install_password": null, + "capture_name_prefix": "packer", + "image_version": "dev" + }, + "sensitive-variables": ["install_password", "ssh_password", "client_secret"], + "builders": [ + { + "name": "vhd", + "type": "azure-arm", + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "subscription_id": "{{user `subscription_id`}}", + "object_id": "{{user `object_id`}}", + "tenant_id": "{{user `tenant_id`}}", + "os_disk_size_gb": "128", + "location": "{{user `location`}}", + "vm_size": "{{user `vm_size`}}", + "resource_group_name": "{{user `resource_group`}}", + "storage_account": "{{user `storage_account`}}", + "temp_resource_group_name": "{{user `temp_resource_group_name`}}", + "capture_container_name": "images", + "capture_name_prefix": "{{user `capture_name_prefix`}}", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "os_type": "Windows", + "image_publisher": "MicrosoftWindowsServer", + "image_offer": "WindowsServer", + "image_sku": "2019-Datacenter", + "communicator": "winrm", + "winrm_use_ssl": "true", + "winrm_insecure": "true", + "winrm_username": "packer" + } + ], + "provisioners": [ + { + "type": "powershell", + "inline":[ + "New-Item -Path {{user `image_folder`}} -ItemType Directory -Force", + "Write-Output {{user `commit_id`}} > {{user `commit_file`}}", + "Write-Host (Get-Content -Path {{user `commit_file`}})" + ] + }, + { + "type": "file", + "source": "{{ template_dir }}/scripts/ImageHelpers", + "destination": "{{user `helper_script_folder`}}" + }, + { + "type": "windows-shell", + "inline": [ + "net user {{user `install_user`}} {{user `install_password`}} /add /passwordchg:no /passwordreq:yes /active:yes /Y" , + "net localgroup Administrators {{user `install_user`}} /add", + "winrm set winrm/config/service/auth @{Basic=\"true\"}", + "winrm get winrm/config/service/auth" + ] + }, + { + "type": "powershell", + "inline": [ + "if (-not ((net localgroup Administrators) -contains '{{user `install_user`}}')) { exit 1 }" + ] + }, + { + "type": "powershell", + "environment_vars": [ + "ImageVersion={{user `image_version`}}" + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Initialize-VM.ps1" + ] + }, + { + "type": "windows-restart", + "restart_timeout": "10m" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-ContainersFeature.ps1" + ] + }, + { + "type": "windows-restart", + "restart_timeout": "10m" + }, + { + "type": "powershell", + "inline": [ + "setx ImageVersion {{user `image_version` }} /m" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Docker.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-PowershellCore.ps1" + ] + }, + { + "type": "windows-restart", + "restart_timeout": "10m" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Docker.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-PowershellCore.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Update-DockerImages.ps1" + ] + }, + { + "type": "powershell", + "scripts": [ + "{{ template_dir }}/scripts/Installers/Vs2019/Install-WDK.ps1" + ] + }, + { + "type": "powershell", + "valid_exit_codes": [ + 0, + 3010 + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Install-VS2019.ps1" + ], + "elevated_user": "{{user `install_user`}}", + "elevated_password": "{{user `install_password`}}" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Install-Wix.ps1" + ] + }, + { + "type": "powershell", + "valid_exit_codes": [ + 0, + 3010 + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-NET48.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-ServiceFabricSDK.ps1" + ] + }, + { + "type": "windows-restart", + "restart_timeout": "10m" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Validate-Wix.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-NET48.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Validate-WDK.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-ServiceFabricSDK.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Update-DotnetTLS.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-AzureCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-AzureDevOpsCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Download-ToolCache.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Install-Python.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Git.ps1" + ] + }, + { + "type": "powershell", + "environment_vars": [ + "GO_VERSIONS=1.10.8,1.11.12,1.12.7,1.13", + "GO_DEFAULT=1.12.7" + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Go.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-PHP.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Ruby.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Rust.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Sbt.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Svn.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Chrome.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Firefox.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-SeleniumWebDrivers.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Enable-DeveloperMode.ps1" + ], + "elevated_user": "{{user `install_user`}}", + "elevated_password": "{{user `install_password`}}" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-WinAppDriver.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-WinAppDriver.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-NodeLts.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-JavaTools.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Cmake.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-DACFx.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Update-AndroidSDK.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-MysqlCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-SQLPowerShellTools.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-DotnetSDK.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-WindowsUpdates.ps1" + ] + }, + { + "type": "windows-shell", + "inline": ["wmic product where \"name like '%%microsoft azure powershell%%'\" call uninstall /nointeractive"] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-AzureModules.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-MinGW.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-TypeScript.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Miniconda.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-AzureCosmosDbEmulator.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-7zip.ps1" + ] + }, + { + "type": "powershell", + "environment_vars": [ + "BOOST_VERSIONS=1.69.0", + "BOOST_DEFAULT=1.69.0" + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Boost.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Mercurial.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Jq.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-InnoSetup.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Perl.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-GitVersion.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-OpenSSL.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-NSIS.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-CloudFoundryCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Vcpkg.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-KubernetesCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Install-Kind.ps1" + ] + }, + { + "type": "windows-restart", + "restart_timeout": "10m" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-AzureModules.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-DotnetTLS.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-AzureCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-AzureDevOpsCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-ToolCache.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Python.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Git.ps1" + ] + }, + { + "type": "powershell", + "environment_vars": [ + "GO_VERSIONS=1.10.8,1.11.12,1.12.7,1.13", + "GO_DEFAULT=1.12.7" + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Go.ps1" + ] + }, + { + "type": "powershell", + "environment_vars": [ + "BOOST_VERSIONS=1.69.0", + "BOOST_DEFAULT=1.69.0" + ], + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Boost.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-PHP.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Ruby.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Rust.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Svn.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Sbt.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Chrome.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Firefox.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-SeleniumWebDrivers.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-NodeLts.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-JavaTools.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Cmake.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-DACFx.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-DotnetSDK.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-MysqlCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-MinGW.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-TypeScript.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Miniconda.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-AzureCosmosDbEmulator.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-7zip.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Mercurial.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Jq.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-InnoSetup.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Perl.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-GitVersion.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-OpenSSL.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-NSIS.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-CloudFoundryCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Vcpkg.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-KubernetesCli.ps1" + ] + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Validate-Kind.ps1" + ] + }, + { + "type": "file", + "source": "C:\\InstalledSoftware.md", + "destination": "{{ template_dir }}/Vs2019-Server2019-Readme.md", + "direction": "download" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Finalize-VM.ps1" + ] + }, + { + "type": "windows-restart", + "restart_timeout": "10m" + }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Installers/Vs2019/Run-Antivirus.ps1" + ] + }, + { + "type": "powershell", + "inline": [ + "if( Test-Path $Env:SystemRoot\\System32\\Sysprep\\unattend.xml ){ rm $Env:SystemRoot\\System32\\Sysprep\\unattend.xml -Force}", + "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit", + "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }" + ] + } + ] +} diff --git a/images/win/scripts/ImageHelpers/ImageHelpers.psd1 b/images/win/scripts/ImageHelpers/ImageHelpers.psd1 new file mode 100644 index 00000000..438a9d32 --- /dev/null +++ b/images/win/scripts/ImageHelpers/ImageHelpers.psd1 @@ -0,0 +1,124 @@ +# +# Module manifest for module 'ImageHelpers' +# +# Generated by: chrispat +# +# Generated on: 11/1/2017 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'ImageHelpers.psm1' + +# Version number of this module. +ModuleVersion = '0.0.1' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'c9334909-16a1-48f1-a94a-c7baf1b961d9' + +# Author of this module +Author = 'chrispat' + +# Company or vendor of this module +CompanyName = 'Unknown' + +# Copyright statement for this module +Copyright = '(c) 2017 chrispat. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Helper functions for creating vsts images' + +# Minimum version of the Windows PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = '*' + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = '*' + +# Variables to export from this module +VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + + diff --git a/images/win/scripts/ImageHelpers/ImageHelpers.psm1 b/images/win/scripts/ImageHelpers/ImageHelpers.psm1 new file mode 100644 index 00000000..12df84e7 --- /dev/null +++ b/images/win/scripts/ImageHelpers/ImageHelpers.psm1 @@ -0,0 +1,19 @@ +[CmdletBinding()] +param() + +. $PSScriptRoot\PathHelpers.ps1 +. $PSScriptRoot\InstallHelpers.ps1 +. $PSScriptRoot\MarkdownHelpers.ps1 + +Export-ModuleMember -Function @( + 'Test-MachinePath' + 'Get-MachinePath' + 'Set-MachinePath' + 'Add-MachinePathItem' + 'Get-SystemVariable' + 'Set-SystemVariable' + 'Install-MSI' + 'Install-EXE' + 'Add-ContentToMarkdown' + 'Add-SoftwareDetailsToMarkdown' +) diff --git a/images/win/scripts/ImageHelpers/InstallHelpers.ps1 b/images/win/scripts/ImageHelpers/InstallHelpers.ps1 new file mode 100644 index 00000000..57eaa1b0 --- /dev/null +++ b/images/win/scripts/ImageHelpers/InstallHelpers.ps1 @@ -0,0 +1,83 @@ +function Install-MSI +{ + Param + ( + [String]$MsiUrl, + [String]$MsiName + ) + + $exitCode = -1 + + try + { + Write-Host "Downloading $MsiName..." + $FilePath = "${env:Temp}\$MsiName" + + Invoke-WebRequest -Uri $MsiUrl -OutFile $FilePath + + $Arguments = ('/i', $FilePath, '/QN', '/norestart' ) + + Write-Host "Starting Install $MsiName..." + $process = Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait -PassThru + $exitCode = $process.ExitCode + + if ($exitCode -eq 0 -or $exitCode -eq 3010) + { + Write-Host -Object 'Installation successful' + return $exitCode + } + else + { + Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." + exit $exitCode + } + } + catch + { + Write-Host -Object "Failed to install the MSI $MsiName" + Write-Host -Object $_.Exception.Message + exit -1 + } +} + + +function Install-EXE +{ + Param + ( + [String]$Url, + [String]$Name, + [String[]]$ArgumentList + ) + + $exitCode = -1 + + try + { + Write-Host "Downloading $Name..." + $FilePath = "${env:Temp}\$Name" + + Invoke-WebRequest -Uri $Url -OutFile $FilePath + + Write-Host "Starting Install $Name..." + $process = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Wait -PassThru + $exitCode = $process.ExitCode + + if ($exitCode -eq 0 -or $exitCode -eq 3010) + { + Write-Host -Object 'Installation successful' + return $exitCode + } + else + { + Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." + return $exitCode + } + } + catch + { + Write-Host -Object "Failed to install the Executable $Name" + Write-Host -Object $_.Exception.Message + return -1 + } +} diff --git a/images/win/scripts/ImageHelpers/MarkdownHelpers.ps1 b/images/win/scripts/ImageHelpers/MarkdownHelpers.ps1 new file mode 100644 index 00000000..3d5f1759 --- /dev/null +++ b/images/win/scripts/ImageHelpers/MarkdownHelpers.ps1 @@ -0,0 +1,25 @@ +function Add-ContentToMarkdown { + [CmdletBinding()] + param( + $Content = "" + ) + + Add-Content 'C:\InstalledSoftware.md' $Content +} + + +function Add-SoftwareDetailsToMarkdown { + [CmdletBinding()] + param( + $SoftwareName = "", + $DescriptionMarkdown = "" + ) + +$Content = @" + +## $SoftwareName + +$DescriptionMarkdown +"@ + Add-ContentToMarkdown -Content $Content +} diff --git a/images/win/scripts/ImageHelpers/PathHelpers.ps1 b/images/win/scripts/ImageHelpers/PathHelpers.ps1 new file mode 100644 index 00000000..0d50cbe3 --- /dev/null +++ b/images/win/scripts/ImageHelpers/PathHelpers.ps1 @@ -0,0 +1,68 @@ +function Test-MachinePath{ + [CmdletBinding()] + param( + [string]$PathItem + ) + + $currentPath = Get-MachinePath + + $pathItems = $currentPath.Split(';') + + if($pathItems.Contains($PathItem)) + { + return $true + } + else + { + return $false + } +} + +function Set-MachinePath{ + [CmdletBinding()] + param( + [string]$NewPath + ) + Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value $NewPath + return $NewPath +} + +function Add-MachinePathItem +{ + [CmdletBinding()] + param( + [string]$PathItem + ) + + $currentPath = Get-MachinePath + $newPath = $PathItem + ';' + $currentPath + return Set-MachinePath -NewPath $newPath +} + +function Get-MachinePath{ + [CmdletBinding()] + param( + + ) + $currentPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path + return $currentPath +} + +function Get-SystemVariable{ + [CmdletBinding()] + param( + [string]$SystemVariable + ) + $currentPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name $SystemVariable).$SystemVariable + return $currentPath +} + +function Set-SystemVariable{ + [CmdletBinding()] + param( + [string]$SystemVariable, + [string]$Value + ) + Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name $SystemVariable -Value $Value + return $Value +} \ No newline at end of file diff --git a/images/win/scripts/ImageHelpers/test/ImageHelpers.Tests.ps1 b/images/win/scripts/ImageHelpers/test/ImageHelpers.Tests.ps1 new file mode 100644 index 00000000..74af9095 --- /dev/null +++ b/images/win/scripts/ImageHelpers/test/ImageHelpers.Tests.ps1 @@ -0,0 +1,13 @@ +$ModuleManifestName = 'ImageHelpers.psd1' +$ModuleManifestPath = "$PSScriptRoot\..\$ModuleManifestName" + + + +Describe 'Module Manifest Tests' { + It 'Passes Test-ModuleManifest' { + Test-ModuleManifest -Path $ModuleManifestPath | Should Not BeNullOrEmpty + $? | Should Be $true + } +} + + diff --git a/images/win/scripts/ImageHelpers/test/PathHelpers.Tests.ps1 b/images/win/scripts/ImageHelpers/test/PathHelpers.Tests.ps1 new file mode 100644 index 00000000..1848fe43 --- /dev/null +++ b/images/win/scripts/ImageHelpers/test/PathHelpers.Tests.ps1 @@ -0,0 +1,34 @@ +. $PSScriptRoot\..\PathHelpers.ps1 + +Describe 'Test-MachinePath Tests' { + Mock Get-MachinePath {return "C:\foo;C:\bar"} + It 'Path contains item' { + Test-MachinePath -PathItem "C:\foo" | Should Be $true + } + It 'Path does not containe item' { + Test-MachinePath -PathItem "C:\baz" | Should Be $false + } +} + +Describe 'Set-MachinePath Tests' { + Mock Get-MachinePath {return "C:\foo;C:\bar"} + Mock Set-ItemProperty {return} + It 'Set-MachinePath should return new path' { + Set-MachinePath -NewPath "C:\baz" | Should Be "C:\baz" + } +} + +Describe "Add-MachinePathItem Tests"{ + Mock Get-MachinePath {return "C:\foo;C:\bar"} + Mock Set-ItemProperty {return} + It 'Add-MachinePathItem should return complete path' { + Add-MachinePathItem -PathItem 'C:\baz' | Should Be 'C:\baz;C:\foo;C:\bar' + } +} + +Describe 'Set-SystemVariable Tests' { + Mock Set-ItemProperty {return} + It 'Set-SystemVariable should return new path' { + Set-SystemVariable -SystemVariable "NewPathVar" -Value "C:\baz" | Should Be "C:\baz" + } +} \ No newline at end of file diff --git a/images/win/scripts/Installers/Download-ToolCache.ps1 b/images/win/scripts/Installers/Download-ToolCache.ps1 new file mode 100644 index 00000000..5f5c3e9e --- /dev/null +++ b/images/win/scripts/Installers/Download-ToolCache.ps1 @@ -0,0 +1,51 @@ +################################################################################ +## File: Download-ToolCache.ps1 +## Desc: Download tool cache +################################################################################ + +Function InstallTool +{ + Param + ( + [System.Object]$ExecutablePath + ) + + Write-Host $ExecutablePath.DirectoryName + Set-Location -Path $ExecutablePath.DirectoryName + Get-Location | Write-Host + if (Test-Path 'tool.zip') + { + Expand-Archive 'tool.zip' -DestinationPath '.' + } + cmd.exe /c 'install_to_tools_cache.bat' +} + +$SourceUrl = "https://vstsagenttools.blob.core.windows.net/tools" + +$Dest = "C:/" + +$Path = "hostedtoolcache/windows" + +$env:Path = "C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy;" + $env:Path + +Write-Host "Started AzCopy from $SourceUrl to $Dest" + +AzCopy /Source:$SourceUrl /Dest:$Dest /S /V /Pattern:$Path + +$ToolsDirectory = $Dest + $Path + +$current = Get-Location +Set-Location -Path $ToolsDirectory + +Get-ChildItem -Recurse -Depth 4 -Filter install_to_tools_cache.bat | ForEach-Object { + #In order to work correctly Python 3.4 x86 must be installed after x64, this is achieved by current toolcache catalog structure + InstallTool($_) +} + +Set-Location -Path $current + +setx AGENT_TOOLSDIRECTORY $ToolsDirectory /M + +#junction point from the previous Python2 directory to the toolcache Python2 +$python2Dir = (Get-Item -Path ($ToolsDirectory + '/Python/2.7*/x64')).FullName +cmd.exe /c mklink /d "C:\Python27amd64" "$python2Dir" diff --git a/images/win/scripts/Installers/Enable-DeveloperMode.ps1 b/images/win/scripts/Installers/Enable-DeveloperMode.ps1 new file mode 100644 index 00000000..796d02d8 --- /dev/null +++ b/images/win/scripts/Installers/Enable-DeveloperMode.ps1 @@ -0,0 +1,13 @@ +################################################################################ +## File: Enable-DeveloperMode.ps1 +## Desc: Enables Developer Mode by toggling registry setting. Developer Mode is required to enable certain tools (e.g. WinAppDriver). +################################################################################ + +# Create AppModelUnlock if it doesn't exist, required for enabling Developer Mode +$RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" +if (-not(Test-Path -Path $RegistryKeyPath)) { + New-Item -Path $RegistryKeyPath -ItemType Directory -Force +} + +# Add registry value to enable Developer Mode +New-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -PropertyType DWORD -Value 1 diff --git a/images/win/scripts/Installers/Finalize-VM.ps1 b/images/win/scripts/Installers/Finalize-VM.ps1 new file mode 100644 index 00000000..d8632568 --- /dev/null +++ b/images/win/scripts/Installers/Finalize-VM.ps1 @@ -0,0 +1,34 @@ +################################################################################ +## File: Finalize-VM.ps1 +## Desc: Clean up folders temp folders after installs to save space +################################################################################ + +Write-Host "Cleanup WinSxS" +Dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase + +$ErrorActionPreference = 'silentlycontinue' + +Write-Host "Clean up various directories" +@( + "C:\\Recovery", + "$env:windir\\logs", + "$env:windir\\winsxs\\manifestcache", + "$env:windir\\Temp", + "$env:windir\\Installer", + "$env:TEMP" +) | ForEach-Object { + if (Test-Path $_) { + Write-Host "Removing $_" + try { + Takeown /d Y /R /f $_ + Icacls $_ /GRANT:r administrators:F /T /c /q 2>&1 | Out-Null + Remove-Item $_ -Recurse -Force | Out-Null + } + catch { $global:error.RemoveAt(0) } + } +} + +$winInstallDir = "$env:windir\\Installer" +New-Item -Path $winInstallDir -ItemType Directory -Force + +$ErrorActionPreference = 'Continue' diff --git a/images/win/scripts/Installers/Install-7zip.ps1 b/images/win/scripts/Installers/Install-7zip.ps1 new file mode 100644 index 00000000..4a073e0a --- /dev/null +++ b/images/win/scripts/Installers/Install-7zip.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-7zip.ps1 +## Desc: Install 7zip +################################################################################ + +choco install 7zip.install -y diff --git a/images/win/scripts/Installers/Install-AzureCli.ps1 b/images/win/scripts/Installers/Install-AzureCli.ps1 new file mode 100644 index 00000000..82f44a64 --- /dev/null +++ b/images/win/scripts/Installers/Install-AzureCli.ps1 @@ -0,0 +1,12 @@ +################################################################################ +## File: Install-AzureCli.ps1 +## Desc: Install Azure CLI +################################################################################ + +choco install azure-cli -y + +$AzureCliExtensionPath = Join-Path $Env:CommonProgramFiles 'AzureCliExtensionDirectory' +New-Item -ItemType "directory" -Path $AzureCliExtensionPath + +[Environment]::SetEnvironmentVariable("AZURE_EXTENSION_DIR", $AzureCliExtensionPath, [System.EnvironmentVariableTarget]::Machine) +$Env:AZURE_EXTENSION_DIR = $AzureCliExtensionPath diff --git a/images/win/scripts/Installers/Install-AzureCosmosDbEmulator.ps1 b/images/win/scripts/Installers/Install-AzureCosmosDbEmulator.ps1 new file mode 100644 index 00000000..9676c069 --- /dev/null +++ b/images/win/scripts/Installers/Install-AzureCosmosDbEmulator.ps1 @@ -0,0 +1,8 @@ +#################################################################################### +## File: Install-AzureCosmosDbEmulator.ps1 +## Desc: Install Azure CosmosDb Emulator +#################################################################################### + +Import-Module -Name ImageHelpers -Force + +Install-MSI -MsiUrl "https://aka.ms/cosmosdb-emulator" -MsiName "AzureCosmosDBEmulator.msi" diff --git a/images/win/scripts/Installers/Install-AzureDevOpsCli.ps1 b/images/win/scripts/Installers/Install-AzureDevOpsCli.ps1 new file mode 100644 index 00000000..b2d4c10b --- /dev/null +++ b/images/win/scripts/Installers/Install-AzureDevOpsCli.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-AzureDevOpsCli.ps1 +## Desc: Install Azure DevOps CLI +################################################################################ + +az extension add -n azure-devops diff --git a/images/win/scripts/Installers/Install-AzureModules.ps1 b/images/win/scripts/Installers/Install-AzureModules.ps1 new file mode 100644 index 00000000..c1f7956a --- /dev/null +++ b/images/win/scripts/Installers/Install-AzureModules.ps1 @@ -0,0 +1,197 @@ +################################################################################ +## File: Install-AzureModules.ps1 +## Desc: Install Azure PowerShell modules +################################################################################ + +Add-Type -AssemblyName System.IO.Compression.FileSystem + +function Download-Zip +{ + [CmdletBinding()] + Param( + [Parameter( + Mandatory = $true + )] + [string] + $BlobUri + ) + + Write-Host "Downloading the zip from blob: '$BlobUri'" + $fileName = "azureps_" + "$(Get-Random)" + ".zip" + $targetLocation = Join-Path $ENV:Temp -ChildPath $fileName + Write-Host "Download target location: '$targetLocation'" + $webClient = New-Object Net.WebClient + $null = $webClient.DownloadFileAsync($BlobUri, $targetLocation) + while ($webClient.IsBusy) { } + Write-Host "Download complete. Target Location: '$targetLocation'" + return $targetLocation +} + +function Extract-Zip +{ + [CmdletBinding()] + Param( + [Parameter( + Mandatory = $true + )] + [string] + $ZipFilePath, + + [Parameter( + Mandatory = $true + )] + [string] + $TargetLocation + ) + + Write-Host "Expanding the Zip File: '$ZipFilePath'. Target: '$TargetLocation'" + $null = [System.IO.Compression.ZipFile]::ExtractToDirectory($ZipFilePath, $TargetLocation) + Write-Host "Extraction completed successfully." +} + +Set-PSRepository -InstallationPolicy Trusted -Name PSGallery + +# We try to detect the whether Azure PowerShell is installed using .msi file. If it is installed, we find it's version, then it needs to be uninstalled manually (because the uninstallation requires the PowerShell session to be closed) +$regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" +$installedApplications = Get-ItemProperty -Path $regKey +$SdkVersion = ($installedApplications | Where-Object { $_.DisplayName -and $_.DisplayName.toLower().Contains("microsoft azure powershell") } | Select-Object -First 1).DisplayVersion + +if($SdkVersion -eq $null) +{ + Write-Host "No .msi Installation Present" +} +else +{ + Write-Host "An Azure PowerShell Installation through installer has been detected. Please close this powershell session and manually uninstall the Azure PowerShell from the Add or Remove Programs in the Control Panel. Then, rerun this script from an Admin PowerShell" + throw "An Azure PowerShell Installation through installer has been detected. Please close this powershell session and manually uninstall the Azure PowerShell from the Add or Remove Programs in the Control Panel. Then, rerun this script from an Admin PowerShell" +} + +# We will try to uninstall any installation of Azure PowerShell + +$modules = Get-Module -Name Azure -ListAvailable +Write-Host "The Azure Modules initially present are:" +$modules | Select-Object Name,Version,Path | Format-Table + +foreach($module in $modules) +{ + # add logging for telling what module we are working on now + if(Test-Path -LiteralPath $module.Path) + { + try + { + Uninstall-Module -Name Azure -RequiredVersion $module.Version.tostring() -Force + } + catch + { + Write-Host "The Uninstallation of Azure Module version: $($module.Version.tostring()) failed with the error: $($_.Exception.Message) . Please Check if there isn't any other PowerShell session open." + throw $_.Exception.Message + } + } +} + +$modules = Get-Module -Name AzureRM -ListAvailable +Write-Host "The AzureRM Modules initially present are:" +$modules | Select-Object Name,Version,Path | Format-Table + +foreach($module in $modules) +{ + # add logging for telling what module we are working on now + if(Test-Path -LiteralPath $module.Path) + { + try + { + Uninstall-Module -Name AzureRM -RequiredVersion $module.Version.tostring() -Force + } + catch + { + Write-Host "The Uninstallation of AzureRM Module version: $($module.Version.tostring()) failed with the error: $($_.Exception.Message) . Please Check if there isn't any other PowerShell session open." + throw $_.Exception.Message + } + } +} + +#after this, the only installations available through a Get-Module cmdlet should be nothing + +$modules = Get-Module -Name Azure -ListAvailable + +foreach($module in $modules) +{ + Write-Host "Module found: $($module.Name) Module Version: $($module.Version)" + if($module.Version.ToString() -ne " ") + { + Write-Host "Another installation of Azure module is detected with version $($module.Version.ToString()) at path: $($module.Path)" + throw "Azure module uninstallation unsuccessful" + } +} + +$modules = Get-Module -Name AzureRM -ListAvailable + +foreach($module in $modules) +{ + write-host "Module found: $($module.Name) Module Version: $($module.Version)" + if($module.Version.ToString() -ne " ") + { + Write-Host "Another installation of AzureRM module is detected with version $($module.Version.ToString()) at path: $($module.Path)" + throw "AzureRM module uninstallation unsuccessful" + } +} + +#### NOW The correct Modules need to be saved in C:\Modules + +if($(Test-Path -LiteralPath "C:\Modules") -eq $true) +{ + Write-Host "C:\Modules directory is already present. Beginning to clear it up completely" + Remove-Item -Path "C:\Modules" -Recurse -Force +} + +mkdir "C:\Modules" + +$directoryListing = Get-ChildItem -Path "C:\Modules" + +if($directoryListing.Length -gt 0) +{ + Write-Host "C:\Modules was not deleted properly. It still has the following contents:" + $directoryListing +} +else { + Write-Host "The Directory is clean. There are no contents present in it" +} + +# Download and unzip the stored AzurePSModules from the vstsagentools public blob +$extractLocation = "C:\Modules" +$azurePsUri = @( + "https://vstsagenttools.blob.core.windows.net/tools/azurepowershellmodules/AzurePSModules.M157.20190808.27979.zip", + "https://vstsagenttools.blob.core.windows.net/tools/azurepowershellmodules/AzureRmPSModules.M157.20190808.27379.zip", + "https://vstsagenttools.blob.core.windows.net/tools/azurepowershellmodules/AzPSModules.M158.20190903.19326.zip" +) + +$azureRMModulePath = "C:\Modules\azurerm_2.1.0" +$azureModulePath = "C:\Modules\azure_2.1.0" +$finalPath = "" +$environmentPSModulePath = [Environment]::GetEnvironmentVariable("PSModulePath", "Machine") +$existingPaths = $environmentPSModulePath -split ';' -replace '\\$','' + +if ($existingPaths -notcontains $azureRMModulePath) { + $finalPath = $azureRMModulePath +} + +if ($existingPaths -notcontains $azureModulePath) { + if($finalPath -ne "") { + $finalPath = $finalPath + ";" + $azureModulePath + } + else { + $finalPath = $azureModulePath + } +} + +if($finalPath -ne "") { + [Environment]::SetEnvironmentVariable("PSModulePath", $finalPath + ";" + $env:PSModulePath, "Machine") +} + +$env:PSModulePath = $env:PSModulePath.TrimStart(';') + +foreach ($uri in $azurePsUri) +{ + $targetFile = Download-Zip -BlobUri $uri + Extract-Zip -ZipFilePath $targetFile -TargetLocation $extractLocation +} diff --git a/images/win/scripts/Installers/Install-Boost.ps1 b/images/win/scripts/Installers/Install-Boost.ps1 new file mode 100644 index 00000000..58be0ab6 --- /dev/null +++ b/images/win/scripts/Installers/Install-Boost.ps1 @@ -0,0 +1,45 @@ +################################################################################ +## File: Install-Boost.ps1 +## Desc: Install boost using tool cache +################################################################################ + +$ToolCache = 'C:\hostedtoolcache\windows\boost' +$BoostDirectory = Join-Path -Path $env:ProgramFiles -ChildPath "Boost" +$BoostVersionsToInstall = $env:BOOST_VERSIONS.split(',') +$BoostDefault = $env:BOOST_DEFAULT + +foreach($BoostVersion in $BoostVersionsToInstall) +{ + $ZipName = Join-Path -Path $ToolCache -ChildPath "boost_${BoostVersion}_msvc-14.1.zip" + + if (-Not (Test-Path $ZipName)) + { + Write-Host "$ZipName not found" + exit 1 + } + + Write-Host "Expanding $ZipName" + + $BoostInstallationDir = Join-Path -Path $BoostDirectory -ChildPath $BoostVersion + # Expand-Archive slower for 70% than 7z + & "$env:ProgramFiles\7-Zip\7z.exe" x $ZipName -o"$BoostDirectory" -y + + $EnvBoostPath = "BOOST_ROOT_{0}" -f ($BoostVersion.Replace('.', '_')) + setx $EnvBoostPath $BoostInstallationDir /M | Out-Null + + if ($BoostVersion -eq $BoostDefault) + { + Write-Host "Adding Boost $BoostVersion to the path..." + # Add the Boost binaries to the path + Add-MachinePathItem $BoostInstallationDir | Out-Null + # Set the BOOSTROOT environment variable + setx BOOST_ROOT $BoostInstallationDir /M | Out-Null + } +} + +# Removing boost cache folder +Write-Host "Removing boost cache folder" +if (Test-Path $ToolCache) +{ + Remove-Item -Path $ToolCache -Force -Recurse +} diff --git a/images/win/scripts/Installers/Install-Chrome.ps1 b/images/win/scripts/Installers/Install-Chrome.ps1 new file mode 100644 index 00000000..32f3bcf1 --- /dev/null +++ b/images/win/scripts/Installers/Install-Chrome.ps1 @@ -0,0 +1,26 @@ +################################################################################ +## File: Install-Chrome.ps1 +## Desc: Install Google Chrome +################################################################################ + +Import-Module -Name ImageHelpers -Force + +$temp_install_dir = 'C:\Windows\Installer' +New-Item -Path $temp_install_dir -ItemType Directory -Force + +Install-MSI -MsiUrl "https://seleniumwebdrivers.blob.core.windows.net/knownchromeversion/googlechromestandaloneenterprise64.msi" -MsiName "googlechromestandaloneenterprise64.msi" + +New-NetFirewallRule -DisplayName "BlockGoogleUpdate" -Direction Outbound -Action Block -Program "C:\Program Files (x86)\Google\Update\GoogleUpdate.exe" + +Stop-Service -Name gupdate -Force +Set-Service -Name gupdate -StartupType "Disabled" +Stop-Service -Name gupdatem -Force +Set-Service -Name gupdatem -StartupType "Disabled" + +New-Item -Path "HKLM:\SOFTWARE\Policies\Google\Update" -Force +New-ItemProperty "HKLM:\SOFTWARE\Policies\Google\Update" -Name "AutoUpdateCheckPeriodMinutes" -Value 00000000 -Force +New-ItemProperty "HKLM:\SOFTWARE\Policies\Google\Update" -Name "UpdateDefault" -Value 00000000 -Force +New-ItemProperty "HKLM:\SOFTWARE\Policies\Google\Update" -Name "DisableAutoUpdateChecksCheckboxValue" -Value 00000001 -Force +New-ItemProperty "HKLM:\SOFTWARE\Policies\Google\Update" -Name "Update{8A69D345-D564-463C-AFF1-A69D9E530F96}" -Value 00000000 -Force +New-Item -Path "HKLM:\SOFTWARE\Policies\Google\Chrome" -Force +New-ItemProperty "HKLM:\SOFTWARE\Policies\Google\Chrome" -Name "DefaultBrowserSettingEnabled" -Value 00000000 -Force diff --git a/images/win/scripts/Installers/Install-CloudFoundryCli.ps1 b/images/win/scripts/Installers/Install-CloudFoundryCli.ps1 new file mode 100644 index 00000000..b8e5bc4c --- /dev/null +++ b/images/win/scripts/Installers/Install-CloudFoundryCli.ps1 @@ -0,0 +1,24 @@ +################################################################################ +## File: Install-CloudFoundryCli.ps1 +## Desc: Install Cloud Foundry CLI +################################################################################ + +Import-Module -Name ImageHelpers + +# Download the latest cf cli exe +Invoke-WebRequest -UseBasicParsing -Uri "https://packages.cloudfoundry.org/stable?release=windows64-exe&source=github" -OutFile cf-cli.zip + +# Create directory for cf cli +$cf_cli_path = "C:\cf-cli" +New-Item -Path $cf_cli_path -ItemType Directory -Force + +# Extract the zip archive +Write-Host "Extracting cf cli..." +Expand-Archive -Path cf-cli.zip -DestinationPath $cf_cli_path -Force + +# Add cf to path +Add-MachinePathItem $cf_cli_path + +# Delete the cfl-cli zip archive +Write-Host "Deleting downloaded archive of cf cli" +Remove-Item cf-cli.zip diff --git a/images/win/scripts/Installers/Install-Cmake.ps1 b/images/win/scripts/Installers/Install-Cmake.ps1 new file mode 100644 index 00000000..c0d2f4b4 --- /dev/null +++ b/images/win/scripts/Installers/Install-Cmake.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-Cmake.ps1 +## Desc: Install Cmake +################################################################################ + +choco install cmake.install -y --installargs 'ADD_CMAKE_TO_PATH=""System""' diff --git a/images/win/scripts/Installers/Install-ContainersFeature.ps1 b/images/win/scripts/Installers/Install-ContainersFeature.ps1 new file mode 100644 index 00000000..0713f606 --- /dev/null +++ b/images/win/scripts/Installers/Install-ContainersFeature.ps1 @@ -0,0 +1,16 @@ +################################################################################ +## File: Install-ContainersFeature.ps1 +## Desc: Install Windows container features. +## Must be an independent step becuase it requires a machine restart +## before we can continue. +################################################################################ + +Write-Host "Install Containers feature" +Install-WindowsFeature -Name Containers + +if ((GWMI Win32_Processor).VirtualizationFirmwareEnabled[0] -and (GWMI Win32_Processor).SecondLevelAddressTranslationExtensions[0]) { + Write-Host "Install Hyper-V feature" + Install-WindowsFeature -Name Hyper-V -IncludeManagementTools +} else { + Write-Host "Skipping installation of Hyper-V feature" +} diff --git a/images/win/scripts/Installers/Install-DACFx.ps1 b/images/win/scripts/Installers/Install-DACFx.ps1 new file mode 100644 index 00000000..d494f12c --- /dev/null +++ b/images/win/scripts/Installers/Install-DACFx.ps1 @@ -0,0 +1,10 @@ +#################################################################################### +## File: Install-DACFx.ps1 +## Desc: Install SQL Server® Data-Tier Application Framework (DACFx) for Windows +#################################################################################### + +Import-Module -Name ImageHelpers -Force + +$exitcode = Install-MSI -MsiUrl "https://download.microsoft.com/download/f/1/9/f19eaee6-0728-4a0b-9755-9808acc8af0b/EN/x64/DacFramework.msi" -MsiName "DacFramework.msi" + +exit $exitcode diff --git a/images/win/scripts/Installers/Install-Docker.ps1 b/images/win/scripts/Installers/Install-Docker.ps1 new file mode 100644 index 00000000..59df7c4a --- /dev/null +++ b/images/win/scripts/Installers/Install-Docker.ps1 @@ -0,0 +1,16 @@ +################################################################################ +## File: Install-Docker.ps1 +## Desc: Install Docker. +## Must be an independent step becuase it requires a restart before we +## can continue. +################################################################################ + +Set-PSRepository -InstallationPolicy Trusted -Name PSGallery +Write-Host "Install-Module DockerProvider" +Install-Module DockerMsftProvider -Force + +Write-Host "Install-Package Docker" +Install-Package -Name docker -ProviderName DockerMsftProvider -Force +Start-Service docker + +choco install docker-compose -y diff --git a/images/win/scripts/Installers/Install-DotnetSDK.ps1 b/images/win/scripts/Installers/Install-DotnetSDK.ps1 new file mode 100644 index 00000000..45169adf --- /dev/null +++ b/images/win/scripts/Installers/Install-DotnetSDK.ps1 @@ -0,0 +1,113 @@ +################################################################################ +## File: Install-DotnetSDK.ps1 +## Desc: Install all released versions of the dotnet sdk and populate package +## cache. Should run after VS and Node +################################################################################ + +# ensure temp +New-Item -Path C:\Temp -Force -ItemType Directory + +[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12" + +$templates = @( + 'console', + 'mstest', + 'web', + 'mvc', + 'webapi' +) + +function InstallSDKVersion ( + $sdkVersion +) +{ + if (!(Test-Path -Path "C:\Program Files\dotnet\sdk\$sdkVersion")) + { + Write-Host "Installing dotnet $sdkVersion" + .\dotnet-install.ps1 -Architecture x64 -Version $sdkVersion -InstallDir $(Join-Path -Path $env:ProgramFiles -ChildPath 'dotnet') + } + else + { + Write-Host "Sdk version $sdkVersion already installed" + } + + # Fix for issue 1276. This will be fixed in 3.1. + Invoke-WebRequest -Uri "https://raw.githubusercontent.com/dotnet/sdk/82bc30c99f1325dfaa7ad450be96857a4fca2845/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.ImportPublishProfile.targets" -outfile "C:\Program Files\dotnet\sdk\$sdkVersion\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.ImportPublishProfile.targets" + + # warm up dotnet for first time experience + $templates | ForEach-Object { + $template = $_ + $projectPath = Join-Path -Path C:\temp -ChildPath $template + New-Item -Path $projectPath -Force -ItemType Directory + Push-Location -Path $projectPath + & $env:ProgramFiles\dotnet\dotnet.exe new globaljson --sdk-version "$sdkVersion" + & $env:ProgramFiles\dotnet\dotnet.exe new $template + Pop-Location + Remove-Item $projectPath -Force -Recurse + } +} + +function InstallAllValidSdks() +{ + Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json' -UseBasicParsing -OutFile 'releases-index.json' + $dotnetChannels = Get-Content -Path 'releases-index.json' | ConvertFrom-Json + + # Consider all channels except preview/eol channels. + # Sort the channels in ascending order + $dotnetChannels = $dotnetChannels.'releases-index' | Where-Object { !$_."support-phase".Equals('preview') -and !$_."support-phase".Equals('eol') } | Sort-Object { [Version] $_."channel-version" } + + # Download installation script. + Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -UseBasicParsing -OutFile 'dotnet-install.ps1' + + ForEach ($dotnetChannel in $dotnetChannels) + { + $channelVersion = $dotnetChannel.'channel-version'; + Invoke-WebRequest -Uri $dotnetChannel.'releases.json' -UseBasicParsing -OutFile "releases-$channelVersion.json" + $currentReleases = Get-Content -Path "releases-$channelVersion.json" | ConvertFrom-Json + # filtering out the preview/rc releases + $currentReleases = $currentReleases.'releases' | Where-Object { !$_.'release-version'.Contains('-') } | Sort-Object { [Version] $_.'release-version' } + ForEach ($release in $currentReleases) + { + if ($release.'sdks'.Count -gt 0) + { + Write-Host 'Found sdks property in release: ' + $release.'release-version' + 'with sdks count: ' + $release.'sdks'.Count + + + # Remove duplicate entries & preview/rc version from download list + # Sort the sdks on version + $sdks = @($release.'sdk'); + $sdks += $release.'sdks' | Where-Object { !$_.'version'.Contains('-') -and !$_.'version'.Equals($release.'sdk'.'version') } + $sdks = $sdks | Sort-Object { [Version] $_.'version' } + + ForEach ($sdk in $sdks) + { + InstallSDKVersion -sdkVersion $sdk.'version' + } + } + elseif (!$release.'sdk'.'version'.Contains('-')) + { + $sdkVersion = $release.'sdk'.'version' + InstallSDKVersion -sdkVersion $sdkVersion + } + } + } +} + +function RunPostInstallationSteps() +{ + Add-MachinePathItem "C:\Program Files\dotnet" + # Run script at startup for all users + $cmdDotNetPath = @" +@echo off +SETX PATH "%USERPROFILE%\.dotnet\tools;%PATH%" +"@ + + $cmdPath = "C:\Program Files\dotnet\userpath.bat" + $cmdDotNetPath | Out-File -Encoding ascii -FilePath $cmdPath + + # Update Run key to run a script at logon + Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "DOTNETUSERPATH" -Value $cmdPath +} + +InstallAllValidSdks +RunPostInstallationSteps diff --git a/images/win/scripts/Installers/Install-Firefox.ps1 b/images/win/scripts/Installers/Install-Firefox.ps1 new file mode 100644 index 00000000..4493beaf --- /dev/null +++ b/images/win/scripts/Installers/Install-Firefox.ps1 @@ -0,0 +1,20 @@ +################################################################################ +## File: Install-Firefox.ps1 +## Desc: Install Mozilla Firefox +################################################################################ + +Import-Module -Name ImageHelpers -Force + +$temp_install_dir = 'C:\Windows\Installer' +New-Item -Path $temp_install_dir -ItemType Directory -Force + +Install-EXE -Url "https://seleniumwebdrivers.blob.core.windows.net/knownfirefoxversion/FirefoxSetup.exe" -Name "FirefoxSetup.exe" -ArgumentList "-ms" + +$path = '{0}\Program Files\Mozilla Firefox\' -f $env:SystemDrive; +New-Item -path $path -Name 'mozilla.cfg' -Value '// +pref("browser.shell.checkDefaultBrowser", false); +pref("app.update.enabled", false);' -ItemType file -force + +$path = '{0}\Program Files\Mozilla Firefox\defaults\pref\' -f $env:SystemDrive; +New-Item -path $path -Name 'local-settings.js' -Value 'pref("general.config.obscure_value", 0); +pref("general.config.filename", "mozilla.cfg");' -ItemType file -force diff --git a/images/win/scripts/Installers/Install-Git.ps1 b/images/win/scripts/Installers/Install-Git.ps1 new file mode 100644 index 00000000..39cc5c6d --- /dev/null +++ b/images/win/scripts/Installers/Install-Git.ps1 @@ -0,0 +1,18 @@ +################################################################################ +## File: Install-Git.ps1 +## Desc: Install Git for Windows +################################################################################ + +Import-Module -Name ImageHelpers + +# Install the latest version of Git which is bundled with Git LFS. +# See https://chocolatey.org/packages/git +choco install git -y --package-parameters="/GitAndUnixToolsOnPath /WindowsTerminal /NoShellIntegration" + +# Disable GCM machine-wide +[Environment]::SetEnvironmentVariable("GCM_INTERACTIVE", "Never", [System.EnvironmentVariableTarget]::Machine) + +Add-MachinePathItem "C:\Program Files\Git\mingw64\bin" +Add-MachinePathItem "C:\Program Files\Git\usr\bin" +Add-MachinePathItem "C:\Program Files\Git\bin" +exit 0 diff --git a/images/win/scripts/Installers/Install-GitVersion.ps1 b/images/win/scripts/Installers/Install-GitVersion.ps1 new file mode 100644 index 00000000..a02e1b8c --- /dev/null +++ b/images/win/scripts/Installers/Install-GitVersion.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-GitVersion.ps1 +## Desc: Install GitVersion +################################################################################ + +choco install gitversion.portable -y diff --git a/images/win/scripts/Installers/Install-Go.ps1 b/images/win/scripts/Installers/Install-Go.ps1 new file mode 100644 index 00000000..63250e34 --- /dev/null +++ b/images/win/scripts/Installers/Install-Go.ps1 @@ -0,0 +1,71 @@ +################################################################################ +## File: Install-Go.ps1 +## Desc: Install Go +################################################################################ + +Import-Module -Name ImageHelpers -Force + +function Install-GoVersion +{ + Param + ( + [String]$goVersion, + [Switch]$addToDefaultPath + ) + + # Download the Go zip archive. + Write-Host "Downloading Go $goVersion..." + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest -UseBasicParsing -Uri "https://dl.google.com/go/go$goVersion.windows-amd64.zip" -OutFile go$goVersion.windows-amd64.zip + + # Extract the zip archive. It contains a single directory named "go". + Write-Host "Extracting Go $goVersion..." + Expand-Archive -Path go$goVersion.windows-amd64.zip -DestinationPath "C:\" -Force + + # Delete unnecessary files to conserve space + Write-Host "Cleaning directories of Go $goVersion..." + if (Test-Path "C:\go\doc") + { + Remove-Item -Recurse -Force "C:\go\doc" + } + if (Test-Path "C:\go\blog") + { + Remove-Item -Recurse -Force "C:\go\blog" + } + + # Rename the extracted "go" directory to include the Go version number (to support side-by-side versions of Go). + $newDirName = "Go$goVersion" + Rename-Item -path "C:\go" -newName $newDirName + + # Delete the Go zip archive. + Write-Host "Deleting downloaded archive of Go $goVersion..." + Remove-Item go$goVersion.windows-a`md64.zip + + # Make this the default version of Go? + if ($addToDefaultPath) + { + Write-Host "Adding Go $goVersion to the path..." + # Add the Go binaries to the path. + Add-MachinePathItem "C:\$newDirName\bin" | Out-Null + # Set the GOROOT environment variable. + setx GOROOT "C:\$newDirName" /M | Out-Null + } + + # Done + Write-Host "Done installing Go $goVersion." + return "C:\$newDirName" +} + +# Install Go +$goVersionsToInstall = $env:GO_VERSIONS.split(",") + +foreach($go in $goVersionsToInstall) { + Write-Host "Installing Go ${go}" + if($go -eq $env:GO_DEFAULT) { + $installDirectory = Install-GoVersion -goVersion $go -addToDefaultPath + } else { + $installDirectory = Install-GoVersion -goVersion $go + } + $envName = "GOROOT_{0}_{1}_X64" -f $go.split(".") + setx $envName "$installDirectory" /M +} diff --git a/images/win/scripts/Installers/Install-InnoSetup.ps1 b/images/win/scripts/Installers/Install-InnoSetup.ps1 new file mode 100644 index 00000000..35f0156f --- /dev/null +++ b/images/win/scripts/Installers/Install-InnoSetup.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-InnoSetup.ps1 +## Desc: Install Inno Setup +################################################################################ + +choco install innosetup -y diff --git a/images/win/scripts/Installers/Install-JavaTools.ps1 b/images/win/scripts/Installers/Install-JavaTools.ps1 new file mode 100644 index 00000000..d86f42c7 --- /dev/null +++ b/images/win/scripts/Installers/Install-JavaTools.ps1 @@ -0,0 +1,98 @@ +################################################################################ +## File: Install-JavaTools.ps1 +## Desc: Install various JDKs and java tools +################################################################################ + +# Download the Azul Systems Zulu JDKs +# See https://www.azul.com/downloads/azure-only/zulu/ +$azulJDK7Uri = 'https://repos.azul.com/azure-only/zulu/packages/zulu-7/7u232/zulu-7-azure-jdk_7.31.0.5-7.0.232-win_x64.zip' +$azulJDK8Uri = 'https://repos.azul.com/azure-only/zulu/packages/zulu-8/8u222/zulu-8-azure-jdk_8.40.0.25-8.0.222-win_x64.zip' +$azulJDK11Uri = 'https://repos.azul.com/azure-only/zulu/packages/zulu-11/11.0.4/zulu-11-azure-jdk_11.33.15-11.0.4-win_x64.zip' + +cd $env:TEMP + +Invoke-WebRequest -UseBasicParsing -Uri $azulJDK7Uri -OutFile azulJDK7.zip +Invoke-WebRequest -UseBasicParsing -Uri $azulJDK8Uri -OutFile azulJDK8.zip +Invoke-WebRequest -UseBasicParsing -Uri $azulJDK11Uri -OutFile azulJDK11.zip + +# Expand the zips +Expand-Archive -Path azulJDK7.zip -DestinationPath "C:\Program Files\Java\" -Force +Expand-Archive -Path azulJDK8.zip -DestinationPath "C:\Program Files\Java\" -Force +Expand-Archive -Path azulJDK11.zip -DestinationPath "C:\Program Files\Java\" -Force + +# Deleting zip folders +Remove-Item -Recurse -Force azulJDK7.zip +Remove-Item -Recurse -Force azulJDK8.zip +Remove-Item -Recurse -Force azulJDK11.zip + +Import-Module -Name ImageHelpers -Force + +$currentPath = Get-MachinePath + +$pathSegments = $currentPath.Split(';') +$newPathSegments = @() + +foreach ($pathSegment in $pathSegments) +{ + if($pathSegment -notlike '*java*') + { + $newPathSegments += $pathSegment + } +} + +$java7Installs = Get-ChildItem -Path 'C:\Program Files\Java' -Filter '*azure-jdk*7*' | Sort-Object -Property Name -Descending | Select-Object -First 1 +$latestJava7Install = $java7Installs.FullName; + +$java8Installs = Get-ChildItem -Path 'C:\Program Files\Java' -Filter '*azure-jdk*8*' | Sort-Object -Property Name -Descending | Select-Object -First 1 +$latestJava8Install = $java8Installs.FullName; + +$java11Installs = Get-ChildItem -Path 'C:\Program Files\Java' -Filter '*azure-jdk*11*' | Sort-Object -Property Name -Descending | Select-Object -First 1 +$latestJava11Install = $java11Installs.FullName; + +$newPath = [string]::Join(';', $newPathSegments) +$newPath = $latestJava8Install + '\bin;' + $newPath + +Set-MachinePath -NewPath $newPath + +setx JAVA_HOME $latestJava8Install /M +setx JAVA_HOME_7_X64 $latestJava7Install /M +setx JAVA_HOME_8_X64 $latestJava8Install /M +setx JAVA_HOME_11_X64 $latestJava11Install /M + +# Install Java tools +# Force chocolatey to ignore dependencies on Ant and Maven or else they will download the Oracle JDK +choco install ant -y -i +choco install maven -y -i --version=3.6.2 +choco install gradle -y + +# Move maven variables to Machine. They may not be in the environment for this script so we need to read them from the registry. +$userSid = (Get-WmiObject win32_useraccount -Filter "name = '$env:USERNAME' AND domain = '$env:USERDOMAIN'").SID +$userEnvironmentKey = 'Registry::HKEY_USERS\' + $userSid + '\Environment' + +$m2_home = (Get-ItemProperty -Path $userEnvironmentKey -Name M2_HOME).M2_HOME +$m2 = $m2_home + '\bin' +$maven_opts = '-Xms256m' + +$m2_repo = 'C:\ProgramData\m2' +New-Item -Path $m2_repo -ItemType Directory -Force + +setx M2 $m2 /M +setx M2_HOME $m2_home /M +setx M2_REPO $m2_repo /M +setx MAVEN_OPTS $maven_opts /M + +# Download cobertura jars +$uri = 'https://ayera.dl.sourceforge.net/project/cobertura/cobertura/2.1.1/cobertura-2.1.1-bin.zip' +$coberturaPath = "C:\cobertura-2.1.1" + +cd $env:TEMP + +Invoke-WebRequest -UseBasicParsing -Uri $uri -OutFile cobertura.zip + +# Expand the zip +Expand-Archive -Path cobertura.zip -DestinationPath "C:\" -Force + +# Deleting zip folder +Remove-Item -Recurse -Force cobertura.zip + +setx COBERTURA_HOME $coberturaPath /M diff --git a/images/win/scripts/Installers/Install-Jq.ps1 b/images/win/scripts/Installers/Install-Jq.ps1 new file mode 100644 index 00000000..5a0af2e3 --- /dev/null +++ b/images/win/scripts/Installers/Install-Jq.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-Jq.ps1 +## Desc: Install jq +################################################################################ + +choco install jq -y diff --git a/images/win/scripts/Installers/Install-Kind.ps1 b/images/win/scripts/Installers/Install-Kind.ps1 new file mode 100644 index 00000000..794a6d9a --- /dev/null +++ b/images/win/scripts/Installers/Install-Kind.ps1 @@ -0,0 +1,40 @@ +################################################################################ +## File: Install-Kind.ps1 +## Desc: Install Kind +################################################################################ + +$stableKindTag = "v0.5.1" +$tagToUse = $stableKindTag; +$destFilePath = "C:\ProgramData\kind" +$outFilePath = "C:\ProgramData\kind\kind.exe" + +try +{ + $getkindUri = "https://github.com/kubernetes-sigs/kind/releases/download/$tagToUse/kind-windows-amd64" + Write-Host "Downloading kind.exe..." + New-Item -Path $destFilePath -ItemType Directory -Force + + Invoke-WebRequest -Uri $getkindUri -OutFile $outFilePath + + Write-Host "Starting Install kind.exe..." + $process = Start-Process -FilePath $outFilePath -Wait -PassThru + $exitCode = $process.ExitCode + + if ($exitCode -eq 0 -or $exitCode -eq 3010) + { + Write-Host -Object 'Installation successful' + Add-MachinePathItem $destFilePath + exit $exitCode + } + else + { + Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." + exit $exitCode + } +} +catch +{ + Write-Host -Object "Failed to install the Executable kind.exe" + Write-Host -Object $_.Exception.Message + exit -1 +} diff --git a/images/win/scripts/Installers/Install-KubernetesCli.ps1 b/images/win/scripts/Installers/Install-KubernetesCli.ps1 new file mode 100644 index 00000000..d96c7d79 --- /dev/null +++ b/images/win/scripts/Installers/Install-KubernetesCli.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-KubernetesCli.ps1 +## Desc: Install KubernetesCli +################################################################################ + +choco install kubernetes-cli -y diff --git a/images/win/scripts/Installers/Install-Mercurial.ps1 b/images/win/scripts/Installers/Install-Mercurial.ps1 new file mode 100644 index 00000000..9f21d97a --- /dev/null +++ b/images/win/scripts/Installers/Install-Mercurial.ps1 @@ -0,0 +1,10 @@ +################################################################################ +## File: Install-Mercurial.ps1 +## Desc: Install Mercurial +################################################################################ + +choco install hg -y --version 5.0.0 + +$hgPath = "${env:ProgramFiles}\Mercurial\" +Add-MachinePathItem $hgPath +$env:Path = Get-MachinePath diff --git a/images/win/scripts/Installers/Install-MinGW.ps1 b/images/win/scripts/Installers/Install-MinGW.ps1 new file mode 100644 index 00000000..5e73d059 --- /dev/null +++ b/images/win/scripts/Installers/Install-MinGW.ps1 @@ -0,0 +1,13 @@ +################################################################################ +## File: Install-MinGW.ps1 +## Desc: Install GNU tools for Windows to C:\tools\mingw64 +################################################################################ + +Import-Module -Name ImageHelpers -Force + +choco install -y mingw + +# Make a copy of mingw32-make.exe to make.exe, which is a more discoverable name +# and so the same command line can be used on Windows as on macOS and Linux +$path = where.exe mingw32-make.exe | Get-Item +Copy-Item -Path $path -Destination (Join-Path $path.Directory 'make.exe') diff --git a/images/win/scripts/Installers/Install-Miniconda.ps1 b/images/win/scripts/Installers/Install-Miniconda.ps1 new file mode 100644 index 00000000..14c5df76 --- /dev/null +++ b/images/win/scripts/Installers/Install-Miniconda.ps1 @@ -0,0 +1,16 @@ +################################################################################ +## File: Install-Miniconda.ps1 +## Desc: Install the latest version of Miniconda and set $env:CONDA +################################################################################ + +Import-Module -Name ImageHelpers -Force + +# Lock to Miniconda 4.6 until we do the work to run `conda init` for the vsts user +# Then we can go back to installing the latest Miniconda +# $url = "https://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe" +$url = "https://repo.continuum.io/miniconda/Miniconda3-4.6.14-Windows-x86_64.exe" +$name = $Url.Split('/')[-1] +$destination = "C:\Miniconda" + +Install-EXE -Url $url -Name $name -ArgumentList "/S /AddToPath=0 /RegisterPython=0 /D=$destination" +Set-SystemVariable -SystemVariable "CONDA" -Value $destination diff --git a/images/win/scripts/Installers/Install-MysqlCli.ps1 b/images/win/scripts/Installers/Install-MysqlCli.ps1 new file mode 100644 index 00000000..e3507581 --- /dev/null +++ b/images/win/scripts/Installers/Install-MysqlCli.ps1 @@ -0,0 +1,39 @@ +################################################################################ +## File: Install-MysqlCli.ps1 +## Desc: Install Mysql CLI +################################################################################ + + +## Downloading mysql jar +$uri = 'https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.21-winx64.zip' +$mysqlPath = 'C:\mysql-5.7.21-winx64\bin' + +# Installing visual c++ redistibutable package. +$InstallerURI = 'https://download.microsoft.com/download/0/5/6/056dcda9-d667-4e27-8001-8a0c6971d6b1/vcredist_x64.exe' +$InstallerName = 'vcredist_x64.exe' +$ArgumentList = ('/install', '/quiet', '/norestart' ) + +$exitCode = Install-EXE -Url $InstallerURI -Name $InstallerName -ArgumentList $ArgumentList +if ($exitCode -eq 0 -or $exitCode -eq 3010) +{ + # MySQL disabled TLS 1.0 support on or about Jul-14-2018. Need to make sure TLS 1.2 is enabled. + [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12" + + # Get the latest mysql command line tools . + Invoke-WebRequest -UseBasicParsing -Uri $uri -OutFile mysql.zip + + # Expand the zip + Expand-Archive -Path mysql.zip -DestinationPath "C:\" -Force + + # Deleting zip folder + Remove-Item -Recurse -Force mysql.zip + + # Adding mysql in system environment path + Add-MachinePathItem $mysqlPath + + return 0; +} +else +{ + return $exitCode; +} diff --git a/images/win/scripts/Installers/Install-NET48.ps1 b/images/win/scripts/Installers/Install-NET48.ps1 new file mode 100644 index 00000000..8a21e85d --- /dev/null +++ b/images/win/scripts/Installers/Install-NET48.ps1 @@ -0,0 +1,13 @@ +################################################################################ +## File: Install-NET48.ps1 +## Desc: Install .NET 4.8 +################################################################################ + +Import-Module -Name ImageHelpers -Force + +# .NET 4.8 Dev pack +$InstallerURI = "https://download.visualstudio.microsoft.com/download/pr/7afca223-55d2-470a-8edc-6a1739ae3252/c8c829444416e811be84c5765ede6148/NDP48-DevPack-ENU.exe" +$InstallerName = "NDP48-DevPack-ENU.exe" +$ArgumentList = ('Setup', '/passive', '/norestart' ) + +Install-EXE -Url $InstallerURI -Name $InstallerName -ArgumentList $ArgumentList diff --git a/images/win/scripts/Installers/Install-NSIS.ps1 b/images/win/scripts/Installers/Install-NSIS.ps1 new file mode 100644 index 00000000..6da7cb73 --- /dev/null +++ b/images/win/scripts/Installers/Install-NSIS.ps1 @@ -0,0 +1,10 @@ +################################################################################ +## File: Install-NSIS.ps1 +## Desc: Install NSIS +################################################################################ + +choco install nsis -y + +$NsisPath = "${env:ProgramFiles(x86)}\NSIS\" +Add-MachinePathItem $NsisPath +$env:Path = Get-MachinePath diff --git a/images/win/scripts/Installers/Install-NodeLts.ps1 b/images/win/scripts/Installers/Install-NodeLts.ps1 new file mode 100644 index 00000000..9318b73b --- /dev/null +++ b/images/win/scripts/Installers/Install-NodeLts.ps1 @@ -0,0 +1,34 @@ +################################################################################ +## File: Install-NodeLts.ps1 +## Desc: Install nodejs-lts and other common node tools. +## Must run after python is configured +################################################################################ + +Import-Module -Name ImageHelpers -Force + +$PrefixPath = 'C:\npm\prefix' +$CachePath = 'C:\npm\cache' + +New-Item -Path $PrefixPath -Force -ItemType Directory +New-Item -Path $CachePath -Force -ItemType Directory + +choco install nodejs-lts -y --force + +Add-MachinePathItem $PrefixPath +$env:Path = Get-MachinePath + +setx NPM_CONFIG_PREFIX $PrefixPath /M +$env:NPM_CONFIG_PREFIX = $PrefixPath + +setx NPM_CONFIG_CACHE $CachePath /M +$env:NPM_CONFIG_CACHE = $CachePath + +npm config set registry http://registry.npmjs.org/ + +npm install -g bower +npm install -g cordova +npm install -g grunt-cli +npm install -g gulp-cli +npm install -g parcel-bundler +npm install -g --save-dev webpack webpack-cli +npm install -g yarn diff --git a/images/win/scripts/Installers/Install-OpenSSL.ps1 b/images/win/scripts/Installers/Install-OpenSSL.ps1 new file mode 100644 index 00000000..43cb28f9 --- /dev/null +++ b/images/win/scripts/Installers/Install-OpenSSL.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-OpenSSL.ps1 +## Desc: Install OpenSSL +################################################################################ + +choco install openssl.light -y diff --git a/images/win/scripts/Installers/Install-PHP.ps1 b/images/win/scripts/Installers/Install-PHP.ps1 new file mode 100644 index 00000000..6221b022 --- /dev/null +++ b/images/win/scripts/Installers/Install-PHP.ps1 @@ -0,0 +1,20 @@ +################################################################################ +## File: Install-PHP.ps1 +## Desc: Install PHP +################################################################################ +$ErrorActionPreference = "Stop" + +Import-Module -Name ImageHelpers + +# Install latest PHP in chocolatey +$installDir = "c:\tools\php" +choco install php -y --force --params "/InstallDir:$installDir" + +# update path to extensions and enable curl and mbstring extensions +((Get-Content -path $installDir\php.ini -Raw) -replace ';extension=curl','extension=curl' -replace ';extension=mbstring','extension=mbstring' -replace ';extension_dir = "ext"','extension_dir = "ext"') | Set-Content -Path $installDir\php.ini + +# Set the PHPROOT environment variable. +setx PHPROOT $installDir /M + +# Done +exit 0 diff --git a/images/win/scripts/Installers/Install-Perl.ps1 b/images/win/scripts/Installers/Install-Perl.ps1 new file mode 100644 index 00000000..86f2d290 --- /dev/null +++ b/images/win/scripts/Installers/Install-Perl.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-Perl.ps1 +## Desc: Install Perl +################################################################################ + +choco install strawberryperl -y diff --git a/images/win/scripts/Installers/Install-PowershellCore.ps1 b/images/win/scripts/Installers/Install-PowershellCore.ps1 new file mode 100644 index 00000000..1fc75708 --- /dev/null +++ b/images/win/scripts/Installers/Install-PowershellCore.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-PowershellCore.ps1 +## Desc: Install PowerShell Core +################################################################################ + +Invoke-Expression "& { $(Invoke-RestMethod https://aka.ms/install-powershell.ps1) } -UseMSI -Quiet" diff --git a/images/win/scripts/Installers/Install-Ruby.ps1 b/images/win/scripts/Installers/Install-Ruby.ps1 new file mode 100644 index 00000000..184d92af --- /dev/null +++ b/images/win/scripts/Installers/Install-Ruby.ps1 @@ -0,0 +1,20 @@ +################################################################################ +## File: Install-Ruby.ps1 +## Desc: Install Ruby for Windows +################################################################################ + +Import-Module -Name ImageHelpers + +# Ruby versions are already available in the tool cache. + +# Tool cache Ruby Path +$toolcacheRubyPath = 'C:\hostedtoolcache\windows\Ruby\2.5.*' + +# Get Latest Ruby 2.5.x +$latestRubyBinPath2_5 = Get-ChildItem -Path $toolcacheRubyPath | Sort-Object {[System.Version]$_.Name} | Select-Object -Last 1 | ForEach-Object { + Join-Path $_.FullName 'x64\bin' +} + +Add-MachinePathItem $latestRubyBinPath2_5 +$env:Path = Get-MachinePath +exit 0 diff --git a/images/win/scripts/Installers/Install-Rust.ps1 b/images/win/scripts/Installers/Install-Rust.ps1 new file mode 100644 index 00000000..fd58801d --- /dev/null +++ b/images/win/scripts/Installers/Install-Rust.ps1 @@ -0,0 +1,53 @@ +################################################################################ +## File: Install-Rust.ps1 +## Desc: Install Rust for Windows +################################################################################ + +Import-Module -Name ImageHelpers + +# Rust Env +$env:RUSTUP_HOME="C:\Rust\.rustup" +$env:CARGO_HOME="C:\Rust\.cargo" + +# Download the latest rustup-init.exe for Windows x64 +# See https://rustup.rs/# +Invoke-WebRequest -UseBasicParsing -Uri "https://win.rustup.rs/x86_64" -OutFile rustup-init.exe + +# Install Rust by running rustup-init.exe (disabling the confirmation prompt with -y) +.\rustup-init.exe -y + +# Delete rustup-init.exe when it's no longer needed +Remove-Item -Path .\rustup-init.exe + +# Add Rust binaries to the path +Add-MachinePathItem "$env:CARGO_HOME\bin" +$env:Path = Get-MachinePath + +# Install common tools +rustup component add rustfmt +rustup component add clippy +cargo install bindgen +cargo install cbindgen + +# Run script at startup for all users +$cmdRustSymScript = @" +@echo off + +if exist $env:CARGO_HOME ( + if not exist %USERPROFILE%\.cargo ( + mklink /J %USERPROFILE%\.cargo $env:CARGO_HOME + ) +) + +if exist $env:RUSTUP_HOME ( + if not exist %USERPROFILE%\.rustup ( + mklink /J %USERPROFILE%\.rustup $env:RUSTUP_HOME + ) +) +"@ + +$cmdPath = "C:\Rust\rustsym.bat" +$cmdRustSymScript | Out-File -Encoding ascii -FilePath $cmdPath + +# Update Run key to run a script at logon +Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "RUSTSYM" -Value $cmdPath diff --git a/images/win/scripts/Installers/Install-SQLPowerShellTools.ps1 b/images/win/scripts/Installers/Install-SQLPowerShellTools.ps1 new file mode 100644 index 00000000..470ee5ee --- /dev/null +++ b/images/win/scripts/Installers/Install-SQLPowerShellTools.ps1 @@ -0,0 +1,61 @@ +################################################################################ +## File: Install-SQLPowerShellTools.ps1 +## Desc: Install SQL PowerShell tool +################################################################################ + +Import-Module -Name ImageHelpers -Force + +Function InstallMSI +{ + Param + ( + [String]$MsiUrl, + [String]$MsiName + ) + + $exitCode = -1 + + try + { + Write-Host "Downloading $MsiName..." + $FilePath = "${env:Temp}\$MsiName" + + Invoke-WebRequest -Uri $MsiUrl -OutFile $FilePath + + $Arguments = ('/i', $FilePath, '/QN', '/norestart' ) + + Write-Host "Starting Install $MsiName..." + $process = Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait -PassThru + $exitCode = $process.ExitCode + + if ($exitCode -eq 0 -or $exitCode -eq 3010) + { + Write-Host -Object 'Installation successful' + return $exitCode + } + else + { + Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." + exit $exitCode + } + } + catch + { + Write-Host -Object "Failed to install the MSI $MsiName" + Write-Host -Object $_.Exception.Message + exit -1 + } +} + +# install required MSIs +$SQLSysClrTypesExitCode = InstallMSI -MsiUrl "https://download.microsoft.com/download/8/7/2/872BCECA-C849-4B40-8EBE-21D48CDF1456/ENU/x64/SQLSysClrTypes.msi" -MsiName "SQLSysClrTypes.msi" + +$SharedManagementObjectsExitCode = InstallMSI -MsiUrl "https://download.microsoft.com/download/8/7/2/872BCECA-C849-4B40-8EBE-21D48CDF1456/ENU/x64/SharedManagementObjects.msi" -MsiName "SharedManagementObjects.msi" + +$PowerShellToolsExitCode = InstallMSI -MsiUrl "https://download.microsoft.com/download/8/7/2/872BCECA-C849-4B40-8EBE-21D48CDF1456/ENU/x64/PowerShellTools.msi" -MsiName "PowerShellTools.msi" + +# install sqlserver PS module +Set-PSRepository -Name PSGallery -InstallationPolicy Trusted +Install-Module -Name SqlServer -AllowClobber + +exit $PowerShellToolsExitCode diff --git a/images/win/scripts/Installers/Install-Sbt.ps1 b/images/win/scripts/Installers/Install-Sbt.ps1 new file mode 100644 index 00000000..f87cf90a --- /dev/null +++ b/images/win/scripts/Installers/Install-Sbt.ps1 @@ -0,0 +1,21 @@ +################################################################################ +## File: Install-Sbt.ps1 +## Team: CI-X +## Desc: Install sbt for Windows +################################################################################ +$ErrorActionPreference = "Stop" + +Import-Module -Name ImageHelpers + +# Install the latest version of sbt. +# See https://chocolatey.org/packages/sbt +choco install sbt -y + +$env:SBT_HOME="${env:ProgramFiles(x86)}\sbt" + +# Add sbt binaries to the path +Add-MachinePathItem "$env:SBT_HOME\bin" +$env:Path = Get-MachinePath + +# Done +exit 0 diff --git a/images/win/scripts/Installers/Install-SeleniumWebDrivers.ps1 b/images/win/scripts/Installers/Install-SeleniumWebDrivers.ps1 new file mode 100644 index 00000000..77f71764 --- /dev/null +++ b/images/win/scripts/Installers/Install-SeleniumWebDrivers.ps1 @@ -0,0 +1,17 @@ +################################################################################ +## File: Install-SeleniumWebDrivers.ps1 +## Desc: Install Selenium Web Drivers +################################################################################ + +Invoke-WebRequest -UseBasicParsing -Uri "https://seleniumwebdrivers.blob.core.windows.net/seleniumwebdrivers/SeleniumWebDrivers.zip" -OutFile SeleniumWebDrivers.zip + +Expand-Archive -Path SeleniumWebDrivers.zip -DestinationPath "C:\" -Force + +Remove-Item SeleniumWebDrivers.zip + +setx IEWebDriver "C:\SeleniumWebDrivers\IEDriver" /M +setx GeckoWebDriver "C:\SeleniumWebDrivers\GeckoDriver" /M +setx ChromeWebDriver "C:\SeleniumWebDrivers\ChromeDriver" /M + +exit 0 + diff --git a/images/win/scripts/Installers/Install-ServiceFabricSDK.ps1 b/images/win/scripts/Installers/Install-ServiceFabricSDK.ps1 new file mode 100644 index 00000000..d13b4395 --- /dev/null +++ b/images/win/scripts/Installers/Install-ServiceFabricSDK.ps1 @@ -0,0 +1,13 @@ +################################################################################ +## File: Install-ServiceFabricSDK.ps1 +## Desc: Install webpicmd and then the service fabric sdk +## must be install after Visual Studio +################################################################################ + +#Creating 'Installer' cache folder if it doesn't exist +$temp_install_dir = 'C:\Windows\Installer' +New-Item -Path $temp_install_dir -ItemType Directory -Force + +Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force + +WebpiCmd.exe /Install /Products:MicrosoftAzure-ServiceFabric-CoreSDK /AcceptEula diff --git a/images/win/scripts/Installers/Install-Svn.ps1 b/images/win/scripts/Installers/Install-Svn.ps1 new file mode 100644 index 00000000..107213e4 --- /dev/null +++ b/images/win/scripts/Installers/Install-Svn.ps1 @@ -0,0 +1,6 @@ +################################################################################ +## File: Install-Svn.ps1 +## Desc: Install Subversion +################################################################################ + +choco install svn -y diff --git a/images/win/scripts/Installers/Install-TypeScript.ps1 b/images/win/scripts/Installers/Install-TypeScript.ps1 new file mode 100644 index 00000000..3bf4480a --- /dev/null +++ b/images/win/scripts/Installers/Install-TypeScript.ps1 @@ -0,0 +1,7 @@ +################################################################################ +## File: Install-TypeScript.ps1 +## Team: CI Build +## Desc: Install Latest TypeScript +################################################################################ + +npm install -g typescript diff --git a/images/win/scripts/Installers/Install-Vcpkg.ps1 b/images/win/scripts/Installers/Install-Vcpkg.ps1 new file mode 100644 index 00000000..373f066a --- /dev/null +++ b/images/win/scripts/Installers/Install-Vcpkg.ps1 @@ -0,0 +1,21 @@ +################################################################################ +## File: Install-Vcpkg.ps1 +## Desc: Install vcpkg +################################################################################ + +Import-Module -Name ImageHelpers -Force + +$Uri = 'https://github.com/Microsoft/vcpkg.git' +$InstallDir = 'C:\vcpkg' +$VcpkgExecPath = 'vcpkg.exe' + +git clone --depth=1 $Uri $InstallDir -q + +# Build and integrate vcpkg +Invoke-Expression "$InstallDir\bootstrap-vcpkg.bat" +Invoke-Expression "$InstallDir\$VcpkgExecPath integrate install" + +# Add vcpkg to system environment +Add-MachinePathItem $InstallDir +$env:Path = Get-MachinePath +setx VCPKG_INSTALLATION_ROOT $InstallDir /M diff --git a/images/win/scripts/Installers/Install-WinAppDriver.ps1 b/images/win/scripts/Installers/Install-WinAppDriver.ps1 new file mode 100644 index 00000000..98358507 --- /dev/null +++ b/images/win/scripts/Installers/Install-WinAppDriver.ps1 @@ -0,0 +1,8 @@ +#################################################################################### +## File: Install-WinAppDriver.ps1 +## Desc: Install Windows Application Driver (WinAppDriver) +#################################################################################### + +Import-Module -Name ImageHelpers -Force +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +Install-MSI -MsiUrl "https://github.com/Microsoft/WinAppDriver/releases/download/v1.1/WindowsApplicationDriver.msi" -MsiName "WindowsApplicationDriver.msi" diff --git a/images/win/scripts/Installers/Install-WindowsUpdates.ps1 b/images/win/scripts/Installers/Install-WindowsUpdates.ps1 new file mode 100644 index 00000000..29d8a5f4 --- /dev/null +++ b/images/win/scripts/Installers/Install-WindowsUpdates.ps1 @@ -0,0 +1,10 @@ +################################################################################ +## File: Install-WindowsUpdates.ps1 +## Desc: Install Windows Updates. +## Should be run at end just before Antivirus. +################################################################################ + +Write-Host "Run windows updates" +Install-Module -Name PSWindowsUpdate -Force -AllowClobber +Get-WUInstall -WindowsUpdate -AcceptAll -UpdateType Software -IgnoreReboot +Get-WUInstall -MicrosoftUpdate -AcceptAll -IgnoreUserInput -IgnoreReboot diff --git a/images/win/scripts/Installers/Update-AndroidSDK.ps1 b/images/win/scripts/Installers/Update-AndroidSDK.ps1 new file mode 100644 index 00000000..b617cb37 --- /dev/null +++ b/images/win/scripts/Installers/Update-AndroidSDK.ps1 @@ -0,0 +1,156 @@ +################################################################################ +## File: Update-AndroidSDK.ps1 +## Desc: Install and update Android SDK and tools +################################################################################ + +# Download the latest command line tools so that we can accept all of the licenses. +# See https://developer.android.com/studio/#command-tools +Invoke-WebRequest -UseBasicParsing -Uri "https://dl.google.com/android/repository/sdk-tools-windows-4333796.zip" -OutFile android-sdk-tools.zip + +# Don't replace the one that VS installs as it seems to break things. +Expand-Archive -Path android-sdk-tools.zip -DestinationPath android-sdk -Force + +$sdk = Get-Item -Path .\android-sdk + +# Install the standard Android SDK licenses. In the past, there wasn't a better way to do this, +# so we are base64-encoding a zip of the licenses directory from another installation. +# To create this base64 string, create a zip file that contains nothing but a 'licenses' folder, +# which folder contains the accepted license files found in 'C:\Program Files (x86)\Android\android-sdk\licenses'. +# Then, run this in PowerShell: +# $LicensesZipFileName = 'C:\Program Files (x86)\Android\android-sdk\Licenses.zip' +# $base64Content = [Convert]::ToBase64String([IO.File]::ReadAllBytes($LicensesZipFileName)) +# echo $base64Content +# +# Future: see if the base64 technique can be avoided by running this PowerShell script to accept all licenses. +# This fails when run on a live agent, likely because non-interactive mode is set. +# It may work fine during image generation (this script). +# for($i=0; $i -lt 100; $i++) { $response += "y`n"}; $response | .\sdkmanager.bat --licenses +$base64Content = "UEsDBBQAAAAAAKJeN06amkPzKgAAACoAAAAhAAAAbGljZW5zZXMvYW5kcm9pZC1nb29nbGV0di1saWNlbnNlDQpmYzk0NmU4ZjIzMWYzZTMxNTliZjBiN2M2NTVjOTI0Y2IyZTM4MzMwUEsDBBQAAAAIAKBrN05E+YSqQwAAAFQAAAAcAAAAbGljZW5zZXMvYW5kcm9pZC1zZGstbGljZW5zZQXByREAIQgEwP9WmYsjhxgOKJN/CNs9vmdOQ2zdRw2dxQnWjqQ/3oIgXQM9vqUiwkiX8ljWea4ZlCF3xTo1pz6w+wdQSwMEFAAAAAAAxV43TpECY7AqAAAAKgAAACQAAABsaWNlbnNlcy9hbmRyb2lkLXNkay1wcmV2aWV3LWxpY2Vuc2UNCjUwNDY2N2Y0YzBkZTdhZjFhMDZkZTlmNGIxNzI3Yjg0MzUxZjI5MTBQSwMEFAAAAAAAzF43TpOr0CgqAAAAKgAAABsAAABsaWNlbnNlcy9nb29nbGUtZ2RrLWxpY2Vuc2UNCjMzYjZhMmI2NDYwN2YxMWI3NTlmMzIwZWY5ZGZmNGFlNWM0N2Q5N2FQSwMEFAAAAAAAz143TqxN4xEqAAAAKgAAACQAAABsaWNlbnNlcy9pbnRlbC1hbmRyb2lkLWV4dHJhLWxpY2Vuc2UNCmQ5NzVmNzUxNjk4YTc3YjY2MmYxMjU0ZGRiZWVkMzkwMWU5NzZmNWFQSwMEFAAAAAAA0l43Tu2ee/8qAAAAKgAAACYAAABsaWNlbnNlcy9taXBzLWFuZHJvaWQtc3lzaW1hZ2UtbGljZW5zZQ0KNjNkNzAzZjU2OTJmZDg5MWQ1YWNhY2ZiZDhlMDlmNDBmYzk3NjEwNVBLAQIUABQAAAAAAKJeN06amkPzKgAAACoAAAAhAAAAAAAAAAEAIAAAAAAAAABsaWNlbnNlcy9hbmRyb2lkLWdvb2dsZXR2LWxpY2Vuc2VQSwECFAAUAAAACACgazdORPmEqkMAAABUAAAAHAAAAAAAAAABACAAAABpAAAAbGljZW5zZXMvYW5kcm9pZC1zZGstbGljZW5zZVBLAQIUABQAAAAAAMVeN06RAmOwKgAAACoAAAAkAAAAAAAAAAEAIAAAAOYAAABsaWNlbnNlcy9hbmRyb2lkLXNkay1wcmV2aWV3LWxpY2Vuc2VQSwECFAAUAAAAAADMXjdOk6vQKCoAAAAqAAAAGwAAAAAAAAABACAAAABSAQAAbGljZW5zZXMvZ29vZ2xlLWdkay1saWNlbnNlUEsBAhQAFAAAAAAAz143TqxN4xEqAAAAKgAAACQAAAAAAAAAAQAgAAAAtQEAAGxpY2Vuc2VzL2ludGVsLWFuZHJvaWQtZXh0cmEtbGljZW5zZVBLAQIUABQAAAAAANJeN07tnnv/KgAAACoAAAAmAAAAAAAAAAEAIAAAACECAABsaWNlbnNlcy9taXBzLWFuZHJvaWQtc3lzaW1hZ2UtbGljZW5zZVBLBQYAAAAABgAGANoBAACPAgAAAAA=" +$content = [System.Convert]::FromBase64String($base64Content) +Set-Content -Path .\android-sdk-licenses.zip -Value $content -Encoding Byte +Expand-Archive -Path .\android-sdk-licenses.zip -DestinationPath 'C:\Program Files (x86)\Android\android-sdk' -Force + + +# run the updates. +# keep newer versions in descending order + +$sdk_root = "C:\Program Files (x86)\Android\android-sdk" + +# The NDK is installed by Visual Studio at this location: +$ndk_root = "C:\Microsoft\AndroidNDK64\" + +if(Test-Path $ndk_root){ + + $androidNDKs = Get-ChildItem -Path $ndk_root | Sort-Object -Property Name -Descending | Select-Object -First 1 + $latestAndroidNDK = $androidNDKs.FullName; + + setx ANDROID_HOME $sdk_root /M + setx ANDROID_NDK_HOME $latestAndroidNDK /M + setx ANDROID_NDK_PATH $latestAndroidNDK /M +} +else { + Write-Host "NDK is not installed at path $ndk_root" + exit 1 +} + + +Push-Location -Path $sdk.FullName + +& '.\tools\bin\sdkmanager.bat' --sdk_root=$sdk_root ` + "platform-tools" ` + "platforms;android-29" ` + "platforms;android-28" ` + "platforms;android-27" ` + "platforms;android-26" ` + "platforms;android-25" ` + "platforms;android-24" ` + "platforms;android-23" ` + "platforms;android-22" ` + "platforms;android-21" ` + "platforms;android-19" ` + "build-tools;29.0.2" ` + "build-tools;29.0.0" ` + "build-tools;28.0.3" ` + "build-tools;28.0.2" ` + "build-tools;28.0.1" ` + "build-tools;28.0.0" ` + "build-tools;27.0.3" ` + "build-tools;27.0.2" ` + "build-tools;27.0.1" ` + "build-tools;27.0.0" ` + "build-tools;26.0.3" ` + "build-tools;26.0.2" ` + "build-tools;26.0.1" ` + "build-tools;26.0.0" ` + "build-tools;25.0.3" ` + "build-tools;25.0.2" ` + "build-tools;25.0.1" ` + "build-tools;25.0.0" ` + "build-tools;24.0.3" ` + "build-tools;24.0.2" ` + "build-tools;24.0.1" ` + "build-tools;24.0.0" ` + "build-tools;23.0.3" ` + "build-tools;23.0.2" ` + "build-tools;23.0.1" ` + "build-tools;22.0.1" ` + "build-tools;21.1.2" ` + "build-tools;20.0.0" ` + "build-tools;19.1.0" ` + "extras;android;m2repository" ` + "extras;google;m2repository" ` + "extras;google;google_play_services" ` + "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.2" ` + "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.1" ` + "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2" ` + "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.1" ` + "add-ons;addon-google_apis-google-24" ` + "add-ons;addon-google_apis-google-23" ` + "add-ons;addon-google_apis-google-22" ` + "add-ons;addon-google_apis-google-21" ` + "cmake;3.6.4111459" ` + "patcher;v4" + +Pop-Location + + +# Adding description of the software to Markdown +$Header = @" + +## Android SDK Build Tools + +"@ + +Add-ContentToMarkdown -Content $Header + +$BuildTools =(Get-ChildItem "C:\Program Files (x86)\Android\android-sdk\build-tools\") ` + | Where { $_.Name -match "[0-9].*" } ` + | Sort-Object -Descending ` + | % { "#### $($_.Name)`n`n_Location:_ $($_.FullName)`n" } + +Add-ContentToMarkdown -Content $BuildTools + + +# Adding description of the software to Markdown +$Header = @" + +## Android SDK Platforms + +"@ + +Add-ContentToMarkdown -Content $Header + +$SdkList =(Get-ChildItem "C:\Program Files (x86)\Android\android-sdk\platforms\") | Sort-Object -Descending | %{ $_.FullName } + +foreach($sdk in $SdkList) +{ + $sdkProps = ConvertFrom-StringData (Get-Content "$sdk\source.properties" -Raw) + + $content = @" +#### $($sdkProps.'Platform.Version') (API $($sdkProps.'AndroidVersion.ApiLevel')) + +_Location:_ $sdk + +"@ + Add-ContentToMarkdown -Content $content +} diff --git a/images/win/scripts/Installers/Update-DotnetTLS.ps1 b/images/win/scripts/Installers/Update-DotnetTLS.ps1 new file mode 100644 index 00000000..82f46473 --- /dev/null +++ b/images/win/scripts/Installers/Update-DotnetTLS.ps1 @@ -0,0 +1,18 @@ +################################################################################ +## File: Update-DotnetTLS.ps1 +## Desc: Update DotNetFramework security protocol to TLS 1.2 +################################################################################ + +$registryPath = "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" +$name = "SchUseStrongCrypto" +$value = "1" +if(Test-Path $registryPath){ + Set-ItemProperty -Path $registryPath -Name $name -Value $value -Type DWORD +} + +$registryPath = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" +if(Test-Path $registryPath){ + Set-ItemProperty -Path $registryPath -Name $name -Value $value -Type DWORD +} + + diff --git a/images/win/scripts/Installers/Validate-7zip.ps1 b/images/win/scripts/Installers/Validate-7zip.ps1 new file mode 100644 index 00000000..fb6bed22 --- /dev/null +++ b/images/win/scripts/Installers/Validate-7zip.ps1 @@ -0,0 +1,25 @@ +################################################################################ +## File: Validate-7zip.ps1 +## Desc: Validate 7zip +################################################################################ + +if (Get-Command -Name '7z') +{ + Write-Host "7zip on path" +} +else +{ + Write-Host '7zip is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "7zip" +$(7z --help).Split([System.Environment]::NewLine)[1] -match "\d+\.\d+" +$7zipVersion = $matches[0] + +$Description = @" +_Version:_ $7zipVersion
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-AzureCli.ps1 b/images/win/scripts/Installers/Validate-AzureCli.ps1 new file mode 100644 index 00000000..16d70e30 --- /dev/null +++ b/images/win/scripts/Installers/Validate-AzureCli.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-AzureCli.ps1 +## Desc: Validate Azure CLI +################################################################################ + +if(Get-Command -Name 'az') +{ + Write-Host "Azure Cli $(az --version) on path" +} +else +{ + Write-Error "Azure Cli not on path" + exit 1 +} + +$azureCliVersion = az -v | findstr azure-cli +$azureCliVersion = $azureCliVersion.trim().Substring("azure-cli".Length).trim() + +# Adding description of the software to Markdown +$SoftwareName = "Azure CLI" + +$Description = @" +_Version:_ $azureCliVersion +_Environment:_ +* PATH: contains location of az.cmd +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-AzureCosmosDbEmulator.ps1 b/images/win/scripts/Installers/Validate-AzureCosmosDbEmulator.ps1 new file mode 100644 index 00000000..663609bd --- /dev/null +++ b/images/win/scripts/Installers/Validate-AzureCosmosDbEmulator.ps1 @@ -0,0 +1,47 @@ +################################################################################ +## File: Validate-AzureCosmosDbEmulator.ps1 +## Desc: Validate Azure CosmosDb Emulator installation. +################################################################################ + +$SoftwareName = 'Azure CosmosDb Emulator' +$regKey = gci HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | gp | ? { $_.DisplayName -eq 'Azure Cosmos DB Emulator' } + +if ($regKey -eq $null) +{ + Write-Host "The $regKey registry key is not set" + exit 1 +} +else +{ + Write-Host "The $regKey registry key is set" +} + +$installDir = $regKey.InstallLocation +if ($installDir -eq $null) +{ + Write-Host "The $SoftwareName installation directory registry value is not set" + exit 1 +} +else +{ + Write-Host "The $SoftwareName installation directory registry value is set to: $installDir" +} + +$exeFilePath = Join-Path $installDir 'CosmosDB.Emulator.exe' +if (!(Test-Path $exeFilePath)) +{ + Write-Host "$SoftwareName is not installed" + exit 1 +} +else +{ + $fileVersion = (Get-Item $exeFilePath).VersionInfo.FileVersion + Write-Host "$SoftwareName is successfully installed: $fileVersion" + + $Description = @" +_Version:_ $fileVersion
+_Location:_ $installDir +"@ + + Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description +} diff --git a/images/win/scripts/Installers/Validate-AzureDevOpsCli.ps1 b/images/win/scripts/Installers/Validate-AzureDevOpsCli.ps1 new file mode 100644 index 00000000..b494bd18 --- /dev/null +++ b/images/win/scripts/Installers/Validate-AzureDevOpsCli.ps1 @@ -0,0 +1,24 @@ +################################################################################ +## File: Validate-AzureDevOpsCli.ps1 +## Desc: Validate Azure DevOps CLI +################################################################################ + +az devops -h + +if($LastExitCode -ne 0) +{ + Write-Error "Azure DevOps Cli extension not present" + exit 1 +} +else +{ + Write-Host "Azure DevOps Cli extension is present" +} + +$azDevopsVer = az -v | findstr azure-devops + +$Description = @" +_Version:_ $azDevopsVer +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName 'Azure DevOps Cli extension' -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-AzureModules.ps1 b/images/win/scripts/Installers/Validate-AzureModules.ps1 new file mode 100644 index 00000000..a1456fac --- /dev/null +++ b/images/win/scripts/Installers/Validate-AzureModules.ps1 @@ -0,0 +1,71 @@ +################################################################################ +## File: Validate-AzureModules.ps1 +## Desc: Validate Azure PowerShell modules +################################################################################ + +Import-Module -Name ImageHelpers -Force + +$DefaultModule = Get-Module -Name AzureRM -ListAvailable | Select-Object -First 1 + +$env:PSModulePath = $env:PSModulePath + ";C:\Modules" + +$azureModules = Get-Module -Name Azure -ListAvailable | Select-Object Name,Version,Path | Format-Table | Out-String + +Write-Host "The Azure Modules finally present are:" +$azureModules + +if( ($azureModules -match "2.1.0") -and ($azureModules -match "3.8.0") -and ($azureModules -match "4.2.1") -and ($azureModules -match "5.1.1")) +{ + Write-Host "Required Azure modules are present" +} +else { + Write-Host "One or more required Azure modules are not present" + throw "One or more required Azure modules are not present." +} + + +$azureRMModules = Get-Module -Name AzureRM -ListAvailable | Select-Object Name,Version,Path | Format-Table | Out-String + +Write-Host "The AzureRM Modules finally present are:" +$azureRMModules + +if( ($azureRMModules -match "2.1.0") -and ($azureRMModules -match "3.8.0") -and ($azureRMModules -match "4.2.1") -and ($azureRMModules -match "5.1.1")) +{ + Write-Host "Required AzureRM modules are present" + +} +else { + Write-Host "One or more required AzureRM modules are not present" + throw "One or more required AzureRM modules are not present." +} + + +$azureModules = Get-Module -Name AzureRM -ListAvailable + + +# Adding description of the software to Markdown +$SoftwareName = "Azure/AzureRM Powershell modules" + +$Description = @" +#### $($DefaultModule.Version) + +This version is installed and is available via `Get-Module -ListAvailable` +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +foreach( $module in $azureModules) +{ + if($module.Version -ne $DefaultModule.Version) + { + + $CurrentModule = @" +#### $($module.Version) + +This version is saved but not installed +_Location:_ $($module.Path) + +"@ + Add-ContentToMarkdown -Content $CurrentModule + } +} diff --git a/images/win/scripts/Installers/Validate-Boost.ps1 b/images/win/scripts/Installers/Validate-Boost.ps1 new file mode 100644 index 00000000..7da2aab8 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Boost.ps1 @@ -0,0 +1,75 @@ +################################################################################ +## File: Validate-Boost.ps1 +## Desc: Validate Boost +################################################################################ + +function Validate-BoostVersion +{ + Param + ( + [String]$BoostRootPath, + [String]$BoostRelease + ) + + $ReleasePath = Join-Path -Path $BoostRootPath -ChildPath $BoostRelease + + if ((Test-Path "$ReleasePath\b2.exe") -and (Test-Path "$ReleasePath\bjam.exe")) + { + Write-Host "Boost.Build $BoostRelease is successfully installed" + Write-Host "Boost.Jam $BoostRelease is successfully installed" + return + } + + Write-Host "$BoostRelease not found" + exit 1 +} + +# Verify that Boost is on the path +if ((Get-Command -Name 'b2') -and (Get-Command -Name 'bjam')) +{ + Write-Host "Boost is on the path" +} +else +{ + Write-Host "Boost is not on the path" + exit 1 +} + +# Adding description of the software to Markdown +$tmplMark = @" +#### {0} + +_Environment:_ +* {1}: root directory of the Boost version {0} installation + +"@ + +$tmplMarkRoot = @" +#### {0} + +* PATH: contains the location of Boost version {0} +* BOOST_ROOT: root directory of the Boost version {0} installation +* {1}: root directory of the Boost version {0} installation +"@ + +$SoftwareName = 'Boost' +$Description = New-Object System.Text.StringBuilder +$BoostRootDirectory = Join-Path -Path $env:ProgramFiles -ChildPath "Boost" +$BoostVersionsToInstall = $env:BOOST_VERSIONS.split(",") + +foreach($Boost in $BoostVersionsToInstall) +{ + Validate-BoostVersion -BoostRootPath $BoostRootDirectory -BoostRelease $Boost + $BoostVersionTag = "BOOST_ROOT_{0}" -f $Boost.Replace('.', '_') + + if($boost -eq $env:BOOST_DEFAULT) + { + $null = $Description.AppendLine(($tmplMarkRoot -f $BoostVersion, $BoostVersionTag)) + } + else + { + $null = $Description.AppendLine(($tmplMark -f $BoostVersion, $BoostVersionTag)) + } +} + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description.ToString() diff --git a/images/win/scripts/Installers/Validate-Chrome.ps1 b/images/win/scripts/Installers/Validate-Chrome.ps1 new file mode 100644 index 00000000..505976e4 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Chrome.ps1 @@ -0,0 +1,25 @@ +################################################################################ +## File: Validate-Chrome.ps1 +## Desc: Validate Google Chrome installation. +################################################################################ + +if(Test-Path "HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe") +{ + (Get-Item (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe').'(Default)').VersionInfo + + $SoftwareName = "Google Chrome" + $fileVersion = (Get-Item (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe').'(Default)').VersionInfo.FileVersion + $Description = @" +_version:_ +$fileVersion +"@ + + Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + exit 0 +} +else +{ + Write-Host "Google Chrome is not installed." + exit 1 +} diff --git a/images/win/scripts/Installers/Validate-CloudFoundryCli.ps1 b/images/win/scripts/Installers/Validate-CloudFoundryCli.ps1 new file mode 100644 index 00000000..5e92f8a5 --- /dev/null +++ b/images/win/scripts/Installers/Validate-CloudFoundryCli.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-CloudFoundryCli.ps1 +## Desc: Validate Cloud Foundry CLI +################################################################################ + +if (Get-Command -Name 'cf') +{ + Write-Host "cf on path" +} +else +{ + Write-Host 'cf is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Cloud Foundry CLI" + +if( $(cf version) -match '\d+\.\d+\.\d+' ) +{ + $version = $Matches[0] +} + +$Description = @" +_Version:_ $version
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Cmake.ps1 b/images/win/scripts/Installers/Validate-Cmake.ps1 new file mode 100644 index 00000000..49a7487c --- /dev/null +++ b/images/win/scripts/Installers/Validate-Cmake.ps1 @@ -0,0 +1,31 @@ +################################################################################ +## File: Validate-Cmake.ps1 +## Desc: Validate Cmake +################################################################################ + +if(Get-Command -Name 'cmake') +{ + Write-Host "Cmake $(cmake -version) on path" +} +else +{ + Write-Host 'cmake not on path' + exit 1 +} + + +if( $( $(cmake -version) | Out-String) -match 'cmake version (?.*).*' ) +{ + $cmakeVersion = $Matches.version.Trim() +} + +# Adding description of the software to Markdown +$SoftwareName = "Cmake" + +$Description = @" +_Version:_ $cmakeVersion
+_Environment:_ +* PATH: contains location of cmake.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-DACFx.ps1 b/images/win/scripts/Installers/Validate-DACFx.ps1 new file mode 100644 index 00000000..587b2b0b --- /dev/null +++ b/images/win/scripts/Installers/Validate-DACFx.ps1 @@ -0,0 +1,33 @@ +#################################################################################### +## File: Validate-DACFx.ps1 +## Desc: Validate SQL Server® Data-Tier Application Framework (DACFx) for Windows +#################################################################################### + +$env:PATH = $env:Path + ';C:\Program Files\Microsoft SQL Server\120\DAC\bin;C:\Program Files\Microsoft SQL Server\130\DAC\bin;C:\Program Files\Microsoft SQL Server\140\DAC\bin;C:\Program Files\Microsoft SQL Server\150\DAC\bin' + +if(Get-Command -Name 'SqlPackage') +{ + + Write-Host "DACFx is installed at path" (Get-Command -Name 'SqlPackage').Source +} +else +{ + throw "DACFx is not installed!" +} + +function Get-DacFxVersion +{ + $regKey = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Data-Tier Application Framework\CurrentVersion" + $Version = (Get-ItemProperty -Path $regKey).'(Default)' + return $Version +} + + +# Adding description of the software to Markdown +$SoftwareName = "SQL Server Data Tier Application Framework (x64)" + +$Description = @" +_Version:_ $(Get-DacFxVersion)
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Docker.ps1 b/images/win/scripts/Installers/Validate-Docker.ps1 new file mode 100644 index 00000000..c3404fa9 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Docker.ps1 @@ -0,0 +1,46 @@ +################################################################################ +## File: Validate-Docker.ps1 +## Desc: Validate Docker. +################################################################################ + + +if((Get-Command -Name 'docker') -and (Get-Command -Name 'docker-compose')) +{ + Write-Host "docker $(docker version) on path" + Write-Host "docker-compose $(docker-compose version) on path" +} +else +{ + Write-Host "docker or docker-compose are not on path" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Docker" + +$version = $(docker version --format '{{.Server.Version}}') + +$Description = @" +_Version:_ $version
+_Environment:_ +* PATH: contains location of docker.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + + +$SoftwareName = "Docker-compose" + +if( $(docker-compose --version) -match 'docker-compose version (?.*), build.*' ) +{ + $dockerComposeVersion = $Matches.version +} + +$Description = @" +_Version:_ $dockerComposeVersion
+_Environment:_ +* PATH: contains location of docker-compose.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-DotnetSDK.ps1 b/images/win/scripts/Installers/Validate-DotnetSDK.ps1 new file mode 100644 index 00000000..a73133c3 --- /dev/null +++ b/images/win/scripts/Installers/Validate-DotnetSDK.ps1 @@ -0,0 +1,46 @@ +################################################################################ +## File: Validate-DotnetSDK.ps1 +## Desc: Validate dotnet +################################################################################ + +if(Get-Command -Name 'dotnet') +{ + Write-Host "dotnet $(dotnet --version) on path" +} +else +{ + Write-Host "dotnet is not on path" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = ".NET Core" + +$Description = @" +The following runtimes and SDKs are installed: + +_Environment:_ +* PATH: contains location of dotnet.exe + +_SDK:_ +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +$SdkList =(Get-ChildItem "C:\Program Files\dotnet\sdk") | Where { $_.Name -match "[0-9].*" } | Sort-Object -Descending | % { "* $($_.Name) $($_.FullName)" } + +Add-ContentToMarkdown -Content $SdkList + + + +$Runtimes = @" + +_Runtime:_ +"@ + +Add-ContentToMarkdown -Content $Runtimes + +$RuntimeList =(Get-ChildItem "C:\Program Files\dotnet\shared\Microsoft.NETCore.App") | Where { $_.Name -match "[0-9].*" } | Sort-Object -Descending | % { "* $($_.Name) $($_.FullName)" } + +Add-ContentToMarkdown -Content $RuntimeList + diff --git a/images/win/scripts/Installers/Validate-DotnetTLS.ps1 b/images/win/scripts/Installers/Validate-DotnetTLS.ps1 new file mode 100644 index 00000000..2ed4a4a0 --- /dev/null +++ b/images/win/scripts/Installers/Validate-DotnetTLS.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-DotnetTLS.ps1 +## Desc: Validate DotNetFramework security protocol to TLS 1.2 +################################################################################ + +$protocols = [Net.ServicePointManager]::SecurityProtocol +$protocolArr = $protocols -split ', ' +if($protocolArr.Contains('Tls12')) +{ + Write-Host "Tls 1.2 has been enabled." +} +else +{ + Write-Host "Tls 1.2 has not been enabled." + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "TLS12" +$version = "1.2"; + +$Description = @" +_Version:_ $version
+_Description:_ .NET has been configured to use TLS 1.2 by default +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + diff --git a/images/win/scripts/Installers/Validate-Firefox.ps1 b/images/win/scripts/Installers/Validate-Firefox.ps1 new file mode 100644 index 00000000..afe71707 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Firefox.ps1 @@ -0,0 +1,25 @@ +################################################################################ +## File: Validate-Firefox.ps1 +## Desc: Validate Mozilla Firefox installation. +################################################################################ + +if(Test-Path "HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe") +{ + (Get-Item (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe').'(Default)').VersionInfo + + $fileVersion = (Get-Item (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe').'(Default)').VersionInfo.FileVersion + $SoftwareName = "Mozilla Firefox" + $Description = @" +_version:_ +$fileVersion +"@ + + Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + exit 0 +} +else +{ + Write-Host "Mozilla Firefox is not installed." + exit 1 +} diff --git a/images/win/scripts/Installers/Validate-Git.ps1 b/images/win/scripts/Installers/Validate-Git.ps1 new file mode 100644 index 00000000..dacb967b --- /dev/null +++ b/images/win/scripts/Installers/Validate-Git.ps1 @@ -0,0 +1,49 @@ +################################################################################ +## File: Validate-Git.ps1 +## Desc: Validate Git for Windows +################################################################################ + +if((Get-Command -Name 'git') -and (Get-Command -Name 'bash') -and (Get-Command -Name 'awk') -and (Get-Command -Name 'git-lfs')) +{ + Write-Host "$(git version) on path" + Write-Host "$(git-lfs version) on path" +} +else +{ + Write-Host "git or git-lfs are not on path." + exit 1 +} + + +if( $(git version) -match 'git version (?.*).win.*' ) +{ + $gitVersion = $Matches.version +} + +if( $(git-lfs version) -match 'git-lfs\/(?.*) \(Git.*' ) +{ + $gitLfsVersion = $Matches.version +} + +# Adding description of the software to Markdown +$SoftwareName = "Git" + +$Description = @" +_Version:_ $gitVersion
+_Environment:_ +* PATH: contains location of git.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +# Adding description of the software to Markdown +$SoftwareName = "Git Large File Storage (LFS)" + +$Description = @" +_Version:_ $gitLfsVersion
+_Environment:_ +* PATH: contains location of git-lfs.exe +* GIT_LFS_PATH: location of git-lfs.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-GitVersion.ps1 b/images/win/scripts/Installers/Validate-GitVersion.ps1 new file mode 100644 index 00000000..32aa2d88 --- /dev/null +++ b/images/win/scripts/Installers/Validate-GitVersion.ps1 @@ -0,0 +1,25 @@ +################################################################################ +## File: Validate-GitVersion.ps1 +## Desc: Validate GitVersion +################################################################################ + +$command = Get-Command -Name 'gitversion' +if ($command) +{ + Write-Host "gitversion on path" +} +else +{ + Write-Host 'gitversion is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "GitVersion" +$version = $command.Version.ToString() + +$Description = @" +_Version:_ $version
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Go.ps1 b/images/win/scripts/Installers/Validate-Go.ps1 new file mode 100644 index 00000000..08c23747 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Go.ps1 @@ -0,0 +1,70 @@ +################################################################################ +## File: Validate-Go.ps1 +## Desc: Validate Go +################################################################################ + +# Function that gets the version of Go at the specified path +function Get-GoVersion +{ + Param + ( + [String]$goRootPath + ) + + $env:Path = "$goRootPath\bin;" + $env:Path + if( $(go version) -match 'go version go(?.*) win.*' ) + { + $goVersion = $Matches.version + return $goVersion + } + + Write-Host "Unable to determine Go version at " + $goRootPath + return "" +} + +# Verify that go.exe is on the path +if(Get-Command -Name 'go') +{ + Write-Host "$(go version) is on the path." +} +else +{ + Write-Host "Go is not on the path." + exit 1 +} + +# Add details of available versions in Markdown +$tmplMark = @" +#### {0} + +_Environment:_ +* {1}: root directory of the Go {0} installation + +"@ + +$tmplMarkRoot = @" +#### {0} + +_Environment:_ +* PATH: contains the location of go.exe version {0} +* GOROOT: root directory of the Go {0} installation +* {1}: root directory of the Go {0} installation +"@ + +$SoftwareName = "Go (x64)" +$Description = New-Object System.Text.StringBuilder +$goVersionsToInstall = $env:GO_VERSIONS.split(",") + +foreach($go in $goVersionsToInstall) { + $goVersion = Get-GoVersion -goRootPath "C:\Go${go}" + $goVersionTag = "GOROOT_{0}_{1}_X64" -f $go.split(".") + if ($goVersion -eq $go) { + if($go -eq $env:GO_DEFAULT) { + $null = $Description.AppendLine(($tmplMarkRoot -f $goVersion, $goVersionTag)) + } else { + $null = $Description.AppendLine(($tmplMark -f $goVersion, $goVersionTag)) + } + } +} + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description.ToString() diff --git a/images/win/scripts/Installers/Validate-InnoSetup.ps1 b/images/win/scripts/Installers/Validate-InnoSetup.ps1 new file mode 100644 index 00000000..3caa7016 --- /dev/null +++ b/images/win/scripts/Installers/Validate-InnoSetup.ps1 @@ -0,0 +1,27 @@ +################################################################################ +## File: Validate-InnoSetup.ps1 +## Desc: Validate Inno Setup +################################################################################ + +if (Get-Command -Name 'iscc') +{ + Write-Host "iscc is on PATH" +} +else +{ + Write-Host "iscc is not on PATH" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Inno Setup" + +$ChocoList = $(choco list --local-only innosetup) | Select-String -Pattern "InnoSetup" +$ChocoList -Match "\d+\.\d+\.\d+" +$Version = $Matches[0] + +$Description = @" +_Version:_ $Version
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-JavaTools.ps1 b/images/win/scripts/Installers/Validate-JavaTools.ps1 new file mode 100644 index 00000000..91ffb42e --- /dev/null +++ b/images/win/scripts/Installers/Validate-JavaTools.ps1 @@ -0,0 +1,113 @@ +################################################################################ +## File: Validate-JavaTools.ps1 +## Desc: Validate various JDKs and java tools +################################################################################ + +if((Get-Command -Name 'java') -and (Get-Command -Name 'mvn') -and (Get-Command -Name 'ant') -and (Get-Command -Name 'gradle')) +{ + Write-Host "Java $(java -version) on path" + Write-Host "Maven $(mvn -version) on path" + Write-Host "Ant $(ant -version) on path" + Write-Host "Gradle $(gradle -version) on path" +} +else +{ + Write-Host "one of Java,Maven,Ant,Gradle is not on path." + exit 1 +} + + +if( $( $(& $env:comspec "/s /c java -version 2>&1") | Out-String) -match '^(?.+) version "(?.+)".*' ) +{ + $javaVersion = $Matches.version +} + +$env:Path = $env:JAVA_HOME_7_X64 + "\bin;" + $env:Path + +if( $( $(& $env:comspec "/s /c java -version 2>&1") | Out-String) -match '^(?.+) version "(?.+)".*' ) +{ + $java7Version = $Matches.version +} + +$env:Path = $env:JAVA_HOME_11_X64 + "\bin;" + $env:Path + +if( $( $(& $env:comspec "/s /c java -version 2>&1") | Out-String) -match '^(?.+) version "(?.+)".*' ) +{ + $java11Version = $Matches.version +} + + +if( $(ant -version) -match 'Apache Ant\(TM\) version (?.*) compiled.*' ) +{ + $antVersion = $Matches.version +} + +if( $( $(mvn -version) | Out-String) -match 'Apache Maven (?.*) \(.*' ) +{ + $mvnVersion = $Matches.version +} + +if( $( $(gradle -version) | Out-String) -match 'Gradle (?.*)' ) +{ + $gradleVersion = $Matches.version.Trim() +} + +# Adding description of the software to Markdown +$SoftwareName = "Java Development Kit" + +$Description = @" +#### $javaVersion + +_Environment:_ +* JAVA_HOME: location of JDK +* PATH: contains bin folder of JDK + +#### $java7Version + +_Location:_ $env:JAVA_HOME_7_X64 + +#### $java11Version + +_Location:_ $env:JAVA_HOME_11_X64 +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + +# Adding description of the software to Markdown +$SoftwareName = "Ant" + +$Description = @" +_Version:_ $antVersion
+_Environment:_ +* PATH: contains location of ant.cmd +* ANT_HOME: location of ant.cmd +* COBERTURA_HOME: location of cobertura-2.1.1.jar +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + +# Adding description of the software to Markdown +$SoftwareName = "Maven" + +$Description = @" +_Version:_ $mvnVersion
+_Environment:_ +* PATH: contains location of mvn.bat +* M2_HOME: Maven installation root +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + +# Adding description of the software to Markdown +$SoftwareName = "Gradle" + +$Description = @" +_Version:_ $gradleVersion
+_Environment:_ +* PATH: contains location of gradle +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Jq.ps1 b/images/win/scripts/Installers/Validate-Jq.ps1 new file mode 100644 index 00000000..85bf2318 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Jq.ps1 @@ -0,0 +1,23 @@ +################################################################################ +## File: Validate-Jq.ps1 +## Desc: Validate jq +################################################################################ + +if (Get-Command -Name 'jq') +{ + Write-Host "jq on path" +} +else +{ + Write-Host 'jq is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "jq" + +$Description = @" +_Version:_ $(jq --version)
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Kind.ps1 b/images/win/scripts/Installers/Validate-Kind.ps1 new file mode 100644 index 00000000..2a33e1de --- /dev/null +++ b/images/win/scripts/Installers/Validate-Kind.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-Kind.ps1 +## Desc: Validate Kind. +################################################################################ + + +if((Get-Command -Name 'kind')) +{ + Write-Host "kind $(kind version) in path" +} +else +{ + Write-Host "kind is not in path" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Kind" + +$version = $(kind version) + +$Description = @" +_Version:_ $version
+_Environment:_ +* PATH: contains location of kind.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-KubernetesCli.ps1 b/images/win/scripts/Installers/Validate-KubernetesCli.ps1 new file mode 100644 index 00000000..05666c14 --- /dev/null +++ b/images/win/scripts/Installers/Validate-KubernetesCli.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-KubernetesCli.ps1 +## Desc: Validate KubernetesCli. +################################################################################ + + +if((Get-Command -Name 'kubectl')) +{ + Write-Host "kubectl $(kubectl version --client=true --short=true) in path" +} +else +{ + Write-Host "kubectl is not in path" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Kubectl" + +$version = $(kubectl version --client=true --short=true) + +$Description = @" +_Version:_ $version
+_Environment:_ +* PATH: contains location of kubectl.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Mercurial.ps1 b/images/win/scripts/Installers/Validate-Mercurial.ps1 new file mode 100644 index 00000000..7351fcab --- /dev/null +++ b/images/win/scripts/Installers/Validate-Mercurial.ps1 @@ -0,0 +1,25 @@ +################################################################################ +## File: Validate-Mercurial.ps1 +## Desc: Validate Mercurial +################################################################################ + +if (Get-Command -Name 'hg') +{ + Write-Host "Mercurial on path" +} +else +{ + Write-Host 'Mercurial is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Mercurial" +$(hg --version).Split([System.Environment]::NewLine)[0] -match "\d+\.\d+\.\d+" +$MercurialVersion = $matches[0] + +$Description = @" +_Version:_ $MercurialVersion
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-MinGW.ps1 b/images/win/scripts/Installers/Validate-MinGW.ps1 new file mode 100644 index 00000000..78c5910f --- /dev/null +++ b/images/win/scripts/Installers/Validate-MinGW.ps1 @@ -0,0 +1,57 @@ +################################################################################ +## File: Validate-MinGW.ps1 +## Desc: Validate MinGW +################################################################################ + +if (Get-Command -Name 'gcc') +{ + Write-Host "gcc is successfully installed:" + gcc --version | Write-Host +} +else +{ + Write-Host "gcc is not on PATH" + exit 1 +} + +if (Get-Command -Name 'g++') +{ + Write-Host "g++ is successfully installed:" + g++ --version | Write-Host +} +else +{ + Write-Host "g++ is not on PATH" + exit 1 +} + +if (Get-Command -Name 'make') +{ + Write-Host "make is successfully installed:" + make --version | Write-Host +} +else +{ + Write-Host "make is not on PATH" + exit 1 +} + +# Adding description of the software to Markdown + +# `gcc --version` gives output like: +# gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 5.3.0 +# Copyright (C) 2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +$SoftwareName = "MinGW" +$(gcc --version).Split([System.Environment]::NewLine)[0] -match "\d\.\d\.\d$" +$minGwVersion = $matches[0] + +$Description = @" +_Version:_ $minGwVersion
+_Environment:_ +* PATH: contains location of the MinGW 'bin' directory +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Miniconda.ps1 b/images/win/scripts/Installers/Validate-Miniconda.ps1 new file mode 100644 index 00000000..defd8a73 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Miniconda.ps1 @@ -0,0 +1,36 @@ +################################################################################ +## File: Validate-Miniconda.ps1 +## Desc: Validate Miniconda +################################################################################ + +if ($env:CONDA) +{ + Write-Host "The CONDA environment variable is set" + Write-Host $env:CONDA +} +else +{ + Write-Host "The CONDA environment variable is not set" + exit 1 +} + +if ((Test-Path "$env:CONDA\python.exe") -and (Test-Path "$env:CONDA\Scripts\conda.exe")) +{ + Write-Host "Miniconda is successfully installed:" + & "$env:CONDA\Scripts\conda.exe" --version | Write-Host +} +else +{ + Write-Host "Miniconda is not installed" + exit 1 +} + +$softwareName = "Miniconda" +$description = @" +_Version:_ $(& "$env:CONDA\Scripts\conda.exe" --version)
+_Environment:_ +* CONDA: contains location of the root of the Miniconda installation +"@ + +# Adding description of the software to Markdown +Add-SoftwareDetailsToMarkdown -SoftwareName $softwareName -DescriptionMarkdown $description diff --git a/images/win/scripts/Installers/Validate-MysqlCli.ps1 b/images/win/scripts/Installers/Validate-MysqlCli.ps1 new file mode 100644 index 00000000..2e4e8296 --- /dev/null +++ b/images/win/scripts/Installers/Validate-MysqlCli.ps1 @@ -0,0 +1,27 @@ +################################################################################ +## File: Validate-MysqlCli.ps1 +## Desc: Validate Mysql Cli +################################################################################ + +$command = Get-Command -Name 'mysql' +if($command) +{ + Write-Host "Mysql is on path" +} +else +{ + Write-Host 'Mysql not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Mysql" +$version = $command.Version.ToString(); + +$Description = @" +_Version:_ $version
+_Environment:_ +* PATH: contains location of mysql.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-NET472.ps1 b/images/win/scripts/Installers/Validate-NET472.ps1 new file mode 100644 index 00000000..20c9d2c0 --- /dev/null +++ b/images/win/scripts/Installers/Validate-NET472.ps1 @@ -0,0 +1,27 @@ +################################################################################ +## File: Validate-NET472.ps1 +## Desc: Validate .NET 4.7.2 +################################################################################ + +Import-Module -Name ImageHelpers -Force + +# For reference, visit https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed#ps_a +if(Get-ChildItem "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" | Get-ItemPropertyValue -Name Release | ForEach-Object { $_ -ge 461814 }) +{ + $version = Get-ChildItem "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" | Get-ItemPropertyValue -Name Version + Write-Host "Installed .Net version " $version +} +else { + Write-Host ".Net 472 not found" + exit 1 +} + + +# Adding description of the software to Markdown +$SoftwareName = ".NET 4.7.2" + +$Description = @" +_Version:_ $version +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-NET48.ps1 b/images/win/scripts/Installers/Validate-NET48.ps1 new file mode 100644 index 00000000..fce090bd --- /dev/null +++ b/images/win/scripts/Installers/Validate-NET48.ps1 @@ -0,0 +1,27 @@ +################################################################################ +## File: Validate-NET48.ps1 +## Desc: Validate .NET 4.8 +################################################################################ + +Import-Module -Name ImageHelpers -Force + +# For reference, visit https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed#ps_a +if(Get-ChildItem "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" | Get-ItemPropertyValue -Name Release | ForEach-Object { $_ -ge 528049 }) +{ + $version = Get-ChildItem "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\" | Get-ItemPropertyValue -Name Version + Write-Host "Installed .Net version " $version +} +else { + Write-Host ".Net 48 not found" + exit 1 +} + + +# Adding description of the software to Markdown +$SoftwareName = ".NET 4.8" + +$Description = @" +_Version:_ $version +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-NSIS.ps1 b/images/win/scripts/Installers/Validate-NSIS.ps1 new file mode 100644 index 00000000..a9865e41 --- /dev/null +++ b/images/win/scripts/Installers/Validate-NSIS.ps1 @@ -0,0 +1,32 @@ +################################################################################ +## File: Validate-NSIS.ps1 +## Desc: Validate NSIS installation. +################################################################################ + +$SoftwareName = 'Nullsoft Install System (NSIS)' + +if (Get-Command -Name makensis) +{ + Write-Host "$SoftwareName is installed" +} +else +{ + Write-Host "$SoftwareName is not installed" + exit 1 +} + +# Adding description of the software to Markdown +$ChocoList = $(choco list --local-only nsis) | Select-String -Pattern "nsis" | Select-Object -First 1 + +if ($ChocoList -Match "\d+\.\d+") +{ + $Version = $Matches[0] +} + + +$Description = @" +_Version:_ $Version
+"@ + +#Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description +Write-Host $description diff --git a/images/win/scripts/Installers/Validate-NodeLts.ps1 b/images/win/scripts/Installers/Validate-NodeLts.ps1 new file mode 100644 index 00000000..49b10b65 --- /dev/null +++ b/images/win/scripts/Installers/Validate-NodeLts.ps1 @@ -0,0 +1,71 @@ +################################################################################ +## File: Validate-NodeLts.ps1 +## Desc: Validate nodejs-lts and other common node tools. +################################################################################ + +if((Get-Command -Name 'node') -and (Get-Command -Name 'npm')) +{ + Write-Host "Node $(node --version) on path" + Write-Host "Npm $(npm -version) on path" +} +else +{ + Write-Host "Node or npm is not on path" + exit 1 +} + +if((Get-Command -Name 'gulp') -and (Get-Command -Name 'grunt') -and (Get-Command -Name 'bower') -and (Get-Command -Name 'cordova') -and (Get-Command -Name 'yarn')) +{ + Write-Host "Gulp $(gulp -version) on path" + Write-Host "Grunt $(grunt -version) on path" + Write-Host "Bower $(bower -version) on path" + Write-Host "Yarn $(yarn -version) on path" +} +else +{ + Write-Host "One of Gulp, Grunt, Bower, Cordova, or Yarn is not on the path." + exit 1 +} + + + +if( $(node --version) -match 'v(?.*)' ) +{ + $nodeVersion = $Matches.version + $nodeArch = $(node -e "console.log(process.arch)") +} + +$npmVersion = $(npm -version) + +# Adding description of the software to Markdown +$SoftwareName = "Node.js" +$GulpInfo = "Gulp $(gulp -version)" +$GruntInfo = "Grunt $(grunt -version)" +$BowerInfo = "Bower $(bower -version)" +$YarnInfo = "Yarn $(yarn -version)" + +$Description = @" +_Version:_ $nodeVersion
+_Architecture:_ $nodeArch
+_Environment:_ +* PATH: contains location of node.exe
+* $GulpInfo
+* $GruntInfo
+* $BowerInfo
+* $YarnInfo
+ +> Note: You can install and use another version of Node.js on Microsoft-hosted agent pools using the [Node tool installer](https://docs.microsoft.com/vsts/pipelines/tasks/tool/node-js) task. +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +# Adding description of the software to Markdown +$SoftwareName = "npm" + +$Description = @" +_Version:_ $npmVersion
+_Environment:_ +* PATH: contains location of npm.cmd +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-OpenSSL.ps1 b/images/win/scripts/Installers/Validate-OpenSSL.ps1 new file mode 100644 index 00000000..fb7b7927 --- /dev/null +++ b/images/win/scripts/Installers/Validate-OpenSSL.ps1 @@ -0,0 +1,29 @@ +################################################################################ +## File: Validate-OpenSSL.ps1 +## Desc: Validate openssl +################################################################################ + +if (Get-Command -Name 'openssl') +{ + Write-Host "openssl on path" +} +else +{ + Write-Host 'openssl is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "OpenSSL" + +$versions = Get-Command openssl -All +foreach ($version in $versions) +{ + $command = "& `"$($version.Source)`" version" + if ( $(Invoke-Expression -Command $command) -match '\d+\.\d+\.\d+\w?' ) + { + $Description += "_Version:_ $($Matches[0]) at $($version.Source)
" + } +} + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-PHP.ps1 b/images/win/scripts/Installers/Validate-PHP.ps1 new file mode 100644 index 00000000..6f6044ef --- /dev/null +++ b/images/win/scripts/Installers/Validate-PHP.ps1 @@ -0,0 +1,49 @@ +################################################################################ +## File: Validate-PHP.ps1 +## Desc: Validate PHP +################################################################################ + +# Function that gets the version of php at the specified path +function Get-PHPVersion +{ + Param + ( + [String]$phpRootPath + ) + + $env:Path = "$phpRootPath;" + $env:Path + if($($(php --version)| Out-String) -match 'PHP (?.*) (.*cli).*') + { + $phpVersion = $Matches.version + return $phpVersion + } + + Write-Host "Unable to determine PHP version at " + $phpRootPath + exit 1 +} + +# Verify that php.exe is on the path +if(Get-Command -Name 'php') +{ + Write-Host "$(php --version) is on the path." +} +else +{ + Write-Host "php is not on the path." + exit 1 +} + +# Get available versions of PHP +$phpVersionOnPath = Get-PHPVersion -phpRootPath "C:\tools\php72" + +# Add details of available versions in Markdown +$SoftwareName = "PHP (x64)" +$Description = @" +#### $phpVersionOnPath + +_Environment:_ +* PATH: contains the location of php.exe version $phpVersionOnPath +* PHPROOT: root directory of the PHP $phpVersionOnPath installation +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Perl.ps1 b/images/win/scripts/Installers/Validate-Perl.ps1 new file mode 100644 index 00000000..95443640 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Perl.ps1 @@ -0,0 +1,23 @@ +################################################################################ +## File: Validate-Perl.ps1 +## Desc: Validate perl +################################################################################ + +if (Get-Command -Name 'perl') +{ + Write-Host "perl on path" +} +else +{ + Write-Host 'perl is not on path' + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Perl" + +$Description = @" +_Version:_ $(perl -e 'print $^V')
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-PowershellCore.ps1 b/images/win/scripts/Installers/Validate-PowershellCore.ps1 new file mode 100644 index 00000000..088a55bf --- /dev/null +++ b/images/win/scripts/Installers/Validate-PowershellCore.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-PowershellCore.ps1 +## Desc: Validate Powershell Core +################################################################################ + +if (Get-Command -Name 'pwsh') +{ + Write-Host "pwsh is on PATH" +} +else +{ + Write-Host "pwsh is not on PATH" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "Powershell Core" + +if(($(pwsh --version) | Out-String) -match 'PowerShell (?.*)') +{ + $PowershellVersion = $Matches.version +} + +$Description = @" +_Version:_ $PowershellVersion
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Python.ps1 b/images/win/scripts/Installers/Validate-Python.ps1 new file mode 100644 index 00000000..42581764 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Python.ps1 @@ -0,0 +1,45 @@ +################################################################################ +## File: Validate-Python.ps1 +## Desc: Configure python on path based on what is installed in the tools cache +## Must run after tools cache is downloaded and validated +################################################################################ + +if(Get-Command -Name 'python') +{ + Write-Host "Python $(& python -V 2>&1) on path" +} +else +{ + Write-Host "Python is not on path" + exit 1 +} + +$Python3Version = $(& python -V 2>&1) + +if ($Python3Version -notlike "Python 3.*") +{ + Write-Error "Python 3 is not in the PATH" +} + + +$python2path = $Env:AGENT_TOOLSDIRECTORY + '/Python/2.7*/x64' +$python2Dir = Get-Item -Path $python2path + +$env:Path = $python2Dir.FullName + ";" + $env:Path + +$Python2Version = & $env:comspec "/s /c python --version 2>&1" + +# Adding description of the software to Markdown +$SoftwareName = "Python (64 bit)" + +$Description = @" +#### $Python3Version +_Environment:_ +* PATH: contains location of python.exe + +#### $Python2Version + +_Location:_ $Python2Path +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Ruby.ps1 b/images/win/scripts/Installers/Validate-Ruby.ps1 new file mode 100644 index 00000000..5243ab4d --- /dev/null +++ b/images/win/scripts/Installers/Validate-Ruby.ps1 @@ -0,0 +1,53 @@ +################################################################################ +## File: Validate-Ruby.ps1 +## Desc: Verify that Ruby is on the path and output version information. +################################################################################ + +# Function that gets the version of Ruby at the specified path +function Get-RubyVersion +{ + Param + ( + [String]$rubyRootPath + ) + + # Prepend to the path like: C:\hostedtoolcache\windows\Ruby\2.5.0\x64\bin + $env:Path = "$rubyRootPath;" + $env:Path + + # Extract the version from Ruby output like: ruby 2.5.1p57 (2018-03-29 revision 63029) [x64-mingw32] + if( $(ruby --version) -match 'ruby (?.*) \(.*' ) + { + $rubyVersion = $Matches.version + return $rubyVersion + } + + Write-Host "Unable to determine Ruby version at " + $rubyRootPath + exit 1 +} + +# Verify that ruby is on the path +if(Get-Command -Name 'ruby') +{ + Write-Host "$(ruby --version) is on the path." +} +else +{ + Write-Host "Ruby is not on the path." + exit 1 +} + +# Default Ruby Version on Path +$rubyExeOnPath = (Get-Command -Name 'ruby').Path +$rubyBinOnPath = Split-Path -Path $rubyExeOnPath +$rubyVersionOnPath = Get-RubyVersion -rubyRootPath $rubyBinOnPath + +# Add details of available versions in Markdown +$SoftwareName = "Ruby (x64)" +$Description = @" +#### $rubyVersionOnPath +_Environment:_ +* Location: $rubyBinOnPath +* PATH: contains the location of ruby.exe version $rubyVersionOnPath +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Rust.ps1 b/images/win/scripts/Installers/Validate-Rust.ps1 new file mode 100644 index 00000000..a1e8694d --- /dev/null +++ b/images/win/scripts/Installers/Validate-Rust.ps1 @@ -0,0 +1,34 @@ +################################################################################ +## File: Validate-Rust.ps1 +## Desc: Verify that Rust is on the path and output version information. +################################################################################ + +if (Get-Command -Name 'rustc') +{ + Push-Location -Path $env:UserProfile + New-Item -Name ".rustup" -Value "C:\Rust\.rustup" -ItemType Junction + New-Item -Name ".cargo" -Value "C:\Rust\.cargo" -ItemType Junction + $RustcVersion = rustc --version + Write-Host "$RustcVersion is on the path" + Pop-Location +} +else +{ + Write-Host "rustc is not on the path" + exit 1 +} + +$RustPath = Split-Path (Get-Command -Name 'rustc').Path +$RustcVersion -Match "\d+\.\d+\.\d+" | Out-Null +$Version = $Matches[0] + +# Adding description of the software to Markdown +$SoftwareName = "Rust (64-bit)" +$Description = @" +#### $Version +_Location:_ $RustPath +_Environment:_ +* PATH: contains the location of rustc.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-SQLPowerShellTools.ps1 b/images/win/scripts/Installers/Validate-SQLPowerShellTools.ps1 new file mode 100644 index 00000000..2ca6b8fa --- /dev/null +++ b/images/win/scripts/Installers/Validate-SQLPowerShellTools.ps1 @@ -0,0 +1,37 @@ +# Validate the installation +$env:PSModulePath = Get-SystemVariable "PSModulePath" +$modules = Get-Module -Name SQLPS -ListAvailable +Write-Host "The SQLPS Modules present are:" +$modules | Select-Object Name,Version,Path | Format-Table + +if ($modules) { + $sqlPSVersion = $modules.Version +} + +# Validate the SQLserver PS module installation +$modules = Get-Module -Name SQLServer -ListAvailable +Write-Host "The SQLServer Modules present are:" +$modules | Select-Object Name,Version,Path | Format-Table + +if ($modules) { + $sqlServerPSModuleVersion = $modules.Version +} + + +# Adding description of the software to Markdown +$SoftwareName = "SQLPS" + +$Description = @" +_Version:_ $sqlPSVersion +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +# Adding description of the software to Markdown +$SoftwareName = "SQLServer PS" + +$Description = @" +_Version:_ $sqlServerPSModuleVersion +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Sbt.ps1 b/images/win/scripts/Installers/Validate-Sbt.ps1 new file mode 100644 index 00000000..ce213c55 --- /dev/null +++ b/images/win/scripts/Installers/Validate-Sbt.ps1 @@ -0,0 +1,18 @@ +################################################################################ +## File: Validate-Sbt.ps1 +## Team: CI-Platform +## Desc: Validate sbt for Windows +################################################################################ + +if((Get-Command -Name 'sbt')) +{ + Write-Host "sbt is on the path" +} +else +{ + Write-Host "sbt is not on path." + exit 1 +} + +# This works around issue where sbt --script-version does some copies and breaks the build +Add-SoftwareDetailsToMarkdown -SoftwareName "sbt" -DescriptionMarkdown "" diff --git a/images/win/scripts/Installers/Validate-SeleniumWebDrivers.ps1 b/images/win/scripts/Installers/Validate-SeleniumWebDrivers.ps1 new file mode 100644 index 00000000..41a6266a --- /dev/null +++ b/images/win/scripts/Installers/Validate-SeleniumWebDrivers.ps1 @@ -0,0 +1,67 @@ +################################################################################ +## File: Validate-Chrome.ps1 +## Desc: Validate Google Chrome installation. +################################################################################ + +$IEDriverPath = $env:IEWebDriver +$GeckoDriverPath = $env:GeckoWebDriver +$ChromeDriverPath = $env:ChromeWebDriver + +if(($IEDriverPath -like "C:\SeleniumWebDrivers\IEDriver") -and ($GeckoDriverPath -like "C:\SeleniumWebDrivers\GeckoDriver") -and ($ChromeDriverPath -like "C:\SeleniumWebDrivers\ChromeDriver")) +{ + + Write-Host "IEDriver installed at " + (Get-Item "C:\SeleniumWebDrivers\IEDriver\IEDriverServer.exe").VersionInfo + + + Write-Host "Gecko Driver installed at " + (Get-Item "C:\SeleniumWebDrivers\GeckoDriver\geckodriver.exe").VersionInfo + + + Write-Host "Chrome Driver installed at " + (Get-Item "C:\SeleniumWebDrivers\ChromeDriver\chromedriver.exe").VersionInfo + + $chromedriverversion = Get-Content -Path "C:\SeleniumWebDrivers\ChromeDriver\versioninfo.txt" + $geckodriverversion = Get-Content -Path "C:\SeleniumWebDrivers\GeckoDriver\versioninfo.txt" + $iedriverversion = Get-Content -Path "C:\SeleniumWebDrivers\IEDriver\versioninfo.txt" + + # Adding description of the software to Markdown + $SoftwareName = "Selenium Web Drivers" + + $Description = @" + +#### Chrome Driver + +_version:_ +$chromedriverversion + +_Environment:_ +* ChromeWebDriver: location of chromedriver.exe + +#### Gecko Driver + +_version:_ +$geckodriverversion + +_Environment:_ +* GeckoWebDriver: location of geckodriver.exe + +#### IE Driver + +_version:_ +$iedriverversion + +_Environment:_ +* IEWebDriver: location of IEDriverServer.exe + +"@ + + Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + + exit 0 +} +else +{ + Write-Host "Selenium Web Drivers are not installed." + exit 1 +} diff --git a/images/win/scripts/Installers/Validate-ServiceFabricSDK.ps1 b/images/win/scripts/Installers/Validate-ServiceFabricSDK.ps1 new file mode 100644 index 00000000..e893c014 --- /dev/null +++ b/images/win/scripts/Installers/Validate-ServiceFabricSDK.ps1 @@ -0,0 +1,44 @@ +################################################################################ +## File: Validate-ServiceFabricSDK.ps1 +## Desc: Validate ServiceFabricSDK +################################################################################ + +$modules = Get-Module -Name ServiceFabric -ListAvailable + +if(($modules | Measure-Object).Count -gt 0) +{ + $modules +} +else { + Write-Host "ServiceFabric Module is not present, it might not be installed" + throw "ServiceFabric Module is not present, it might not be installed" +} + + +function Get-ServiceFabricSDKVersion +{ + $regKey = "HKLM:\Software\Microsoft\Service Fabric SDK" + $installedApplications = Get-ItemProperty -Path $regKey + $Version = (Get-ItemProperty -Path $regKey).FabricSDKVersion + return $Version +} + + +function Get-ServiceFabricVersion +{ + $regKey = "HKLM:\Software\Microsoft\Service Fabric" + $installedApplications = Get-ItemProperty -Path $regKey + $Version = (Get-ItemProperty -Path $regKey).FabricVersion + return $Version +} + + +# Adding description of the software to Markdown +$SoftwareName = "Azure Service Fabric" + +$Description = @" +_SDK Version:_ $(Get-ServiceFabricSDKVersion)
+_Runtime Version:_ $(Get-ServiceFabricVersion) +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Svn.ps1 b/images/win/scripts/Installers/Validate-Svn.ps1 new file mode 100644 index 00000000..1e9b141a --- /dev/null +++ b/images/win/scripts/Installers/Validate-Svn.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Validate-Svn.ps1 +## Desc: Validate Subversion +################################################################################ + +if(Get-Command -Name 'svn') +{ + Write-Host "Subversion $(svn --version --quiet) is on the path." +} +else +{ + Write-Host "Subversion is not on the path." + exit 1 +} + + +$svnVersion = $(svn --version --quiet) + +# Adding description of the software to Markdown +$SoftwareName = "Subversion" + +$Description = @" +_Version:_ $svnVersion
+_Environment:_ +* PATH: contains location of svn.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-ToolCache.ps1 b/images/win/scripts/Installers/Validate-ToolCache.ps1 new file mode 100644 index 00000000..028f1319 --- /dev/null +++ b/images/win/scripts/Installers/Validate-ToolCache.ps1 @@ -0,0 +1,94 @@ +################################################################################ +## File: Validate-ToolCache.ps1 +## Desc: Validate Tool Cache +################################################################################ + +# Helpers +function GetChildFolders { + param ( + [Parameter(Mandatory = $True)] + [string]$Path + ) + return Get-ChildItem -Path $Path -Directory -Name +} + +function ToolcacheTest { + param ( + [Parameter(Mandatory = $True)] + [string]$SoftwareName, + [Parameter(Mandatory = $True)] + [string[]]$ExecTests, + [Parameter(Mandatory = $True)] + [string]$Note + ) + if (Test-Path "$env:AGENT_TOOLSDIRECTORY\$SoftwareName") + { + $description = "" + [array]$versions = GetChildFolders -Path "$env:AGENT_TOOLSDIRECTORY\$SoftwareName" + if ($versions.count -gt 0){ + foreach ($version in $versions) + { + $architectures = GetChildFolders -Path "$env:AGENT_TOOLSDIRECTORY\$SoftwareName\$version" + + Write-Host "$SoftwareName version - $version : $([system.String]::Join(",", $architectures))" + + foreach ($arch in $architectures) + { + $path = "$env:AGENT_TOOLSDIRECTORY\$SoftwareName\$version\$arch" + foreach ($test in $ExecTests) + { + if (Test-Path "$path\$test") + { + Write-Host "$SoftwareName($test) $version($arch) is successfully installed:" + Write-Host (& "$path\$test" --version) + } + else + { + Write-Host "$SoftwareName($test) $version ($arch) is not installed" + exit 1 + } + } + + $description += "_Version:_ $version ($arch)
" + } + } + + $description += $Note + Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $description + } + else + { + Write-Host "$env:AGENT_TOOLSDIRECTORY\$SoftwareName does not include any folders" + exit 1 + } + } + else + { + Write-Host "$env:AGENT_TOOLSDIRECTORY\$SoftwareName does not exist" + exit 1 + } +} + +# Python test +$PythonNote += @" +
+> Note: These versions of Python are available through the [Use Python Version](https://go.microsoft.com/fwlink/?linkid=871498) task. +"@ +$PythonTests = @("python.exe", "Scripts\pip.exe") +ToolcacheTest -SoftwareName "Python" -ExecTests $PythonTests -Note $PythonNote + +# PyPy test +$PyPyNote += @" +
+> Note: These versions of PyPy are available through the [Use Python Version](https://go.microsoft.com/fwlink/?linkid=871498) task. +"@ +$PyPyTests = @("python.exe", "bin\pip.exe") +ToolcacheTest -SoftwareName "PyPy" -ExecTests $PyPyTests -Note $PyPyNote + +# Ruby test +$RubyNote += @" +
+> Note: These versions of Ruby are available through the [Use Ruby Version](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/tool/use-ruby-version) task. +"@ +$RubyTests = @("bin\ruby.exe") +ToolcacheTest -SoftwareName "Ruby" -ExecTests $RubyTests -Note $RubyNote diff --git a/images/win/scripts/Installers/Validate-TypeScript.ps1 b/images/win/scripts/Installers/Validate-TypeScript.ps1 new file mode 100644 index 00000000..430e6456 --- /dev/null +++ b/images/win/scripts/Installers/Validate-TypeScript.ps1 @@ -0,0 +1,27 @@ +################################################################################ +## File: Validate-TypeScript.ps1 +## Team: CI Build +## Desc: Validate Typescript Installation +################################################################################ + +if(Get-Command -Name 'tsc') +{ + Write-Host "TypeScript $(tsc --version) is on the path." +} +else +{ + Write-Host "TypeScript is not on the path." + exit 1 +} + + +$typescriptVersion = $(tsc --version) + +# Adding description of the software to Markdown +$SoftwareName = "TypeScript" + +$Description = @" +_Version:_ $typescriptVersion
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-Vcpkg.ps1 b/images/win/scripts/Installers/Validate-Vcpkg.ps1 new file mode 100644 index 00000000..834acf0b --- /dev/null +++ b/images/win/scripts/Installers/Validate-Vcpkg.ps1 @@ -0,0 +1,46 @@ +################################################################################ +## File: Validate-Vcpkg.ps1 +## Desc: Validate vcpkg Cli +################################################################################ + +if (Get-Command -Name 'Vcpkg') +{ + Write-Host 'Vcpkg is succesfully installed:' + vcpkg version | Write-Host +} +else +{ + Write-Host 'Vcpkg is not on PATH' + exit 1 +} + +if ($env:VCPKG_INSTALLATION_ROOT) +{ + Write-Host "The VCPKG_INSTALLATION_ROOT environment variable is set" + Write-Host $env:VCPKG_INSTALLATION_ROOT +} +else +{ + Write-Host "The VCPKG_INSTALLATION_ROOT environment variable is not set" + exit 1 +} + +# Adding description of the software to Markdown + +# `vcpkg version` gives output like: +# Vcpkg package management program version 2018.11.23-nohash +# +# See LICENSE.txt for license information. + +$SoftwareName = 'Vcpkg' +$(vcpkg version).Split([System.Environment]::NewLine)[0] -match "\d+.\d+.\d+.*" +$VcpkgVersion = $Matches[0] + +$Description = @" +_Version:_ $VcpkgVersion
+_Environment:_ +* PATH: contains location of the vcpkg directory +* VCPKG_INSTALLATION_ROOT: root directory of the vcpkg installation +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Validate-WinAppDriver.ps1 b/images/win/scripts/Installers/Validate-WinAppDriver.ps1 new file mode 100644 index 00000000..9852b345 --- /dev/null +++ b/images/win/scripts/Installers/Validate-WinAppDriver.ps1 @@ -0,0 +1,45 @@ +################################################################################ +## File: Validate-WinAppDriver.ps1 +## Desc: Validate WinAppDriver installation +################################################################################ + +$wad = "Windows Application Driver"; +if (${Env:ProgramFiles(x86)}) +{ + $wadPath = "${Env:ProgramFiles(x86)}\$wad" +} +else +{ + $wadPath = "${Env:ProgramFiles}\$wad" +} + +if(Test-Path $wadPath -PathType Any) +{ + Write-Host "WinAppDriver directory found." +} +else +{ + Write-Host "Failed to locate WinAppDriver directory. Exiting." + exit 1 +} + +#Validate if Developer Mode is enabled +$path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"; +if((Get-ItemProperty -Path $path | Select-Object -ExpandProperty "AllowDevelopmentWithoutDevLicense") -eq 1) +{ + Write-Host "Developer Mode is successfully provisioned." +} +else +{ + Write-Host "Developer Mode was not successfully provisioned." + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "WinAppDriver" +$version = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe").FileVersion +$Description = @" +_Version:_ $version
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 b/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 new file mode 100644 index 00000000..0cbb5c77 --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 @@ -0,0 +1,145 @@ +################################################################################ +## File: Initialize-VM.ps1 +## Desc: VM initialization script, machine level configuration +################################################################################ + +function Disable-InternetExplorerESC { + $AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}" + $UserKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}" + Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0 -Force + Set-ItemProperty -Path $UserKey -Name "IsInstalled" -Value 0 -Force + Stop-Process -Name Explorer -Force -ErrorAction Continue + Write-Host "IE Enhanced Security Configuration (ESC) has been disabled." +} + +function Disable-InternetExplorerWelcomeScreen { + $AdminKey = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main" + New-Item -Path $AdminKey -Value 1 -Force + Set-ItemProperty -Path $AdminKey -Name "DisableFirstRunCustomize" -Value 1 -Force + Write-Host "Disabled IE Welcome screen" +} + +function Disable-UserAccessControl { + Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "ConsentPromptBehaviorAdmin" -Value 00000000 -Force + Write-Host "User Access Control (UAC) has been disabled." +} + +Import-Module -Name ImageHelpers -Force + +Write-Host "Setup PowerShellGet" +# Set-PSRepository -InstallationPolicy Trusted -Name PSGallery +Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force +Install-Module -Name PowerShellGet -Force +Set-PSRepository -InstallationPolicy Trusted -Name PSGallery + + +Write-Host "Disable Antivirus" +Set-MpPreference -DisableRealtimeMonitoring $true + +# Disable Windows Update +$AutoUpdatePath = "HKLM:SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" +If (Test-Path -Path $AutoUpdatePath) { + Set-ItemProperty -Path $AutoUpdatePath -Name NoAutoUpdate -Value 1 + Write-Host "Disabled Windows Update" +} +else { + Write-Host "Windows Update key does not exist" +} + +# Install .NET Framework 3.5 (required by Chocolatey) +Install-WindowsFeature -Name NET-Framework-Features -IncludeAllSubFeature +# Explicitly install all 4.7 sub features to include ASP.Net. +# As of 1/16/2019, WinServer 19 lists .Net 4.7 as NET-Framework-45-Features +Install-WindowsFeature -Name NET-Framework-45-Features -IncludeAllSubFeature + +Write-Host "Disable UAC" +Disable-UserAccessControl + +Write-Host "Disable IE Welcome Screen" +Disable-InternetExplorerWelcomeScreen + +Write-Host "Disable IE ESC" +Disable-InternetExplorerESC + +Write-Host "Setting local execution policy" +Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -ErrorAction Continue | Out-Null +Get-ExecutionPolicy -List + +Write-Host "Enable long path behavior" +# See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation +Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1 + +Write-Host "Install chocolatey" +$chocoExePath = 'C:\ProgramData\Chocolatey\bin' + +if ($($env:Path).ToLower().Contains($($chocoExePath).ToLower())) { + Write-Host "Chocolatey found in PATH, skipping install..." + Exit +} + +# Add to system PATH +$systemPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine) +$systemPath += ';' + $chocoExePath +[Environment]::SetEnvironmentVariable("PATH", $systemPath, [System.EnvironmentVariableTarget]::Machine) + +# Update local process' path +$userPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::User) +if ($userPath) { + $env:Path = $systemPath + ";" + $userPath +} +else { + $env:Path = $systemPath +} + +# Run the installer +Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) + +# Turn off confirmation +choco feature enable -n allowGlobalConfirmation + +# Install webpi +choco install webpicmd -y + +# Expand disk size of OS drive + +New-Item -Path d:\ -Name cmds.txt -ItemType File -Force + +Add-Content -Path d:\cmds.txt "SELECT VOLUME=C`r`nEXTEND" + +$expandResult = (diskpart /s 'd:\cmds.txt') + +Write-Host $expandResult + +Write-Host "Disk sizes after expansion" + +wmic logicaldisk get size,freespace,caption + + +# Adding description of the software to Markdown + +$Content = @" +# Azure Pipelines Hosted Windows 2019 + +The following software is installed on machines in the Azure Pipelines **Hosted Windows 2019** (v$env:ImageVersion) pool. + +Components marked with **\*** have been upgraded since the previous version of the image. + +"@ + +Add-ContentToMarkdown -Content $Content + + +$SoftwareName = "Chocolatey" + +if( $( $(choco version) | Out-String) -match 'Chocolatey v(?.*).*' ) +{ + $chocoVersion = $Matches.version.Trim() +} + +$Description = @" +_Version:_ $chocoVersion
+_Environment:_ +* PATH: contains location for choco.exe +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Windows2019/Install-Python.ps1 b/images/win/scripts/Installers/Windows2019/Install-Python.ps1 new file mode 100644 index 00000000..4bc73c56 --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Install-Python.ps1 @@ -0,0 +1,28 @@ +################################################################################ +## File: Install-Python.ps1 +## Desc: Configure python on path with 3.7.* version from the tools cache +## Must run after tools cache is setup +################################################################################ + +Import-Module -Name ImageHelpers -Force + +$python37path = $Env:AGENT_TOOLSDIRECTORY + '/Python/3.7*/x64' +$pythonDir = Get-Item -Path $python37path + +if($pythonDir -is [array]) +{ + Write-Host "More than one python 3.7.* installations found" + Write-Host $pythonDir + exit 1 +} + +$currentPath = Get-MachinePath + +if ($currentPath | Select-String -SimpleMatch $pythonDir.FullName) +{ + Write-Host $pythonDir.FullName ' is already in PATH' + exit 0 +} + +Add-MachinePathItem -PathItem $pythonDir.FullName +Add-MachinePathItem -PathItem "$($pythonDir.FullName)\Scripts" diff --git a/images/win/scripts/Installers/Windows2019/Install-VS2019.ps1 b/images/win/scripts/Installers/Windows2019/Install-VS2019.ps1 new file mode 100644 index 00000000..3e64e6fd --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Install-VS2019.ps1 @@ -0,0 +1,188 @@ +################################################################################ +## File: Install-VS2019.ps1 +## Desc: Install Visual Studio 2019 +################################################################################ +$ErrorActionPreference = "Stop" + +Function InstallVS +{ + Param + ( + [String]$WorkLoads, + [String]$Sku, + [String] $VSBootstrapperURL + ) + + $exitCode = -1 + + try + { + Write-Host "Enable short name support on Windows needed for Xamarin Android AOT, defaults appear to have been changed in Azure VMs" + $shortNameEnableProcess = Start-Process -FilePath fsutil.exe -ArgumentList ('8dot3name', 'set', '0') -Wait -PassThru + $shortNameEnableExitCode = $shortNameEnableProcess.ExitCode + + if ($shortNameEnableExitCode -ne 0) + { + Write-Host -Object 'Enabling short name support on Windows failed. This needs to be enabled prior to VS 2017 install for Xamarin Andriod AOT to work.' + exit $shortNameEnableExitCode + } + + Write-Host "Downloading Bootstrapper ..." + Invoke-WebRequest -Uri $VSBootstrapperURL -OutFile "${env:Temp}\vs_$Sku.exe" + + $FilePath = "${env:Temp}\vs_$Sku.exe" + $Arguments = ('/c', $FilePath, $WorkLoads, '--quiet', '--norestart', '--wait', '--nocache' ) + + Write-Host "Starting Install ..." + $process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru + $exitCode = $process.ExitCode + + if ($exitCode -eq 0 -or $exitCode -eq 3010) + { + Write-Host -Object 'Installation successful' + return $exitCode + } + else + { + Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." + + # this wont work because of log size limitation in extension manager + # Get-Content $customLogFilePath | Write-Host + + exit $exitCode + } + } + catch + { + Write-Host -Object "Failed to install Visual Studio. Check the logs for details in $customLogFilePath" + Write-Host -Object $_.Exception.Message + exit -1 + } +} + +$WorkLoads = '--allWorkloads --includeRecommended ' + ` + '--add Component.Dotfuscator ' + ` + '--add Component.Linux.CMake ' + ` + '--add Component.UnityEngine.x64 ' + ` + '--add Component.UnityEngine.x86 ' + ` + '--add Component.Unreal.Android ' + ` + '--add Microsoft.Component.Azure.DataLake.Tools ' + ` + '--add Microsoft.Component.CookiecutterTools ' + ` + '--add Microsoft.Component.PythonTools.Miniconda ' + ` + '--add Microsoft.Component.PythonTools.Web ' + ` + '--add Microsoft.Component.VC.Runtime.UCRTSDK ' + ` + '--add Microsoft.Net.ComponentGroup.4.6.2.DeveloperTools ' + ` + '--add Microsoft.Net.ComponentGroup.4.7.1.DeveloperTools ' + ` + '--add Microsoft.Net.ComponentGroup.4.7.DeveloperTools ' + ` + '--add Microsoft.VisualStudio.Component.AspNet45 ' + ` + '--add Microsoft.VisualStudio.Component.Azure.Kubernetes.Tools ' + ` + '--add Microsoft.VisualStudio.Component.Azure.MobileAppsSdk ' + ` + '--add Microsoft.VisualStudio.Component.Azure.ServiceFabric.Tools ' + ` + '--add Microsoft.VisualStudio.Component.Azure.Storage.AzCopy ' + ` + '--add Microsoft.VisualStudio.Component.Debugger.JustInTime ' + ` + '--add Microsoft.VisualStudio.Component.DslTools ' + ` + '--add Microsoft.VisualStudio.Component.EntityFramework ' + ` + '--add Microsoft.VisualStudio.Component.FSharp.Desktop ' + ` + '--add Microsoft.VisualStudio.Component.LinqToSql ' + ` + '--add Microsoft.VisualStudio.Component.PortableLibrary ' + ` + '--add Microsoft.VisualStudio.Component.TeamOffice ' + ` + '--add Microsoft.VisualStudio.Component.TestTools.CodedUITest ' + ` + '--add Microsoft.VisualStudio.Component.TestTools.WebLoadTest ' + ` + '--add Microsoft.VisualStudio.Component.UWP.VC.ARM64 ' + ` + '--add Microsoft.VisualStudio.Component.VC.140 ' + ` + '--add Microsoft.VisualStudio.Component.VC.ATL.ARM ' + ` + '--add Microsoft.VisualStudio.Component.VC.ATLMFC ' + ` + '--add Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre ' + ` + '--add Microsoft.VisualStudio.Component.VC.CLI.Support ' + ` + '--add Microsoft.VisualStudio.Component.VC.CMake.Project ' + ` + '--add Microsoft.VisualStudio.Component.VC.DiagnosticTools ' + ` + '--add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset ' + ` + '--add Microsoft.VisualStudio.Component.VC.MFC.ARM ' + ` + '--add Microsoft.VisualStudio.Component.VC.MFC.ARM.Spectre ' + ` + '--add Microsoft.VisualStudio.Component.VC.MFC.ARM64 ' + ` + '--add Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre ' + ` + '--add Microsoft.VisualStudio.Component.VC.Runtimes.ARM.Spectre ' + ` + '--add Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre ' + ` + '--add Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre ' + ` + '--add Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest ' + ` + '--add Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest ' + ` + '--add Microsoft.VisualStudio.Component.VC.v141 ' + ` + '--add Microsoft.VisualStudio.Component.Windows10SDK.16299 ' + ` + '--add Microsoft.VisualStudio.Component.Windows10SDK.17134 ' + ` + '--add Microsoft.VisualStudio.Component.Windows10SDK.17763 ' + ` + '--add Microsoft.VisualStudio.Component.Windows10SDK.18362 ' + ` + '--add Microsoft.VisualStudio.ComponentGroup.Azure.CloudServices ' + ` + '--add Microsoft.VisualStudio.ComponentGroup.Azure.ResourceManager.Tools ' + ` + '--add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Llvm.Clang ' + ` + '--add Microsoft.VisualStudio.ComponentGroup.Web.CloudTools ' + ` + '--add Microsoft.VisualStudio.Workload.Azure ' + ` + '--add Microsoft.VisualStudio.Workload.Data ' + ` + '--add Microsoft.VisualStudio.Workload.DataScience ' + ` + '--add Microsoft.VisualStudio.Workload.ManagedDesktop ' + ` + '--add Microsoft.VisualStudio.Workload.ManagedGame ' + ` + '--add Microsoft.VisualStudio.Workload.NativeCrossPlat ' + ` + '--add Microsoft.VisualStudio.Workload.NativeDesktop ' + ` + '--add Microsoft.VisualStudio.Workload.NativeGame ' + ` + '--add Microsoft.VisualStudio.Workload.NativeMobile ' + ` + '--add Microsoft.VisualStudio.Workload.NetCoreTools ' + ` + '--add Microsoft.VisualStudio.Workload.NetCrossPlat ' + ` + '--add Microsoft.VisualStudio.Workload.NetWeb ' + ` + '--add Microsoft.VisualStudio.Workload.Node ' + ` + '--add Microsoft.VisualStudio.Workload.Office ' + ` + '--add Microsoft.VisualStudio.Workload.Python ' + ` + '--remove Component.CPython3.x64 ' + ` + '--add Microsoft.VisualStudio.Workload.Universal ' + ` + '--add Microsoft.VisualStudio.Workload.VisualStudioExtension' + + +$ReleaseInPath = 'Enterprise' +$Sku = 'Enterprise' +$VSBootstrapperURL = 'https://aka.ms/vs/16/release/vs_Enterprise.exe' + +$ErrorActionPreference = 'Stop' + +# Install VS +$exitCode = InstallVS -WorkLoads $WorkLoads -Sku $Sku -VSBootstrapperURL $VSBootstrapperURL + +# Find the version of VS installed for this instance +# Only supports a single instance +$vsProgramData = Get-Item -Path "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances" +$instanceFolders = Get-ChildItem -Path $vsProgramData.FullName + +if($instanceFolders -is [array]) +{ + Write-Host "More than one instance installed" + exit 1 +} + +$catalogContent = Get-Content -Path ($instanceFolders.FullName + '\catalog.json') +$catalog = $catalogContent | ConvertFrom-Json +$version = $catalog.info.id +Write-Host "Visual Studio version" $version "installed" + +# Initialize Visual Studio Experimental Instance +&"C:\Program Files (x86)\Microsoft Visual Studio\2019\$ReleaseInPath\Common7\IDE\devenv.exe" /RootSuffix Exp /ResetSettings General.vssettings /Command File.Exit + +# Updating content of MachineState.json file to disable autoupdate of VSIX extensions +$newContent = '{"Extensions":[{"Key":"1e906ff5-9da8-4091-a299-5c253c55fdc9","Value":{"ShouldAutoUpdate":false}},{"Key":"Microsoft.VisualStudio.Web.AzureFunctions","Value":{"ShouldAutoUpdate":false}}],"ShouldAutoUpdate":false,"ShouldCheckForUpdates":false}' +Set-Content -Path "C:\Program Files (x86)\Microsoft Visual Studio\2019\$ReleaseInPath\Common7\IDE\Extensions\MachineState.json" -Value $newContent + + +# Adding description of the software to Markdown + +$SoftwareName = "Visual Studio 2019 Enterprise" + +$Description = @" +_Version:_ $version
+_Location:_ C:\Program Files (x86)\Microsoft Visual Studio\2019\$ReleaseInPath + +The following workloads and components are installed with Visual Studio 2019: +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +# Adding explicitly added Workloads details to markdown by parsing $Workloads +Add-ContentToMarkdown -Content $($WorkLoads.Split('--') | % { if( ($_.Split(" "))[0] -like "add") { "* " +($_.Split(" "))[1] } } ) + + +exit $exitCode diff --git a/images/win/scripts/Installers/Windows2019/Install-WDK.ps1 b/images/win/scripts/Installers/Windows2019/Install-WDK.ps1 new file mode 100644 index 00000000..192e4789 --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Install-WDK.ps1 @@ -0,0 +1,53 @@ +################################################################################ +## File: Install-WDK.ps1 +## Desc: Install the Windows Driver Kit +################################################################################ + +# Version: 10.0.17763.0 +# Update Validate-WDK.ps1 if the version changes! +# There doesn't seem to be any way to check the version programmatically + +# Requires Windows SDK with the same version number as the WDK +$winSdkUrl = "https://go.microsoft.com/fwlink/p/?LinkID=2023014" +$wdkUrl = "https://go.microsoft.com/fwlink/?linkid=2026156" + +# `winsdksetup.exe /features + /quiet` installs all features without showing the GUI +$sdkExitCode = Install-EXE -Url $winSdkUrl -Name "winsdksetup.exe" -ArgumentList ("/features", "+", "/quiet") + +if ($sdkExitCode -ne 0) +{ + Write-Host "Failed to install the Windows SDK." + exit $sdkExitCode +} + +# `wdksetup.exe /features + /quiet` installs all features without showing the GUI +$wdkExitCode = Install-EXE -Url $wdkUrl -Name "wdksetup.exe" -ArgumentList ("/features", "+", "/quiet") + +if ($wdkExitCode -ne 0) +{ + Write-Host "Failed to install the Windows Driver Kit." + exit $wdkExitCode +} + +# Need to install the VSIX to get the build targets when running VSBuild +# Write-Host "Installing WDK.vsix" +<# ISSUE - VSIX installer failing on VS2019 + $process = Start-Process ` + -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VSIXInstaller.exe" ` + -ArgumentList ("/quiet", '"C:\Program Files (x86)\Windows Kits\10\Vsix\WDK.vsix"') ` + -Wait ` + -PassThru + + $exitCode = $process.ExitCode + +if ($exitCode -eq 0 -or $exitCode -eq 1001) # 1001 means the extension is already installed +{ + Write-Host "WDK.vsix installed successfully" +} +else +{ + Write-Host "Unsuccessful exit code returned by the installation process: $exitCode." +} + +exit $exitCode +#> diff --git a/images/win/scripts/Installers/Windows2019/Install-Wix.ps1 b/images/win/scripts/Installers/Windows2019/Install-Wix.ps1 new file mode 100644 index 00000000..1e433289 --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Install-Wix.ps1 @@ -0,0 +1,53 @@ +################################################################################ +## File: Install-Wix.ps1 +## Desc: Install WIX. +################################################################################ +function Install-VsixExtension +{ + Param + ( + [String]$Url, + [String]$Name + ) + + $ReleaseInPath = 'Enterprise' + $exitCode = -1 + + try + { + Write-Host "Downloading $Name..." + $FilePath = "${env:Temp}\$Name" + + Invoke-WebRequest -Uri $Url -OutFile $FilePath + + $ArgumentList = ('/quiet', $FilePath) + + Write-Host "Starting Install $Name..." + $process = Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\2019\$ReleaseInPath\Common7\IDE\VSIXInstaller.exe" -ArgumentList $ArgumentList -Wait -PassThru + $exitCode = $process.ExitCode + + if ($exitCode -eq 0 -or $exitCode -eq 3010) + { + Write-Host -Object 'Installation successful' + return $exitCode + } + else + { + Write-Host -Object "Non zero exit code returned by the installation process : $exitCode." + return $exitCode + } + } + catch + { + Write-Host -Object "Failed to install the Extension $Name" + Write-Host -Object $_.Exception.Message + return -1 + } +} + + +choco install wixtoolset -y --force + +#Installing VS extension 'Wix Toolset Visual Studio 2019 Extension' +$exitCode = Install-VsixExtension -Url 'https://wixtoolset.gallerycdn.vsassets.io/extensions/wixtoolset/wixtoolsetvisualstudio2019extension/1.0.0.4/1563296438961/Votive2019.vsix' -Name 'Votive2019.vsix' +#return $exitCode diff --git a/images/win/scripts/Installers/Windows2019/Run-Antivirus.ps1 b/images/win/scripts/Installers/Windows2019/Run-Antivirus.ps1 new file mode 100644 index 00000000..bf57ed30 --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Run-Antivirus.ps1 @@ -0,0 +1,27 @@ +################################################################################ +## File: Run-Antivirus.ps1 +## Desc: Run a full antivirus scan. +## Run right after cleanup before we sysprep +################################################################################ + +Write-Host "Make sure windefend is going to start" +Start-Service windefend -ErrorAction Continue + +Write-Host "Waiting for windefend to report as running" +$service = Get-Service "Windefend" +$service.WaitForStatus("Running","00:10:00") + +Write-Host "Run antivirus" +Push-Location "C:\Program Files\Windows Defender" + +# Tell Defender to use 100% of the CPU during the scan +Set-MpPreference -ScanAvgCPULoadFactor 100 + +# Full Scan +.\MpCmdRun.exe -Scan -ScanType 2 +Pop-Location + +Update-MpSignature +Write-Host "Set antivirus parmeters" +Set-MpPreference -ScanAvgCPULoadFactor 5 ` + -ExclusionPath "D:\", "C:\" diff --git a/images/win/scripts/Installers/Windows2019/Update-DockerImages.ps1 b/images/win/scripts/Installers/Windows2019/Update-DockerImages.ps1 new file mode 100644 index 00000000..8aa369f2 --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Update-DockerImages.ps1 @@ -0,0 +1,36 @@ +################################################################################ +## File: Update-DockerImages.ps1 +## Desc: Pull some standard docker images. +## Must be run after docker is installed. +################################################################################ + +function DockerPull { + Param ([string]$image) + + Write-Host Installing $image ... + docker pull $image + + if (!$?) { + echo "Docker pull failed with a non-zero exit code" + exit 1 + } +} + +DockerPull mcr.microsoft.com/windows/servercore:ltsc2019 +DockerPull mcr.microsoft.com/windows/nanoserver:1809 +DockerPull microsoft/aspnetcore-build:1.0-2.0 +DockerPull mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019 +DockerPull mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2019 + + +# Adding description of the software to Markdown + +$SoftwareName = "Docker images" + +$Description = @" +The following container images have been cached: +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description + +Add-ContentToMarkdown -Content $(docker images --digests --format "* {{.Repository}}:{{.Tag}} (Digest: {{.Digest}})") diff --git a/images/win/scripts/Installers/Windows2019/Validate-WDK.ps1 b/images/win/scripts/Installers/Windows2019/Validate-WDK.ps1 new file mode 100644 index 00000000..3d2b8c6a --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Validate-WDK.ps1 @@ -0,0 +1,13 @@ +################################################################################ +## File: Validate-WDK.ps1 +## Desc: Validate the installation of the Windows Driver Kit +################################################################################ + +# Adding description of the software to Markdown +$SoftwareName = "Windows Driver Kit" + +$Description = @" +_Version:_ 10.0.17763.0
+"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/Installers/Windows2019/Validate-Wix.ps1 b/images/win/scripts/Installers/Windows2019/Validate-Wix.ps1 new file mode 100644 index 00000000..1eddcd6a --- /dev/null +++ b/images/win/scripts/Installers/Windows2019/Validate-Wix.ps1 @@ -0,0 +1,61 @@ +################################################################################ +## File: Validate-Wix.ps1 +## Desc: Validate WIX. +################################################################################ + +Import-Module -Name ImageHelpers -Force +function Get-WixVersion { + $regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" + $installedApplications = Get-ItemProperty -Path $regKey + $Version = ($installedApplications | Where-Object { $_.DisplayName -and $_.DisplayName.toLower().Contains("wix") } | Select-Object -First 1).DisplayVersion + return $Version +} + +#Gets the extension details from state.json +function Get-WixExtensionPackage { + $vsProgramData = Get-Item -Path "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances" + $instanceFolders = Get-ChildItem -Path $vsProgramData.FullName + + if($instanceFolders -is [array]) + { + Write-Host "More than one instance installed" + exit 1 + } + + $stateContent = Get-Content -Path ($instanceFolders.FullName + '\state.packages.json') + $state = $stateContent | ConvertFrom-Json + $WixPackage = $state.packages | where { $_.id -eq "WixToolset.VisualStudioExtension.Dev16" } + return $WixPackage +} + +$WixToolSetVersion = Get-WixVersion + +if($WixToolSetVersion) { + Write-Host "Wix Toolset version" $WixPackage.version "installed" +} +else { + Write-Host "Wix Toolset is not installed" + exit 1 +} + +$WixPackage = Get-WixExtensionPackage + +if($WixPackage) { + Write-Host "Wix Extension version" $WixPackage.version "installed" +} +else { + Write-Host "Wix Extension is not installed" + exit 1 +} + +# Adding description of the software to Markdown +$SoftwareName = "WIX Tools" + +$Description = @" +_Toolset Version:_ $WixToolSetVersion
+_WIX Toolset Visual Studio Extension Version:_ $($WixPackage.version)
+_Environment:_ +* WIX: Installation root of WIX +"@ + +Add-SoftwareDetailsToMarkdown -SoftwareName $SoftwareName -DescriptionMarkdown $Description diff --git a/images/win/scripts/README.md b/images/win/scripts/README.md new file mode 100644 index 00000000..cde361cd --- /dev/null +++ b/images/win/scripts/README.md @@ -0,0 +1 @@ +Common scripts for all Windows images. \ No newline at end of file