├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── announcement.yml │ ├── bug-report.yml │ ├── config.yml │ └── tool-request.yml ├── pull_request_template.md └── workflows │ ├── check-pinned-versions.yml │ ├── codeql-analysis.yml │ ├── create_github_release.yml │ ├── create_pull_request.yml │ ├── create_sbom_report.yml │ ├── linter.yml │ ├── merge_pull_request.yml │ ├── powershell-tests.yml │ ├── trigger-ubuntu-win-build.yml │ ├── ubuntu2204.yml │ ├── ubuntu2404.yml │ ├── update_github_release.yml │ ├── validate-json-schema.yml │ ├── windows2019.yml │ ├── windows2022.yml │ └── windows2025.yml ├── .gitignore ├── .vscode ├── extensions.json ├── settings.json └── tasks.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── docs ├── create-image-and-azure-resources.md └── dotnet-ubuntu.md ├── helpers ├── CheckJsonSchema.ps1 ├── CheckOutdatedVersionPinning.ps1 ├── CreateAzureVMFromPackerTemplate.ps1 ├── GenerateResourcesAndImage.ps1 ├── GitHubApi.psm1 ├── WaitWorkflowCompletion.ps1 └── software-report-base │ ├── Calculate-ImagesDifference.ps1 │ ├── SoftwareReport.BaseNodes.psm1 │ ├── SoftwareReport.DifferenceCalculator.psm1 │ ├── SoftwareReport.DifferenceRender.psm1 │ ├── SoftwareReport.Nodes.psm1 │ ├── SoftwareReport.psm1 │ └── tests │ ├── SoftwareReport.Difference.E2E.Tests.ps1 │ ├── SoftwareReport.DifferenceCalculator.Unit.Tests.ps1 │ ├── SoftwareReport.DifferenceRender.Unit.Tests.ps1 │ ├── SoftwareReport.E2E.Tests.ps1 │ ├── SoftwareReport.Nodes.Unit.Tests.ps1 │ └── TestHelpers.psm1 ├── images.CI ├── credscan-exclusions.json ├── linux-and-win │ ├── build-image.ps1 │ ├── cleanup.ps1 │ └── create-release.ps1 ├── measure-provisioners-duration.ps1 └── shebang-linter.ps1 ├── images ├── macos │ ├── assets │ │ ├── add-certificate.swift │ │ ├── auto-software-update-arm64.exp │ │ ├── bashprofile │ │ ├── bashrc │ │ └── bootstrap-provisioner │ │ │ ├── change_password │ │ │ ├── installNewProvisioner.sh │ │ │ ├── kcpassword.py │ │ │ └── setAutoLogin.sh │ ├── macos-13-Readme.md │ ├── macos-13-arm64-Readme.md │ ├── macos-14-Readme.md │ ├── macos-14-arm64-Readme.md │ ├── macos-15-Readme.md │ ├── macos-15-arm64-Readme.md │ ├── scripts │ │ ├── build │ │ │ ├── Configure-Toolset.ps1 │ │ │ ├── Configure-Xcode-Simulators.ps1 │ │ │ ├── Install-Toolset.ps1 │ │ │ ├── Install-Xcode.ps1 │ │ │ ├── Update-XcodeSimulators.ps1 │ │ │ ├── configure-auto-updates.sh │ │ │ ├── configure-autologin.sh │ │ │ ├── configure-hostname.sh │ │ │ ├── configure-machine.sh │ │ │ ├── configure-ntpconf.sh │ │ │ ├── configure-preimagedata.sh │ │ │ ├── configure-shell.sh │ │ │ ├── configure-ssh.sh │ │ │ ├── configure-system.sh │ │ │ ├── configure-tccdb-macos.sh │ │ │ ├── configure-windows.sh │ │ │ ├── configure-xcode.sh │ │ │ ├── install-actions-cache.sh │ │ │ ├── install-android-sdk.sh │ │ │ ├── install-audiodevice.sh │ │ │ ├── install-aws-tools.sh │ │ │ ├── install-azcopy.sh │ │ │ ├── install-bicep.sh │ │ │ ├── install-chrome.sh │ │ │ ├── install-cocoapods.sh │ │ │ ├── install-codeql-bundle.sh │ │ │ ├── install-common-utils.sh │ │ │ ├── install-dotnet.sh │ │ │ ├── install-edge.sh │ │ │ ├── install-firefox.sh │ │ │ ├── install-gcc.sh │ │ │ ├── install-git.sh │ │ │ ├── install-homebrew.sh │ │ │ ├── install-llvm.sh │ │ │ ├── install-mono.sh │ │ │ ├── install-nginx.sh │ │ │ ├── install-node.sh │ │ │ ├── install-openjdk.sh │ │ │ ├── install-openssl.sh │ │ │ ├── install-php.sh │ │ │ ├── install-postgresql.sh │ │ │ ├── install-powershell.sh │ │ │ ├── install-pypy.sh │ │ │ ├── install-python.sh │ │ │ ├── install-rosetta.sh │ │ │ ├── install-ruby.sh │ │ │ ├── install-rubygems.sh │ │ │ ├── install-runner-package.sh │ │ │ ├── install-rust.sh │ │ │ ├── install-safari.sh │ │ │ ├── install-swiftlint.sh │ │ │ ├── install-unxip.sh │ │ │ ├── install-vcpkg.sh │ │ │ └── install-xcode-clt.sh │ │ ├── docs-gen │ │ │ ├── Generate-SoftwareReport.ps1 │ │ │ ├── SoftwareReport.Android.psm1 │ │ │ ├── SoftwareReport.Browsers.psm1 │ │ │ ├── SoftwareReport.Common.psm1 │ │ │ ├── SoftwareReport.Helpers.psm1 │ │ │ ├── SoftwareReport.Java.psm1 │ │ │ ├── SoftwareReport.Toolcache.psm1 │ │ │ └── SoftwareReport.Xcode.psm1 │ │ ├── helpers │ │ │ ├── Common.Helpers.psm1 │ │ │ ├── Xcode.Helpers.psm1 │ │ │ ├── Xcode.Installer.psm1 │ │ │ ├── confirm-identified-developers-macos13.scpt │ │ │ ├── confirm-identified-developers-macos14.scpt │ │ │ ├── confirm-identified-developers-macos15.scpt │ │ │ ├── invoke-tests.sh │ │ │ └── utils.sh │ │ └── tests │ │ │ ├── ActionArchiveCache.Tests.ps1 │ │ │ ├── Android.Tests.ps1 │ │ │ ├── BasicTools.Tests.ps1 │ │ │ ├── Browsers.Tests.ps1 │ │ │ ├── Common.Tests.ps1 │ │ │ ├── Databases.Tests.ps1 │ │ │ ├── Git.Tests.ps1 │ │ │ ├── Helpers.psm1 │ │ │ ├── Java.Tests.ps1 │ │ │ ├── LLVM.Tests.ps1 │ │ │ ├── Linters.Tests.ps1 │ │ │ ├── Mono.Tests.ps1 │ │ │ ├── Node.Tests.ps1 │ │ │ ├── OpenSSL.Tests.ps1 │ │ │ ├── PHP.Tests.ps1 │ │ │ ├── Powershell.Tests.ps1 │ │ │ ├── Python.Tests.ps1 │ │ │ ├── Rosetta.Tests.ps1 │ │ │ ├── Ruby.Tests.ps1 │ │ │ ├── RubyGem.Tests.ps1 │ │ │ ├── RunAll-Tests.ps1 │ │ │ ├── RunnerCache.Tests.ps1 │ │ │ ├── Rust.Tests.ps1 │ │ │ ├── System.Tests.ps1 │ │ │ ├── Toolcache.Tests.ps1 │ │ │ ├── Toolset.Tests.ps1 │ │ │ └── Xcode.Tests.ps1 │ ├── templates │ │ ├── macOS-13.anka.pkr.hcl │ │ ├── macOS-13.arm64.anka.pkr.hcl │ │ ├── macOS-14.anka.pkr.hcl │ │ ├── macOS-14.arm64.anka.pkr.hcl │ │ ├── macOS-15.anka.pkr.hcl │ │ └── macOS-15.arm64.anka.pkr.hcl │ └── toolsets │ │ ├── Readme.md │ │ ├── toolset-13.json │ │ ├── toolset-14.json │ │ └── toolset-15.json ├── ubuntu │ ├── Ubuntu2204-Readme.md │ ├── Ubuntu2404-Readme.md │ ├── assets │ │ ├── post-gen │ │ │ ├── cleanup-logs.sh │ │ │ ├── environment-variables.sh │ │ │ └── systemd-linger.sh │ │ └── ubuntu2204.conf │ ├── scripts │ │ ├── build │ │ │ ├── Configure-Toolset.ps1 │ │ │ ├── Install-PowerShellAzModules.ps1 │ │ │ ├── Install-PowerShellModules.ps1 │ │ │ ├── Install-Toolset.ps1 │ │ │ ├── cleanup.sh │ │ │ ├── configure-apt-mock.sh │ │ │ ├── configure-apt-sources.sh │ │ │ ├── configure-apt.sh │ │ │ ├── configure-dpkg.sh │ │ │ ├── configure-environment.sh │ │ │ ├── configure-image-data.sh │ │ │ ├── configure-limits.sh │ │ │ ├── configure-snap.sh │ │ │ ├── configure-system.sh │ │ │ ├── install-actions-cache.sh │ │ │ ├── install-aliyun-cli.sh │ │ │ ├── install-android-sdk.sh │ │ │ ├── install-apache.sh │ │ │ ├── install-apt-common.sh │ │ │ ├── install-apt-vital.sh │ │ │ ├── install-aws-tools.sh │ │ │ ├── install-azcopy.sh │ │ │ ├── install-azure-cli.sh │ │ │ ├── install-azure-devops-cli.sh │ │ │ ├── install-bazel.sh │ │ │ ├── install-bicep.sh │ │ │ ├── install-clang.sh │ │ │ ├── install-cmake.sh │ │ │ ├── install-codeql-bundle.sh │ │ │ ├── install-container-tools.sh │ │ │ ├── install-docker.sh │ │ │ ├── install-dotnetcore-sdk.sh │ │ │ ├── install-firefox.sh │ │ │ ├── install-gcc-compilers.sh │ │ │ ├── install-gfortran.sh │ │ │ ├── install-git-lfs.sh │ │ │ ├── install-git.sh │ │ │ ├── install-github-cli.sh │ │ │ ├── install-google-chrome.sh │ │ │ ├── install-google-cloud-cli.sh │ │ │ ├── install-haskell.sh │ │ │ ├── install-heroku.sh │ │ │ ├── install-homebrew.sh │ │ │ ├── install-java-tools.sh │ │ │ ├── install-julia.sh │ │ │ ├── install-kotlin.sh │ │ │ ├── install-kubernetes-tools.sh │ │ │ ├── install-leiningen.sh │ │ │ ├── install-microsoft-edge.sh │ │ │ ├── install-miniconda.sh │ │ │ ├── install-mono.sh │ │ │ ├── install-ms-repos.sh │ │ │ ├── install-mssql-tools.sh │ │ │ ├── install-mysql.sh │ │ │ ├── install-nginx.sh │ │ │ ├── install-ninja.sh │ │ │ ├── install-nodejs.sh │ │ │ ├── install-nvm.sh │ │ │ ├── install-oc-cli.sh │ │ │ ├── install-oras-cli.sh │ │ │ ├── install-packer.sh │ │ │ ├── install-php.sh │ │ │ ├── install-pipx-packages.sh │ │ │ ├── install-postgresql.sh │ │ │ ├── install-powershell.sh │ │ │ ├── install-pulumi.sh │ │ │ ├── install-pypy.sh │ │ │ ├── install-python.sh │ │ │ ├── install-rlang.sh │ │ │ ├── install-ruby.sh │ │ │ ├── install-runner-package.sh │ │ │ ├── install-rust.sh │ │ │ ├── install-sbt.sh │ │ │ ├── install-selenium.sh │ │ │ ├── install-sqlpackage.sh │ │ │ ├── install-swift.sh │ │ │ ├── install-terraform.sh │ │ │ ├── install-vcpkg.sh │ │ │ ├── install-yq.sh │ │ │ ├── install-zstd.sh │ │ │ └── post-build-validation.sh │ │ ├── docs-gen │ │ │ ├── Generate-SoftwareReport.ps1 │ │ │ ├── SoftwareReport.Android.psm1 │ │ │ ├── SoftwareReport.Browsers.psm1 │ │ │ ├── SoftwareReport.CachedTools.psm1 │ │ │ ├── SoftwareReport.Common.psm1 │ │ │ ├── SoftwareReport.Databases.psm1 │ │ │ ├── SoftwareReport.Helpers.psm1 │ │ │ ├── SoftwareReport.Java.psm1 │ │ │ ├── SoftwareReport.Rust.psm1 │ │ │ ├── SoftwareReport.Tools.psm1 │ │ │ └── SoftwareReport.WebServers.psm1 │ │ ├── helpers │ │ │ ├── Common.Helpers.psm1 │ │ │ ├── etc-environment.sh │ │ │ ├── install.sh │ │ │ ├── invoke-tests.sh │ │ │ └── os.sh │ │ └── tests │ │ │ ├── ActionArchiveCache.Tests.ps1 │ │ │ ├── Android.Tests.ps1 │ │ │ ├── Apt.Tests.ps1 │ │ │ ├── Browsers.Tests.ps1 │ │ │ ├── CLI.Tools.Tests.ps1 │ │ │ ├── Common.Tests.ps1 │ │ │ ├── Databases.Tests.ps1 │ │ │ ├── DotnetSDK.Tests.ps1 │ │ │ ├── Haskell.Tests.ps1 │ │ │ ├── Helpers.psm1 │ │ │ ├── Java.Tests.ps1 │ │ │ ├── Node.Tests.ps1 │ │ │ ├── PowerShellModules.Tests.ps1 │ │ │ ├── RunAll-Tests.ps1 │ │ │ ├── RunnerCache.Tests.ps1 │ │ │ ├── System.Tests.ps1 │ │ │ ├── Tools.Tests.ps1 │ │ │ ├── Toolset.Tests.ps1 │ │ │ └── WebServers.Tests.ps1 │ ├── templates │ │ ├── build.ubuntu-22_04.pkr.hcl │ │ ├── build.ubuntu-24_04.pkr.hcl │ │ ├── locals.ubuntu.pkr.hcl │ │ ├── source.ubuntu.pkr.hcl │ │ └── variable.ubuntu.pkr.hcl │ └── toolsets │ │ ├── toolset-2204.json │ │ └── toolset-2404.json └── windows │ ├── Windows2019-Readme.md │ ├── Windows2022-Readme.md │ ├── Windows2025-Readme.md │ ├── assets │ └── post-gen │ │ ├── GenerateIISExpressCertificate.ps1 │ │ ├── InternetExplorerConfiguration.ps1 │ │ ├── Msys2FirstLaunch.ps1 │ │ ├── VSConfiguration.ps1 │ │ └── warmup.vdproj │ ├── scripts │ ├── build │ │ ├── Configure-BaseImage.ps1 │ │ ├── Configure-DeveloperMode.ps1 │ │ ├── Configure-Diagnostics.ps1 │ │ ├── Configure-DotnetSecureChannel.ps1 │ │ ├── Configure-DynamicPort.ps1 │ │ ├── Configure-GDIProcessHandleQuota.ps1 │ │ ├── Configure-ImageDataFile.ps1 │ │ ├── Configure-PowerShell.ps1 │ │ ├── Configure-Shell.ps1 │ │ ├── Configure-System.ps1 │ │ ├── Configure-SystemEnvironment.ps1 │ │ ├── Configure-Toolset.ps1 │ │ ├── Configure-User.ps1 │ │ ├── Configure-WindowsDefender.ps1 │ │ ├── Install-AWSTools.ps1 │ │ ├── Install-ActionsCache.ps1 │ │ ├── Install-AliyunCli.ps1 │ │ ├── Install-AndroidSDK.ps1 │ │ ├── Install-Apache.ps1 │ │ ├── Install-AzureCli.ps1 │ │ ├── Install-AzureCosmosDbEmulator.ps1 │ │ ├── Install-AzureDevOpsCli.ps1 │ │ ├── Install-Bazel.ps1 │ │ ├── Install-BizTalkBuildComponent.ps1 │ │ ├── Install-Chocolatey.ps1 │ │ ├── Install-ChocolateyPackages.ps1 │ │ ├── Install-Chrome.ps1 │ │ ├── Install-CloudFoundryCli.ps1 │ │ ├── Install-CodeQLBundle.ps1 │ │ ├── Install-DACFx.ps1 │ │ ├── Install-Docker.ps1 │ │ ├── Install-DockerCompose.ps1 │ │ ├── Install-DockerWinCred.ps1 │ │ ├── Install-DotnetSDK.ps1 │ │ ├── Install-EdgeDriver.ps1 │ │ ├── Install-Firefox.ps1 │ │ ├── Install-Git.ps1 │ │ ├── Install-GitHub-CLI.ps1 │ │ ├── Install-GoogleCloudCLI.ps1 │ │ ├── Install-Haskell.ps1 │ │ ├── Install-IEWebDriver.ps1 │ │ ├── Install-JavaTools.ps1 │ │ ├── Install-Kotlin.ps1 │ │ ├── Install-KubernetesTools.ps1 │ │ ├── Install-LLVM.ps1 │ │ ├── Install-Mercurial.ps1 │ │ ├── Install-Mingw64.ps1 │ │ ├── Install-Miniconda.ps1 │ │ ├── Install-MongoDB.ps1 │ │ ├── Install-Msys2.ps1 │ │ ├── Install-MysqlCli.ps1 │ │ ├── Install-NET48-devpack.ps1 │ │ ├── Install-NET48.ps1 │ │ ├── Install-NSIS.ps1 │ │ ├── Install-NativeImages.ps1 │ │ ├── Install-Nginx.ps1 │ │ ├── Install-NodeJS.ps1 │ │ ├── Install-OpenSSL.ps1 │ │ ├── Install-PHP.ps1 │ │ ├── Install-Pipx.ps1 │ │ ├── Install-PostgreSQL.ps1 │ │ ├── Install-PowerShellModules.ps1 │ │ ├── Install-PowershellAzModules.ps1 │ │ ├── Install-PowershellCore.ps1 │ │ ├── Install-PyPy.ps1 │ │ ├── Install-R.ps1 │ │ ├── Install-RootCA.ps1 │ │ ├── Install-Ruby.ps1 │ │ ├── Install-Runner.ps1 │ │ ├── Install-Rust.ps1 │ │ ├── Install-SQLOLEDBDriver.ps1 │ │ ├── Install-SQLPowerShellTools.ps1 │ │ ├── Install-Sbt.ps1 │ │ ├── Install-Selenium.ps1 │ │ ├── Install-ServiceFabricSDK.ps1 │ │ ├── Install-Stack.ps1 │ │ ├── Install-Toolset.ps1 │ │ ├── Install-TortoiseSvn.ps1 │ │ ├── Install-VCRedist.ps1 │ │ ├── Install-VSExtensions.ps1 │ │ ├── Install-Vcpkg.ps1 │ │ ├── Install-VisualStudio.ps1 │ │ ├── Install-WDK.ps1 │ │ ├── Install-WSL2.ps1 │ │ ├── Install-WebPlatformInstaller.ps1 │ │ ├── Install-WinAppDriver.ps1 │ │ ├── Install-WindowsFeatures.ps1 │ │ ├── Install-WindowsUpdates.ps1 │ │ ├── Install-WindowsUpdatesAfterReboot.ps1 │ │ ├── Install-Wix.ps1 │ │ ├── Install-Zstd.ps1 │ │ ├── Invoke-Cleanup.ps1 │ │ └── Post-Build-Validation.ps1 │ ├── docs-gen │ │ ├── Generate-SoftwareReport.ps1 │ │ ├── SoftwareReport.Android.psm1 │ │ ├── SoftwareReport.Browsers.psm1 │ │ ├── SoftwareReport.CachedTools.psm1 │ │ ├── SoftwareReport.Common.psm1 │ │ ├── SoftwareReport.Databases.psm1 │ │ ├── SoftwareReport.Helpers.psm1 │ │ ├── SoftwareReport.Java.psm1 │ │ ├── SoftwareReport.Tools.psm1 │ │ ├── SoftwareReport.VisualStudio.psm1 │ │ └── SoftwareReport.WebServers.psm1 │ ├── helpers │ │ ├── AndroidHelpers.ps1 │ │ ├── ChocoHelpers.ps1 │ │ ├── ImageHelpers.psd1 │ │ ├── ImageHelpers.psm1 │ │ ├── InstallHelpers.ps1 │ │ ├── PathHelpers.ps1 │ │ ├── VisualStudioHelpers.ps1 │ │ └── test │ │ │ └── ImageHelpers.Tests.ps1 │ └── tests │ │ ├── ActionArchiveCache.Tests.ps1 │ │ ├── Android.Tests.ps1 │ │ ├── Apache.Tests.ps1 │ │ ├── BizTalk.Tests.ps1 │ │ ├── Browsers.Tests.ps1 │ │ ├── CLI.Tools.Tests.ps1 │ │ ├── ChocoPackages.Tests.ps1 │ │ ├── Databases.Tests.ps1 │ │ ├── Docker.Tests.ps1 │ │ ├── DotnetSDK.Tests.ps1 │ │ ├── Git.Tests.ps1 │ │ ├── Haskell.Tests.ps1 │ │ ├── Helpers.psm1 │ │ ├── Java.Tests.ps1 │ │ ├── LLVM.Tests.ps1 │ │ ├── MSYS2.Tests.ps1 │ │ ├── Miniconda.Tests.ps1 │ │ ├── Nginx.Tests.ps1 │ │ ├── Node.Tests.ps1 │ │ ├── PHP.Tests.ps1 │ │ ├── PipxPackages.Tests.ps1 │ │ ├── PowerShellAzModules.Tests.ps1 │ │ ├── PowerShellModules.Tests.ps1 │ │ ├── RunAll-Tests.ps1 │ │ ├── RunnerCache.tests.ps1 │ │ ├── Rust.Tests.ps1 │ │ ├── SSDTExtensions.Tests.ps1 │ │ ├── Shell.Tests.ps1 │ │ ├── Tools.Tests.ps1 │ │ ├── Toolset.Tests.ps1 │ │ ├── VisualStudio.Tests.ps1 │ │ ├── Vsix.Tests.ps1 │ │ ├── WDK.Tests.ps1 │ │ ├── WinAppDriver.Tests.ps1 │ │ ├── WindowsFeatures.Tests.ps1 │ │ └── Wix.Tests.ps1 │ ├── templates │ ├── build.windows-2019.pkr.hcl │ ├── build.windows-2022.pkr.hcl │ ├── build.windows-2025.pkr.hcl │ ├── locals.windows.pkr.hcl │ ├── source.windows.pkr.hcl │ └── variable.windows.pkr.hcl │ └── toolsets │ ├── toolset-2019.json │ ├── toolset-2022.json │ └── toolset-2025.json └── schemas └── toolset-schema.json /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @actions/runner-images-team 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | 3 | contact_links: 4 | - name: Get help in GitHub Discussions 5 | url: https://github.com/actions/runner-images/discussions 6 | about: Have a question? Feel free to ask in the runner-images GitHub Discussions! 7 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | New tool, Bug fixing, or Improvement? 3 | Please include a summary of the change and which issue is fixed. Also include relevant motivation and context. 4 | **For new tools, please provide total size and installation time.** 5 | 6 | <!-- Currently, we can't accept external contributions to macOS source. Please find more details in [CONTRIBUTING.md](CONTRIBUTING.md#macOS) guide --> 7 | 8 | #### Related issue: 9 | 10 | ## Check list 11 | - [ ] Related issue / work item is attached 12 | - [ ] Tests are written (if applicable) 13 | - [ ] Documentation is updated (if applicable) 14 | - [ ] Changes are tested and related VM images are successfully generated 15 | -------------------------------------------------------------------------------- /.github/workflows/check-pinned-versions.yml: -------------------------------------------------------------------------------- 1 | name: Check Outdated Version Pinning 2 | 3 | on: 4 | schedule: 5 | - cron: '0 12 * * 1' # Run at 12:00 UTC every Monday 6 | 7 | permissions: 8 | issues: write 9 | contents: read 10 | 11 | jobs: 12 | check-pinning-dates: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v4 17 | 18 | - name: Validate JSON Schema 19 | shell: pwsh 20 | run: ./helpers/CheckOutdatedVersionPinning.ps1 21 | env: 22 | GH_TOKEN: ${{ github.token }} 23 | -------------------------------------------------------------------------------- /.github/workflows/create_github_release.yml: -------------------------------------------------------------------------------- 1 | name: Create GitHub release 2 | 3 | on: 4 | repository_dispatch: 5 | types: [create-github-release] 6 | 7 | 8 | jobs: 9 | Create_GitHub_release: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Create release for ${{ github.event.client_payload.ReleaseBranchName }} 16 | uses: ncipollo/release-action@v1.16.0 17 | with: 18 | tag: ${{ github.event.client_payload.ReleaseBranchName }} 19 | name: ${{ github.event.client_payload.ReleaseTitle }} 20 | body: ${{ github.event.client_payload.ReleaseBody }} 21 | prerelease: ${{ github.event.client_payload.Prerelease }} 22 | commit: ${{ github.event.client_payload.Commitish }} 23 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | # CI Validation 2 | 3 | name: Linter 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '**.json' 10 | - '**.md' 11 | - '**.sh' 12 | 13 | jobs: 14 | build: 15 | name: Lint JSON & MD files 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout Code 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Lint Code Base 25 | uses: github/super-linter/slim@v7 26 | env: 27 | VALIDATE_ALL_CODEBASE: false 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | VALIDATE_JSON: true 30 | VALIDATE_MARKDOWN: true 31 | DEFAULT_BRANCH: ${{ github.base_ref }} 32 | FILTER_REGEX_EXCLUDE: .*images/*/.*-Readme.md 33 | 34 | - name: Checking shebang lines in MacOS and Ubuntu releases. 35 | run: ./images.CI/shebang-linter.ps1 36 | shell: pwsh 37 | -------------------------------------------------------------------------------- /.github/workflows/powershell-tests.yml: -------------------------------------------------------------------------------- 1 | # CI Validation 2 | 3 | name: PowerShell Tests 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - 'helpers/software-report-base/**' 10 | 11 | jobs: 12 | powershell-tests: 13 | name: PowerShell tests 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout Repository 18 | uses: actions/checkout@v4 19 | 20 | - name: Run Software Report module tests 21 | shell: pwsh 22 | run: | 23 | $ErrorActionPreference = "Stop" 24 | Invoke-Pester -Output Detailed "helpers/software-report-base/tests" 25 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu2204.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Ubuntu22.04 CI 2 | run-name: Ubuntu22.04 - ${{ github.event.pull_request.title }} 3 | 4 | on: 5 | pull_request_target: 6 | types: labeled 7 | paths: 8 | - 'images/ubuntu/**' 9 | 10 | defaults: 11 | run: 12 | shell: pwsh 13 | 14 | jobs: 15 | Ubuntu_2204: 16 | if: github.event.label.name == 'CI ubuntu-all' || github.event.label.name == 'CI ubuntu-2204' 17 | uses: ./.github/workflows/trigger-ubuntu-win-build.yml 18 | with: 19 | image_type: 'ubuntu2204' 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu2404.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Ubuntu24.04 CI 2 | run-name: Ubuntu24.04 - ${{ github.event.pull_request.title }} 3 | 4 | on: 5 | pull_request_target: 6 | types: labeled 7 | paths: 8 | - 'images/ubuntu/**' 9 | 10 | defaults: 11 | run: 12 | shell: pwsh 13 | 14 | jobs: 15 | Ubuntu_2404: 16 | if: github.event.label.name == 'CI ubuntu-all' || github.event.label.name == 'CI ubuntu-2404' 17 | uses: ./.github/workflows/trigger-ubuntu-win-build.yml 18 | with: 19 | image_type: 'ubuntu2404' 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/update_github_release.yml: -------------------------------------------------------------------------------- 1 | name: Update release 2 | 3 | on: 4 | repository_dispatch: 5 | types: [update-github-release] 6 | 7 | 8 | jobs: 9 | Update_GitHub_release: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Update release for ${{ github.event.client_payload.ReleaseBranchName }} 16 | uses: actions/github-script@v7 17 | with: 18 | github-token: ${{secrets.GITHUB_TOKEN}} 19 | script: | 20 | const response = await github.rest.repos.getReleaseByTag({ 21 | owner: context.repo.owner, 22 | repo: context.repo.repo, 23 | tag: "${{ github.event.client_payload.ReleaseBranchName }}" 24 | }); 25 | github.rest.repos.updateRelease({ 26 | owner: context.repo.owner, 27 | repo: context.repo.repo, 28 | release_id: response.data.id, 29 | prerelease: ${{ github.event.client_payload.Prerelease }} 30 | }); 31 | -------------------------------------------------------------------------------- /.github/workflows/validate-json-schema.yml: -------------------------------------------------------------------------------- 1 | name: Validate JSON Schema 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | validate-json-schema: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v4 17 | 18 | - name: Validate JSON Schema 19 | shell: pwsh 20 | run: ./helpers/CheckJsonSchema.ps1 21 | -------------------------------------------------------------------------------- /.github/workflows/windows2019.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Windows19 CI 2 | run-name: Windows2019 - ${{ github.event.pull_request.title }} 3 | 4 | on: 5 | pull_request_target: 6 | types: labeled 7 | paths: 8 | - 'images/windows/**' 9 | 10 | defaults: 11 | run: 12 | shell: pwsh 13 | 14 | jobs: 15 | Windows_2019: 16 | if: github.event.label.name == 'CI windows-all' || github.event.label.name == 'CI windows-2019' 17 | uses: ./.github/workflows/trigger-ubuntu-win-build.yml 18 | with: 19 | image_type: 'windows2019' 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/windows2022.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Windows22 CI 2 | run-name: Windows2022 - ${{ github.event.pull_request.title }} 3 | 4 | on: 5 | pull_request_target: 6 | types: labeled 7 | paths: 8 | - 'images/windows/**' 9 | 10 | defaults: 11 | run: 12 | shell: pwsh 13 | 14 | jobs: 15 | Windows_2022: 16 | if: github.event.label.name == 'CI windows-all' || github.event.label.name == 'CI windows-2022' 17 | uses: ./.github/workflows/trigger-ubuntu-win-build.yml 18 | with: 19 | image_type: 'windows2022' 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.github/workflows/windows2025.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Windows25 CI 2 | run-name: Windows2025 - ${{ github.event.pull_request.title }} 3 | 4 | on: 5 | pull_request_target: 6 | types: labeled 7 | paths: 8 | - 'images/windows/**' 9 | 10 | defaults: 11 | run: 12 | shell: pwsh 13 | 14 | jobs: 15 | Windows_2025: 16 | if: github.event.label.name == 'CI windows-all' || github.event.label.name == 'CI windows-2025' 17 | uses: ./.github/workflows/trigger-ubuntu-win-build.yml 18 | with: 19 | image_type: 'windows2025' 20 | secrets: inherit 21 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "streetsidesoftware.code-spell-checker", 4 | "hashicorp.hcl", 5 | "davidanson.vscode-markdownlint", 6 | "ms-vscode.powershell", 7 | "timonwong.shellcheck" 8 | ] 9 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.trimFinalNewlines": true, 3 | "files.insertFinalNewline": true, 4 | "powershell.codeFormatting.addWhitespaceAroundPipe": true, 5 | "powershell.codeFormatting.alignPropertyValuePairs": true, 6 | "powershell.codeFormatting.autoCorrectAliases": true, 7 | "powershell.codeFormatting.newLineAfterCloseBrace": false, 8 | "powershell.codeFormatting.newLineAfterOpenBrace": true, 9 | "powershell.codeFormatting.openBraceOnSameLine": true, 10 | "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationForFirstPipeline", 11 | "powershell.codeFormatting.preset": "OTBS", 12 | "powershell.codeFormatting.trimWhitespaceAroundPipe": true, 13 | "powershell.codeFormatting.whitespaceAfterSeparator": true, 14 | "powershell.codeFormatting.whitespaceAroundOperator": true, 15 | "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, 16 | "powershell.codeFormatting.whitespaceBeforeOpenParen": true, 17 | "powershell.codeFormatting.whitespaceBetweenParameters": true, 18 | "powershell.codeFormatting.whitespaceInsideBrace": true, 19 | "shellcheck.exclude": [ 20 | "SC1090","SC2096" 21 | ], 22 | "shellcheck.customArgs": [ 23 | "-x" 24 | ], 25 | "json.schemas": [ 26 | { 27 | "fileMatch": [ 28 | "**/toolset-*.json" 29 | ], 30 | "url": "./schemas/toolset-schema.json" 31 | } 32 | ] 33 | 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 GitHub 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | If you discover a security issue in this repo, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github) 2 | 3 | Thanks for helping make GitHub Actions safe for everyone. 4 | -------------------------------------------------------------------------------- /helpers/software-report-base/SoftwareReport.psm1: -------------------------------------------------------------------------------- 1 | using module ./SoftwareReport.BaseNodes.psm1 2 | using module ./SoftwareReport.Nodes.psm1 3 | 4 | class SoftwareReport { 5 | [ValidateNotNullOrEmpty()] 6 | [HeaderNode] $Root 7 | 8 | SoftwareReport([String] $Title) { 9 | $this.Root = [HeaderNode]::new($Title) 10 | } 11 | 12 | SoftwareReport([HeaderNode] $Root) { 13 | $this.Root = $Root 14 | } 15 | 16 | [String] ToJson() { 17 | return $this.Root.ToJsonObject() | ConvertTo-Json -Depth 10 18 | } 19 | 20 | static [SoftwareReport] FromJson([String] $JsonString) { 21 | $jsonObj = $JsonString | ConvertFrom-Json 22 | $rootNode = [NodesFactory]::ParseNodeFromObject($jsonObj) 23 | return [SoftwareReport]::new($rootNode) 24 | } 25 | 26 | [String] ToMarkdown() { 27 | return $this.Root.ToMarkdown().Trim() 28 | } 29 | 30 | [String] GetImageVersion() { 31 | $imageVersionNode = $this.Root.Children ?? @() | Where-Object { ($_ -is [ToolVersionNode]) -and ($_.ToolName -eq "Image Version:") } | Select-Object -First 1 32 | return $imageVersionNode.Version ?? "Unknown version" 33 | } 34 | } -------------------------------------------------------------------------------- /helpers/software-report-base/tests/TestHelpers.psm1: -------------------------------------------------------------------------------- 1 | function ShouldBeArray([Array] $ActualValue, [Array]$ExpectedValue, [Switch] $Negate, [String] $Because) { 2 | if ($Negate) { 3 | throw "Negation is not supported for Should-BeArray" 4 | } 5 | 6 | if ($ExpectedValue.Count -eq 0) { 7 | throw "Expected array cannot be empty. Use Should-BeNullOrEmpty instead." 8 | } 9 | 10 | $ExpectedValue | ForEach-Object { 11 | if ($_.GetType() -notin @([String], [Int32])) { 12 | throw "Only string or int arrays are supported in Should-BeArray" 13 | } 14 | } 15 | 16 | $actualValueJson = $ActualValue | ConvertTo-Json 17 | $expectedValueJson = $ExpectedValue | ConvertTo-Json 18 | 19 | $succeeded = ($ActualValue.Count -eq $ExpectedValue.Count) -and ($actualValueJson -eq $expectedValueJson) 20 | 21 | if (-not $succeeded) { 22 | $failureMessage = "Expected array '$actualValueJson' to be equal to '$expectedValueJson'" 23 | } 24 | 25 | return [PSCustomObject]@{ 26 | Succeeded = $succeeded 27 | FailureMessage = $failureMessage 28 | } 29 | } 30 | 31 | Add-ShouldOperator -Name BeArray ` 32 | -InternalName 'ShouldBeArray' ` 33 | -Test ${function:ShouldBeArray} ` 34 | -SupportsArrayInput -------------------------------------------------------------------------------- /images.CI/credscan-exclusions.json: -------------------------------------------------------------------------------- 1 | { 2 | "tool": "Credential Scanner", 3 | "suppressions": [ 4 | { 5 | "placeholder": "P@ssword!!", 6 | "_justification": "Password used by SQL Express. It is required to interact with database." 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /images.CI/linux-and-win/cleanup.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter (Mandatory=$true)] [string] $TempResourceGroupName 3 | ) 4 | 5 | $groupExist = az group exists --name $TempResourceGroupName 6 | if ($groupExist -eq "true") { 7 | Write-Host "Found a match, deleting temporary files" 8 | az group delete --name $TempResourceGroupName --yes | Out-Null 9 | Write-Host "Temporary group was deleted successfully" 10 | } else { 11 | Write-Host "No temporary groups found" 12 | } 13 | -------------------------------------------------------------------------------- /images.CI/linux-and-win/create-release.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter (Mandatory)] [UInt32] $BuildId, 3 | [Parameter (Mandatory)] [string] $Organization, 4 | [Parameter (Mandatory)] [string] $Project, 5 | [Parameter (Mandatory)] [string] $ImageType, 6 | [Parameter (Mandatory)] [string] $ManagedImageName, 7 | [Parameter (Mandatory)] [string] $DefinitionId, 8 | [Parameter (Mandatory)] [string] $AccessToken 9 | ) 10 | 11 | $Body = @{ 12 | definitionId = $DefinitionId 13 | variables = @{ 14 | ImageBuildId = @{ 15 | value = $BuildId 16 | } 17 | ImageType = @{ 18 | value = $ImageType 19 | } 20 | ManagedImageName = @{ 21 | value = $ManagedImageName 22 | } 23 | } 24 | isDraft = "false" 25 | } | ConvertTo-Json -Depth 3 26 | 27 | $URL = "https://vsrm.dev.azure.com/$Organization/$Project/_apis/release/releases?api-version=5.1" 28 | $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("'':${AccessToken}")) 29 | $headers = @{ 30 | Authorization = "Basic ${base64AuthInfo}" 31 | } 32 | 33 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13 34 | $NewRelease = Invoke-RestMethod $URL -Body $Body -Method "POST" -Headers $headers -ContentType "application/json" 35 | 36 | Write-Host "Created release: $($NewRelease._links.web.href)" 37 | -------------------------------------------------------------------------------- /images/macos/assets/auto-software-update-arm64.exp: -------------------------------------------------------------------------------- 1 | #! /usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn sudo /usr/sbin/softwareupdate --restart --verbose --install "MACOSUPDATE" 5 | expect "Password*" 6 | send "[lindex $argv 0]\r" 7 | expect eof 8 | -------------------------------------------------------------------------------- /images/macos/assets/bashprofile: -------------------------------------------------------------------------------- 1 | [ -f $HOME/.bashrc ] && source $HOME/.bashrc 2 | -------------------------------------------------------------------------------- /images/macos/assets/bashrc: -------------------------------------------------------------------------------- 1 | export LC_CTYPE=en_US.UTF-8 2 | export LC_ALL=en_US.UTF-8 3 | export LANG=en_US.UTF-8 4 | 5 | export ANDROID_HOME=${HOME}/Library/Android/sdk 6 | export ANDROID_SDK_ROOT=${HOME}/Library/Android/sdk 7 | 8 | export VM_ASSETS=/usr/local/opt/$USER/scripts 9 | 10 | export NUNIT_BASE_PATH=/Library/Developer/nunit 11 | export NUNIT3_PATH=/Library/Developer/nunit/3.6.0 12 | 13 | export AGENT_TOOLSDIRECTORY=$HOME/hostedtoolcache 14 | export RUNNER_TOOL_CACHE=$HOME/hostedtoolcache 15 | export ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE=$HOME/actionarchivecache 16 | 17 | export PATH=/Library/Frameworks/Mono.framework/Versions/Current/Commands:$PATH 18 | export PATH=/Library/Frameworks/Python.framework/Versions/Current/bin:$PATH 19 | export PATH=$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$PATH 20 | export PATH=/usr/local/bin:/usr/local/sbin:~/bin:~/.yarn/bin:$PATH 21 | export PATH="/usr/local/opt/curl/bin:$PATH" 22 | export PATH=$HOME/.cargo/bin:$PATH 23 | 24 | export RCT_NO_LAUNCH_PACKAGER=1 25 | export DOTNET_ROOT=$HOME/.dotnet 26 | export DOTNET_MULTILEVEL_LOOKUP=0 27 | 28 | export HOMEBREW_NO_AUTO_UPDATE=1 29 | export HOMEBREW_NO_INSTALL_CLEANUP=1 30 | export HOMEBREW_CASK_OPTS="--no-quarantine" 31 | 32 | export BOOTSTRAP_HASKELL_NONINTERACTIVE=1 33 | export BOOTSTRAP_HASKELL_INSTALL_NO_STACK_HOOK=1 34 | -------------------------------------------------------------------------------- /images/macos/assets/bootstrap-provisioner/change_password: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | USERNAME="$1" 3 | OLD_PASSWD="$2" 4 | NEW_PASSWD="$3" 5 | UPDATE_LOGIN_KEYCHAIN="${4:-true}" 6 | 7 | sudo /usr/sbin/sysadminctl -resetPasswordFor $USERNAME -newPassword "$NEW_PASSWD" -adminUser $USERNAME -adminPassword "$OLD_PASSWD" 8 | sudo /usr/bin/python3 /Users/$USERNAME/bootstrap/kcpassword.py "$NEW_PASSWD" 9 | sudo /usr/bin/defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser "$USERNAME" 10 | 11 | if [[ $UPDATE_LOGIN_KEYCHAIN == "true" ]]; then 12 | /usr/bin/security set-keychain-password -o "$OLD_PASSWD" -p "$NEW_PASSWD" /Users/$USERNAME/Library/Keychains/login.keychain 13 | fi 14 | -------------------------------------------------------------------------------- /images/macos/assets/bootstrap-provisioner/installNewProvisioner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | BOOTSTRAP_PATH="$1" 3 | ProvisionerPackageUri="$2" 4 | ProvisionerScriptUri="$3" 5 | ScriptName="$4" 6 | ScriptParam="$5" 7 | Username="$6" 8 | arch=$(arch) 9 | 10 | if [[ $arch == "arm64" ]]; then 11 | export PATH=/usr/bin:/usr/sbin:/usr/local/bin:/bin:/sbin:/opt/homebrew/bin 12 | else 13 | export PATH=/usr/bin:/usr/sbin:/usr/local/bin:/bin:/sbin 14 | fi 15 | 16 | PROVISIONER_ROOT=/usr/local/opt/${Username} 17 | sudo mkdir -p ${PROVISIONER_ROOT} 18 | sudo chown ${Username} ${PROVISIONER_ROOT} 19 | 20 | tee -a ${PROVISIONER_ROOT}/runprovisioner.sh > /dev/null <<\EOF 21 | #!/bin/bash 22 | 23 | . ${HOME}/.bashrc 24 | 25 | /usr/local/opt/$USER/provisioner/provisioner 26 | EOF 27 | 28 | chmod +x $PROVISIONER_ROOT/runprovisioner.sh 29 | 30 | aria2c \ 31 | --enable-color=false \ 32 | --file-allocation=none \ 33 | -d ${BOOTSTRAP_PATH} "${ProvisionerPackageUri}" >> ${BOOTSTRAP_PATH}/download.log 34 | 35 | aria2c \ 36 | --enable-color=false \ 37 | --file-allocation=none \ 38 | -d ${BOOTSTRAP_PATH} "${ProvisionerScriptUri}" >> ${BOOTSTRAP_PATH}/download.log 39 | 40 | chmod +x ${BOOTSTRAP_PATH}/${ScriptName} 41 | 42 | # Install Provisioner with provided scripts 43 | eval "$BOOTSTRAP_PATH/$ScriptName $BOOTSTRAP_PATH/$ScriptParam $Username" 2>&1 | tee "$BOOTSTRAP_PATH/install.log" 44 | # State File 45 | touch $BOOTSTRAP_PATH/provisionerDone -------------------------------------------------------------------------------- /images/macos/scripts/build/configure-auto-updates.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: configure-auto-updates.sh 4 | ## Desc: Disabling automatic updates 5 | ################################################################################ 6 | 7 | sudo softwareupdate --schedule off 8 | defaults write com.apple.SoftwareUpdate AutomaticDownload -int 0 9 | defaults write com.apple.SoftwareUpdate CriticalUpdateInstall -int 0 10 | defaults write com.apple.commerce AutoUpdate -bool false 11 | defaults write com.apple.SoftwareUpdate AutomaticCheckEnabled -bool false 12 | -------------------------------------------------------------------------------- /images/macos/scripts/build/configure-hostname.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: configure-hostname.sh 4 | ## Desc: Change the hostname at startup to prevent duplicates 5 | ## Hostname and Computername should contain .local in name to avoid name resolution issues 6 | ################################################################################ 7 | 8 | tee -a /usr/local/bin/change_hostname.sh > /dev/null <<\EOF 9 | #!/bin/bash -e -o pipefail 10 | 11 | name="Mac-$(python3 -c 'from time import time; print(int(round(time() * 1000)))')" 12 | scutil --set HostName "${name}.local" 13 | scutil --set LocalHostName $name 14 | scutil --set ComputerName "${name}.local" 15 | EOF 16 | 17 | chmod +x /usr/local/bin/change_hostname.sh 18 | 19 | sudo tee -a /Library/LaunchDaemons/change_hostname.plist > /dev/null <<\EOF 20 | <?xml version="1.0" encoding="UTF-8"?> 21 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"> 22 | <plist version="1.0"> 23 | <dict> 24 | <key>Label</key> 25 | <string>change-hostname</string> 26 | <key>Program</key> 27 | <string>/usr/local/bin/change_hostname.sh</string> 28 | <key>RunAtLoad</key> 29 | <true/> 30 | </dict> 31 | </plist> 32 | EOF 33 | -------------------------------------------------------------------------------- /images/macos/scripts/build/configure-ntpconf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: configure-ntpconf.sh 4 | ## Desc: Configure NTP servers and set the timezone to UTC 5 | ################################################################################ 6 | 7 | echo Additional NTP servers adding into /etc/ntp.conf file... 8 | cat > /etc/ntp.conf << EOF 9 | server 0.pool.ntp.org 10 | server 1.pool.ntp.org 11 | server 2.pool.ntp.org 12 | server 3.pool.ntp.org 13 | server time.apple.com 14 | server time.windows.com 15 | EOF 16 | 17 | # Set the timezone to UTC. 18 | echo "The Timezone setting to UTC..." 19 | ln -sf /usr/share/zoneinfo/UTC /etc/localtime 20 | -------------------------------------------------------------------------------- /images/macos/scripts/build/configure-shell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: configure-shell.sh 4 | ## Desc: Configure shell to use bash 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | arch=$(get_arch) 9 | 10 | echo "Changing shell to bash" 11 | sudo chsh -s /bin/bash $USERNAME 12 | sudo chsh -s /bin/bash root 13 | 14 | # Check MacOS architecture and add HOMEBREW PATH to bashrc 15 | if [[ $arch == "arm64" ]]; then 16 | echo "Adding Homebrew environment to bash" 17 | # Discussed here: https://github.com/Homebrew/brew/pull/18366 18 | echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.bashrc 19 | fi 20 | -------------------------------------------------------------------------------- /images/macos/scripts/build/configure-ssh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: configure-ssh.sh 4 | ## Desc: Configure ssh 5 | ################################################################################ 6 | 7 | [[ ! -d ~/.ssh ]] && mkdir ~/.ssh 2>/dev/null 8 | chmod 777 ~/.ssh 9 | 10 | ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> ~/.ssh/known_hosts 11 | ssh-keyscan -t rsa ssh.dev.azure.com >> ~/.ssh/known_hosts 12 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-actions-cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-actions-cache.sh 4 | ## Desc: Download latest release from https://github.com/actions/action-versions 5 | ## Maintainer: #actions-runtime and @TingluoHuang 6 | ################################################################################ 7 | 8 | source ~/utils/utils.sh 9 | 10 | echo "Check if ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE folder exist..." 11 | if [[ ! -d $ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE ]]; then 12 | mkdir -p $ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE 13 | fi 14 | 15 | download_url=$(resolve_github_release_asset_url "actions/action-versions" "contains(\"action-versions.tar.gz\")" "latest" "$API_PAT") 16 | echo "Downloading action-versions $download_url" 17 | archive_path=$(download_with_retry $download_url) 18 | tar -xzf $archive_path -C $ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE 19 | 20 | invoke_tests "ActionArchiveCache" 21 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-audiodevice.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-audiodevice.sh 4 | ## Desc: Install audio device 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "install switchaudio-osx" 10 | brew_smart_install "switchaudio-osx" 11 | 12 | echo "install sox" 13 | brew_smart_install "sox" 14 | 15 | invoke_tests "System" "Audio Device" 16 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-aws-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-aws-tools.sh 4 | ## Desc: Install the AWS CLI, Session Manager plugin for the AWS CLI, and AWS SAM CLI 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing aws..." 10 | awscliv2_pkg_path=$(download_with_retry "https://awscli.amazonaws.com/AWSCLIV2.pkg") 11 | sudo installer -pkg "$awscliv2_pkg_path" -target / 12 | 13 | echo "Installing aws sam cli..." 14 | brew tap aws/tap 15 | brew_smart_install aws-sam-cli 16 | 17 | echo "Install aws cli session manager" 18 | brew install --cask session-manager-plugin 19 | 20 | invoke_tests "Common" "AWS" 21 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-azcopy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-azcopy.sh 4 | ## Desc: Install AzCopy 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | if is_Arm64; then 10 | url="https://aka.ms/downloadazcopy-v10-mac-arm64" 11 | else 12 | url="https://aka.ms/downloadazcopy-v10-mac" 13 | fi 14 | 15 | # Install AzCopy 16 | archive_path=$(download_with_retry ${url}) 17 | unzip -qq $archive_path -d /tmp/azcopy 18 | extract_path=$(echo /tmp/azcopy/azcopy*) 19 | cp $extract_path/azcopy /usr/local/bin/azcopy 20 | chmod +x /usr/local/bin/azcopy 21 | 22 | 23 | invoke_tests "Common" "AzCopy" 24 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-bicep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-bicep.sh 4 | ## Desc: Install bicep cli 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing bicep cli..." 10 | brew tap azure/bicep 11 | brew_smart_install bicep 12 | 13 | invoke_tests "Common" "Bicep" 14 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-cocoapods.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-cocoapods.sh 4 | ## Desc: Install Cocoapods 5 | ################################################################################ 6 | 7 | # Setup the Cocoapods 8 | echo "Installing Cocoapods..." 9 | pod setup 10 | 11 | # Create a symlink to /usr/local/bin since it was removed due to Homebrew change. 12 | ln -sf $(which pod) /usr/local/bin/pod 13 | 14 | invoke_tests "Common" "CocoaPods" 15 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-firefox.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-firefox.sh 4 | ## Desc: Install firefox browser 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing Firefox..." 10 | brew install --cask firefox 11 | 12 | echo "Installing Geckodriver..." 13 | brew_smart_install "geckodriver" 14 | geckoPath="$(brew --prefix geckodriver)/bin" 15 | 16 | echo "Add GECKOWEBDRIVER to bashrc..." 17 | echo "export GECKOWEBDRIVER=${geckoPath}" >> ${HOME}/.bashrc 18 | 19 | invoke_tests "Browsers" "Firefox" 20 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-gcc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-gcc.sh 4 | ## Desc: Install GCC 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | gccVersions=$(get_toolset_value '.gcc.versions | .[]') 10 | 11 | for gccVersion in $gccVersions; do 12 | brew_smart_install "gcc@${gccVersion}" 13 | done 14 | 15 | # Delete default gfortran link if it exists https://github.com/actions/runner-images/issues/1280 16 | gfortranPath=$(which gfortran) || true 17 | if [[ $gfortranPath ]]; then 18 | rm $gfortranPath 19 | fi 20 | 21 | invoke_tests "Common" "GCC" 22 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-git.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-git.sh 4 | ## Desc: Install Git and Git LFS 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing Git..." 10 | brew_smart_install "git" 11 | 12 | git config --global --add safe.directory "*" 13 | 14 | echo "Installing Git LFS" 15 | brew_smart_install "git-lfs" 16 | 17 | # Update global git config 18 | git lfs install 19 | # Update system git config 20 | sudo git lfs install --system 21 | 22 | echo "Disable all the Git help messages..." 23 | git config --global advice.pushUpdateRejected false 24 | git config --global advice.pushNonFFCurrent false 25 | git config --global advice.pushNonFFMatching false 26 | git config --global advice.pushAlreadyExists false 27 | git config --global advice.pushFetchFirst false 28 | git config --global advice.pushNeedsForce false 29 | git config --global advice.statusHints false 30 | git config --global advice.statusUoption false 31 | git config --global advice.commitBeforeMerge false 32 | git config --global advice.resolveConflict false 33 | git config --global advice.implicitIdentity false 34 | git config --global advice.detachedHead false 35 | git config --global advice.amWorkDir false 36 | git config --global advice.rmHints false 37 | 38 | invoke_tests "Git" 39 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-llvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-llvm.sh 4 | ## Desc: Install LLVM 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | llvmVersion=$(get_toolset_value '.llvm.version') 10 | 11 | brew_smart_install "llvm@${llvmVersion}" 12 | 13 | invoke_tests "LLVM" 14 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-nginx.sh 4 | ## Desc: Install Nginx 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | brew_smart_install nginx 10 | sudo sed -Ei '' 's/listen.*/listen 80;/' $(brew --prefix)/etc/nginx/nginx.conf 11 | 12 | invoke_tests "WebServers" "Nginx" 13 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-node.sh 4 | ## Desc: Install Node.js 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | defaultVersion=$(get_toolset_value '.node.default') 10 | 11 | echo "Installing Node.js $defaultVersion" 12 | brew_smart_install "node@$defaultVersion" 13 | brew link node@$defaultVersion --force --overwrite 14 | 15 | echo Installing yarn... 16 | yarn_installer_path=$(download_with_retry "https://yarnpkg.com/install.sh") 17 | bash $yarn_installer_path 18 | 19 | invoke_tests "Node" "Node.js" 20 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-openssl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-openssl.sh 4 | ## Desc: Install openssl 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Install openssl@1.1" 10 | 11 | COMMIT=d91dabd087cb0b906c92a825df9e5e5e1a4f59f8 12 | FORMULA_URL="https://raw.githubusercontent.com/Homebrew/homebrew-core/$COMMIT/Formula/o/openssl@1.1.rb" 13 | FORMULA_PATH="$(brew --repository)/Library/Taps/homebrew/homebrew-core/Formula/o/openssl@1.1.rb" 14 | mkdir -p "$(dirname $FORMULA_PATH)" 15 | curl -fsSL $FORMULA_URL -o $FORMULA_PATH 16 | HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_FROM_API=1 brew install openssl@1.1 17 | 18 | if ! is_Arm64; then 19 | # Symlink brew openssl@1.1 to `/usr/local/bin` as Homebrew refuses 20 | ln -sf $(brew --prefix openssl@1.1)/bin/openssl /usr/local/bin/openssl 21 | else 22 | # arm64 has a different installation prefix for brew 23 | ln -sf $(brew --prefix openssl@1.1)/bin/openssl /opt/homebrew/bin/openssl 24 | fi 25 | 26 | if ! is_Arm64; then 27 | # Most of build systems and scripts look up ssl here 28 | ln -sf $(brew --cellar openssl@1.1)/1.1* /usr/local/opt/openssl 29 | fi 30 | 31 | invoke_tests "OpenSSL" 32 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-php.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-php.sh 4 | ## Desc: Install PHP 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo Installing PHP 10 | phpVersionToolset=$(get_toolset_value '.php.version') 11 | brew_smart_install "php@${phpVersionToolset}" 12 | 13 | echo Installing composer 14 | brew_smart_install "composer" 15 | 16 | invoke_tests "PHP" 17 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-postgresql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-postgresql.sh 4 | ## Desc: Install PostgreSQL 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | # Fetch PostgreSQL version to install from the toolset 10 | toolsetVersion=$(get_toolset_value '.postgresql.version') 11 | 12 | # Install latest version of PostgreSQL 13 | brew_smart_install postgresql@$toolsetVersion 14 | 15 | # Service PostgreSQL should be started before use 16 | postgreService=$(brew services list | grep -oe "postgresql\S*") 17 | brew services start $postgreService 18 | 19 | # Verify PostgreSQL is ready for accept incoming connections 20 | echo "Check PostgreSQL service is running" 21 | i=10 22 | COMMAND='pg_isready' 23 | while [[ $i -gt 0 ]]; do 24 | echo "Check PostgreSQL service status" 25 | eval $COMMAND && break 26 | ((i--)) 27 | if [[ $i == 0 ]]; then 28 | echo "PostgreSQL service not ready, all attempts exhausted" 29 | exit 1 30 | fi 31 | echo "PostgreSQL service not ready, wait 10 more sec, attempts left: $i" 32 | sleep 10 33 | done 34 | 35 | # Stop PostgreSQL 36 | brew services stop $postgreService 37 | 38 | invoke_tests "Databases" "PostgreSQL" 39 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-python.sh 4 | ## Desc: Install Python 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing Python Tooling" 10 | 11 | # Close Finder window 12 | close_finder_window 13 | 14 | echo "Brew Installing Python 3" 15 | brew_smart_install "python@3.12" 16 | 17 | echo "Installing pipx" 18 | 19 | if is_Arm64; then 20 | export PIPX_BIN_DIR="$HOME/.local/bin" 21 | export PIPX_HOME="$HOME/.local/pipx" 22 | else 23 | export PIPX_BIN_DIR=/usr/local/opt/pipx_bin 24 | export PIPX_HOME=/usr/local/opt/pipx 25 | fi 26 | 27 | brew_smart_install "pipx" 28 | 29 | echo "export PIPX_BIN_DIR=${PIPX_BIN_DIR}" >> ${HOME}/.bashrc 30 | echo "export PIPX_HOME=${PIPX_HOME}" >> ${HOME}/.bashrc 31 | echo 'export PATH="$PIPX_BIN_DIR:$PATH"' >> ${HOME}/.bashrc 32 | 33 | invoke_tests "Python" 34 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-rosetta.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-rosetta.sh 4 | ## Desc: Install Rosetta 5 | ################################################################################ 6 | 7 | echo "Installing Rosetta" 8 | /usr/sbin/softwareupdate --install-rosetta --agree-to-license 9 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-rubygems.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-rubygems.sh 4 | ## Desc: Install RubyGems 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Updating RubyGems..." 10 | gem update --system 11 | 12 | # Temporarily install activesupport 7.2.2.1 due to compatibility issues with cocoapods https://github.com/CocoaPods/CocoaPods/issues/12081 13 | gem install activesupport -v 7.2.2.1 14 | 15 | gemsToInstall=$(get_toolset_value '.ruby.rubygems | .[]') 16 | if [[ -n $gemsToInstall ]]; then 17 | for gem in $gemsToInstall; do 18 | echo "Installing gem $gem" 19 | gem install $gem 20 | done 21 | fi 22 | 23 | invoke_tests "RubyGem" 24 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-runner-package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-runner-package.sh 4 | ## Desc: Download and Install runner package 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source ~/utils/utils.sh 9 | 10 | AGENT_PATH="/opt/runner-cache" 11 | arch=$(get_arch) 12 | download_url=$(resolve_github_release_asset_url "actions/runner" 'test("actions-runner-osx-'"$arch"'-[0-9]+\\.[0-9]{3}\\.[0-9]+\\.tar\\.gzquot;)' "latest" "$API_PAT") 13 | archive_name="${download_url##*/}" 14 | archive_path=$(download_with_retry "$download_url") 15 | 16 | if [[ ! -d $AGENT_PATH ]]; then 17 | sudo mkdir -p -m 775 $AGENT_PATH 18 | sudo chown $USER:admin $AGENT_PATH 19 | fi 20 | 21 | sudo mv "$archive_path" "$AGENT_PATH/$archive_name" 22 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-rust.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-rust.sh 4 | ## Desc: Install Rust 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing Rustup..." 10 | brew_smart_install "rustup-init" 11 | 12 | echo "Installing Rust language..." 13 | rustup-init -y --no-modify-path --default-toolchain=stable --profile=minimal 14 | 15 | echo "Initialize environment variables..." 16 | CARGO_HOME=$HOME/.cargo 17 | 18 | echo "Install common tools..." 19 | rustup component add rustfmt clippy 20 | 21 | echo "Cleanup Cargo registry cached data..." 22 | rm -rf $CARGO_HOME/registry/* 23 | 24 | invoke_tests "Rust" 25 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-safari.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-safari.sh 4 | ## Desc: Install Safari browser 5 | ################################################################################ 6 | 7 | echo "Enabling safari driver..." 8 | # https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari 9 | # Safari’s executable is located at /usr/bin/safaridriver 10 | # Configure Safari to Enable WebDriver Support 11 | sudo safaridriver --enable 12 | 13 | echo "Enabling the 'Allow Remote Automation' option in Safari's Develop menu" 14 | mkdir -p $HOME/Library/WebDriver 15 | safari_plist="$HOME/Library/WebDriver/com.apple.Safari.plist" 16 | # "|| true" is needed to suppress exit code 1 in case if property or file doesn't exist 17 | /usr/libexec/PlistBuddy -c 'delete AllowRemoteAutomation' $safari_plist || true 18 | /usr/libexec/PlistBuddy -c 'add AllowRemoteAutomation bool true' $safari_plist 19 | 20 | invoke_tests "Browsers" "Safari" 21 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-swiftlint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-swiftlint.sh 4 | ## Desc: Install SwiftLint 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing Swiftlint..." 10 | 11 | brew_smart_install "swiftlint" 12 | 13 | invoke_tests "Linters" "SwiftLint" 14 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-unxip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-unxip.sh 4 | ## Desc: Install unxip 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | echo "Installing unxip..." 10 | unxip_pkg=$(download_with_retry "https://github.com/saagarjha/unxip/releases/download/v3.1/unxip") 11 | unxip_pkg_sha256="926ecd7bffa201c7b2b8a729fc70fbf228cf624a0e6856c13f935a97fa4fc71a" 12 | use_checksum_comparison $unxip_pkg $unxip_pkg_sha256 13 | install "$unxip_pkg" /usr/local/bin/unxip 14 | 15 | invoke_tests "Common" "Unxip" 16 | -------------------------------------------------------------------------------- /images/macos/scripts/build/install-vcpkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | ################################################################################ 3 | ## File: install-vcpkg.sh 4 | ## Desc: Install vcpkg 5 | ################################################################################ 6 | 7 | source ~/utils/utils.sh 8 | 9 | # Set env variable for vcpkg 10 | VCPKG_INSTALLATION_ROOT=/usr/local/share/vcpkg 11 | echo "export VCPKG_INSTALLATION_ROOT=${VCPKG_INSTALLATION_ROOT}" | tee -a ~/.bashrc 12 | 13 | # Install vcpkg 14 | sudo git clone https://github.com/Microsoft/vcpkg $VCPKG_INSTALLATION_ROOT 15 | sudo $VCPKG_INSTALLATION_ROOT/bootstrap-vcpkg.sh 16 | $VCPKG_INSTALLATION_ROOT/vcpkg integrate install 17 | sudo chmod -R 0777 $VCPKG_INSTALLATION_ROOT 18 | ln -sf $VCPKG_INSTALLATION_ROOT/vcpkg /usr/local/bin 19 | 20 | invoke_tests "Common" "vcpkg" 21 | -------------------------------------------------------------------------------- /images/macos/scripts/docs-gen/SoftwareReport.Java.psm1: -------------------------------------------------------------------------------- 1 | function Get-JavaVersions { 2 | $defaultJavaPath = (Get-Item env:JAVA_HOME).value 3 | 4 | $os = Get-OSVersion 5 | if ($os.IsVenturaArm64 -or $os.IsSonomaArm64 -or $os.IsSequoiaArm64) { 6 | $javaVersions = Get-Item env:JAVA_HOME_*_arm64 7 | } else { 8 | $javaVersions = Get-Item env:JAVA_HOME_*_X64 9 | } 10 | 11 | $sortRules = @{ 12 | Expression = { [Int32]$_.Name.Split("_")[2] } 13 | Descending = $false 14 | } 15 | 16 | return $javaVersions | Sort-Object $sortRules | ForEach-Object { 17 | $javaPath = $_.Value 18 | # Take semver from the java path 19 | $version = $javaPath.split('/')[5] 20 | $fullVersion = $version.Replace('-', '+') 21 | $defaultPostfix = ($javaPath -eq $defaultJavaPath) ? " (default)" : "" 22 | 23 | [PSCustomObject] @{ 24 | "Version" = $fullVersion + $defaultPostfix 25 | "Environment Variable" = $_.Name 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /images/macos/scripts/helpers/confirm-identified-developers-macos13.scpt: -------------------------------------------------------------------------------- 1 | # This AppleScript clicks "Allow" for "System Software from developer "Parallels International GmbH" 2 | # Steps: 3 | # - Open System Settings -> Privacy & Security 4 | # - Click 'Allow' for 'System Software from developer "Parallels International GmbH' 5 | # - Enter password for runner 6 | 7 | on run argv 8 | set userpassword to item 1 of argv 9 | 10 | tell application "System Settings" 11 | activate 12 | delay 5 13 | end tell 14 | 15 | tell application "System Events" 16 | tell process "System Settings" 17 | set frontmost to true 18 | repeat until exists window 1 19 | delay 2 20 | end repeat 21 | 22 | tell splitter group 1 of group 1 of window 1 23 | select row 20 of outline 1 of scroll area 1 of group 1 24 | delay 5 25 | click UI Element 2 of group 4 of scroll area 1 of group 1 of group 2 26 | delay 5 27 | keystroke userpassword 28 | delay 5 29 | keystroke return 30 | delay 5 31 | end tell 32 | end tell 33 | end tell 34 | end run 35 | -------------------------------------------------------------------------------- /images/macos/scripts/helpers/confirm-identified-developers-macos14.scpt: -------------------------------------------------------------------------------- 1 | # This AppleScript clicks "Allow" for "System Software from developer "Parallels International GmbH" 2 | # Steps: 3 | # - Open System Settings -> Privacy & Security 4 | # - Click 'Allow' for 'System Software from developer "Parallels International GmbH' 5 | # - Enter password for runner 6 | 7 | on run argv 8 | set userpassword to item 1 of argv 9 | 10 | tell application "System Settings" 11 | activate 12 | delay 5 13 | end tell 14 | 15 | tell application "System Events" 16 | tell process "System Settings" 17 | set frontmost to true 18 | repeat until exists window 1 19 | delay 2 20 | end repeat 21 | 22 | tell splitter group 1 of group 1 of window 1 23 | select row 18 of outline 1 of scroll area 1 of group 1 24 | delay 5 25 | click UI Element 2 of group 5 of scroll area 1 of group 1 of group 2 26 | delay 5 27 | keystroke userpassword 28 | delay 5 29 | keystroke return 30 | delay 5 31 | end tell 32 | end tell 33 | end tell 34 | end run 35 | -------------------------------------------------------------------------------- /images/macos/scripts/helpers/confirm-identified-developers-macos15.scpt: -------------------------------------------------------------------------------- 1 | # This AppleScript clicks "Allow" for "System Software from developer "Parallels International GmbH" 2 | # Steps: 3 | # - Open System Settings -> Privacy & Security 4 | # - Click 'Allow' for 'System Software from developer "Parallels International GmbH' 5 | # - Enter password for runner 6 | 7 | on run argv 8 | set userpassword to item 1 of argv 9 | 10 | tell application "System Settings" 11 | activate 12 | delay 5 13 | end tell 14 | 15 | tell application "System Events" 16 | tell process "System Settings" 17 | set frontmost to true 18 | repeat until exists window 1 19 | delay 2 20 | end repeat 21 | 22 | tell splitter group 1 of group 1 of window 1 23 | select row 27 of outline 1 of scroll area 1 of group 1 24 | delay 5 25 | click UI element 1 of row 27 of outline 1 of scroll area 1 of group 1 26 | delay 5 27 | keystroke userpassword 28 | delay 5 29 | keystroke return 30 | delay 5 31 | end tell 32 | end tell 33 | end tell 34 | end run 35 | -------------------------------------------------------------------------------- /images/macos/scripts/helpers/invoke-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e -o pipefail 2 | 3 | source $HOME/.bashrc 4 | pwsh -Command "Import-Module '$HOME/image-generation/tests/Helpers.psm1' -DisableNameChecking 5 | Invoke-PesterTests -TestFile \"$1\" -TestName \"$2\"" 6 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/ActionArchiveCache.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "ActionArchiveCache" { 2 | Context "Action archive cache directory not empty" { 3 | It "$HOME/actionarchivecache not empty" { 4 | (Get-ChildItem -Path "$env:HOME/actionarchivecache/*.tar.gz" -Recurse).Count | Should -BeGreaterThan 0 5 | } 6 | } 7 | 8 | Context "Action tarball not empty" { 9 | $testCases = Get-ChildItem -Path "$env:HOME/actionarchivecache/*.tar.gz" -Recurse | ForEach-Object { @{ ActionTarball = $_.FullName } } 10 | It "<ActionTarball>" -TestCases $testCases { 11 | param ([string] $ActionTarball) 12 | (Get-Item "$ActionTarball").Length | Should -BeGreaterThan 0 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Databases.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "MongoDB" -Skip:($os.IsVentura -or $os.IsSonoma -or $os.IsSequoia) { 6 | It "<ToolName>" -TestCases @( 7 | @{ ToolName = "mongo" } 8 | @{ ToolName = "mongod" } 9 | ) { 10 | $toolsetVersion = (Get-ToolsetContent).mongodb.version 11 | (&$ToolName --version)[2].Split('"')[-2] | Should -BeLike "$toolsetVersion*" 12 | } 13 | } 14 | 15 | Describe "PostgreSQL" -Skip:($os.IsVentura -or $os.IsSonoma -or $os.IsSequoia) { 16 | It "PostgreSQL version should correspond to the version in the toolset" { 17 | $toolsetVersion = (Get-ToolsetContent).postgresql.version 18 | # Client version 19 | (psql --version).split()[-2] | Should -BeLike "$toolsetVersion*" 20 | # Server version 21 | (pg_config --version).split()[-2] | Should -BeLike "$toolsetVersion*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Git.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "Git" { 6 | It "git is installed" { 7 | "git --version" | Should -ReturnZeroExitCode 8 | } 9 | It "git lfs is installed" { 10 | "git lfs version" | Should -ReturnZeroExitCode 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/LLVM.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | Describe "Clang/LLVM" { 4 | BeforeAll { 5 | $toolsetVersion = (Get-ToolsetContent).llvm.version 6 | } 7 | 8 | It "Clang/LLVM <toolsetVersion> is installed and version is correct" { 9 | $clangVersion = & "$(brew --prefix llvm@$toolsetVersion)/bin/clang" --version 10 | $clangVersion[0] | Should -BeLike "*${toolsetVersion}*" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Linters.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/Helpers.psm1" -DisableNameChecking 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "SwiftLint" -Skip:($os.IsVenturaArm64 -or $os.IsSonomaArm64 -or $os.IsSequoiaArm64) { 6 | It "SwiftLint" { 7 | "swiftlint version" | Should -ReturnZeroExitCode 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Node.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | Import-Module "$PSScriptRoot/Helpers.psm1" -DisableNameChecking 3 | 4 | $os = Get-OSVersion 5 | 6 | Describe "Node.js" { 7 | It "Node.js is installed" { 8 | "node --version" | Should -ReturnZeroExitCode 9 | } 10 | 11 | It "Node.js version should correspond to the version in the toolset" { 12 | node --version | Should -BeLike "v$((Get-ToolsetContent).node.default)*" 13 | } 14 | 15 | It "NPM is installed" { 16 | "npm --version" | Should -ReturnZeroExitCode 17 | } 18 | 19 | It "Yarn is installed" { 20 | "yarn --version" | Should -ReturnZeroExitCode 21 | } 22 | } 23 | 24 | Describe "Global NPM Packages" { 25 | $globalNpmPackages = (Get-ToolsetContent).npm.global_packages 26 | $globalNpmPackagesWithTests = $globalNpmPackages | Where-Object { $_.test } | ForEach-Object { @{ Name = $_.name; Test = $_.test } } 27 | 28 | It "<Name>" -TestCases $globalNpmPackagesWithTests { 29 | $Test | Should -ReturnZeroExitCode 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/OpenSSL.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | Describe "OpenSSL" { 4 | Context "OpenSSL Version" { 5 | It "OpenSSL is available" { 6 | "openssl version" | Should -ReturnZeroExitCode 7 | } 8 | } 9 | 10 | Context "OpenSSL 1.1 Path Check" { 11 | It "OpenSSL 1.1 path exists" { 12 | $openSSLpath = brew --prefix openssl@1.1 13 | $openSSLpath | Should -Exist 14 | } 15 | } 16 | 17 | Context "OpenSSL 1.1 is default" { 18 | It "Default OpenSSL version is 1.1" { 19 | $commandResult = Get-CommandResult "openssl version" 20 | $commandResult.Output | Should -Match "OpenSSL 1.1" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/PHP.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "PHP" { 6 | Context "PHP" -Skip:($os.IsVenturaArm64 -or $os.IsSonomaArm64 -or $os.IsSequoiaArm64) { 7 | It "PHP Path" { 8 | Get-ToolPath "php" | Should -Not -BeLike "/usr/bin/php*" 9 | } 10 | It "PHP version" { 11 | $phpVersionToolset = (Get-ToolsetContent).php.version 12 | $phpInstalledVersion = php --version | Out-String | Select-String "${phpVersionToolset}" 13 | $phpInstalledVersion | Should -BeLike "PHP ${phpVersionToolset}*" 14 | } 15 | } 16 | 17 | Context "Composer" -Skip:($os.IsVenturaArm64 -or $os.IsSonomaArm64 -or $os.IsSequoiaArm64) { 18 | It "Composer" { 19 | "composer --version" | Should -ReturnZeroExitCode 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Rosetta.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "Rosetta" -Skip:(-not $os.IsArm64) { 6 | It "Rosetta is available" { 7 | $commandResult = Get-CommandResult "/usr/bin/pgrep oahd" 8 | $commandResult.Output | Should -Match "\d+" 9 | $commandResult.ExitCode | Should -Be 0 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Ruby.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | Import-Module "$PSScriptRoot/Helpers.psm1" -DisableNameChecking 3 | 4 | Describe "Ruby" { 5 | It "Ruby is available" { 6 | "ruby --version" | Should -ReturnZeroExitCode 7 | } 8 | 9 | It "Ruby is installed via HomeBrew" { 10 | Get-ToolPath "ruby" | Should -Not -BeLike "/usr/bin/ruby*" 11 | } 12 | 13 | It "Ruby tools are consistent" { 14 | $os = Get-OSVersion 15 | $expectedPrefix = if ($os.IsArm64) { "/opt/homebrew" } else { "/usr/local" } 16 | Get-ToolPath "ruby" | Should -Match "^$expectedPrefix.*" 17 | Get-ToolPath "gem" | Should -Match "^$expectedPrefix.*" 18 | Get-ToolPath "bundler" | Should -Match "^$expectedPrefix.*" 19 | } 20 | 21 | It "Ruby gems permissions are valid" { 22 | "gem install bundle" | Should -ReturnZeroExitCode 23 | "gem uninstall bundle" | Should -ReturnZeroExitCode 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/RubyGem.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "RubyGems" { 6 | $gemTestCases = (Get-ToolsetContent).ruby.rubygems | ForEach-Object { 7 | @{gemName = $_} 8 | } 9 | 10 | if ($gemTestCases) { 11 | It "Gem <gemName> is installed" -TestCases $gemTestCases { 12 | "gem list -i '^$gemName#39;" | Should -MatchCommandOutput "true" 13 | } 14 | } 15 | } 16 | 17 | Describe "Bundler" { 18 | It "Bundler" { 19 | "bundler --version" | Should -ReturnZeroExitCode 20 | } 21 | } 22 | 23 | Describe "Fastlane" { 24 | It "Fastlane" { 25 | "fastlane --version" | Should -ReturnZeroExitCode 26 | } 27 | } 28 | 29 | Describe "xcpretty" -Skip:($os.IsVentura -or $os.IsSonoma -or $os.IsSequoia) { 30 | It "xcpretty" { 31 | "xcpretty --version" | Should -ReturnZeroExitCode 32 | } 33 | } 34 | 35 | Describe "jazzy" -Skip:($os.IsVentura -or $os.IsSonoma -or $os.IsSequoia) { 36 | It "jazzy" { 37 | "jazzy --version" | Should -ReturnZeroExitCode 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/RunAll-Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/Helpers.psm1" -DisableNameChecking 2 | 3 | Invoke-PesterTests "*" 4 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/RunnerCache.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "RunnerCache" { 2 | Context "runner cache directory not empty" { 3 | It "<RunnerCachePath> not empty" -TestCases @{ RunnerCachePath = "/opt/runner-cache" } { 4 | (Get-ChildItem -Path "$RunnerCachePath/*.tar.gz" -Recurse).Count | Should -BeGreaterThan 0 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Rust.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | $os = Get-OSVersion 4 | 5 | Describe "Rust" { 6 | Context "Rust" { 7 | It "Rustup is installed" { 8 | "rustup --version" | Should -ReturnZeroExitCode 9 | } 10 | 11 | It "Rustc is installed" { 12 | "rustc --version" | Should -ReturnZeroExitCode 13 | } 14 | } 15 | 16 | Context "Cargo" { 17 | It "Cargo is installed" { 18 | "cargo --version" | Should -ReturnZeroExitCode 19 | } 20 | } 21 | Context "Cargo dependencies" -Skip:($os.IsVentura -or $os.IsSonoma -or $os.IsSequoia) { 22 | It "bindgen" { 23 | "bindgen --version" | Should -ReturnZeroExitCode 24 | } 25 | 26 | It "cbindgen" { 27 | "cbindgen --version" | Should -ReturnZeroExitCode 28 | } 29 | 30 | It "Cargo audit" { 31 | "cargo audit --version" | Should -ReturnZeroExitCode 32 | } 33 | 34 | It "Cargo outdated" { 35 | "cargo outdated --version" | Should -ReturnZeroExitCode 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /images/macos/scripts/tests/Toolset.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/Helpers.psm1" 2 | 3 | $toolsets = Get-ChildItem -Path $PSScriptRoot -Filter "toolset-*.json" 4 | 5 | function Get-ShortVersion([System.Version] $Version) { 6 | return [System.Version]::Parse($Version).ToString(2) 7 | } 8 | 9 | Describe "Toolset JSON validation" { 10 | $toolsets | ForEach-Object { 11 | It "$($_.Name) is valid" { 12 | $jsonContent = Get-Content -Raw $_.Fullname 13 | $jsonContent | Test-Json | Should -BeTrue 14 | } 15 | } 16 | } 17 | 18 | $toolsets | ForEach-Object { 19 | Describe "$($_.Name)" { 20 | $toolset = Get-Content -Raw $_.Fullname | ConvertFrom-Json 21 | 22 | Context "Xcode" { 23 | It "Default Xcode should be defined" { 24 | $toolset.xcode.default | Should -BeTrue 25 | } 26 | 27 | It "Default Xcode is listed in Xcode list" { 28 | $toolset.xcode.versions | Should -Contain $toolset.xcode.default 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /images/ubuntu/assets/post-gen/cleanup-logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # journalctl 4 | if command -v journalctl; then 5 | journalctl --rotate 6 | journalctl --vacuum-time=1s 7 | fi 8 | 9 | # delete all .gz and rotated file 10 | find /var/log -type f -regex ".*\.gzquot; -delete 11 | find /var/log -type f -regex ".*\.[0-9]quot; -delete 12 | 13 | # wipe log files 14 | find /var/log/ -type f -exec cp /dev/null {} \; -------------------------------------------------------------------------------- /images/ubuntu/assets/post-gen/environment-variables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Replace $HOME with the default user's home directory for environmental variables related to the default user home directory 4 | 5 | homeDir=$(cut -d: -f6 /etc/passwd | tail -1) 6 | sed -i "s|\$HOME|$homeDir|g" /etc/environment -------------------------------------------------------------------------------- /images/ubuntu/assets/post-gen/systemd-linger.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Enable user session on boot, not on login 4 | UserId=$(cut -d: -f3 /etc/passwd | tail -1) 5 | loginctl enable-linger $UserId 6 | -------------------------------------------------------------------------------- /images/ubuntu/assets/ubuntu2204.conf: -------------------------------------------------------------------------------- 1 | # Name of pool supported by this image 2 | POOL_NAME="Ubuntu 2204" 3 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/Install-PowerShellAzModules.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-PowerShellAzModules.ps1 3 | ## Desc: Install Az modules for PowerShell 4 | ################################################################################ 5 | 6 | $ErrorActionPreference = "Stop" 7 | $ProgressPreference = "SilentlyContinue" 8 | 9 | Import-Module "$env:HELPER_SCRIPTS/../tests/Helpers.psm1" 10 | 11 | # Get modules content from toolset 12 | $modules = (Get-ToolsetContent).azureModules 13 | $installPSModulePath = "/usr/share" 14 | 15 | foreach ($module in $modules) { 16 | $moduleName = $module.name 17 | 18 | Write-Host "Installing ${moduleName} to the ${installPSModulePath} path..." 19 | foreach ($version in $module.versions) { 20 | $modulePath = Join-Path -Path $installPSModulePath -ChildPath "${moduleName}_${version}" 21 | Write-Host " - $version [$modulePath]" 22 | Save-Module -Path $modulePath -Name $moduleName -RequiredVersion $version -Force 23 | } 24 | 25 | } 26 | 27 | Invoke-PesterTests -TestFile "PowerShellModules" -TestName "AzureModules" 28 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/Install-PowerShellModules.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-PowerShellModules.ps1 3 | ## Desc: Install modules for PowerShell 4 | ################################################################################ 5 | 6 | $ErrorActionPreference = "Stop" 7 | $ProgressPreference = "SilentlyContinue" 8 | 9 | Import-Module "$env:HELPER_SCRIPTS/../tests/Helpers.psm1" 10 | 11 | # Specifies the installation policy 12 | Set-PSRepository -InstallationPolicy Trusted -Name PSGallery 13 | 14 | # Try to update PowerShellGet before the actual installation 15 | Install-Module -Name PowerShellGet -Force 16 | Update-Module -Name PowerShellGet -Force 17 | 18 | # Install PowerShell modules 19 | $modules = (Get-ToolsetContent).powershellModules 20 | 21 | foreach($module in $modules) { 22 | $moduleName = $module.name 23 | 24 | Write-Host "Installing ${moduleName} module" 25 | if ($module.versions) { 26 | foreach ($version in $module.versions) { 27 | Write-Host " - $version" 28 | Install-Module -Name $moduleName -RequiredVersion $version -Scope AllUsers -SkipPublisherCheck -Force 29 | } 30 | } else { 31 | Install-Module -Name $moduleName -Scope AllUsers -SkipPublisherCheck -Force 32 | } 33 | } 34 | 35 | Invoke-PesterTests -TestFile "PowerShellModules" -TestName "PowerShellModules" 36 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: cleanup.sh 4 | ## Desc: Perform cleanup 5 | ################################################################################ 6 | 7 | # before cleanup 8 | before=$(df / -Pm | awk 'NR==2{print $4}') 9 | 10 | # clears out the local repository of retrieved package files 11 | # It removes everything but the lock file from /var/cache/apt/archives/ and /var/cache/apt/archives/partial 12 | apt-get clean 13 | rm -rf /tmp/* 14 | rm -rf /root/.cache 15 | 16 | # journalctl 17 | if command -v journalctl; then 18 | journalctl --rotate 19 | journalctl --vacuum-time=1s 20 | fi 21 | 22 | # delete all .gz and rotated file 23 | find /var/log -type f -regex ".*\.gzquot; -delete 24 | find /var/log -type f -regex ".*\.[0-9]quot; -delete 25 | 26 | # wipe log files 27 | find /var/log/ -type f -exec cp /dev/null {} \; 28 | 29 | # delete symlink for tests running 30 | rm -f /usr/local/bin/invoke_tests 31 | 32 | # remove apt mock 33 | prefix=/usr/local/bin 34 | for tool in apt apt-get apt-key;do 35 | sudo rm -f $prefix/$tool 36 | done 37 | 38 | # after cleanup 39 | after=$(df / -Pm | awk 'NR==2{print $4}') 40 | 41 | # display size 42 | echo "Before: $before MB" 43 | echo "After : $after MB" 44 | echo "Delta : $(($after-$before)) MB" 45 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/configure-apt-sources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: configure-apt-sources.sh 4 | ## Desc: Configure apt sources with failover from Azure to Ubuntu archives. 5 | ################################################################################ 6 | 7 | source $HELPER_SCRIPTS/os.sh 8 | 9 | touch /etc/apt/apt-mirrors.txt 10 | 11 | printf "http://azure.archive.ubuntu.com/ubuntu/\tpriority:1\n" | tee -a /etc/apt/apt-mirrors.txt 12 | printf "https://archive.ubuntu.com/ubuntu/\tpriority:2\n" | tee -a /etc/apt/apt-mirrors.txt 13 | printf "https://security.ubuntu.com/ubuntu/\tpriority:3\n" | tee -a /etc/apt/apt-mirrors.txt 14 | 15 | if is_ubuntu24; then 16 | sed -i 's|http://azure\.archive\.ubuntu\.com/ubuntu/|mirror+file:/etc/apt/apt-mirrors.txt|' /etc/apt/sources.list.d/ubuntu.sources 17 | 18 | # Apt changes to survive Cloud Init 19 | cp -f /etc/apt/sources.list.d/ubuntu.sources /etc/cloud/templates/sources.list.ubuntu.deb822.tmpl 20 | else 21 | sed -i 's|http://azure\.archive\.ubuntu\.com/ubuntu/|mirror+file:/etc/apt/apt-mirrors.txt|' /etc/apt/sources.list 22 | 23 | # Apt changes to survive Cloud Init 24 | cp -f /etc/apt/sources.list /etc/cloud/templates/sources.list.ubuntu.tmpl 25 | fi 26 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/configure-image-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: configure-image-data.sh 4 | ## Desc: Create a file with image data and documentation links 5 | ################################################################################ 6 | 7 | imagedata_file=$IMAGEDATA_FILE 8 | image_version=$IMAGE_VERSION 9 | image_version_major=${image_version/.*/} 10 | image_version_minor=$(echo $image_version | cut -d "." -f 2) 11 | os_name=$(lsb_release -ds | sed "s/ /\\\n/g") 12 | os_version=$(lsb_release -rs) 13 | image_label="ubuntu-${os_version}" 14 | version_major=${os_version/.*/} 15 | version_wo_dot=${os_version/./} 16 | github_url="https://github.com/actions/runner-images/blob" 17 | 18 | software_url="${github_url}/ubuntu${version_major}/${image_version_major}.${image_version_minor}/images/ubuntu/Ubuntu${version_wo_dot}-Readme.md" 19 | releaseUrl="https://github.com/actions/runner-images/releases/tag/ubuntu${version_major}%2F${image_version_major}.${image_version_minor}" 20 | 21 | cat <<EOF > $imagedata_file 22 | [ 23 | { 24 | "group": "Operating System", 25 | "detail": "${os_name}" 26 | }, 27 | { 28 | "group": "Runner Image", 29 | "detail": "Image: ${image_label}\nVersion: ${image_version}\nIncluded Software: ${software_url}\nImage Release: ${releaseUrl}" 30 | } 31 | ] 32 | EOF 33 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/configure-limits.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: configure-limits.sh 4 | ## Desc: Configure limits 5 | ################################################################################ 6 | 7 | echo 'session required pam_limits.so' >> /etc/pam.d/common-session 8 | echo 'session required pam_limits.so' >> /etc/pam.d/common-session-noninteractive 9 | echo 'DefaultLimitNOFILE=65536' >> /etc/systemd/system.conf 10 | echo 'DefaultLimitSTACK=16M:infinity' >> /etc/systemd/system.conf 11 | 12 | # Raise Number of File Descriptors 13 | echo '* soft nofile 65536' >> /etc/security/limits.conf 14 | echo '* hard nofile 65536' >> /etc/security/limits.conf 15 | 16 | # Double stack size from default 8192KB 17 | echo '* soft stack 16384' >> /etc/security/limits.conf 18 | echo '* hard stack 16384' >> /etc/security/limits.conf 19 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/configure-snap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: configure-snap.sh 4 | ## Desc: Configure snap 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | 10 | # Update /etc/environment to include /snap/bin in PATH 11 | # because /etc/profile.d is ignored by `--norc` shell launch option 12 | 13 | prepend_etc_environment_path "/snap/bin" 14 | 15 | # Put snapd auto refresh on hold 16 | # as it may generate too much traffic on Canonical's snap server 17 | # when they are rolling a new major update out. 18 | # Hold is calculated as today's date + 60 days 19 | 20 | # snapd is started automatically, but during image generation 21 | # a unix socket may die, restart snapd.service (and therefore snapd.socket) 22 | # to make sure the socket is alive. 23 | 24 | systemctl restart snapd.socket 25 | systemctl restart snapd 26 | snap set system refresh.hold="$(date --date='today+60 days' +%Y-%m-%dT%H:%M:%S%:z)" 27 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/configure-system.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: configure-system.sh 4 | ## Desc: Post deployment system configuration actions 5 | ################################################################################ 6 | 7 | source $HELPER_SCRIPT_FOLDER/etc-environment.sh 8 | source $HELPER_SCRIPT_FOLDER/os.sh 9 | 10 | mv -f /imagegeneration/post-generation /opt 11 | 12 | echo "chmod -R 777 /opt" 13 | chmod -R 777 /opt 14 | echo "chmod -R 777 /usr/share" 15 | chmod -R 777 /usr/share 16 | 17 | chmod 755 $IMAGE_FOLDER 18 | 19 | # Remove quotes around PATH 20 | ENVPATH=$(grep 'PATH=' /etc/environment | head -n 1 | sed -z 's/^PATH=*//') 21 | ENVPATH=${ENVPATH#"\""} 22 | ENVPATH=${ENVPATH%"\""} 23 | replace_etc_environment_variable "PATH" "${ENVPATH}" 24 | echo "Updated /etc/environment: $(cat /etc/environment)" 25 | 26 | # Clean yarn and npm cache 27 | if yarn --version > /dev/null; then 28 | yarn cache clean 29 | fi 30 | 31 | if npm --version; then 32 | npm cache clean --force 33 | fi 34 | 35 | if is_ubuntu24; then 36 | # Prevent needrestart from restarting the provisioner service. 37 | # Currently only happens on Ubuntu 24.04, so make it conditional for the time being 38 | # as configuration is too different between Ubuntu versions. 39 | sed -i '/^\s*};/i \ qr(^runner-provisioner) => 0,' /etc/needrestart/needrestart.conf 40 | fi 41 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-actions-cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-actions-cache.sh 4 | ## Desc: Download latest release from https://github.com/actions/action-versions 5 | ## Maintainer: #actions-runtime and @TingluoHuang 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/install.sh 10 | source $HELPER_SCRIPTS/etc-environment.sh 11 | 12 | # Prepare directory and env variable for ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE 13 | ACTION_ARCHIVE_CACHE_DIR=/opt/actionarchivecache 14 | mkdir -p $ACTION_ARCHIVE_CACHE_DIR 15 | chmod -R 777 $ACTION_ARCHIVE_CACHE_DIR 16 | echo "Setting up ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE variable to ${ACTION_ARCHIVE_CACHE_DIR}" 17 | set_etc_environment_variable "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE" "${ACTION_ARCHIVE_CACHE_DIR}" 18 | 19 | # Download latest release from github.com/actions/action-versions and untar to /opt/actionarchivecache 20 | download_url=$(resolve_github_release_asset_url "actions/action-versions" "endswith(\"action-versions.tar.gz\")" "latest") 21 | archive_path=$(download_with_retry "$download_url") 22 | tar -xzf "$archive_path" -C $ACTION_ARCHIVE_CACHE_DIR 23 | 24 | invoke_tests "ActionArchiveCache" 25 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-aliyun-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-aliyun-cli.sh 4 | ## Desc: Install Alibaba Cloud CLI 5 | ## Supply chain security: Alibaba Cloud CLI - checksum validation 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/os.sh 10 | source $HELPER_SCRIPTS/install.sh 11 | 12 | # Install Alibaba Cloud CLI 13 | 14 | download_url=$(resolve_github_release_asset_url "aliyun/aliyun-cli" "contains(\"aliyun-cli-linux\") and endswith(\"amd64.tgz\")" "latest") 15 | hash_url="https://github.com/aliyun/aliyun-cli/releases/latest/download/SHASUMS256.txt" 16 | 17 | archive_path=$(download_with_retry "$download_url") 18 | 19 | # Supply chain security - Alibaba Cloud CLI 20 | external_hash=$(get_checksum_from_url "$hash_url" "aliyun-cli-linux.*amd64.tgz" "SHA256") 21 | 22 | use_checksum_comparison "$archive_path" "$external_hash" 23 | 24 | tar xzf "$archive_path" 25 | mv aliyun /usr/local/bin 26 | 27 | invoke_tests "CLI.Tools" "Aliyun CLI" 28 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-apache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-apache.sh 4 | ## Desc: Install Apache HTTP Server 5 | ################################################################################ 6 | 7 | # Install Apache 8 | apt-get install apache2 9 | 10 | # Disable apache2.service 11 | systemctl is-active --quiet apache2.service && systemctl stop apache2.service 12 | systemctl disable apache2.service 13 | 14 | invoke_tests "WebServers" "Apache" 15 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-apt-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-apt-common.sh 4 | ## Desc: Install basic command line utilities and dev packages 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | common_packages=$(get_toolset_value .apt.common_packages[]) 11 | cmd_packages=$(get_toolset_value .apt.cmd_packages[]) 12 | 13 | for package in $common_packages $cmd_packages; do 14 | echo "Install $package" 15 | apt-get install --no-install-recommends $package 16 | done 17 | 18 | invoke_tests "Apt" 19 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-apt-vital.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-apt-vital.sh 4 | ## Desc: Install vital command line utilities 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | vital_packages=$(get_toolset_value .apt.vital_packages[]) 11 | apt-get install --no-install-recommends $vital_packages 12 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-azcopy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-azcopy.sh 4 | ## Desc: Install AzCopy 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # Install AzCopy10 11 | archive_path=$(download_with_retry "https://aka.ms/downloadazcopy-v10-linux") 12 | tar xzf "$archive_path" --strip-components=1 -C /tmp 13 | install /tmp/azcopy /usr/local/bin/azcopy 14 | 15 | # Create azcopy 10 alias for backward compatibility 16 | ln -sf /usr/local/bin/azcopy /usr/local/bin/azcopy10 17 | 18 | invoke_tests "Tools" "azcopy" 19 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-azure-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-azure-cli.sh 4 | ## Desc: Install Azure CLI (az) 5 | ################################################################################ 6 | 7 | # Install Azure CLI (instructions taken from https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) 8 | curl -fsSL https://aka.ms/InstallAzureCLIDeb | sudo bash 9 | 10 | echo "azure-cli https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt" >> $HELPER_SCRIPTS/apt-sources.txt 11 | 12 | rm -f /etc/apt/sources.list.d/azure-cli.list 13 | rm -f /etc/apt/sources.list.d/azure-cli.list.save 14 | 15 | invoke_tests "CLI.Tools" "Azure CLI" 16 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-azure-devops-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-azure-devops-cli.sh 4 | ## Desc: Install Azure DevOps CLI (az devops) 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | 10 | # AZURE_EXTENSION_DIR shell variable defines where modules are installed 11 | # https://docs.microsoft.com/en-us/cli/azure/azure-cli-extensions-overview 12 | export AZURE_EXTENSION_DIR=/opt/az/azcliextensions 13 | set_etc_environment_variable "AZURE_EXTENSION_DIR" "${AZURE_EXTENSION_DIR}" 14 | 15 | # install azure devops Cli extension 16 | az extension add -n azure-devops 17 | 18 | invoke_tests "CLI.Tools" "Azure DevOps CLI" 19 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-bazel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-bazel.sh 4 | ## Desc: Install Bazel and Bazelisk (A user-friendly launcher for Bazel) 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # Install bazelisk 11 | npm install -g @bazel/bazelisk 12 | 13 | # run bazelisk once in order to install /usr/local/bin/bazel binary 14 | sudo -u $SUDO_USER bazel version 15 | 16 | invoke_tests "Tools" "Bazel" 17 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-bicep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-bicep.sh 4 | ## Desc: Install bicep cli 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # Install Bicep CLI 11 | download_url=$(resolve_github_release_asset_url "Azure/bicep" "endswith(\"bicep-linux-x64\")" "latest") 12 | bicep_binary_path=$(download_with_retry "${download_url}") 13 | 14 | # Mark it as executable 15 | install "$bicep_binary_path" /usr/local/bin/bicep 16 | 17 | invoke_tests "Tools" "Bicep" 18 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-cmake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-cmake.sh 4 | ## Desc: Install CMake 5 | ## Supply chain security: CMake - checksum validation 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | # Test to see if the software in question is already installed, if not install it 12 | echo "Checking to see if the installer script has already been run" 13 | if command -v cmake; then 14 | echo "cmake is already installed" 15 | else 16 | # Download script to install CMake 17 | download_url=$(resolve_github_release_asset_url "Kitware/CMake" "endswith(\"inux-x86_64.sh\")" "3.31.6") 18 | curl -fsSL "${download_url}" -o cmakeinstall.sh 19 | 20 | # Supply chain security - CMake 21 | hash_url=$(resolve_github_release_asset_url "Kitware/CMake" "endswith(\"SHA-256.txt\")" "3.31.6") 22 | external_hash=$(get_checksum_from_url "$hash_url" "linux-x86_64.sh" "SHA256") 23 | use_checksum_comparison "cmakeinstall.sh" "$external_hash" 24 | 25 | # Install CMake and remove the install script 26 | chmod +x cmakeinstall.sh \ 27 | && ./cmakeinstall.sh --prefix=/usr/local --exclude-subdir \ 28 | && rm cmakeinstall.sh 29 | fi 30 | 31 | invoke_tests "Tools" "Cmake" 32 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-container-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-container-tools.sh 4 | ## Desc: Install container tools: podman, buildah and skopeo onto the image 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/os.sh 9 | 10 | # 11 | # pin podman due to https://github.com/actions/runner-images/issues/7753 12 | # https://bugs.launchpad.net/ubuntu/+source/libpod/+bug/2024394 13 | # 14 | if ! is_ubuntu22; then 15 | install_packages=(podman buildah skopeo) 16 | else 17 | install_packages=(podman=3.4.4+ds1-1ubuntu1 buildah skopeo) 18 | fi 19 | 20 | 21 | if is_ubuntu22; then 22 | # Install containernetworking-plugins for Ubuntu 22 23 | curl -O http://archive.ubuntu.com/ubuntu/pool/universe/g/golang-github-containernetworking-plugins/containernetworking-plugins_1.1.1+ds1-3build1_amd64.deb 24 | dpkg -i containernetworking-plugins_1.1.1+ds1-3build1_amd64.deb 25 | fi 26 | 27 | # Install podman, buildah, skopeo container's tools 28 | apt-get update 29 | apt-get install ${install_packages[@]} 30 | mkdir -p /etc/containers 31 | printf "[registries.search]\nregistries = ['docker.io', 'quay.io']\n" | tee /etc/containers/registries.conf 32 | 33 | invoke_tests "Tools" "Containers" 34 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-gcc-compilers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-gcc-compilers.sh 4 | ## Desc: Install GNU C++ compilers 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | versions=$(get_toolset_value '.gcc.versions[]') 11 | 12 | for version in ${versions[*]}; do 13 | echo "Installing $version..." 14 | apt-get install $version 15 | done 16 | 17 | invoke_tests "Tools" "gcc" 18 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-gfortran.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-gfortran.sh 4 | ## Desc: Install GNU Fortran 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | versions=$(get_toolset_value '.gfortran.versions[]') 11 | 12 | for version in ${versions[*]}; do 13 | echo "Installing $version..." 14 | apt-get install $version 15 | done 16 | 17 | echo "Install versionless gfortran (latest)" 18 | apt-get install gfortran 19 | 20 | invoke_tests "Tools" "gfortran" 21 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-git-lfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-git-lfs.sh 4 | ## Desc: Install Git-lfs 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | GIT_LFS_REPO="https://packagecloud.io/install/repositories/github/git-lfs" 11 | 12 | # Install git-lfs 13 | curl -fsSL $GIT_LFS_REPO/script.deb.sh | bash 14 | apt-get install git-lfs 15 | 16 | # Remove source repo's 17 | rm /etc/apt/sources.list.d/github_git-lfs.list 18 | 19 | # Document apt source repo's 20 | echo "git-lfs $GIT_LFS_REPO" >> $HELPER_SCRIPTS/apt-sources.txt 21 | 22 | invoke_tests "Tools" "Git-lfs" 23 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-git.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-git.sh 4 | ## Desc: Install Git and Git-FTP 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | GIT_REPO="ppa:git-core/ppa" 11 | 12 | ## Install git 13 | add-apt-repository $GIT_REPO -y 14 | apt-get update 15 | apt-get install git 16 | 17 | # Git version 2.35.2 introduces security fix that breaks action\checkout https://github.com/actions/checkout/issues/760 18 | cat <<EOF >> /etc/gitconfig 19 | [safe] 20 | directory = * 21 | EOF 22 | 23 | # Install git-ftp 24 | apt-get install git-ftp 25 | 26 | # Remove source repo's 27 | add-apt-repository --remove $GIT_REPO 28 | 29 | # Document apt source repo's 30 | echo "git-core $GIT_REPO" >> $HELPER_SCRIPTS/apt-sources.txt 31 | 32 | # Add well-known SSH host keys to known_hosts 33 | ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> /etc/ssh/ssh_known_hosts 34 | ssh-keyscan -t rsa ssh.dev.azure.com >> /etc/ssh/ssh_known_hosts 35 | 36 | invoke_tests "Tools" "Git" 37 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-github-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-github-cli.sh 4 | ## Desc: Install GitHub CLI 5 | ## Must be run as non-root user after homebrew 6 | ## Supply chain security: GitHub CLI - checksum validation 7 | ################################################################################ 8 | 9 | # Source the helpers for use with the script 10 | source $HELPER_SCRIPTS/install.sh 11 | 12 | # Download GitHub CLI 13 | gh_cli_url=$(resolve_github_release_asset_url "cli/cli" "contains(\"linux\") and contains(\"amd64\") and endswith(\".deb\")" "latest") 14 | gh_cli_deb_path=$(download_with_retry "$gh_cli_url") 15 | 16 | # Supply chain security - GitHub CLI 17 | hash_url=$(resolve_github_release_asset_url "cli/cli" "endswith(\"checksums.txt\")" "latest") 18 | external_hash=$(get_checksum_from_url "$hash_url" "linux_amd64.deb" "SHA256") 19 | use_checksum_comparison "$gh_cli_deb_path" "$external_hash" 20 | 21 | # Install GitHub CLI 22 | apt-get install "$gh_cli_deb_path" 23 | 24 | invoke_tests "CLI.Tools" "GitHub CLI" 25 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-google-cloud-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-google-cloud-cli.sh 4 | ## Desc: Install the Google Cloud CLI 5 | ################################################################################ 6 | 7 | REPO_URL="https://packages.cloud.google.com/apt" 8 | 9 | # Install the Google Cloud CLI 10 | echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] $REPO_URL cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list 11 | wget -qO- https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor > /usr/share/keyrings/cloud.google.gpg 12 | apt-get update 13 | apt-get install google-cloud-cli 14 | 15 | # remove apt 16 | rm /etc/apt/sources.list.d/google-cloud-sdk.list 17 | rm /usr/share/keyrings/cloud.google.gpg 18 | 19 | # add repo to the apt-sources.txt 20 | echo "google-cloud-sdk $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt 21 | 22 | invoke_tests "CLI.Tools" "Google Cloud CLI" 23 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-heroku.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-heroku.sh 4 | ## Desc: Install Heroku CLI. Based on instructions found here: https://devcenter.heroku.com/articles/heroku-cli 5 | ################################################################################ 6 | 7 | REPO_URL="https://cli-assets.heroku.com/channels/stable/apt" 8 | GPG_KEY="/usr/share/keyrings/heroku.gpg" 9 | REPO_PATH="/etc/apt/sources.list.d/heroku.list" 10 | 11 | # add heroku repository to apt 12 | curl -fsSL "${REPO_URL}/release.key" | gpg --dearmor -o $GPG_KEY 13 | echo "deb [trusted=yes] $REPO_URL ./" > $REPO_PATH 14 | 15 | # install heroku 16 | apt-get update 17 | apt-get install heroku 18 | 19 | # remove heroku's apt repository 20 | rm $REPO_PATH 21 | rm $GPG_KEY 22 | 23 | invoke_tests "Tools" "Heroku" 24 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-homebrew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-homebrew.sh 4 | ## Desc: Install Homebrew on Linux 5 | ## Caveat: Brew MUST NOT be used to install any tool during the image build to avoid dependencies, which may come along with the tool 6 | ################################################################################ 7 | 8 | # Source the helpers 9 | source $HELPER_SCRIPTS/etc-environment.sh 10 | source $HELPER_SCRIPTS/install.sh 11 | 12 | # Install the Homebrew on Linux 13 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 14 | 15 | # Invoke shellenv to make brew available during running session 16 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 17 | 18 | set_etc_environment_variable HOMEBREW_NO_AUTO_UPDATE 1 19 | set_etc_environment_variable HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS 3650 20 | 21 | # Validate the installation ad hoc 22 | echo "Validate the installation reloading /etc/environment" 23 | reload_etc_environment 24 | 25 | gfortran=$(brew --prefix)/bin/gfortran 26 | # Remove gfortran symlink, not to conflict with system gfortran 27 | if [[ -e $gfortran ]]; then 28 | rm $gfortran 29 | fi 30 | 31 | invoke_tests "Tools" "Homebrew" 32 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-julia.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-julia.sh 4 | ## Desc: Install Julia and add to the path 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # get the latest julia version 11 | json=$(curl -fsSL "https://julialang-s3.julialang.org/bin/versions.json") 12 | julia_version=$(echo $json | jq -r '.[].files[] | select(.triplet=="x86_64-linux-gnu" and (.version | contains("-") | not)).version' | sort -V | tail -n1) 13 | 14 | # download julia archive 15 | julia_tar_url=$(echo $json | jq -r ".[].files[].url | select(endswith(\"julia-${julia_version}-linux-x86_64.tar.gz\"))") 16 | julia_archive_path=$(download_with_retry "$julia_tar_url") 17 | 18 | # extract files and make symlink 19 | julia_installation_path="/usr/local/julia${julia_version}" 20 | mkdir -p "${julia_installation_path}" 21 | tar -C "${julia_installation_path}" -xzf "$julia_archive_path" --strip-components=1 22 | ln -s "${julia_installation_path}/bin/julia" /usr/bin/julia 23 | 24 | invoke_tests "Tools" "Julia" 25 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-kotlin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-kotlin.sh 4 | ## Desc: Install Kotlin 5 | ## Supply chain security: Kotlin - checksum validation 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | KOTLIN_ROOT="/usr/share" 12 | download_url=$(resolve_github_release_asset_url "JetBrains/kotlin" "contains(\"kotlin-compiler\") and endswith(\".zip\")" "2.1.10") 13 | archive_path=$(download_with_retry "$download_url") 14 | 15 | # Supply chain security - Kotlin 16 | kotlin_hash_file=$(download_with_retry "${download_url}.sha256") 17 | kotlin_hash=$(cat "$kotlin_hash_file") 18 | use_checksum_comparison "$archive_path" "$kotlin_hash" 19 | 20 | unzip -qq "$archive_path" -d $KOTLIN_ROOT 21 | rm $KOTLIN_ROOT/kotlinc/bin/*.bat 22 | ln -sf $KOTLIN_ROOT/kotlinc/bin/* /usr/bin 23 | 24 | invoke_tests "Tools" "Kotlin" 25 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-leiningen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-leiningen.sh 4 | ## Desc: Install Leiningen 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | 10 | LEIN_BIN=/usr/local/bin/lein 11 | curl -fsSL https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > $LEIN_BIN 12 | chmod 0755 $LEIN_BIN 13 | 14 | # Run lein to trigger self-install 15 | export LEIN_HOME=/usr/local/lib/lein 16 | lein 17 | 18 | LEIN_JAR=$(find $LEIN_HOME -name "leiningen-*-standalone.jar") 19 | set_etc_environment_variable "LEIN_JAR" "${LEIN_JAR}" 20 | set_etc_environment_variable "LEIN_HOME" "${LEIN_HOME}" 21 | 22 | invoke_tests "Tools" "Leiningen" 23 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-miniconda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-miniconda.sh 4 | ## Desc: Install miniconda 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | 10 | # Install Miniconda 11 | curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda.sh \ 12 | && chmod +x miniconda.sh \ 13 | && ./miniconda.sh -b -p /usr/share/miniconda \ 14 | && rm miniconda.sh 15 | 16 | CONDA=/usr/share/miniconda 17 | set_etc_environment_variable "CONDA" "${CONDA}" 18 | 19 | ln -s $CONDA/bin/conda /usr/bin/conda 20 | 21 | invoke_tests "Tools" "Conda" 22 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-mono.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-mono.sh 4 | ## Desc: Install Mono 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/os.sh 9 | 10 | os_label=$(lsb_release -cs) 11 | REPO_URL="https://download.mono-project.com/repo/ubuntu" 12 | GPG_KEY="/usr/share/keyrings/mono-official-stable.gpg" 13 | REPO_PATH="/etc/apt/sources.list.d/mono-official-stable.list" 14 | 15 | # There are no packages for Ubuntu 22 in the repo, but developers confirmed that packages from Ubuntu 20 should work 16 | if is_ubuntu22; then 17 | os_label="focal" 18 | fi 19 | 20 | # Install Mono repo 21 | curl -fsSL https://download.mono-project.com/repo/xamarin.gpg | gpg --dearmor -o $GPG_KEY 22 | echo "deb [signed-by=$GPG_KEY] $REPO_URL stable-$os_label main" > $REPO_PATH 23 | 24 | # Install Mono 25 | apt-get update 26 | apt-get install --no-install-recommends apt-transport-https mono-complete nuget 27 | 28 | # Remove Mono's apt repo 29 | rm $REPO_PATH 30 | rm -f "${REPO_PATH}.save" 31 | rm $GPG_KEY 32 | 33 | # Document source repo 34 | echo "mono https://download.mono-project.com/repo/ubuntu stable-$os_label main" >> $HELPER_SCRIPTS/apt-sources.txt 35 | 36 | invoke_tests "Tools" "Mono" 37 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-ms-repos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-ms-repos.sh 4 | ## Desc: Install official Microsoft package repos for the distribution 5 | ################################################################################ 6 | 7 | os_label=$(lsb_release -rs) 8 | 9 | # Install Microsoft repository 10 | wget https://packages.microsoft.com/config/ubuntu/$os_label/packages-microsoft-prod.deb 11 | dpkg -i packages-microsoft-prod.deb 12 | 13 | # update 14 | apt-get install apt-transport-https ca-certificates curl software-properties-common 15 | apt-get update 16 | apt-get dist-upgrade 17 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-mssql-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-mssql-tools.sh 4 | ## Desc: Install MS SQL Server client tools (https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools?view=sql-server-2017) 5 | ################################################################################ 6 | 7 | export ACCEPT_EULA=Y 8 | 9 | apt-get update 10 | apt-get install mssql-tools unixodbc-dev 11 | apt-get -f install 12 | ln -s /opt/mssql-tools/bin/* /usr/local/bin/ 13 | 14 | invoke_tests "Tools" "MSSQLCommandLineTools" 15 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-mysql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-mysql.sh 4 | ## Desc: Install MySQL Client 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/os.sh 9 | 10 | # Mysql setting up root password 11 | MYSQL_ROOT_PASSWORD=root 12 | echo "mysql-server mysql-server/root_password password $MYSQL_ROOT_PASSWORD" | debconf-set-selections 13 | echo "mysql-server mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD" | debconf-set-selections 14 | 15 | export ACCEPT_EULA=Y 16 | 17 | # Install MySQL Client 18 | apt-get install mysql-client 19 | 20 | # Install MySQL Server 21 | apt-get install mysql-server 22 | 23 | # Install MySQL Dev tools 24 | apt-get install libmysqlclient-dev 25 | 26 | # Disable mysql.service 27 | systemctl is-active --quiet mysql.service && systemctl stop mysql.service 28 | systemctl disable mysql.service 29 | 30 | invoke_tests "Databases" "MySQL" 31 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-nginx.sh 4 | ## Desc: Install Nginx 5 | ################################################################################ 6 | 7 | # Install Nginx 8 | apt-get install nginx 9 | 10 | # Disable nginx.service 11 | systemctl is-active --quiet nginx.service && systemctl stop nginx.service 12 | systemctl disable nginx.service 13 | 14 | invoke_tests "WebServers" "Nginx" 15 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-ninja.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-ninja.sh 4 | ## Desc: Install ninja-build 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # Install ninja 11 | download_url=$(resolve_github_release_asset_url "ninja-build/ninja" "endswith(\"ninja-linux.zip\")" "latest") 12 | ninja_binary_path=$(download_with_retry "${download_url}") 13 | 14 | # Unzip the ninja binary 15 | unzip -qq "$ninja_binary_path" -d /usr/local/bin 16 | 17 | invoke_tests "Tools" "Ninja" 18 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-nodejs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-nodejs.sh 4 | ## Desc: Install Node.js LTS and related tooling (Gulp, Grunt) 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # Install default Node.js 11 | default_version=$(get_toolset_value '.node.default') 12 | curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n -o ~/n 13 | bash ~/n $default_version 14 | 15 | # Install node modules 16 | node_modules=$(get_toolset_value '.node_modules[].name') 17 | npm install -g $node_modules 18 | 19 | echo "Creating the symlink for [now] command to vercel CLI" 20 | ln -s /usr/local/bin/vercel /usr/local/bin/now 21 | 22 | # fix global modules installation as regular user 23 | # related issue https://github.com/actions/runner-images/issues/3727 24 | sudo chmod -R 777 /usr/local/lib/node_modules 25 | sudo chmod -R 777 /usr/local/bin 26 | 27 | rm -rf ~/n 28 | 29 | invoke_tests "Node" "Node.js" 30 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-nvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-nvm.sh 4 | ## Desc: Install Nvm 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | 10 | export NVM_DIR="/etc/skel/.nvm" 11 | mkdir $NVM_DIR 12 | nvm_version=$(curl -fsSL https://api.github.com/repos/nvm-sh/nvm/releases/latest | jq -r '.tag_name') 13 | curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/$nvm_version/install.sh | bash 14 | set_etc_environment_variable "NVM_DIR" '$HOME/.nvm' 15 | 16 | echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' | tee -a /etc/skel/.bash_profile 17 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" 18 | 19 | invoke_tests "Tools" "nvm" 20 | 21 | # set system node.js as default one 22 | nvm alias default system 23 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-oc-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-oc-cli.sh 4 | ## Desc: Install the OC CLI 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/os.sh 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | 12 | # Install the oc CLI 13 | download_url="https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux.tar.gz" 14 | 15 | archive_path=$(download_with_retry "$download_url") 16 | 17 | tar xzf "$archive_path" -C "/usr/local/bin" oc 18 | 19 | invoke_tests "CLI.Tools" "OC CLI" 20 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-oras-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-oras-cli.sh 4 | ## Desc: Install ORAS CLI 5 | ## Supply chain security: ORAS CLI - checksum validation 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | # Determine latest ORAS CLI version 12 | download_url=$(resolve_github_release_asset_url "oras-project/oras" "endswith(\"linux_amd64.tar.gz\")" "latest") 13 | 14 | # Download ORAS CLI 15 | archive_path=$(download_with_retry "$download_url") 16 | 17 | # Supply chain security - ORAS CLI 18 | hash_url=$(resolve_github_release_asset_url "oras-project/oras" "endswith(\"checksums.txt\")" "latest") 19 | external_hash=$(get_checksum_from_url "${hash_url}" "linux_amd64.tar.gz" "SHA256") 20 | use_checksum_comparison "$archive_path" "${external_hash}" 21 | 22 | # Unzip ORAS CLI 23 | tar xzf "$archive_path" -C /usr/local/bin oras 24 | 25 | invoke_tests "CLI.Tools" "Oras CLI" 26 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-packer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-packer.sh 4 | ## Desc: Install packer 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | # Install Packer 11 | download_url=$(curl -fsSL https://api.releases.hashicorp.com/v1/releases/packer/latest | jq -r '.builds[] | select((.arch=="amd64") and (.os=="linux")).url') 12 | archive_path=$(download_with_retry "$download_url") 13 | unzip -o -qq "$archive_path" -d /usr/local/bin 14 | 15 | invoke_tests "Tools" "Packer" 16 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-pipx-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-pipx-packages.sh 4 | ## Desc: Install tools via pipx 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | export PATH="$PATH:/opt/pipx_bin" 11 | 12 | pipx_packages=$(get_toolset_value ".pipx[] .package") 13 | 14 | for package in $pipx_packages; do 15 | echo "Install $package into default python" 16 | pipx install $package 17 | 18 | # https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html 19 | # Install ansible into an existing ansible-core Virtual Environment 20 | if [[ $package == "ansible-core" ]]; then 21 | pipx inject $package ansible 22 | fi 23 | done 24 | 25 | invoke_tests "Common" "PipxPackages" 26 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-postgresql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-postgresql.sh 4 | ## Desc: Install PostgreSQL 5 | ################################################################################ 6 | 7 | # Source the helpers 8 | source $HELPER_SCRIPTS/os.sh 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | REPO_URL="https://apt.postgresql.org/pub/repos/apt/" 12 | 13 | # Preparing repo for PostgreSQL 14 | wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /usr/share/keyrings/postgresql.gpg 15 | echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] $REPO_URL $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list 16 | 17 | # Fetch PostgreSQL version to install from the toolset 18 | toolset_version=$(get_toolset_value '.postgresql.version') 19 | 20 | # Install PostgreSQL 21 | echo "Install PostgreSQL" 22 | apt update 23 | apt-get install postgresql-$toolset_version 24 | 25 | echo "Install libpq-dev" 26 | apt-get install libpq-dev 27 | 28 | # Disable postgresql.service 29 | systemctl is-active --quiet postgresql.service && systemctl stop postgresql.service 30 | systemctl disable postgresql.service 31 | 32 | rm /etc/apt/sources.list.d/pgdg.list 33 | rm /usr/share/keyrings/postgresql.gpg 34 | 35 | echo "postgresql $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt 36 | 37 | invoke_tests "Databases" "PostgreSQL" 38 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-powershell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-powershell.sh 4 | ## Desc: Install PowerShell Core 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | source $HELPER_SCRIPTS/os.sh 10 | 11 | pwsh_version=$(get_toolset_value .pwsh.version) 12 | 13 | # Install Powershell 14 | 15 | apt-get install powershell=$pwsh_version* 16 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-pulumi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-pulumi.sh 4 | ## Desc: Install Pulumi 5 | ## Supply chain security: Pulumi - checksum validation 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | # Dowload Pulumi 12 | version=$(curl -fsSL "https://www.pulumi.com/latest-version") 13 | download_url="https://get.pulumi.com/releases/sdk/pulumi-v${version}-linux-x64.tar.gz" 14 | archive_path=$(download_with_retry "$download_url") 15 | 16 | # Supply chain security - Pulumi 17 | external_hash=$(get_checksum_from_url "https://github.com/pulumi/pulumi/releases/download/v${version}/SHA512SUMS" "linux-x64.tar.gz" "SHA512") 18 | use_checksum_comparison "$archive_path" "$external_hash" "512" 19 | 20 | # Unzipping Pulumi 21 | tar --strip=1 -xf "$archive_path" -C /usr/local/bin 22 | 23 | invoke_tests "Tools" "Pulumi" 24 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-rlang.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-rlang.sh 4 | ## Desc: Install R 5 | ################################################################################ 6 | 7 | # install R 8 | os_label=$(lsb_release -cs) 9 | 10 | wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | gpg --dearmor > /usr/share/keyrings/rlang.gpg 11 | echo "deb [signed-by=/usr/share/keyrings/rlang.gpg] https://cloud.r-project.org/bin/linux/ubuntu $os_label-cran40/" > /etc/apt/sources.list.d/rlang.list 12 | 13 | apt-get update 14 | apt-get install r-base 15 | 16 | rm /etc/apt/sources.list.d/rlang.list 17 | rm /usr/share/keyrings/rlang.gpg 18 | 19 | invoke_tests "Tools" "R" 20 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-runner-package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-runner-package.sh 4 | ## Desc: Download and Install runner package 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | 10 | download_url=$(resolve_github_release_asset_url "actions/runner" 'test("actions-runner-linux-x64-[0-9]+\\.[0-9]{3}\\.[0-9]+\\.tar\\.gzquot;)' "latest") 11 | archive_name="${download_url##*/}" 12 | archive_path=$(download_with_retry "$download_url") 13 | 14 | mkdir -p /opt/runner-cache 15 | mv "$archive_path" "/opt/runner-cache/$archive_name" 16 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-rust.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-rust.sh 4 | ## Desc: Install Rust 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | source $HELPER_SCRIPTS/os.sh 10 | 11 | export RUSTUP_HOME=/etc/skel/.rustup 12 | export CARGO_HOME=/etc/skel/.cargo 13 | 14 | curl -fsSL https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal 15 | 16 | # Initialize environment variables 17 | source $CARGO_HOME/env 18 | 19 | # Install common tools 20 | rustup component add rustfmt clippy 21 | 22 | if is_ubuntu22; then 23 | cargo install --locked bindgen-cli cbindgen cargo-audit cargo-outdated 24 | fi 25 | 26 | # Cleanup Cargo cache 27 | rm -rf ${CARGO_HOME}/registry/* 28 | 29 | # Update /etc/environment 30 | prepend_etc_environment_path '$HOME/.cargo/bin' 31 | 32 | invoke_tests "Tools" "Rust" 33 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-sbt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-sbt.sh 4 | ## Desc: Install sbt 5 | ################################################################################ 6 | 7 | source $HELPER_SCRIPTS/install.sh 8 | 9 | # Install latest sbt release 10 | download_url=$(resolve_github_release_asset_url "sbt/sbt" "endswith(\".tgz\")" "latest") 11 | archive_path=$(download_with_retry "$download_url") 12 | tar zxf "$archive_path" -C /usr/share 13 | ln -s /usr/share/sbt/bin/sbt /usr/bin/sbt 14 | 15 | invoke_tests "Tools" "Sbt" 16 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-selenium.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-selenium.sh 4 | ## Desc: Install selenium server 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | source $HELPER_SCRIPTS/etc-environment.sh 10 | 11 | selenium_major_version=$(get_toolset_value '.selenium.version') 12 | 13 | # Download Selenium server 14 | selenium_download_url=$(resolve_github_release_asset_url "SeleniumHQ/selenium" "contains(\"selenium-server-\") and endswith(\".jar\")" "$selenium_major_version\.+" "" "true") 15 | selenium_jar_path=$(download_with_retry "$selenium_download_url" "/usr/share/java/selenium-server.jar") 16 | 17 | # Create an empty file to retrieve selenium version 18 | selenium_full_version=$(echo $selenium_download_url | awk -F"selenium-server-|.jar" '{print $2}') 19 | touch "/usr/share/java/selenium-server-$selenium_full_version" 20 | 21 | # Add SELENIUM_JAR_PATH environment variable 22 | set_etc_environment_variable "SELENIUM_JAR_PATH" "$selenium_jar_path" 23 | 24 | invoke_tests "Tools" "Selenium" 25 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-sqlpackage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-sqlpackage.sh 4 | ## Desc: Install SqlPackage CLI to DacFx (https://docs.microsoft.com/sql/tools/sqlpackage/sqlpackage-download#get-sqlpackage-net-core-for-linux) 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/install.sh 9 | source $HELPER_SCRIPTS/os.sh 10 | 11 | # Install libssl1.1 dependency 12 | if is_ubuntu22; then 13 | focal_list=/etc/apt/sources.list.d/focal-security.list 14 | echo "deb https://archive.ubuntu.com/ubuntu/ focal-security main" | tee "${focal_list}" 15 | apt-get update --quiet 16 | 17 | apt-get install --no-install-recommends libssl1.1 18 | 19 | rm "${focal_list}" 20 | apt-get update --quiet 21 | fi 22 | 23 | # Install SqlPackage 24 | archive_path=$(download_with_retry "https://aka.ms/sqlpackage-linux") 25 | unzip -qq "$archive_path" -d /usr/local/sqlpackage 26 | chmod +x /usr/local/sqlpackage/sqlpackage 27 | ln -sf /usr/local/sqlpackage/sqlpackage /usr/local/bin 28 | 29 | invoke_tests "Tools" "SqlPackage" 30 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-terraform.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-terraform.sh 4 | ## Desc: Install terraform 5 | ################################################################################ 6 | 7 | source $HELPER_SCRIPTS/install.sh 8 | 9 | # Install Terraform 10 | download_url=$(curl -fsSL https://api.releases.hashicorp.com/v1/releases/terraform/latest | jq -r '.builds[] | select((.arch=="amd64") and (.os=="linux")).url') 11 | archive_path=$(download_with_retry "${download_url}") 12 | unzip -qq "$archive_path" -d /usr/local/bin 13 | 14 | invoke_tests "Tools" "Terraform" 15 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-vcpkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-vcpkg.sh 4 | ## Desc: Install vcpkg 5 | ################################################################################ 6 | 7 | # Source the helpers for use with the script 8 | source $HELPER_SCRIPTS/etc-environment.sh 9 | 10 | # Set env variable for vcpkg 11 | VCPKG_INSTALLATION_ROOT=/usr/local/share/vcpkg 12 | set_etc_environment_variable "VCPKG_INSTALLATION_ROOT" "${VCPKG_INSTALLATION_ROOT}" 13 | 14 | # Install vcpkg 15 | git clone https://github.com/Microsoft/vcpkg $VCPKG_INSTALLATION_ROOT 16 | 17 | $VCPKG_INSTALLATION_ROOT/bootstrap-vcpkg.sh 18 | 19 | # workaround https://github.com/microsoft/vcpkg/issues/27786 20 | 21 | mkdir -p /root/.vcpkg/ $HOME/.vcpkg 22 | touch /root/.vcpkg/vcpkg.path.txt $HOME/.vcpkg/vcpkg.path.txt 23 | 24 | $VCPKG_INSTALLATION_ROOT/vcpkg integrate install 25 | chmod 0777 -R $VCPKG_INSTALLATION_ROOT 26 | ln -sf $VCPKG_INSTALLATION_ROOT/vcpkg /usr/local/bin 27 | 28 | rm -rf /root/.vcpkg $HOME/.vcpkg 29 | 30 | invoke_tests "Tools" "Vcpkg" 31 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/install-yq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: install-yq.sh 4 | ## Desc: Install yq - a command-line YAML, JSON and XML processor 5 | ## Supply chain security: yq - checksum validation 6 | ################################################################################ 7 | 8 | # Source the helpers for use with the script 9 | source $HELPER_SCRIPTS/install.sh 10 | 11 | # Download yq 12 | yq_url=$(resolve_github_release_asset_url "mikefarah/yq" "endswith(\"yq_linux_amd64\")" "latest") 13 | binary_path=$(download_with_retry "${yq_url}") 14 | 15 | # Supply chain security - yq 16 | hash_url=$(resolve_github_release_asset_url "mikefarah/yq" "endswith(\"checksums\")" "latest") 17 | external_hash=$(get_checksum_from_url "${hash_url}" "yq_linux_amd64 " "SHA256" "true" " " "19") 18 | use_checksum_comparison "$binary_path" "$external_hash" 19 | 20 | # Install yq 21 | install "$binary_path" /usr/bin/yq 22 | 23 | invoke_tests "Tools" "yq" 24 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/build/post-build-validation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: post-build-validation.sh 4 | ## Desc: Validate different aspects of the image after build 5 | ################################################################################ 6 | 7 | echo "Test microsoft defender not installed using '-d /opt/microsoft/mdatp'" 8 | # Validate Defender not installed test 1 9 | if [ -d /opt/microsoft/mdatp ]; then 10 | echo "Microsoft Defender for Endpoint is installed." 11 | exit 1 12 | fi 13 | 14 | echo "Test microsoft defender not installed using 'systemctl list-units --type=service --all | grep mdatp'" 15 | # Validate Defender not installed test 2 16 | if systemctl list-units --type=service --all | grep -w mdatp &>/dev/null; then 17 | echo "Microsoft Defender for Endpoint is installed." 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/docs-gen/SoftwareReport.CachedTools.psm1: -------------------------------------------------------------------------------- 1 | function Get-ToolcacheRubyVersions { 2 | $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Ruby" 3 | return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ } 4 | } 5 | 6 | function Get-ToolcachePythonVersions { 7 | $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Python" 8 | return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ } 9 | } 10 | 11 | function Get-ToolcachePyPyVersions { 12 | $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "PyPy" 13 | Get-ChildItem -Path $toolcachePath -Name | Sort-Object { [Version] $_ } | ForEach-Object { 14 | $pypyRootPath = Join-Path $toolcachePath $_ "x64" 15 | [string] $pypyVersionOutput = & "$pypyRootPath/bin/python" -c "import sys;print(sys.version)" 16 | $pypyVersionOutput -match "^([\d\.]+) \(.+\) \[PyPy ([\d\.]+\S*) .+]quot; | Out-Null 17 | return "{0} [PyPy {1}]" -f $Matches[1], $Matches[2] 18 | } 19 | } 20 | 21 | function Get-ToolcacheNodeVersions { 22 | $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "node" 23 | return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ } 24 | } 25 | 26 | function Get-ToolcacheGoVersions { 27 | $toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "go" 28 | return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ } 29 | } 30 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/docs-gen/SoftwareReport.Helpers.psm1: -------------------------------------------------------------------------------- 1 | function Get-StringPart { 2 | param ( 3 | [Parameter(ValueFromPipeline)] 4 | [string] $ToolOutput, 5 | [string] $Delimiter = " ", 6 | [int[]] $Part 7 | ) 8 | 9 | $parts = $ToolOutput.Split($Delimiter, [System.StringSplitOptions]::RemoveEmptyEntries) 10 | $selectedParts = $parts[$Part] 11 | return [string]::Join($Delimiter, $selectedParts) 12 | } 13 | 14 | function Get-PathWithLink { 15 | param ( 16 | [string] $InputPath 17 | ) 18 | 19 | $link = Get-Item $InputPath | Select-Object -ExpandProperty Target 20 | if (-not [string]::IsNullOrEmpty($link)) { 21 | return "${InputPath} -> ${link}" 22 | } 23 | return "${InputPath}" 24 | } 25 | 26 | function Get-OSVersionShort { 27 | $(Get-OSVersionFull) | Get-StringPart -Delimiter '.' -Part 0,1 28 | } 29 | 30 | function Get-OSVersionFull { 31 | lsb_release -ds | Get-StringPart -Part 1, 2 32 | } 33 | 34 | function Get-KernelVersion { 35 | $kernelVersion = uname -r 36 | return $kernelVersion 37 | } 38 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/docs-gen/SoftwareReport.Java.psm1: -------------------------------------------------------------------------------- 1 | function Get-JavaVersionsTable { 2 | $javaToolcacheVersions = Get-ChildItem $env:AGENT_TOOLSDIRECTORY/Java*/* -Directory | Sort-Object { [int] $_.Name.Split(".")[0] } 3 | 4 | return $javaToolcacheVersions | ForEach-Object { 5 | $majorVersion = $_.Name.split(".")[0] 6 | $fullVersion = $_.Name.Replace("-", "+") 7 | $defaultJavaPath = $env:JAVA_HOME 8 | $javaPath = Get-Item env:JAVA_HOME_${majorVersion}_X64 9 | 10 | $defaultPostfix = ($javaPath.Value -eq $defaultJavaPath) ? " (default)" : "" 11 | 12 | [PSCustomObject] @{ 13 | "Version" = $fullVersion + $defaultPostfix 14 | "Environment Variable" = $javaPath.Name 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/docs-gen/SoftwareReport.WebServers.psm1: -------------------------------------------------------------------------------- 1 | function Get-ApacheVersion { 2 | $name = "apache2" 3 | $port = 80 4 | $version = bash -c "apache2 -v | grep -Po 'Apache/(\d+.){2}\d+'" | Get-StringPart -Part 1 -Delimiter "/" 5 | $serviceStatus = systemctl status apache2 | grep "Active:" | Get-StringPart -Part 1 6 | $configFile = "/etc/apache2/apache2.conf" 7 | return [PsCustomObject]@{ 8 | "Name" = $name 9 | "Version" = $version 10 | "ConfigFile" = $configFile 11 | "ServiceStatus" = $serviceStatus 12 | "ListenPort" = $port 13 | } 14 | } 15 | 16 | function Get-NginxVersion { 17 | $name = "nginx" 18 | $port = 80 19 | $version = (dpkg-query --showformat='${Version}' --show nginx).Split('-')[0] 20 | $serviceStatus = systemctl status nginx | grep "Active:" | Get-StringPart -Part 1 21 | $configFile = "/etc/nginx/nginx.conf" 22 | return [PsCustomObject]@{ 23 | "Name" = $name 24 | "Version" = $version 25 | "ConfigFile" = $configFile 26 | "ServiceStatus" = $serviceStatus 27 | "ListenPort" = $port 28 | } 29 | } 30 | 31 | function Build-WebServersTable { 32 | $servers = @() 33 | $servers += (Get-ApacheVersion) 34 | $servers += (Get-NginxVersion) 35 | 36 | return $servers 37 | } 38 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/helpers/invoke-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: invoke-tests.sh 4 | ## Desc: Helper function for invoking tests 5 | ################################################################################ 6 | 7 | pwsh -Command "Import-Module '$HELPER_SCRIPTS/../tests/Helpers.psm1' -DisableNameChecking 8 | Invoke-PesterTests -TestFile \"$1\" -TestName \"$2\"" 9 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/helpers/os.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ################################################################################ 3 | ## File: os.sh 4 | ## Desc: Helper functions for OS releases 5 | ################################################################################ 6 | 7 | is_ubuntu22() { 8 | lsb_release -rs | grep -q '22.04' 9 | } 10 | 11 | is_ubuntu24() { 12 | lsb_release -rs | grep -q '24.04' 13 | } 14 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/ActionArchiveCache.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "ActionArchiveCache" { 2 | BeforeDiscovery { 3 | $actionArchiveCachePath = "/opt/actionarchivecache" 4 | $tarballTestCases = Get-ChildItem -Path "$actionArchiveCachePath/*.tar.gz" -Recurse | ForEach-Object { @{ ActionTarball = $_.FullName } } 5 | } 6 | 7 | Context "Action archive cache directory not empty" { 8 | It "<ActionArchiveCachepath> not empty" -TestCases @{ ActionArchiveCachepath = $actionArchiveCachePath } { 9 | (Get-ChildItem -Path "$ActionArchiveCachepath/*.tar.gz" -Recurse).Count | Should -BeGreaterThan 0 10 | } 11 | } 12 | 13 | Context "Action tarball not empty" { 14 | It "<ActionTarball>" -TestCases $tarballTestCases { 15 | (Get-Item "$ActionTarball").Length | Should -BeGreaterThan 0 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/Apt.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" 2 | 3 | Describe "Apt" { 4 | $packages = (Get-ToolsetContent).apt.cmd_packages + (Get-ToolsetContent).apt.vital_packages 5 | $testCases = $packages | ForEach-Object { @{ toolName = $_ } } 6 | 7 | It "<toolName> is available" -TestCases $testCases { 8 | switch ($toolName) { 9 | "acl" { $toolName = "getfacl"; break } 10 | "aria2" { $toolName = "aria2c"; break } 11 | "p7zip-full" { $toolName = "p7zip"; break } 12 | "subversion" { $toolName = "svn"; break } 13 | "sphinxsearch" { $toolName = "searchd"; break } 14 | "binutils" { $toolName = "strings"; break } 15 | "coreutils" { $toolName = "tr"; break } 16 | "net-tools" { $toolName = "netstat"; break } 17 | "mercurial" { $toolName = "hg"; break } 18 | "findutils" { $toolName = "find"; break } 19 | "systemd-coredump" { $toolName = "coredumpctl"; break } 20 | } 21 | 22 | (Get-Command -Name $toolName).CommandType | Should -BeExactly "Application" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/Browsers.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Firefox" { 2 | It "Firefox" { 3 | "firefox --version" | Should -ReturnZeroExitCode 4 | } 5 | 6 | It "Geckodriver" { 7 | "geckodriver --version" | Should -ReturnZeroExitCode 8 | } 9 | } 10 | 11 | Describe "Chrome" { 12 | It "Chrome" { 13 | "google-chrome --version" | Should -ReturnZeroExitCode 14 | } 15 | 16 | It "Chrome Driver" { 17 | "chromedriver --version" | Should -ReturnZeroExitCode 18 | } 19 | 20 | It "Chrome and Chrome Driver major versions are the same" { 21 | $chromeMajor = (google-chrome --version).Trim("Google Chrome ").Split(".")[0] 22 | $chromeDriverMajor = (chromedriver --version).Trim("ChromeDriver ").Split(".")[0] 23 | $chromeMajor | Should -BeExactly $chromeDriverMajor 24 | } 25 | } 26 | 27 | Describe "Edge" { 28 | It "Edge" { 29 | "microsoft-edge --version" | Should -ReturnZeroExitCode 30 | } 31 | 32 | It "Edge Driver" { 33 | "msedgedriver --version" | Should -ReturnZeroExitCode 34 | } 35 | } 36 | 37 | Describe "Chromium" { 38 | It "Chromium" { 39 | "chromium-browser --version" | Should -ReturnZeroExitCode 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/Common.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "PHP" { 2 | $testCases = (Get-ToolsetContent).php.versions | ForEach-Object { @{PhpVersion = $_} } 3 | 4 | It "php <phpVersion>" -TestCases $testCases { 5 | "php${PhpVersion} --version" | Should -ReturnZeroExitCode 6 | "php-config${PhpVersion} --version" | Should -ReturnZeroExitCode 7 | "phpize${PhpVersion} --version" | Should -ReturnZeroExitCode 8 | } 9 | 10 | It "PHPUnit" { 11 | "phpunit --version" | Should -ReturnZeroExitCode 12 | } 13 | 14 | It "Composer" { 15 | "composer --version" | Should -ReturnZeroExitCode 16 | } 17 | 18 | It "Pear" { 19 | "pear" | Should -ReturnZeroExitCode 20 | } 21 | 22 | It "Pecl" { 23 | "pecl" | Should -ReturnZeroExitCode 24 | } 25 | } 26 | 27 | Describe "Swift" { 28 | It "swift" { 29 | "swift --version" | Should -ReturnZeroExitCode 30 | } 31 | 32 | It "swiftc" { 33 | "swiftc --version" | Should -ReturnZeroExitCode 34 | } 35 | 36 | It "libsourcekitd" { 37 | "/usr/local/lib/libsourcekitdInProc.so" | Should -Exist 38 | } 39 | } 40 | 41 | Describe "PipxPackages" { 42 | $testCases = (Get-ToolsetContent).pipx | ForEach-Object { @{package=$_.package; cmd = $_.cmd} } 43 | 44 | It "<package>" -TestCases $testCases { 45 | "$cmd --version" | Should -ReturnZeroExitCode 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/Databases.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "PostgreSQL" { 2 | It "PostgreSQL Service" { 3 | "sudo systemctl start postgresql" | Should -ReturnZeroExitCode 4 | "pg_isready" | Should -OutputTextMatchingRegex "/var/run/postgresql:5432 - accepting connections" 5 | "sudo systemctl stop postgresql" | Should -ReturnZeroExitCode 6 | } 7 | 8 | It "PostgreSQL version should correspond to the version in the toolset" { 9 | $toolsetVersion = (Get-ToolsetContent).postgresql.version 10 | # Client version 11 | (psql --version).split()[-1] | Should -BeLike "$toolsetVersion*" 12 | # Server version 13 | (pg_config --version).split()[-1] | Should -BeLike "$toolsetVersion*" 14 | } 15 | } 16 | 17 | Describe "MySQL" { 18 | It "MySQL CLI" { 19 | "mysql -V" | Should -ReturnZeroExitCode 20 | } 21 | 22 | It "MySQL Service" { 23 | "sudo systemctl start mysql" | Should -ReturnZeroExitCode 24 | mysql -s -N -h localhost -uroot -proot -e "select count(*) from mysql.user where user='root' and authentication_string is null;" | Should -BeExactly 0 25 | "sudo mysql -vvv -e 'CREATE DATABASE smoke_test' -uroot -proot" | Should -ReturnZeroExitCode 26 | "sudo mysql -vvv -e 'DROP DATABASE smoke_test' -uroot -proot" | Should -ReturnZeroExitCode 27 | "sudo systemctl stop mysql" | Should -ReturnZeroExitCode 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/Haskell.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Haskell" { 2 | $GHCCommonPath = "/usr/local/.ghcup/ghc" 3 | $GHCVersions = Get-ChildItem -Path $GHCCommonPath | Where-Object { $_.Name -match "\d+\.\d+" } 4 | 5 | $testCase = @{ GHCVersions = $GHCVersions } 6 | 7 | It "GHC directory contains two version of GHC" -TestCases $testCase { 8 | $GHCVersions.Count | Should -Be 2 9 | } 10 | 11 | $testCases = $GHCVersions | ForEach-Object { @{ GHCPath = "${_}/bin/ghc"} } 12 | 13 | It "GHC version <GHCPath>" -TestCases $testCases { 14 | "$GHCPath --version" | Should -ReturnZeroExitCode 15 | } 16 | 17 | It "GHCup" { 18 | "ghcup --version" | Should -ReturnZeroExitCode 19 | } 20 | 21 | It "Default GHC" { 22 | "ghc --version" | Should -ReturnZeroExitCode 23 | } 24 | 25 | It "Cabal" { 26 | "cabal --version" | Should -ReturnZeroExitCode 27 | } 28 | 29 | It "Stack" { 30 | "stack --version" | Should -ReturnZeroExitCode 31 | } 32 | 33 | It "Stack hook is not installed" { 34 | "$HOME/.stack/hooks/ghc-install.sh" | Should -Not -Exist 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/Node.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Node.js" { 2 | $binaries = @("node") 3 | $module_commands = (Get-ToolsetContent).node_modules | ForEach-Object { $_.command } 4 | $testCases = $binaries + $module_commands | ForEach-Object { @{NodeCommand = $_} } 5 | 6 | It "<NodeCommand>" -TestCases $testCases { 7 | "$NodeCommand --version" | Should -ReturnZeroExitCode 8 | } 9 | 10 | It "Node.js version should correspond to the version in the toolset" { 11 | node --version | Should -BeLike "v$((Get-ToolsetContent).node.default).*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/RunAll-Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$PSScriptRoot/Helpers.psm1" -DisableNameChecking 2 | 3 | Invoke-PesterTests "*" 4 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/RunnerCache.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "RunnerCache" { 2 | Context "runner cache directory not empty" { 3 | It "<RunnerCachePath> not empty" -TestCases @{ RunnerCachePath = "/opt/runner-cache" } { 4 | (Get-ChildItem -Path "$RunnerCachePath/*.tar.gz" -Recurse).Count | Should -BeGreaterThan 0 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/System.Tests.ps1: -------------------------------------------------------------------------------- 1 | # The $env:AGENT_NAME and $env:RUNNER_NAME are predefined variables for the ADO pipelines and for the GitHub actions respectively. 2 | # If the test is running on the ADO pipeline or on the GitHub actions, the test will be skipped 3 | Describe "Disk free space" -Skip:(-not [String]::IsNullOrEmpty($env:AGENT_NAME) -or -not [String]::IsNullOrEmpty($env:RUNNER_NAME)) { 4 | It "Image has enough free space" { 5 | $freeSpace = (Get-PSDrive "/").Free 6 | $freeSpace | Should -BeGreaterOrEqual 17GB 7 | } 8 | } 9 | 10 | Describe "fwupd removed" { 11 | It "Is not present on box" { 12 | $systemctlOutput = & systemctl list-unit fwupd-refresh.timer --no-legend 13 | # When disabled the output looks like this: 14 | #❯ systemctl list-units fwupd-refresh.timer --no-legend 15 | #● fwupd-refresh.timer masked failed failed fwupd-refresh.timer 16 | # When enabled the output looks like this: 17 | #❯ systemctl list-units fwupd-refresh.timer --no-legend 18 | #fwupd-refresh.timer loaded active waiting Refresh fwupd metadata regularly 19 | $systemctlOutput | Should -Not -Match "active" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /images/ubuntu/scripts/tests/WebServers.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Apache" { 2 | It "Apache CLI" { 3 | "apache2 -v" | Should -ReturnZeroExitCode 4 | } 5 | 6 | It "Apache Service" { 7 | "sudo systemctl start apache2" | Should -ReturnZeroExitCode 8 | "apachectl configtest" | Should -ReturnZeroExitCode 9 | "sudo systemctl stop apache2" | Should -ReturnZeroExitCode 10 | } 11 | } 12 | 13 | Describe "Nginx" { 14 | It "Nginx CLI" { 15 | "nginx -v" | Should -ReturnZeroExitCode 16 | } 17 | 18 | It "Nginx Service" { 19 | "sudo systemctl start nginx" | Should -ReturnZeroExitCode 20 | "sudo nginx -t" | Should -ReturnZeroExitCode 21 | "sudo systemctl stop nginx" | Should -ReturnZeroExitCode 22 | } 23 | } -------------------------------------------------------------------------------- /images/ubuntu/templates/locals.ubuntu.pkr.hcl: -------------------------------------------------------------------------------- 1 | locals { 2 | image_properties_map = { 3 | "ubuntu22" = { 4 | publisher = "canonical" 5 | offer = "0001-com-ubuntu-server-jammy" 6 | sku = "22_04-lts" 7 | os_disk_size_gb = coalesce(var.os_disk_size_gb, 75) 8 | }, 9 | "ubuntu24" = { 10 | publisher = "canonical" 11 | offer = "ubuntu-24_04-lts" 12 | sku = "server-gen1" 13 | os_disk_size_gb = coalesce(var.os_disk_size_gb, 75) 14 | } 15 | } 16 | 17 | image_properties = local.image_properties_map[var.image_os] 18 | } 19 | -------------------------------------------------------------------------------- /images/windows/assets/post-gen/InternetExplorerConfiguration.ps1: -------------------------------------------------------------------------------- 1 | # https://docs.microsoft.com/en-us/troubleshoot/browsers/enhanced-security-configuration-faq#how-to-disable-internet-explorer-esc-by-using-a-script 2 | # turn off the Internet Explorer Enhanced Security feature 3 | Rundll32 iesetup.dll, IEHardenLMSettings, 1, True 4 | Rundll32 iesetup.dll, IEHardenUser, 1, True 5 | Rundll32 iesetup.dll, IEHardenAdmin, 1, True 6 | $AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}" 7 | $UserKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}" 8 | Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0 -Force 9 | Set-ItemProperty -Path $UserKey -Name "IsInstalled" -Value 0 -Force 10 | # restart Explorer process 11 | $ieProcess = Get-Process -Name Explorer -ErrorAction Ignore 12 | if ($ieProcess) { 13 | Stop-Process -Name Explorer -Force -ErrorAction Ignore 14 | } 15 | Write-Host "IE Enhanced Security Configuration (ESC) has been disabled." 16 | -------------------------------------------------------------------------------- /images/windows/assets/post-gen/Msys2FirstLaunch.ps1: -------------------------------------------------------------------------------- 1 | # create user profile at the first launch 2 | $null = cmd /c "C:\msys64\usr\bin\bash.exe -leo pipefail -c 'echo $SHELL' 2>&1" -------------------------------------------------------------------------------- /images/windows/assets/post-gen/VSConfiguration.ps1: -------------------------------------------------------------------------------- 1 | $vsInstallRoot = (Get-VisualStudioInstance).InstallationPath 2 | $devEnvPath = "$vsInstallRoot\Common7\IDE\devenv.exe" 3 | 4 | # Initialize Visual Studio Experimental Instance 5 | # The Out-Null cmdlet is required to ensure PowerShell waits until the '/ResetSettings' command fully completes. 6 | & "$devEnvPath" /RootSuffix Exp /ResetSettings General.vssettings /Command File.Exit | Out-Null 7 | 8 | cmd.exe /c "`"$devEnvPath`" /updateconfiguration" 9 | 10 | # 11 | # https://github.com/actions/runner-images/issues/5301 12 | # 13 | $warmup_vdproj = $(Join-Path $PSScriptRoot 'warmup.vdproj') 14 | & "$devEnvPath" $warmup_vdproj /build Release | Out-Null 15 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Configure-DeveloperMode.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Configure-DeveloperMode.ps1 3 | ## Desc: Enables Developer Mode by toggling registry setting. Developer Mode is required to enable certain tools (e.g. WinAppDriver). 4 | ################################################################################ 5 | 6 | # Create AppModelUnlock if it doesn't exist, required for enabling Developer Mode 7 | $registryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" 8 | if (-not(Test-Path -Path $registryKeyPath)) { 9 | New-Item -Path $registryKeyPath -ItemType Directory -Force 10 | } 11 | 12 | # Add registry value to enable Developer Mode 13 | New-ItemProperty -Path $registryKeyPath -Name AllowDevelopmentWithoutDevLicense -PropertyType DWORD -Value 1 14 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Configure-DotnetSecureChannel.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Configure-DotnetSecureChannel.ps1 3 | ## Desc: Configure .NET to use TLS 1.2 4 | ################################################################################ 5 | 6 | $registryPath = "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" 7 | $name = "SchUseStrongCrypto" 8 | $value = "1" 9 | if (Test-Path $registryPath) { 10 | Set-ItemProperty -Path $registryPath -Name $name -Value $value -Type DWORD 11 | } 12 | 13 | $registryPath = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" 14 | if (Test-Path $registryPath) { 15 | Set-ItemProperty -Path $registryPath -Name $name -Value $value -Type DWORD 16 | } 17 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Configure-GDIProcessHandleQuota.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Configure-GDIProcessHandleQuota.ps1 3 | ## Desc: Set the GDIProcessHandleQuota value to 20000 4 | ################################################################################ 5 | 6 | # https://docs.microsoft.com/en-us/windows/win32/sysinfo/gdi-objects 7 | # This value can be set to a number between 256 and 65,536 8 | 9 | $defaultValue = 20000 10 | Write-Host "Set the GDIProcessHandleQuota value to $defaultValue" 11 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name GDIProcessHandleQuota -Value $defaultValue 12 | Set-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows" -Name GDIProcessHandleQuota -Value $defaultValue 13 | 14 | Invoke-PesterTests -TestFile "WindowsFeatures" -TestName "GDIProcessHandleQuota" 15 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Configure-Shell.ps1: -------------------------------------------------------------------------------- 1 | # Create shells folder 2 | $shellPath = "C:\shells" 3 | New-Item -Path $shellPath -ItemType Directory | Out-Null 4 | 5 | # add a wrapper for C:\msys64\usr\bin\bash.exe 6 | @' 7 | @echo off 8 | setlocal 9 | IF NOT DEFINED MSYS2_PATH_TYPE set MSYS2_PATH_TYPE=strict 10 | IF NOT DEFINED MSYSTEM set MSYSTEM=mingw64 11 | set CHERE_INVOKING=1 12 | C:\msys64\usr\bin\bash.exe -leo pipefail %* 13 | '@ | Out-File -FilePath "$shellPath\msys2bash.cmd" -Encoding ascii 14 | 15 | # gitbash <--> C:\Program Files\Git\bin\bash.exe 16 | New-Item -ItemType SymbolicLink -Path "$shellPath\gitbash.exe" -Target "$env:ProgramFiles\Git\bin\bash.exe" | Out-Null 17 | 18 | # wslbash <--> C:\Windows\System32\bash.exe 19 | New-Item -ItemType SymbolicLink -Path "$shellPath\wslbash.exe" -Target "$env:SystemRoot\System32\bash.exe" | Out-Null 20 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Configure-SystemEnvironment.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Configure-SystemEnvironment.ps1 3 | ## Desc: Configures system environment variables 4 | ################################################################################ 5 | 6 | $variables = @{ 7 | "ImageVersion" = $env:IMAGE_VERSION 8 | "ImageOS" = $env:IMAGE_OS 9 | "AGENT_TOOLSDIRECTORY" = $env:AGENT_TOOLSDIRECTORY 10 | "RUNNER_TOOL_CACHE" = $env:AGENT_TOOLSDIRECTORY 11 | } 12 | 13 | $variables.GetEnumerator() | ForEach-Object { 14 | [Environment]::SetEnvironmentVariable($_.Key, $_.Value, "Machine") 15 | } 16 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-ActionsCache.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-ActionsCache.ps1 3 | ## Desc: Downloads latest release from https://github.com/actions/action-versions 4 | ## Maintainer: #actions-runtime and @TingluoHuang 5 | ################################################################################ 6 | 7 | $actionArchiveCache = "C:\actionarchivecache\" 8 | 9 | if (-not (Test-Path $actionArchiveCache)) { 10 | Write-Host "Creating action archive cache folder" 11 | New-Item -ItemType Directory -Path $actionArchiveCache | Out-Null 12 | } 13 | 14 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 15 | -Repo "actions/action-versions" ` 16 | -Version "latest" ` 17 | -Asset "action-versions.zip" 18 | 19 | Write-Host "Download Latest action-versions archive from $downloadUrl" 20 | $actionVersionsArchivePath = Invoke-DownloadWithRetry $downloadUrl 21 | 22 | Write-Host "Expand action-versions archive" 23 | Expand-7ZipArchive -Path $actionVersionsArchivePath -DestinationPath $actionArchiveCache 24 | 25 | [Environment]::SetEnvironmentVariable("ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE", $actionArchiveCache, "Machine") 26 | 27 | Invoke-PesterTests -TestFile "ActionArchiveCache" 28 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-AliyunCli.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-AliyunCli.ps1 3 | ## Desc: Install Alibaba Cloud CLI 4 | ## Supply chain security: Alibaba Cloud CLI - checksum validation 5 | ################################################################################ 6 | 7 | Write-Host "Download Latest aliyun-cli archive" 8 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 9 | -Repo "aliyun/aliyun-cli" ` 10 | -Version "latest" ` 11 | -UrlMatchPattern "aliyun-cli-windows-*-amd64.zip" 12 | $packagePath = Invoke-DownloadWithRetry $downloadUrl 13 | 14 | #region Supply chain security - Alibaba Cloud CLI 15 | $packageName = Split-Path $downloadUrl -Leaf 16 | $externalHash = Get-ChecksumFromUrl -Type "SHA256" ` 17 | -Url ($downloadUrl -replace $packageName, "SHASUMS256.txt") ` 18 | -FileName $packageName 19 | Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash 20 | #endregion 21 | 22 | Write-Host "Expand aliyun-cli archive" 23 | $aliyunPath = "C:\aliyun-cli" 24 | New-Item -Path $aliyunPath -ItemType Directory -Force 25 | Expand-7ZipArchive -Path $packagePath -DestinationPath $aliyunPath 26 | 27 | # Add aliyun-cli to path 28 | Add-MachinePathItem $aliyunPath 29 | 30 | Invoke-PesterTests -TestFile "CLI.Tools" -TestName "Aliyun CLI" 31 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Apache.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Apache.ps1 3 | ## Desc: Install Apache HTTP Server 4 | ################################################################################ 5 | 6 | # Stop w3svc service 7 | Stop-Service -Name w3svc 8 | 9 | # Install latest apache in chocolatey 10 | $installDir = "C:\tools" 11 | Install-ChocoPackage apache-httpd -ArgumentList "--force", "--params", "/installLocation:$installDir /port:80" 12 | 13 | # Stop and disable Apache service 14 | Stop-Service -Name Apache 15 | Set-Service -Name Apache -StartupType Disabled 16 | 17 | # Start w3svc service 18 | Start-Service -Name w3svc 19 | 20 | # Invoke Pester Tests 21 | Invoke-PesterTests -TestFile "Apache" 22 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-AzureCli.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-AzureCli.ps1 3 | ## Desc: Install and warm-up Azure CLI 4 | ################################################################################ 5 | 6 | Write-Host 'Install the latest Azure CLI release' 7 | 8 | $azureCliConfigPath = 'C:\azureCli' 9 | # Store azure-cli cache outside of the provisioning user's profile 10 | [Environment]::SetEnvironmentVariable('AZURE_CONFIG_DIR', $azureCliConfigPath, "Machine") 11 | 12 | $azureCliExtensionPath = Join-Path $env:CommonProgramFiles 'AzureCliExtensionDirectory' 13 | New-Item -ItemType 'Directory' -Path $azureCliExtensionPath | Out-Null 14 | [Environment]::SetEnvironmentVariable('AZURE_EXTENSION_DIR', $azureCliExtensionPath, "Machine") 15 | 16 | Install-Binary -Type MSI ` 17 | -Url 'https://aka.ms/installazurecliwindowsx64' ` 18 | -ExpectedSubject $(Get-MicrosoftPublisher) 19 | 20 | Update-Environment 21 | 22 | # Warm-up Azure CLI 23 | Write-Host "Warmup 'az'" 24 | az --help | Out-Null 25 | if ($LASTEXITCODE -ne 0) { 26 | throw "Command 'az --help' failed" 27 | } 28 | 29 | Invoke-PesterTests -TestFile 'CLI.Tools' -TestName 'Azure CLI' 30 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-AzureCosmosDbEmulator.ps1: -------------------------------------------------------------------------------- 1 | #################################################################################### 2 | ## File: Install-AzureCosmosDbEmulator.ps1 3 | ## Desc: Install Azure CosmosDb Emulator 4 | #################################################################################### 5 | 6 | Install-Binary -Type MSI ` 7 | -Url "https://aka.ms/cosmosdb-emulator" 8 | 9 | Invoke-PesterTests -TestFile "Tools" -TestName "Azure Cosmos DB Emulator" 10 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Bazel.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Bazel.ps1 3 | ## Desc: Install Bazel and Bazelisk (A user-friendly launcher for Bazel) 4 | ################################################################################ 5 | 6 | Install-ChocoPackage bazel 7 | 8 | npm install -g @bazel/bazelisk 9 | if ($LASTEXITCODE -ne 0) { 10 | throw "Command 'npm install -g @bazel/bazelisk' failed" 11 | } 12 | 13 | Invoke-PesterTests -TestFile "Tools" -TestName "Bazel" 14 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-BizTalkBuildComponent.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-BizTalkBuildComponent.ps1 3 | ## Desc: Install BizTalk Project Build Component 4 | ################################################################################ 5 | 6 | $downloadUrl = "https://aka.ms/BuildComponentSetup.EN" 7 | 8 | Write-Host "Downloading BizTalk Project Build Component archive..." 9 | $zipFile = Invoke-DownloadWithRetry $downloadUrl 10 | 11 | $setupPath = Join-Path $env:TEMP_DIR "BizTalkBuildComponent" 12 | if (-not (Test-Path -Path $setupPath)) { 13 | New-Item -Path $setupPath -ItemType Directory -Force | Out-Null 14 | } 15 | Expand-7ZipArchive -Path $zipFile -DestinationPath $setupPath 16 | 17 | Write-Host "Installing BizTalk Project Build Component..." 18 | Install-Binary ` 19 | -LocalPath "$setupPath\Bootstrap.msi" ` 20 | -ExtraInstallArgs ("/l*v", "$setupPath\bootstrap.log") ` 21 | -ExpectedSubject $(Get-MicrosoftPublisher) 22 | Install-Binary ` 23 | -LocalPath "$setupPath\BuildComponentSetup.msi" ` 24 | -ExtraInstallArgs ("/l*v", "$setupPath\buildComponentSetup.log") ` 25 | -ExpectedSubject $(Get-MicrosoftPublisher) 26 | 27 | Invoke-PesterTests -TestFile "BizTalk" -TestName "BizTalk Build Component Setup" 28 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Chocolatey.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Chocolatey.ps1 3 | ## Desc: Install Chocolatey package manager 4 | ################################################################################ 5 | 6 | Write-Host "Set TLS1.2" 7 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12" 8 | 9 | Write-Host "Install chocolatey" 10 | 11 | # Add to system PATH 12 | Add-MachinePathItem 'C:\ProgramData\Chocolatey\bin' 13 | Update-Environment 14 | 15 | # Verify and run choco installer 16 | $installScriptPath = Invoke-DownloadWithRetry 'https://chocolatey.org/install.ps1' 17 | Test-FileSignature -Path $installScriptPath -ExpectedSubject 'CN="Chocolatey Software, Inc", O="Chocolatey Software, Inc", L=Topeka, S=Kansas, C=US' 18 | Invoke-Expression $installScriptPath 19 | 20 | # Turn off confirmation 21 | choco feature enable -n allowGlobalConfirmation 22 | 23 | # Initialize environmental variable ChocolateyToolsLocation by invoking choco Get-ToolsLocation function 24 | Import-Module "$env:ChocolateyInstall\helpers\chocolateyInstaller.psm1" -Force 25 | Get-ToolsLocation 26 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-ChocolateyPackages.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-ChocolateyPackages.ps1 3 | ## Desc: Install common Chocolatey packages 4 | ################################################################################ 5 | 6 | $commonPackages = (Get-ToolsetContent).choco.common_packages 7 | 8 | foreach ($package in $commonPackages) { 9 | Install-ChocoPackage $package.name -Version $package.version -ArgumentList $package.args 10 | } 11 | 12 | Invoke-PesterTests -TestFile "ChocoPackages" 13 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-CloudFoundryCli.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-CloudFoundryCli.ps1 3 | ## Desc: Install Cloud Foundry CLI 4 | ################################################################################ 5 | 6 | # Download the latest cf cli exe 7 | $cloudFoundryCliUrl = "https://packages.cloudfoundry.org/stable?release=windows64-exe&source=github" 8 | 9 | $cloudFoundryArchPath = Invoke-DownloadWithRetry $cloudFoundryCliUrl 10 | 11 | # Create directory for cf cli 12 | $cloudFoundryCliPath = "C:\cf-cli" 13 | New-Item -Path $cloudFoundryCliPath -ItemType Directory -Force 14 | 15 | # Extract the zip archive 16 | Write-Host "Extracting cf cli..." 17 | Expand-7ZipArchive -Path $cloudFoundryArchPath -DestinationPath $cloudFoundryCliPath 18 | 19 | # Add cf to path 20 | Add-MachinePathItem $cloudFoundryCliPath 21 | 22 | # Validate cf signature 23 | Test-FileSignature -Path "$cloudFoundryCliPath\cf.exe" -ExpectedSubject 'CN="LF Projects, LLC", O="LF Projects, LLC", L=Wilmington, S=Delaware, C=US' 24 | 25 | Invoke-PesterTests -TestFile "CLI.Tools" -TestName "CloudFoundry CLI" 26 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-DACFx.ps1: -------------------------------------------------------------------------------- 1 | #################################################################################### 2 | ## File: Install-DACFx.ps1 3 | ## Desc: Install SQL Server® Data-Tier Application Framework (DacFx) for Windows 4 | #################################################################################### 5 | 6 | Install-Binary -Type MSI ` 7 | -Url 'https://aka.ms/dacfx-msi' ` 8 | -ExpectedSubject $(Get-MicrosoftPublisher) 9 | 10 | Invoke-PesterTests -TestFile "Tools" -TestName "DACFx" 11 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-DockerCompose.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Docker-Compose.ps1 3 | ## Desc: Install Docker Compose. 4 | ################################################################################ 5 | Write-Host "Install-Package Docker-Compose v2" 6 | $toolsetVersion = (Get-ToolsetContent).docker.components.compose 7 | $composeVersion = (Get-GithubReleasesByVersion -Repo "docker/compose" -Version "${toolsetVersion}").version 8 | $dockerComposev2Url = "https://github.com/docker/compose/releases/download/v${composeVersion}/docker-compose-windows-x86_64.exe" 9 | $cliPluginsDir = "C:\ProgramData\docker\cli-plugins" 10 | New-Item -Path $cliPluginsDir -ItemType Directory 11 | Invoke-DownloadWithRetry -Url $dockerComposev2Url -Path "$cliPluginsDir\docker-compose.exe" 12 | 13 | Invoke-PesterTests -TestFile "Docker" -TestName "DockerCompose" 14 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-DockerWinCred.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Docker-WinCred.ps1 3 | ## Desc: Install Docker credential helper. 4 | ## Supply chain security: checksum validation 5 | ################################################################################ 6 | 7 | Write-Host "Install docker-wincred" 8 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 9 | -Repo "docker/docker-credential-helpers" ` 10 | -Version "latest" ` 11 | -UrlMatchPattern "docker-credential-wincred-*amd64.exe" 12 | $binaryPath = Invoke-DownloadWithRetry -Url $downloadUrl -Path "C:\Windows\System32\docker-credential-wincred.exe" 13 | 14 | #region Supply chain security 15 | $binaryName = Split-Path $downloadUrl -Leaf 16 | $externalHash = Get-ChecksumFromUrl -Type "SHA256" ` 17 | -Url ($downloadUrl -replace $binaryName, "checksums.txt") ` 18 | -FileName $binaryName 19 | Test-FileChecksum -Path $binaryPath -ExpectedSHA256Sum $externalHash 20 | #endregion 21 | 22 | Invoke-PesterTests -TestFile "Docker" -TestName "DockerWinCred" 23 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-GitHub-CLI.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-GitHub-CLI.ps1 3 | ## Desc: Install GitHub CLI 4 | ## Supply chain security: GitHub CLI - checksum validation 5 | ################################################################################ 6 | 7 | Write-Host "Get the latest gh version..." 8 | 9 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 10 | -Repo "cli/cli" ` 11 | -Version "latest" ` 12 | -UrlMatchPattern "gh_*_windows_amd64.msi" 13 | 14 | $checksumsUrl = Resolve-GithubReleaseAssetUrl ` 15 | -Repo "cli/cli" ` 16 | -Version "latest" ` 17 | -UrlMatchPattern "gh_*_checksums.txt" 18 | $externalHash = Get-ChecksumFromUrl -Type "SHA256" ` 19 | -Url $checksumsUrl ` 20 | -FileName (Split-Path $downloadUrl -Leaf) 21 | 22 | Install-Binary ` 23 | -Url $downloadUrl ` 24 | -ExpectedSHA256Sum $externalHash 25 | 26 | Add-MachinePathItem "C:\Program Files (x86)\GitHub CLI" 27 | 28 | Invoke-PesterTests -TestFile "CLI.Tools" -TestName "GitHub CLI" 29 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-GoogleCloudCLI.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-GoogleCloudCLI.ps1 3 | ## Desc: Install Google Cloud CLI 4 | ################################################################################ 5 | 6 | # https://cloud.google.com/sdk/docs/downloads-interactive 7 | Install-Binary ` 8 | -Url 'https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe' ` 9 | -InstallArgs @("/S", "/allusers", "/noreporting") ` 10 | -ExpectedSubject 'CN=Google LLC, O=Google LLC, L=Mountain View, S=California, C=US, SERIALNUMBER=3582691, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, OID.1.3.6.1.4.1.311.60.2.1.3=US' 11 | 12 | Invoke-PesterTests -TestFile "Tools" -TestName "GoogleCloudCLI" 13 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-IEWebDriver.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-IEWebDriver.ps1 3 | ## Desc: Install IE Web Driver 4 | ################################################################################ 5 | 6 | $seleniumMajorVersion = (Get-ToolsetContent).selenium.version 7 | $ieDriverUrl = Resolve-GithubReleaseAssetUrl ` 8 | -Repo "SeleniumHQ/selenium" ` 9 | -Version "$seleniumMajorVersion.*" ` 10 | -Asset "IEDriverServer_x64_*.zip" 11 | 12 | # Download IE selenium driver 13 | Write-Host "Selenium IEDriverServer download and install..." 14 | $driverZipFile = Invoke-DownloadWithRetry $ieDriverUrl 15 | 16 | $ieDriverPath = "C:\SeleniumWebDrivers\IEDriver" 17 | if (-not (Test-Path -Path $ieDriverPath)) { 18 | New-Item -Path $ieDriverPath -ItemType Directory -Force | Out-Null 19 | } 20 | 21 | Expand-7ZipArchive -Path $driverZipFile -DestinationPath $ieDriverPath 22 | Remove-Item $driverZipFile 23 | 24 | Write-Host "Get the IEDriver version..." 25 | (Get-Item "$ieDriverPath\IEDriverServer.exe").VersionInfo.FileVersion | Out-File -FilePath "$ieDriverPath\versioninfo.txt" 26 | 27 | Write-Host "Setting the IEWebDriver environment variables" 28 | [Environment]::SetEnvironmentVariable("IEWebDriver", $ieDriverPath, "Machine") 29 | 30 | Invoke-PesterTests -TestFile "Browsers" -TestName "Internet Explorer" 31 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Kotlin.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Kotlin.ps1 3 | ## Desc: Install Kotlin 4 | ## Supply chain security: Kotlin - checksum validation 5 | ################################################################################ 6 | 7 | # Install Kotlin 8 | $kotlinVersion = (Get-ToolsetContent).kotlin.version 9 | 10 | $kotlinDownloadUrl = Resolve-GithubReleaseAssetUrl ` 11 | -Repo "JetBrains/kotlin" ` 12 | -Version "$kotlinVersion" ` 13 | -Asset "kotlin-compiler-*.zip" 14 | $kotlinArchivePath = Invoke-DownloadWithRetry $kotlinDownloadUrl 15 | 16 | #region Supply chain security 17 | $externalHash = Get-Content $(Invoke-DownloadWithRetry "$kotlinDownloadUrl.sha256") 18 | Test-FileChecksum $kotlinArchivePath -ExpectedSHA256Sum $externalHash 19 | #endregion 20 | 21 | Write-Host "Expand Kotlin archive" 22 | $kotlinPath = "C:\tools" 23 | Expand-7ZipArchive -Path $kotlinArchivePath -DestinationPath $kotlinPath 24 | 25 | # Add to PATH 26 | Add-MachinePathItem "$kotlinPath\kotlinc\bin" 27 | 28 | Invoke-PesterTests -TestFile "Tools" -TestName "Kotlin" 29 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-LLVM.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-LLVM.ps1 3 | ## Desc: Install the latest stable version of llvm and clang compilers 4 | ################################################################################ 5 | 6 | $llvmVersion = (Get-ToolsetContent).llvm.version 7 | $latestChocoVersion = Resolve-ChocoPackageVersion -PackageName "llvm" -TargetVersion $llvmVersion 8 | Install-ChocoPackage llvm -ArgumentList '--version', $latestChocoVersion 9 | 10 | Invoke-PesterTests -TestFile "LLVM" 11 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Mercurial.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Mercurial.ps1 3 | ## Desc: Install Mercurial 4 | ################################################################################ 5 | 6 | Install-ChocoPackage hg -ArgumentList "--version", "5.0.0" 7 | 8 | Add-MachinePathItem "${env:ProgramFiles}\Mercurial\" 9 | Update-Environment 10 | 11 | Invoke-PesterTests -TestFile "Tools" -TestName "Mercurial" 12 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Miniconda.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Miniconda.ps1 3 | ## Desc: Install the latest version of Miniconda and set $env:CONDA 4 | ## Supply chain security: checksum validation 5 | ################################################################################ 6 | 7 | $condaDestination = "C:\Miniconda" 8 | $installerName = "Miniconda3-latest-Windows-x86_64.exe" 9 | 10 | #region Supply chain security 11 | $distributorFileHash = $null 12 | $checksums = (ConvertFrom-HTML -Uri 'https://repo.anaconda.com/miniconda/').SelectNodes('//html/body/table/tr') 13 | 14 | foreach ($node in $checksums) { 15 | if ($node.ChildNodes[1].InnerText -eq $installerName) { 16 | $distributorFileHash = $node.ChildNodes[7].InnerText 17 | } 18 | } 19 | 20 | if ($null -eq $distributorFileHash) { 21 | throw "Unable to find checksum for $installerName in https://repo.anaconda.com/miniconda/" 22 | } 23 | #endregion 24 | 25 | Install-Binary ` 26 | -Url "https://repo.anaconda.com/miniconda/${installerName}" ` 27 | -InstallArgs @("/S", "/AddToPath=0", "/RegisterPython=0", "/D=$condaDestination") ` 28 | -ExpectedSHA256Sum $distributorFileHash 29 | 30 | [Environment]::SetEnvironmentVariable("CONDA", $condaDestination, "Machine") 31 | 32 | Invoke-PesterTests -TestFile "Miniconda" 33 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-NET48-devpack.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-NET48-devpack.ps1 3 | ## Desc: Install .NET 4.8 devpack 4 | ## Supply chain security: checksum validation 5 | ################################################################################ 6 | 7 | # .NET 4.8 Dev pack 8 | Install-Binary ` 9 | -Url 'https://download.visualstudio.microsoft.com/download/pr/014120d7-d689-4305-befd-3cb711108212/0307177e14752e359fde5423ab583e43/ndp48-devpack-enu.exe' ` 10 | -InstallArgs @("Setup", "/passive", "/norestart") ` 11 | -ExpectedSHA256Sum '0A7AC4A9B44CED6BB7A0EBF3AD9BA29F60BD4D3BEB2047E19F4D8749DE61F5AC' 12 | 13 | Invoke-PesterTests -TestFile "Tools" -TestName "NET48" 14 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-NET48.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-NET48.ps1 3 | ## Desc: Install .NET 4.8 4 | ## Supply chain security: checksum validation 5 | ################################################################################ 6 | 7 | # .NET 4.8 Dev pack 8 | Install-Binary ` 9 | -Url 'https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe' ` 10 | -InstallArgs @("Setup", "/passive", "/norestart") ` 11 | -ExpectedSHA256Sum '68C9986A8DCC0214D909AA1F31BEE9FB5461BB839EDCA996A75B08DDFFC1483F' 12 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-NSIS.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-NSIS.ps1 3 | ## Desc: Install NSIS 4 | ## Supply chain security: NSIS - managed by package manager 5 | ################################################################################ 6 | 7 | $nsisVersion = (Get-ToolsetContent).nsis.version 8 | 9 | Install-ChocoPackage nsis -ArgumentList "--version", "$nsisVersion" 10 | 11 | Add-MachinePathItem "${env:ProgramFiles(x86)}\NSIS\" 12 | Update-Environment 13 | 14 | Invoke-PesterTests -TestFile "Tools" -TestName "NSIS" 15 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-NativeImages.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-NativeImages.ps1 3 | ## Desc: Generate and install native images for .NET assemblies 4 | ################################################################################ 5 | 6 | Write-Host "NGen: install Microsoft.PowerShell.Utility.Activities..." 7 | & $env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install "Microsoft.PowerShell.Utility.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" | Out-Null 8 | if ($LASTEXITCODE -ne 0) { 9 | throw "Installation of Microsoft.PowerShell.Utility.Activities failed with exit code $LASTEXITCODE" 10 | } 11 | 12 | Write-Host "NGen: update x64 native images..." 13 | & $env:SystemRoot\Microsoft.NET\Framework64\v4.0.30319\ngen.exe update | Out-Null 14 | if ($LASTEXITCODE -ne 0) { 15 | throw "Update of x64 native images failed with exit code $LASTEXITCODE" 16 | } 17 | 18 | Write-Host "NGen: update x86 native images..." 19 | & $env:SystemRoot\Microsoft.NET\Framework\v4.0.30319\ngen.exe update | Out-Null 20 | if ($LASTEXITCODE -ne 0) { 21 | throw "Update of x86 native images failed with exit code $LASTEXITCODE" 22 | } 23 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Nginx.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Nginx.ps1 3 | ## Desc: Install Nginx 4 | ################################################################################ 5 | 6 | # Stop w3svc service 7 | Stop-Service -Name w3svc 8 | 9 | # Install latest nginx in chocolatey 10 | $installDir = "C:\tools" 11 | Install-ChocoPackage nginx -ArgumentList "--force", "--params", "/installLocation:$installDir /port:80" 12 | 13 | # Stop and disable Nginx service 14 | Stop-Service -Name nginx 15 | Set-Service -Name nginx -StartupType Disabled 16 | 17 | # Start w3svc service 18 | Start-Service -Name w3svc 19 | 20 | # Invoke Pester Tests 21 | Invoke-PesterTests -TestFile "Nginx" 22 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-PHP.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-PHP.ps1 3 | ## Desc: Install PHP 4 | ################################################################################ 5 | 6 | # Install latest PHP in chocolatey 7 | $installDir = "c:\tools\php" 8 | $phpMajorMinor = (Get-ToolsetContent).php.version 9 | $phpVersionToInstall = Resolve-ChocoPackageVersion -PackageName "php" -TargetVersion $phpMajorMinor 10 | Install-ChocoPackage php -ArgumentList "--params", "/InstallDir:$installDir", "--version=$phpVersionToInstall" 11 | 12 | # Install latest Composer in chocolatey 13 | Install-ChocoPackage composer -ArgumentList "--install-args", "/DEV=$installDir /PHP=$installDir" 14 | 15 | # update path to extensions and enable curl and mbstring extensions, and enable php openssl extensions. 16 | ((Get-Content -path $installDir\php.ini -Raw) -replace ';extension=curl','extension=curl' -replace ';extension=mbstring','extension=mbstring' -replace ';extension_dir = "ext"','extension_dir = "ext"' -replace ';extension=openssl','extension=openssl') | Set-Content -Path $installDir\php.ini 17 | 18 | # Set the PHPROOT environment variable. 19 | [Environment]::SetEnvironmentVariable("PHPROOT", $installDir, "Machine") 20 | 21 | # Invoke Pester Tests 22 | Invoke-PesterTests -TestFile "PHP" 23 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-PowerShellModules.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-PowershellModules.ps1 3 | ## Desc: Install common PowerShell modules 4 | ################################################################################ 5 | 6 | # Set TLS1.2 7 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor "Tls12" 8 | 9 | # Install PowerShell modules 10 | $modules = (Get-ToolsetContent).powershellModules 11 | 12 | foreach ($module in $modules) { 13 | $moduleName = $module.name 14 | Write-Host "Installing ${moduleName} module" 15 | 16 | if ($module.versions) { 17 | foreach ($version in $module.versions) { 18 | Write-Host " - $version" 19 | Install-Module -Name $moduleName -RequiredVersion $version -Scope AllUsers -SkipPublisherCheck -Force 20 | } 21 | } else { 22 | Install-Module -Name $moduleName -Scope AllUsers -SkipPublisherCheck -Force 23 | } 24 | } 25 | 26 | Import-Module Pester 27 | Invoke-PesterTests -TestFile "PowerShellModules" -TestName "PowerShellModules" 28 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-R.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-R.ps1 3 | ## Desc: Install R for Windows 4 | ################################################################################ 5 | 6 | Install-ChocoPackage R.Project 7 | Install-ChocoPackage rtools 8 | 9 | $rscriptPath = Resolve-Path "C:\Program Files\R\*\bin\x64" 10 | Add-MachinePathItem $rscriptPath 11 | Invoke-PesterTests -TestFile "Tools" -TestName "R" 12 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Runner.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Runner.ps1 3 | ## Desc: Install Runner for GitHub Actions 4 | ## Supply chain security: none 5 | ################################################################################ 6 | 7 | Write-Host "Download latest Runner for GitHub Actions" 8 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 9 | -Repo "actions/runner" ` 10 | -Version "latest" ` 11 | -UrlMatchPattern "actions-runner-win-x64-*[0-9.].zip" 12 | $fileName = Split-Path $downloadUrl -Leaf 13 | New-Item -Path "C:\ProgramData\runner" -ItemType Directory 14 | Invoke-DownloadWithRetry -Url $downloadUrl -Path "C:\ProgramData\runner\$fileName" 15 | 16 | Invoke-PesterTests -TestFile "RunnerCache" 17 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-SQLOLEDBDriver.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-SQLOLEDBDriver.ps1 3 | ## Desc: Install OLE DB Driver for SQL Server 4 | ################################################################################ 5 | 6 | Install-Binary -Type MSI ` 7 | -Url "https://go.microsoft.com/fwlink/?linkid=2242656" ` 8 | -ExtraInstallArgs @("ADDLOCAL=ALL", "IACCEPTMSOLEDBSQLLICENSETERMS=YES") ` 9 | -ExpectedSubject $(Get-MicrosoftPublisher) 10 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-SQLPowerShellTools.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-SQLPowerShellTools.ps1 3 | ## Desc: Install SQL PowerShell tool 4 | ################################################################################ 5 | 6 | $baseUrl = "https://download.microsoft.com/download/B/1/7/B1783FE9-717B-4F78-A39A-A2E27E3D679D/ENU/x64" 7 | 8 | # install required MSIs 9 | Install-Binary ` 10 | -Url "${baseUrl}/SQLSysClrTypes.msi" ` 11 | -ExpectedSubject $(Get-MicrosoftPublisher) 12 | 13 | Install-Binary ` 14 | -Url "${baseUrl}/SharedManagementObjects.msi" ` 15 | -ExpectedSubject $(Get-MicrosoftPublisher) 16 | 17 | Install-Binary ` 18 | -Url "${baseUrl}/PowerShellTools.msi" ` 19 | -ExpectedSubject $(Get-MicrosoftPublisher) 20 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Sbt.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Sbt.ps1 3 | ## Desc: Install sbt for Windows 4 | ################################################################################ 5 | 6 | # Install the latest version of sbt. 7 | # See https://chocolatey.org/packages/sbt 8 | Install-ChocoPackage sbt 9 | 10 | $env:SBT_HOME="${env:ProgramFiles(x86)}\sbt" 11 | 12 | # Add sbt binaries to the path 13 | Add-MachinePathItem "$env:SBT_HOME\bin" 14 | 15 | Invoke-PesterTests -TestFile "Tools" -TestName "Sbt" 16 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Selenium.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Selenium.ps1 3 | ## Desc: Install Selenium Server standalone 4 | ################################################################################ 5 | 6 | # Create Selenium directory 7 | $seleniumDirectory = "C:\selenium\" 8 | New-Item -ItemType directory -Path $seleniumDirectory 9 | 10 | # Download Selenium 11 | $seleniumMajorVersion = (Get-ToolsetContent).selenium.version 12 | 13 | $seleniumDownloadUrl = Resolve-GithubReleaseAssetUrl ` 14 | -Repo "SeleniumHQ/selenium" ` 15 | -Version "$seleniumMajorVersion.*" ` 16 | -Asset "selenium-server-*.jar" ` 17 | -AllowMultipleMatches 18 | 19 | $seleniumBinPath = Join-Path $seleniumDirectory "selenium-server.jar" 20 | Invoke-DownloadWithRetry -Url $seleniumDownloadUrl -Path $seleniumBinPath 21 | 22 | # Create an empty file to retrieve Selenium version 23 | $seleniumFullVersion = $seleniumDownloadUrl.Split("-")[1].Split("/")[0] 24 | New-Item -Path $seleniumDirectory -Name "selenium-server-$seleniumFullVersion" 25 | 26 | # Add SELENIUM_JAR_PATH environment variable 27 | [Environment]::SetEnvironmentVariable("SELENIUM_JAR_PATH", $seleniumBinPath, "Machine") 28 | 29 | Invoke-PesterTests -TestFile "Browsers" -TestName "Selenium" 30 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-ServiceFabricSDK.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-ServiceFabricSDK.ps1 3 | ## Desc: Install webpicmd and then the service fabric sdk 4 | ## must be install after Visual Studio 5 | ## Supply chain security: checksum validation 6 | ################################################################################ 7 | 8 | # Creating 'Installer' cache folder if it doesn't exist 9 | New-Item -Path 'C:\Windows\Installer' -ItemType Directory -Force 10 | 11 | # Get Service Fabric components versions 12 | $runtimeVersion = (Get-ToolsetContent).serviceFabric.runtime.version 13 | $sdkVersion = (Get-ToolsetContent).serviceFabric.sdk.version 14 | 15 | $urlBase = "https://download.microsoft.com/download/b/8/a/b8a2fb98-0ec1-41e5-be98-9d8b5abf7856" 16 | 17 | # Install Service Fabric Runtime for Windows 18 | Install-Binary ` 19 | -Url "${urlBase}/MicrosoftServiceFabric.${runtimeVersion}.exe" ` 20 | -InstallArgs @("/accepteula ", "/quiet", "/force") ` 21 | -ExpectedSHA256Sum (Get-ToolsetContent).serviceFabric.runtime.checksum 22 | 23 | 24 | # Install Service Fabric SDK 25 | Install-Binary ` 26 | -Url "${urlBase}/MicrosoftServiceFabricSDK.${sdkVersion}.msi" ` 27 | -ExpectedSHA256Sum (Get-ToolsetContent).serviceFabric.sdk.checksum 28 | 29 | Invoke-PesterTests -TestFile "Tools" -TestName "ServiceFabricSDK" 30 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-TortoiseSvn.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-TortoiseSvn.ps1 3 | ## Desc: Install TortoiseSvn 4 | ################################################################################ 5 | 6 | Install-ChocoPackage tortoisesvn 7 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-VCRedist.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-VCRedist.ps1 3 | ## Desc: Install Visual C++ Redistributable 4 | ## Supply chain security: checksum validation 5 | ################################################################################ 6 | 7 | $baseUrl = "https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC" 8 | $argumentList = ("/install", "/quiet", "/norestart") 9 | 10 | Install-Binary ` 11 | -Url "${baseUrl}/vcredist_x86.exe" ` 12 | -InstallArgs $argumentList ` 13 | -ExpectedSHA256Sum '99DCE3C841CC6028560830F7866C9CE2928C98CF3256892EF8E6CF755147B0D8' 14 | 15 | Install-Binary ` 16 | -Url "${baseUrl}/vcredist_x64.exe" ` 17 | -InstallArgs $argumentList ` 18 | -ExpectedSHA256Sum 'F3B7A76D84D23F91957AA18456A14B4E90609E4CE8194C5653384ED38DADA6F3' 19 | 20 | Invoke-PesterTests -TestFile "Tools" -TestName "VCRedist" 21 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-VSExtensions.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################### 2 | ## File: Install-VSExtensions.ps1 3 | ## Desc: Install the Visual Studio Extensions from toolset.json 4 | ################################################################################### 5 | 6 | $toolset = Get-ToolsetContent 7 | $vsixPackagesList = $toolset.visualStudio.vsix 8 | if (-not $vsixPackagesList) { 9 | Write-Host "No extensions to install" 10 | exit 0 11 | } 12 | 13 | $vsixPackagesList | ForEach-Object { 14 | # Retrieve cdn endpoint to avoid HTTP error 429 15 | # https://github.com/actions/runner-images/issues/3074 16 | $vsixPackage = Get-VsixInfoFromMarketplace $_ 17 | Write-Host "Installing $vsixPackage" 18 | if ($vsixPackage.FileName.EndsWith(".vsix")) { 19 | Install-VSIXFromUrl $vsixPackage.DownloadUri 20 | } else { 21 | Install-Binary ` 22 | -Url $vsixPackage.DownloadUri ` 23 | -InstallArgs @('/install', '/quiet', '/norestart') 24 | } 25 | } 26 | 27 | Invoke-PesterTests -TestFile "Vsix" 28 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Vcpkg.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Vcpkg.ps1 3 | ## Desc: Install vcpkg 4 | ################################################################################ 5 | 6 | $Uri = 'https://github.com/Microsoft/vcpkg.git' 7 | $InstallDir = 'C:\vcpkg' 8 | $VcpkgExecPath = 'vcpkg.exe' 9 | 10 | git clone $Uri $InstallDir -q 11 | 12 | # Build and integrate vcpkg 13 | Invoke-Expression "$InstallDir\bootstrap-vcpkg.bat" 14 | if ($LASTEXITCODE -ne 0) { 15 | throw "vcpkg bootstrap failed with exit code $LASTEXITCODE" 16 | } 17 | Invoke-Expression "$InstallDir\$VcpkgExecPath integrate install" 18 | if ($LASTEXITCODE -ne 0) { 19 | throw "vcpkg integration failed with exit code $LASTEXITCODE" 20 | } 21 | 22 | # Add vcpkg to system environment 23 | Add-MachinePathItem $InstallDir 24 | [Environment]::SetEnvironmentVariable("VCPKG_INSTALLATION_ROOT", $InstallDir, "Machine") 25 | Update-Environment 26 | 27 | Invoke-PesterTests -TestFile "Tools" -TestName "Vcpkg" 28 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-WSL2.ps1: -------------------------------------------------------------------------------- 1 | Write-Host "Install WSL2" 2 | 3 | $version = (Get-GithubReleasesByVersion -Repo "microsoft/WSL" -Version "latest").version 4 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 5 | -Repo "microsoft/WSL" ` 6 | -Version $version ` 7 | -UrlMatchPattern "wsl.*.x64.msi" 8 | 9 | Install-Binary -Type MSI ` 10 | -Url $downloadUrl 11 | 12 | Write-Host "Performing wsl --install --no-distribution" 13 | wsl.exe --install --no-distribution 14 | 15 | Invoke-PesterTests -TestFile "WindowsFeatures" -TestName "WSL2" 16 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-WebPlatformInstaller.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-WebPI.ps1 3 | ## Desc: Install WebPlatformInstaller 4 | ################################################################################ 5 | 6 | Install-Binary -Type MSI ` 7 | -Url 'https://go.microsoft.com/fwlink/?LinkId=287166' ` 8 | -ExpectedSubject $(Get-MicrosoftPublisher) 9 | 10 | Invoke-PesterTests -TestFile "Tools" -TestName "WebPlatformInstaller" 11 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-WinAppDriver.ps1: -------------------------------------------------------------------------------- 1 | #################################################################################### 2 | ## File: Install-WinAppDriver.ps1 3 | ## Desc: Install Windows Application Driver (WinAppDriver) 4 | #################################################################################### 5 | 6 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 7 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 8 | -Repo "microsoft/WinAppDriver" ` 9 | -Version "latest" ` 10 | -UrlMatchPattern "WindowsApplicationDriver_*.msi" 11 | 12 | Install-Binary ` 13 | -Url $downloadUrl ` 14 | -ExpectedSubject $(Get-MicrosoftPublisher) 15 | 16 | Invoke-PesterTests -TestFile "WinAppDriver" -TestName "WinAppDriver" 17 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-WindowsUpdatesAfterReboot.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-WindowsUpdatesAfterReboot.ps1 3 | ## Desc: Waits for Windows Updates to finish installing after reboot 4 | ################################################################################ 5 | 6 | Invoke-ScriptBlockWithRetry -RetryCount 10 -RetryIntervalSeconds 120 -Command { 7 | $inProgress = Get-WindowsUpdateStates | Where-Object State -eq "Running" | Where-Object Title -notmatch "Microsoft Defender Antivirus" 8 | if ( $inProgress ) { 9 | $title = $inProgress.Title -join "`n" 10 | throw "Windows updates are still installing: $title" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Wix.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Wix.ps1 3 | ## Desc: Install WIX. 4 | ################################################################################ 5 | 6 | Install-ChocoPackage wixtoolset -ArgumentList "--force" 7 | 8 | Update-Environment 9 | $currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") 10 | $newPath = $currentPath + ";$(Join-Path -Path $env:WIX -ChildPath "bin")" 11 | [Environment]::SetEnvironmentVariable("PATH", $newPath, "Machine") 12 | Update-Environment 13 | 14 | Invoke-PesterTests -TestFile "Wix" 15 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Install-Zstd.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: Install-Zstd.ps1 3 | ## Desc: Install zstd 4 | ################################################################################ 5 | 6 | $downloadUrl = Resolve-GithubReleaseAssetUrl ` 7 | -Repo "facebook/zstd" ` 8 | -Version "latest" ` 9 | -UrlMatchPattern "zstd-*-win64.zip" 10 | $zstdArchivePath = Invoke-DownloadWithRetry $downloadUrl 11 | $zstdName = [IO.Path]::GetFileNameWithoutExtension($zstdArchivePath) 12 | 13 | $toolPath = "C:\tools" 14 | $zstdPath = Join-Path $toolPath zstd 15 | $filesInArchive = 7z l $zstdArchivePath | Out-String 16 | 17 | if ($filesInArchive.Contains($zstdName)) { 18 | Expand-7ZipArchive -Path $zstdArchivePath -DestinationPath $toolPath 19 | Invoke-ScriptBlockWithRetry -Command { 20 | Move-Item -Path "${zstdPath}*" -Destination $zstdPath -ErrorAction Stop 21 | } 22 | } else { 23 | Expand-7ZipArchive -Path $zstdArchivePath -DestinationPath $zstdPath 24 | } 25 | 26 | # Add zstd-win64 to PATH 27 | Add-MachinePathItem $zstdPath 28 | 29 | Invoke-PesterTests -TestFile "Tools" -TestName "Zstd" 30 | -------------------------------------------------------------------------------- /images/windows/scripts/build/Post-Build-Validation.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: post-build-validation.sh 3 | ## Desc: Validate different aspects of the image after build 4 | ################################################################################ 5 | 6 | Write-Host "Test Microsoft Defender not set up using 'sc query sense'" 7 | $response = sc query sense 8 | foreach ($item in $response) { 9 | if ($item -match "STATE") { 10 | $state = $item.Split(":")[1].Trim() 11 | if ($state -notmatch "RUNNING") { 12 | Write-Host "MDE is not running" 13 | } else { 14 | Write-Host "MDE is running" 15 | exit 1 16 | } 17 | } 18 | } 19 | 20 | Write-Host "Test Microsoft Defender not set up by checking for the MDE extension" 21 | if (Test-Path -Path "C:\Packages\Plugins\Microsoft.Azure.AzureDefenderForServers.MDE.Windows") { 22 | Write-Error "MDE extension detected, MDE is more likely installed on the system" 23 | exit 1 24 | } else { 25 | Write-Host "MDE is not setup on the system" 26 | } 27 | -------------------------------------------------------------------------------- /images/windows/scripts/docs-gen/SoftwareReport.Helpers.psm1: -------------------------------------------------------------------------------- 1 | function Get-LinkTarget { 2 | param ( 3 | [string] $inputPath 4 | ) 5 | $link = Get-Item $inputPath | Select-Object -ExpandProperty Target 6 | if ($link) { 7 | return " -> $link" 8 | } 9 | return "" 10 | } 11 | 12 | function Get-PathWithLink { 13 | param ( 14 | [string] $inputPath 15 | ) 16 | $link = Get-LinkTarget($inputPath) 17 | return "${inputPath}${link}" 18 | } 19 | 20 | function Get-StringPart { 21 | param ( 22 | [Parameter(ValueFromPipeline)] 23 | [string] $toolOutput, 24 | [string] $Delimiter = " ", 25 | [int[]] $Part 26 | ) 27 | $parts = $toolOutput.Split($Delimiter, [System.StringSplitOptions]::RemoveEmptyEntries) 28 | $selectedParts = $parts[$Part] 29 | return [string]::Join($Delimiter, $selectedParts) 30 | } 31 | -------------------------------------------------------------------------------- /images/windows/scripts/docs-gen/SoftwareReport.Java.psm1: -------------------------------------------------------------------------------- 1 | function Get-JavaVersions { 2 | $defaultJavaPath = $env:JAVA_HOME 3 | $javaVersions = Get-Item env:JAVA_HOME_*_X64 4 | $sortRules = @{ 5 | Expression = { [Int32] $_.Name.Split("_")[2] } 6 | Descending = $false 7 | } 8 | 9 | return $javaVersions | Sort-Object $sortRules | ForEach-Object { 10 | $javaPath = $_.Value 11 | # Take semver from the java path 12 | # The path contains '-' sign in the version number instead of '+' due to the following issue, need to substitute it back https://github.com/actions/runner-images/issues/3014 13 | $versionInPath = (Split-Path $javaPath) -replace "\w:\\.*\\" 14 | $version = $versionInPath -replace '-', '+' 15 | $defaultPostfix = ($javaPath -eq $defaultJavaPath) ? " (default)" : "" 16 | 17 | [PSCustomObject] @{ 18 | "Version" = $version + $defaultPostfix 19 | "Environment Variable" = $_.Name 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /images/windows/scripts/helpers/test/ImageHelpers.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModuleManifestName = 'ImageHelpers.psd1' 2 | $ModuleManifestPath = "$PSScriptRoot\..\$ModuleManifestName" 3 | 4 | 5 | 6 | Describe 'Module Manifest Tests' { 7 | It 'Passes Test-ModuleManifest' { 8 | Test-ModuleManifest -Path $ModuleManifestPath | Should Not BeNullOrEmpty 9 | $? | Should Be $true 10 | } 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/ActionArchiveCache.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "ActionArchiveCache" { 2 | Context "Action archive cache directory not empty" { 3 | It "C:\actionarchivecache not empty" { 4 | (Get-ChildItem -Path "C:\actionarchivecache\*.zip" -Recurse).Count | Should -BeGreaterThan 0 5 | } 6 | } 7 | 8 | Context "Action zipball not empty" { 9 | $testCases = Get-ChildItem -Path "C:\actionarchivecache\*.zip" -Recurse | ForEach-Object { @{ ActionZipball = $_.FullName } } 10 | It "<ActionZipball>" -TestCases $testCases { 11 | param ([string] $ActionZipball) 12 | (Get-Item "$ActionZipball").Length | Should -BeGreaterThan 0 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Apache.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Apache" { 2 | Context "Path" { 3 | It "Apache" { 4 | $apachePath = Join-Path (Join-Path "C:\tools\" (Get-Item C:\tools\apache*).Name) "\bin\httpd" 5 | "$apachePath -V" | Should -ReturnZeroExitCode 6 | } 7 | } 8 | 9 | Context "Service" { 10 | $apacheService = Get-Service -Name Apache 11 | $apacheServiceTests = @{ 12 | Name = $apacheService.Name 13 | Status = $apacheService.Status 14 | StartType = $apacheService.StartType 15 | } 16 | 17 | It "<Name> service is stopped" -TestCases $apacheServiceTests { 18 | $Status | Should -Be "Stopped" 19 | } 20 | 21 | It "<Name> service is disabled" -TestCases $apacheServiceTests { 22 | $StartType | Should -Be "Disabled" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/BizTalk.Tests.ps1: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## File: BizTalk.Tests.ps1 3 | ## Desc: Test BizTalk project build component installed. 4 | ################################################################################ 5 | 6 | Describe "BizTalk Build Component Setup" -Skip:(-not (Test-IsWin19)) { 7 | It "BizTalk Registry Check" { 8 | Test-Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\BizTalk Server\3.0" | Should -BeTrue 9 | } 10 | 11 | It "BizTalk Folder Check" { 12 | "${env:ProgramFiles(x86)}\Microsoft BizTalk Server" | Should -Exist 13 | } 14 | 15 | It "BizTalk Build Targets files Check" { 16 | "${env:ProgramFiles(x86)}\MSBuild\Microsoft\BizTalk\BizTalkC.targets" | Should -Exist 17 | "${env:ProgramFiles(x86)}\MSBuild\Microsoft\BizTalk\BizTalkCommon.targets" | Should -Exist 18 | } 19 | } -------------------------------------------------------------------------------- /images/windows/scripts/tests/CLI.Tools.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | Describe "Azure CLI" { 3 | It "Azure CLI" { 4 | "az --version" | Should -ReturnZeroExitCode 5 | } 6 | } 7 | 8 | Describe "Azure DevOps CLI" { 9 | It "az devops" { 10 | "az devops -h" | Should -ReturnZeroExitCode 11 | } 12 | } 13 | 14 | Describe "Aliyun CLI" -Skip:(Test-IsWin25) { 15 | It "Aliyun CLI" { 16 | "aliyun version" | Should -ReturnZeroExitCode 17 | } 18 | } 19 | 20 | 21 | Describe "AWS" { 22 | It "AWS CLI" { 23 | "aws --version" | Should -ReturnZeroExitCode 24 | } 25 | 26 | It "Session Manager Plugin for the AWS CLI" { 27 | @(session-manager-plugin) -Match '\S' | Out-String | Should -Match "plugin was installed successfully" 28 | } 29 | 30 | It "AWS SAM CLI" { 31 | "sam --version" | Should -ReturnZeroExitCode 32 | } 33 | } 34 | 35 | 36 | Describe "GitHub CLI" { 37 | It "gh" { 38 | "gh --version" | Should -ReturnZeroExitCode 39 | } 40 | } 41 | 42 | Describe "CloudFoundry CLI" -Skip:(-not (Test-IsWin19)) { 43 | It "cf is located in C:\cf-cli" { 44 | "C:\cf-cli\cf.exe" | Should -Exist 45 | } 46 | 47 | It "cf" { 48 | "cf --version" | Should -ReturnZeroExitCode 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Docker.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Docker" { 2 | It "docker is installed" { 3 | "docker --version" | Should -ReturnZeroExitCode 4 | } 5 | 6 | It "docker service is up" { 7 | "docker images" | Should -ReturnZeroExitCode 8 | } 9 | 10 | It "docker symlink" { 11 | "C:\Windows\SysWOW64\docker.exe ps" | Should -ReturnZeroExitCode 12 | } 13 | } 14 | 15 | Describe "DockerCompose" { 16 | It "docker compose v2" { 17 | "docker compose version" | Should -ReturnZeroExitCode 18 | } 19 | 20 | } 21 | 22 | Describe "DockerWinCred" { 23 | It "docker-wincred" { 24 | "docker-credential-wincred version" | Should -ReturnZeroExitCode 25 | } 26 | } 27 | 28 | Describe "DockerImages" -Skip:(Test-IsWin25) { 29 | Context "docker images" { 30 | $testCases = (Get-ToolsetContent).docker.images | ForEach-Object { @{ ImageName = $_ } } 31 | 32 | It "<ImageName>" -TestCases $testCases { 33 | docker images "$ImageName" --format "{{.Repository}}" | Should -Not -BeNullOrEmpty 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/DotnetSDK.Tests.ps1: -------------------------------------------------------------------------------- 1 | $dotnetVersions = (Get-ToolsetContent).dotnet.versions 2 | $dotnetTools = (Get-ToolsetContent).dotnet.tools 3 | 4 | Describe "Dotnet SDK and tools" { 5 | 6 | Context "Default" { 7 | It "Default Dotnet SDK is available" { 8 | "dotnet --version" | Should -ReturnZeroExitCode 9 | } 10 | } 11 | 12 | foreach ($version in $dotnetVersions) { 13 | Context "Dotnet $version" { 14 | $dotnet = @{ dotnetVersion = $version } 15 | 16 | It "SDK $version is available" -TestCases $dotnet { 17 | (dotnet --list-sdks | Where-Object { $_ -match "${dotnetVersion}\.[0-9]*" }).Count | Should -BeGreaterThan 0 18 | } 19 | 20 | It "Runtime $version is available" -TestCases $dotnet { 21 | (dotnet --list-runtimes | Where-Object { $_ -match "${dotnetVersion}\.[0-9]*" }).Count | Should -BeGreaterThan 0 22 | } 23 | } 24 | } 25 | 26 | Context "Dotnet tools" { 27 | $env:Path += ";C:\Users\Default\.dotnet\tools" 28 | $testCases = $dotnetTools | ForEach-Object { @{ ToolName = $_.name; TestInstance = $_.test }} 29 | 30 | It "<ToolName> is available" -TestCases $testCases { 31 | "$TestInstance" | Should -ReturnZeroExitCode 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Git.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Git" { 2 | $gitTools = 'bash', 'awk', 'git', 'git-lfs' 3 | $gitTestCases = $gitTools | ForEach-Object { 4 | @{ 5 | toolName = $_ 6 | source = [regex]::Escape("$env:ProgramFiles\Git") 7 | } 8 | } 9 | 10 | It "<toolName> is installed" -TestCases $gitTestCases { 11 | "$toolName --version" | Should -ReturnZeroExitCode 12 | } 13 | 14 | It "<toolName> is located in '<source>'" -TestCases $gitTestCases { 15 | (Get-Command -Name $toolName).Source | Should -Match $source 16 | } 17 | 18 | It "Git core.symlinks=true option is enabled" { 19 | git config core.symlinks | Should -BeExactly true 20 | } 21 | 22 | It "GCM_INTERACTIVE environment variable should be equal Never" { 23 | $env:GCM_INTERACTIVE | Should -BeExactly Never 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/LLVM.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Clang/LLVM" { 2 | BeforeAll { 3 | $toolsetVersion = (Get-ToolsetContent).llvm.version 4 | } 5 | 6 | It "Clang/LLVM <toolsetVersion> installed and version is correct" { 7 | $clangVersion = clang --version 8 | $clangVersion[0] | Should -BeLike "*${toolsetVersion}*" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Miniconda.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Miniconda" { 2 | It "Miniconda Environment variables is set. " { 3 | ${env:CONDA} | Should -Not -BeNullOrEmpty 4 | } 5 | 6 | It "Miniconda $env:CONDA\<PathTest> " -TestCases @( 7 | @{ PathTest = "python.exe" } 8 | @{ PathTest = "Scripts\conda.exe" } 9 | ) { 10 | $condaPath = Join-Path ${env:CONDA} $PathTest 11 | $condaPath | Should -Exist 12 | "$condaPath --version" | Should -ReturnZeroExitCode 13 | } 14 | } -------------------------------------------------------------------------------- /images/windows/scripts/tests/Nginx.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Nginx" { 2 | Context "Path" { 3 | It "Nginx" { 4 | $nginxPath = Join-Path (Join-Path "C:\tools\" (Get-Item C:\tools\nginx*).Name) "nginx" 5 | "$nginxPath -v" | Should -ReturnZeroExitCode 6 | } 7 | } 8 | 9 | Context "Service" { 10 | $nginxService = Get-Service -Name nginx 11 | $nginxServiceTests = @{ 12 | Name = $nginxService.Name 13 | Status = $nginxService.Status 14 | StartType = $nginxService.StartType 15 | } 16 | 17 | It "<Name> service is stopped" -TestCases $nginxServiceTests { 18 | $Status | Should -Be "Stopped" 19 | } 20 | 21 | It "<Name> service is disabled" -TestCases $nginxServiceTests { 22 | $StartType | Should -Be "Disabled" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Node.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Node.JS" { 2 | Context "Basic modules"{ 3 | It "<ToolName> " -TestCases @( 4 | @{ ToolName = "node" } 5 | @{ ToolName = "npm" } 6 | ) { 7 | "$ToolName --version" | Should -ReturnZeroExitCode 8 | } 9 | } 10 | 11 | $globalNpmPackages = (Get-ToolsetContent).npm.global_packages 12 | $globalNpmPackagesWithTests = $globalNpmPackages | Where-Object { $_.test } | ForEach-Object { @{ Name = $_.name; Test = $_.test } } 13 | 14 | Context "Global NPM Packages" { 15 | It "<Name>" -TestCases $globalNpmPackagesWithTests { 16 | $Test | Should -ReturnZeroExitCode 17 | } 18 | } 19 | 20 | Context "Node.js version" { 21 | It "Node.js version should correspond to the version in the toolset" { 22 | node --version | Should -BeLike "v$((Get-ToolsetContent).node.default)*" 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /images/windows/scripts/tests/PHP.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "PHP" { 2 | It "Check PHP version" { 3 | $phpMajorMinor = (Get-ToolsetContent).php.version 4 | $phpInstalledVersion = php --version | Select-String -Pattern "PHP $phpMajorMinor" 5 | $phpInstalledVersion | Should -BeLike "*${phpMajorMinor}*" 6 | } 7 | 8 | It "Check Composer in the PATH" { 9 | "composer --version" | Should -ReturnZeroExitCode 10 | } 11 | 12 | It "PHP Environment variables is set." { 13 | ${env:PHPROOT} | Should -Not -BeNullOrEmpty 14 | ${env:PHPROOT} | Should -Exist 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/PipxPackages.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "PipxPackages" { 2 | $pipxToolset = (Get-ToolsetContent).pipx 3 | $testCases = $pipxToolset | ForEach-Object { @{package = $_.package; cmd = $_.cmd} } 4 | It "<package>" -TestCases $testCases { 5 | "$cmd" | Should -ReturnZeroExitCode 6 | } 7 | } -------------------------------------------------------------------------------- /images/windows/scripts/tests/PowerShellModules.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "PowerShellModules" { 2 | $modules = (Get-ToolsetContent).powershellModules 3 | $withoutVersionsModules = $modules | Where-Object {-not $_.versions} | ForEach-Object { 4 | @{moduleName = $_.name} 5 | } 6 | 7 | $withVersionsModules = $modules | Where-Object {$_.versions} | ForEach-Object { 8 | $moduleName = $_.name 9 | $_.versions | ForEach-Object { 10 | @{moduleName = $moduleName; expectedVersion = $_} 11 | } 12 | } 13 | 14 | It "<moduleName> is installed" -TestCases $withoutVersionsModules { 15 | Get-Module -Name $moduleName -ListAvailable | Should -BeTrue 16 | } 17 | 18 | if ($withVersionsModules) { 19 | It "<moduleName> with <expectedVersion> is installed" -TestCases $withVersionsModules { 20 | (Get-Module -Name $moduleName -ListAvailable).Version -contains $expectedVersion | Should -BeTrue 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/RunAll-Tests.ps1: -------------------------------------------------------------------------------- 1 | Invoke-PesterTests "*" -------------------------------------------------------------------------------- /images/windows/scripts/tests/RunnerCache.tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "RunnerCache" { 2 | Context "runner cache directory not empty" { 3 | It "C:\ProgramData\runner" { 4 | (Get-ChildItem -Path "C:\ProgramData\runner\*.zip" -Recurse).Count | Should -BeGreaterThan 0 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/SSDTExtensions.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "SSDTExtensions" { 2 | #These extensions don't have any proper name in the state.packages.json file, only id is available, which can be found on extension marketplace download page 3 | 4 | if (Test-isWin19) { 5 | $testExtenions = @( 6 | @{id = "04a86fc2-dbd5-4222-848e-911638e487fe"} 7 | @{id = "851E7A09-7B2B-4F06-A15D-BABFCB26B970"} 8 | @{id = "717ad572-c4b7-435c-c166-c2969777f718"} 9 | ) 10 | 11 | It "Extensions id=<id>" -TestCases $testExtenions { 12 | $version = Get-VSExtensionVersion -packageName "${id}" 13 | $version | Should -Not -BeNullOrEmpty 14 | } 15 | } else { 16 | It "Extension SSDT" { 17 | $version = Get-VSExtensionVersion -packageName "SSDT" 18 | $version | Should -Not -BeNullOrEmpty 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Shell.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Shell" { 2 | $shellTestCases = @( 3 | @{Name = "C:\shells\gitbash.exe"; Target = "$env:ProgramFiles\Git\bin\bash.exe"}, 4 | @{Name = "C:\shells\msys2bash.cmd"; Target = $null} 5 | @{Name = "C:\shells\wslbash.exe"; Target = "$env:SystemRoot\System32\bash.exe"} 6 | ) 7 | 8 | It "<Name> target to <Target>" -TestCases $shellTestCases { 9 | (Get-Item $Name).Target | Should -BeExactly $Target 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Vsix.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Vsix" { 2 | $toolset = Get-ToolsetContent 3 | $requiredVsixPackages = $toolset.visualStudio.vsix 4 | 5 | $allPackages = (Get-VisualStudioInstance).Packages 6 | $testCases = $requiredVsixPackages | ForEach-Object { 7 | $vsixPackage = Get-VsixInfoFromMarketplace $_ 8 | @{ 9 | VsixName = $vsixPackage.ExtensionName 10 | VsixId = $vsixPackage.VsixId 11 | AllPackages = $allPackages 12 | } 13 | } 14 | if ($testCases.Count -gt 0) { 15 | It "Extension <VsixName> is installed" -TestCases $testCases { 16 | $objVsix = $AllPackages | Where-Object { $_.id -eq $VsixId } 17 | $objVsix | Should -Not -BeNullOrEmpty 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/WDK.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "WDK" -Skip:(Test-IsWin25) { 2 | It "WDK exists" { 3 | $regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" 4 | $installedApplications = Get-ItemProperty -Path $regKey 5 | $WDKVersion = $installedApplications | Where-Object DisplayName -eq 'Windows Driver Kit' | Select-Object -First 1 -ExpandProperty DisplayVersion 6 | $WDKVersion | Should -Not -BeNullOrEmpty 7 | } 8 | 9 | It "Windows Driver Kit VSIX extension" { 10 | $version = Get-VSExtensionVersion -packageName "Microsoft.Windows.DriverKit" 11 | $version | Should -Not -BeNullOrEmpty 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/WinAppDriver.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "WinAppDriver" { 2 | It "WinAppDriver directory exists" { 3 | Test-Path -Path "${env:ProgramFiles(x86)}\Windows Application Driver" | Should -BeTrue 4 | } 5 | } 6 | 7 | Describe "Developer Mode" { 8 | It "Developer Mode is enabled" { 9 | $path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"; 10 | Get-ItemProperty -Path $path | Select-Object -ExpandProperty "AllowDevelopmentWithoutDevLicense" | Should -Be 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /images/windows/scripts/tests/Wix.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Wix" { 2 | BeforeAll { 3 | $regKey = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" 4 | $installedApplications = Get-ItemProperty -Path $regKey 5 | $version = ($installedApplications | Where-Object { $_.BundleCachePath -imatch ".*\\WiX\d*\.exequot; } | Select-Object -First 1).DisplayName 6 | } 7 | 8 | It "Wix Toolset version from registry" { 9 | $version | Should -Not -BeNullOrEmpty 10 | } 11 | 12 | It "Wix variable exists" { 13 | $env:WIX | Should -Not -BeNullOrEmpty 14 | } 15 | 16 | It "Wix binaries folder exists" { 17 | Test-Path -Path $(Join-Path -Path $env:WIX -ChildPath "bin") | Should -Be $true 18 | } 19 | 20 | It "Wix binaries folder is in PATH" { 21 | $testPath = Join-Path -Path $env:WIX -ChildPath "bin" 22 | $env:PATH -split ";" | Should -Contain "$testPath" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /images/windows/templates/locals.windows.pkr.hcl: -------------------------------------------------------------------------------- 1 | locals { 2 | image_properties_map = { 3 | "win19" = { 4 | publisher = "MicrosoftWindowsServer" 5 | offer = "WindowsServer" 6 | sku = "2019-Datacenter" 7 | os_disk_size_gb = coalesce(var.os_disk_size_gb, 256) 8 | }, 9 | "win22" = { 10 | publisher = "MicrosoftWindowsServer" 11 | offer = "WindowsServer" 12 | sku = "2022-Datacenter" 13 | os_disk_size_gb = coalesce(var.os_disk_size_gb, 256) 14 | }, 15 | "win25" = { 16 | publisher = "MicrosoftWindowsServer" 17 | offer = "WindowsServer" 18 | sku = "2025-Datacenter" 19 | os_disk_size_gb = coalesce(var.os_disk_size_gb, 150) 20 | } 21 | } 22 | 23 | image_properties = local.image_properties_map[var.image_os] 24 | } 25 | -------------------------------------------------------------------------------- /schemas/toolset-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "patternProperties": { 5 | "^.*quot;: { 6 | "if": { 7 | "type": "object", 8 | "required": [ 9 | "version" 10 | ], 11 | "properties": { 12 | "version": { 13 | "type": "string", 14 | "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+.*quot; 15 | } 16 | } 17 | }, 18 | "then": { 19 | "required": [ 20 | "pinnedDetails" 21 | ], 22 | "properties": { 23 | "pinnedDetails": { 24 | "type": "object", 25 | "properties": { 26 | "reason": { 27 | "type": "string" 28 | }, 29 | "link": { 30 | "type": "string" 31 | }, 32 | "review-at": { 33 | "type": "string", 34 | "format": "date" 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | --------------------------------------------------------------------------------