| # This script is executed on every boot. Even though we lack even basic error |
| # reporting and handling, at least make sure that it is not executed twice. |
| if (Test-Path "c:\bazel_ci\install_completed.txt") { |
| Exit |
| } |
| |
| # Stop on action error. |
| # TODO(dmarting): for executable, we need to check for $LastExitCode each time. |
| $ErrorActionPreference = "Stop" |
| |
| if (-Not (Test-Path c:\bazel_ci)) { |
| New-Item c:\bazel_ci -type directory |
| } |
| Set-Location c:\bazel_ci |
| |
| # Install Chocolatey |
| Invoke-Expression ((New-Object Net.WebClient).DownloadString("https://chocolatey.org/install.ps1")) |
| |
| # Initialize msys |
| $msysRoot='c:\tools\msys64\' |
| |
| # Finally initialize and upgrade MSYS2 according to https://msys2.github.io |
| Write-Host "Initializing MSYS2..." |
| $msysShell = Join-Path $msysRoot msys2_shell.bat |
| Start-Process -Wait $msysShell -ArgumentList '-c', exit |
| |
| $command = 'pacman --noconfirm --needed -Sy bash pacman pacman-mirrors msys2-runtime' |
| Write-Host "Updating system packages with '$command'..." |
| Start-Process -Wait $msysShell -ArgumentList '-c', "'$command'" |
| |
| $command = 'pacman --noconfirm -Su' |
| Write-Host "Upgrading full system with '$command'..." |
| Start-Process -Wait $msysShell -ArgumentList '-c', "'$command'" |
| |
| # Download and install Python |
| New-Item c:\temp -type directory |
| (New-Object Net.WebClient).DownloadFile("https://www.python.org/ftp/python/2.7.11/python-2.7.11.amd64.msi", |
| "c:\temp\python-2.7.11.amd64.msi") |
| & msiexec /qn TARGETDIR=c:\python_27_amd64\files\ /i c:\temp\python-2.7.11.amd64.msi |
| |
| [Environment]::SetEnvironmentVariable("Path", $env:Path + ";c:\python_27_amd64\files", |
| [System.EnvironmentVariableTarget]::Machine) |
| |
| # Download and install Anaconda3, because python3 is required by TensorFlow on Windows |
| $anaconda3_tmp_folder = "c:\temp\anaconda3" |
| New-Item $anaconda3_tmp_folder -type directory -force |
| $anaconda3_installer = $anaconda3_tmp_folder + "\Anaconda3-4.2.0-Windows-x86_64.exe" |
| (New-Object Net.WebClient).DownloadFile("https://repo.continuum.io/archive/Anaconda3-4.2.0-Windows-x86_64.exe", $anaconda3_installer) |
| Start-Process -Wait $anaconda3_installer -ArgumentList "/AddToPath=0? /InstallationType=AllUsers /S /D='C:\Program Files\Anaconda3'" |
| |
| # Install pyreadline (Windows-compatible Python GNU readline library) and portpicker. |
| # Required by TensorFlow Python tests (tfdbg). |
| & "C:\Program Files\Anaconda3\Scripts\pip.exe" install pyreadline portpicker |
| |
| # Install all the Windows software we need: |
| # - JDK, because, Bazel is written in Java |
| # - NSSM, because that's the easiest way to create services |
| # - Chrome, because the default IE setup is way too crippled by security measures |
| & choco install nssm -y --allow-empty-checksums |
| & choco install jdk8 -y --allow-empty-checksums |
| & choco install googlechrome -y --allow-empty-checksums |
| |
| # Fetch the instance ID from GCE |
| $webclient=(New-Object Net.WebClient) |
| $webclient.Headers.Add("Metadata-Flavor", "Google") |
| $jenkins_node=$webclient.DownloadString("http://metadata/computeMetadata/v1/instance/attributes/jenkins_node") |
| if ($jenkins_node -match '.*-staging$') {$jenkins_master='jenkins-staging'} |
| else {$jenkins_master='jenkins'} |
| |
| # Save the Jenkins slave.jar to a suitable location |
| Invoke-WebRequest http://${jenkins_master}/jnlpJars/slave.jar -OutFile slave.jar |
| |
| # Install the necessary packages in msys2 |
| $bash_installer=@' |
| pacman -Syyu --noconfirm |
| pacman -S --noconfirm git curl gcc zip unzip zlib-devel isl tar patch |
| '@ |
| Write-Output $bash_installer | Out-File -Encoding ascii install.sh |
| # -l is required so that PATH in bash is set properly |
| & c:\tools\msys64\usr\bin\bash -l /c/bazel_ci/install.sh |
| |
| # Find the JDK. The path changes frequently, so hardcoding it is not enough. |
| $java=Get-ChildItem "c:\Program Files\Java\jdk*" | Select-Object -Index 0 | foreach { $_.FullName } |
| |
| # Get the latest release version number of Bazel |
| $url = "https://github.com/bazelbuild/bazel/releases/latest" |
| $req=[system.Net.HttpWebRequest]::Create($url); |
| $res = $req.getresponse(); |
| $res.Close(); |
| $bazel_version=$res.ResponseUri.AbsolutePath.TrimStart("/bazelbuild/bazel/releases/tag/") |
| |
| # Download the latest bazel |
| |
| # This will be replaced in vm.sh with $MSVC_LABEL='-msvc' for Windows MSVC nodes |
| $MSVC_LABEL='' |
| $folder="c:\bazel_ci\installs\${BAZEL_VERSION}" |
| $url="https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel${MSVC_LABEL}-${BAZEL_VERSION}-windows-x86_64.exe" |
| New-Item $folder -type directory -force |
| |
| # Continue if MSVC Bazel download fails due to not releasing yet |
| # TODO(pcloudy): Remove this after MSVC Bazel is released |
| if ($MSVC_LABEL -eq '-msvc') { $ErrorActionPreference = 'Continue' } |
| (New-Object Net.WebClient).DownloadFile("${url}", "${folder}\bazel.exe") |
| if ($MSVC_LABEL -eq '-msvc') { $ErrorActionPreference = 'Stop' } |
| |
| # Create a junction to the latest release |
| # The CI machines have Powershell 4 installed, so we cannot use New-Item to |
| # create a junction, so shell out to mklink. |
| cmd.exe /C mklink /j C:\bazel_ci\installs\latest $folder |
| |
| # On MSVC nodes, we still need to download a Bazel for bootstrap. |
| # TODO(pcloudy): Refactor this after MSVC Bazel is released. |
| if ($MSVC_LABEL -eq '-msvc') { |
| $folder="c:\bazel_ci\installs\bootstrap" |
| $url="https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-windows-x86_64.exe" |
| New-Item $folder -type directory -force |
| (New-Object Net.WebClient).DownloadFile("${url}", "${folder}\bazel.exe") |
| } else { |
| cmd.exe /C mklink /j C:\bazel_ci\installs\bootstrap $folder |
| } |
| |
| |
| # Replace the host name in the JNLP file, because Jenkins, in its infinite |
| # wisdom, does not let us change that separately from its external hostname. |
| $jnlp=((New-Object Net.WebClient).DownloadString("http://${jenkins_master}/computer/${jenkins_node}/slave-agent.jnlp")) |
| $jnlp=$jnlp -replace "http://ci.bazel.io", "http://${jenkins_master}" |
| $jnlp=$jnlp -replace "http://ci-staging.bazel.io", "http://${jenkins_master}" |
| Write-Output $jnlp | Out-File -Encoding ascii slave-agent.jnlp |
| |
| # Create the service that runs the Jenkins slave |
| # We can't execute Java directly because then it mysteriously fails with |
| # "Sockets error: 10106: create", so we redirect through Powershell |
| # The path change is needed because Jenkins cannot execute a different git |
| # binary on different nodes, so we need to simply use "git" |
| $agent_script=@" |
| `$env:path="c:\tools\msys64\usr\bin;`$env:path" |
| cd c:\bazel_ci |
| # A path name with c:\ in the JNLP URL makes Java hang. I don't know why. |
| # Jenkins tries to reconnect to the wrong port if the server is restarted. |
| # -noReconnect makes the agent die, and it is then subsequently restarted by |
| # Windows because it is a service, and then all is well. |
| & "$java\bin\java" -jar c:\bazel_ci\slave.jar -jnlpUrl file:///bazel_ci/slave-agent.jnlp -noReconnect |
| "@ |
| Write-Output $agent_script | Out-File -Encoding ascii agent_script.ps1 |
| |
| & nssm install bazel_ci powershell c:\bazel_ci\agent_script.ps1 |
| & nssm set bazel_ci AppStdout c:\bazel_ci\stdout.log |
| & nssm set bazel_ci AppStderr c:\bazel_ci\stderr.log |
| & nssm start bazel_ci |
| |
| Write-Output "DONE" | Out-File -Encoding ascii "c:\bazel_ci\install_completed.txt" |