feature: initial commit for all new image changes

This commit is contained in:
Subir Ghosh
2024-11-13 17:16:01 -07:00
parent de6aa9e70e
commit fcf3d0ac96
1042 changed files with 45086 additions and 1 deletions
@@ -0,0 +1,83 @@
################################################################################
## File: Configure-Toolset.ps1
## Team: CI-Build
## Desc: Configure toolset
################################################################################
Import-Module "$env:HELPER_SCRIPTS/../tests/Helpers.psm1"
function Get-TCToolVersionPath {
param(
[Parameter(Mandatory)]
[string] $ToolName,
[Parameter(Mandatory)]
[string] $ToolVersion,
[Parameter(Mandatory)]
[string] $ToolArchitecture
)
$toolPath = Join-Path -Path $env:AGENT_TOOLSDIRECTORY -ChildPath $ToolName
$toolPathVersion = Join-Path -Path $toolPath -ChildPath $ToolVersion
$foundVersion = Get-Item $toolPathVersion | Sort-Object -Property { [version] $_.name } -Descending | Select-Object -First 1
$installationDir = Join-Path -Path $foundVersion -ChildPath $ToolArchitecture
return $installationDir
}
function Add-GlobalEnvironmentVariable {
param(
[Parameter(Mandatory)]
[string] $Name,
[Parameter(Mandatory)]
[string] $Value,
[string] $FilePath = "/etc/environment"
)
$envVar = "{0}={1}" -f $Name, $Value
Tee-Object -InputObject $envVar -FilePath $FilePath -Append
}
$ErrorActionPreference = "Stop"
Write-Host "Configure toolcache tools environment..."
$toolEnvConfigs = @{
go = @{
command = "ln -s {0}/bin/* /usr/bin/"
variableTemplate = "GOROOT_{0}_{1}_X64"
}
}
# Get toolcache content from toolset
$tools = (Get-ToolsetContent).toolcache | Where-Object { $toolEnvConfigs.Keys -contains $_.name }
foreach ($tool in $tools) {
$toolEnvConfig = $toolEnvConfigs[$tool.name]
if (-not ([string]::IsNullOrEmpty($toolEnvConfig.variableTemplate))) {
foreach ($toolVersion in $tool.versions) {
Write-Host "Set $($tool.name) $toolVersion environment variable..."
$toolPath = Get-TCToolVersionPath -ToolName $tool.name -ToolVersion $toolVersion -ToolArchitecture $tool.arch
$envVariableName = $toolEnvConfig.variableTemplate -f $toolVersion.split(".")
Add-GlobalEnvironmentVariable -Name $envVariableName -Value $toolPath
}
}
# Invoke command and add env variable for the default tool version
if (-not ([string]::IsNullOrEmpty($tool.default))) {
$toolDefaultPath = Get-TCToolVersionPath -ToolName $tool.name -ToolVersion $tool.default -ToolArchitecture $tool.arch
if (-not ([string]::IsNullOrEmpty($toolEnvConfig.defaultVariable))) {
Write-Host "Set default $($toolEnvConfig.defaultVariable) for $($tool.name) $($tool.default) environment variable..."
Add-GlobalEnvironmentVariable -Name $toolEnvConfig.defaultVariable -Value $toolDefaultPath
}
if (-not ([string]::IsNullOrEmpty($toolEnvConfig.command))) {
$command = $toolEnvConfig.command -f $toolDefaultPath
Write-Host "Invoke $command command for default $($tool.name) $($tool.default) ..."
Invoke-Expression -Command $command
}
}
}
Invoke-PesterTests -TestFile "Toolset" -TestName "Toolset"
@@ -0,0 +1,27 @@
################################################################################
## File: Install-PowerShellAzModules.ps1
## Desc: Install Az modules for PowerShell
################################################################################
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
Import-Module "$env:HELPER_SCRIPTS/../tests/Helpers.psm1"
# Get modules content from toolset
$modules = (Get-ToolsetContent).azureModules
$installPSModulePath = "/usr/share"
foreach ($module in $modules) {
$moduleName = $module.name
Write-Host "Installing ${moduleName} to the ${installPSModulePath} path..."
foreach ($version in $module.versions) {
$modulePath = Join-Path -Path $installPSModulePath -ChildPath "${moduleName}_${version}"
Write-Host " - $version [$modulePath]"
Save-Module -Path $modulePath -Name $moduleName -RequiredVersion $version -Force
}
}
Invoke-PesterTests -TestFile "PowerShellModules" -TestName "AzureModules"
@@ -0,0 +1,35 @@
################################################################################
## File: Install-PowerShellModules.ps1
## Desc: Install modules for PowerShell
################################################################################
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
Import-Module "$env:HELPER_SCRIPTS/../tests/Helpers.psm1"
# Specifies the installation policy
Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
# Try to update PowerShellGet before the actual installation
Install-Module -Name PowerShellGet -Force
Update-Module -Name PowerShellGet -Force
# Install PowerShell modules
$modules = (Get-ToolsetContent).powershellModules
foreach($module in $modules) {
$moduleName = $module.name
Write-Host "Installing ${moduleName} module"
if ($module.versions) {
foreach ($version in $module.versions) {
Write-Host " - $version"
Install-Module -Name $moduleName -RequiredVersion $version -Scope AllUsers -SkipPublisherCheck -Force
}
} else {
Install-Module -Name $moduleName -Scope AllUsers -SkipPublisherCheck -Force
}
}
Invoke-PesterTests -TestFile "PowerShellModules" -TestName "PowerShellModules"
@@ -0,0 +1,55 @@
################################################################################
## File: Install-Toolset.ps1
## Team: CI-Build
## Desc: Install toolset
################################################################################
Import-Module "$env:HELPER_SCRIPTS/../tests/Helpers.psm1"
function Install-Asset {
param(
[Parameter(Mandatory = $true)]
[object] $ReleaseAsset
)
Write-Host "Download $($ReleaseAsset.filename)"
$assetArchivePath = Invoke-DownloadWithRetry $ReleaseAsset.download_url
Write-Host "Extract $($ReleaseAsset.filename) content..."
$assetFolderPath = Join-Path "/tmp" "$($ReleaseAsset.filename)-temp-dir"
New-Item -ItemType Directory -Path $assetFolderPath | Out-Null
tar -xzf $assetArchivePath -C $assetFolderPath
Write-Host "Invoke installation script..."
Push-Location -Path $assetFolderPath
Invoke-Expression "bash ./setup.sh"
Pop-Location
}
$ErrorActionPreference = "Stop"
# Get toolcache content from toolset
$tools = (Get-ToolsetContent).toolcache | Where-Object { $_.url -ne $null }
foreach ($tool in $tools) {
# Get versions manifest for current tool
$assets = Invoke-RestMethod $tool.url
# Get github release asset for each version
foreach ($toolVersion in $tool.versions) {
$asset = $assets | Where-Object version -like $toolVersion `
| Select-Object -ExpandProperty files `
| Where-Object { ($_.platform -eq $tool.platform) -and ($_.arch -eq $tool.arch) -and ($_.platform_version -eq $tool.platform_version)} `
| Select-Object -First 1
if (-not $asset) {
Write-Host "Asset for $($tool.name) $toolVersion $($tool.arch) not found in versions manifest"
exit 1
}
Write-Host "Installing $($tool.name) $toolVersion $($tool.arch)..."
Install-Asset -ReleaseAsset $asset
}
chown -R "$($env:SUDO_USER):$($env:SUDO_USER)" "/opt/hostedtoolcache/$($tool.name)"
}
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash -e
################################################################################
## File: cleanup.sh
## Desc: Perform cleanup
################################################################################
# before cleanup
before=$(df / -Pm | awk 'NR==2{print $4}')
# clears out the local repository of retrieved package files
# It removes everything but the lock file from /var/cache/apt/archives/ and /var/cache/apt/archives/partial
apt-get clean
rm -rf /tmp/*
rm -rf /root/.cache
# journalctl
if command -v journalctl; then
journalctl --rotate
journalctl --vacuum-time=1s
fi
# delete all .gz and rotated file
find /var/log -type f -regex ".*\.gz$" -delete
find /var/log -type f -regex ".*\.[0-9]$" -delete
# wipe log files
find /var/log/ -type f -exec cp /dev/null {} \;
# delete symlink for tests running
rm -f /usr/local/bin/invoke_tests
# remove apt mock
prefix=/usr/local/bin
for tool in apt apt-get apt-key;do
sudo rm -f $prefix/$tool
done
# after cleanup
after=$(df / -Pm | awk 'NR==2{print $4}')
# display size
echo "Before: $before MB"
echo "After : $after MB"
echo "Delta : $(($after-$before)) MB"
@@ -0,0 +1,54 @@
#!/bin/bash -e
################################################################################
## File: configure-apt-mock.sh
## Desc: A temporary workaround for https://github.com/Azure/azure-linux-extensions/issues/1238.
## Cleaned up during cleanup.sh.
################################################################################
prefix=/usr/local/bin
for real_tool in /usr/bin/apt /usr/bin/apt-get /usr/bin/apt-key; do
tool=$(basename $real_tool)
cat >$prefix/$tool <<EOT
#!/bin/sh
i=1
while [ \$i -le 30 ];do
err=\$(mktemp)
$real_tool "\$@" 2>\$err
# no errors, break the loop and continue normal flow
test -f \$err || break
cat \$err >&2
retry=false
if grep -q 'Could not get lock' \$err;then
# apt db locked needs retry
retry=true
elif grep -q 'Could not open file /var/lib/apt/lists' \$err;then
# apt update is not completed, needs retry
retry=true
elif grep -q 'IPC connect call failed' \$err;then
# the delay should help with gpg-agent not ready
retry=true
elif grep -q 'Temporary failure in name resolution' \$err;then
# It looks like DNS is not updated with random generated hostname yet
retry=true
elif grep -q 'dpkg frontend is locked by another process' \$err;then
# dpkg process is busy by another process
retry=true
fi
rm \$err
if [ \$retry = false ]; then
break
fi
sleep 5
echo "...retry \$i"
i=\$((i + 1))
done
EOT
chmod +x $prefix/$tool
done
@@ -0,0 +1,16 @@
#!/bin/bash -e
################################################################################
## File: configure-apt-sources.sh
## Desc: Configure apt sources with failover from Azure to Ubuntu archives.
################################################################################
touch /etc/apt/apt-mirrors.txt
printf "http://azure.archive.ubuntu.com/ubuntu/\tpriority:1\n" | tee -a /etc/apt/apt-mirrors.txt
printf "http://archive.ubuntu.com/ubuntu/\tpriority:2\n" | tee -a /etc/apt/apt-mirrors.txt
printf "http://security.ubuntu.com/ubuntu/\tpriority:3\n" | tee -a /etc/apt/apt-mirrors.txt
sed -i 's/http:\/\/azure.archive.ubuntu.com\/ubuntu\//mirror+file:\/etc\/apt\/apt-mirrors.txt/' /etc/apt/sources.list
# Apt changes to survive Cloud Init
cp -f /etc/apt/sources.list /etc/cloud/templates/sources.list.ubuntu.tmpl
@@ -0,0 +1,55 @@
#!/bin/bash -e
################################################################################
## File: configure-apt.sh
## Desc: Configure apt, install jq and apt-fast packages.
################################################################################
source $HELPER_SCRIPTS/os.sh
# Stop and disable apt-daily upgrade services;
systemctl stop apt-daily.timer
systemctl disable apt-daily.timer
systemctl disable apt-daily.service
systemctl stop apt-daily-upgrade.timer
systemctl disable apt-daily-upgrade.timer
systemctl disable apt-daily-upgrade.service
# Enable retry logic for apt up to 10 times
echo "APT::Acquire::Retries \"10\";" > /etc/apt/apt.conf.d/80-retries
# Configure apt to always assume Y
echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes
# APT understands a field called Phased-Update-Percentage which can be used to control the rollout of a new version. It is an integer between 0 and 100.
# In case you have multiple systems that you want to receive the same set of updates,
# you can set APT::Machine-ID to a UUID such that they all phase the same,
# or set APT::Get::Never-Include-Phased-Updates or APT::Get::Always-Include-Phased-Updates to true such that APT will never/always consider phased updates.
# apt-cache policy pkgname
echo 'APT::Get::Always-Include-Phased-Updates "true";' > /etc/apt/apt.conf.d/99-phased-updates
# Fix bad proxy and http headers settings
cat <<EOF >> /etc/apt/apt.conf.d/99bad_proxy
Acquire::http::Pipeline-Depth 0;
Acquire::http::No-Cache true;
Acquire::BrokenProxy true;
EOF
# Uninstall unattended-upgrades
apt-get purge unattended-upgrades
echo 'APT sources'
if ! is_ubuntu24; then
cat /etc/apt/sources.list
else
cat /etc/apt/sources.list.d/ubuntu.sources
fi
apt-get update
# Install jq
apt-get install jq
if ! is_ubuntu24; then
# Install apt-fast using quick-install.sh
# https://github.com/ilikenwf/apt-fast
bash -c "$(curl -fsSL https://raw.githubusercontent.com/ilikenwf/apt-fast/master/quick-install.sh)"
fi
@@ -0,0 +1,32 @@
#!/bin/bash -e
################################################################################
## File: configure-dpkg.sh
## Desc: Configure dpkg
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
# This is the anti-frontend. It never interacts with you at all,
# and makes the default answers be used for all questions. It
# might mail error messages to root, but that's it; otherwise it
# is completely silent and unobtrusive, a perfect frontend for
# automatic installs. If you are using this front-end, and require
# non-default answers to questions, you will need to pre-seed the
# debconf database
set_etc_environment_variable "DEBIAN_FRONTEND" "noninteractive"
# dpkg can be instructed not to ask for confirmation
# when replacing a configuration file (with the --force-confdef --force-confold options)
cat <<EOF >> /etc/apt/apt.conf.d/10dpkg-options
Dpkg::Options {
"--force-confdef";
"--force-confold";
}
EOF
# hide information about packages that are no longer required
cat <<EOF >> /etc/apt/apt.conf.d/10apt-autoremove
APT::Get::AutomaticRemove "0";
APT::Get::HideAutoRemove "1";
EOF
@@ -0,0 +1,71 @@
#!/bin/bash -e
################################################################################
## File: configure-environment.sh
## Desc: Configure system and environment
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/etc-environment.sh
# Set ImageVersion and ImageOS env variables
set_etc_environment_variable "ImageVersion" "${IMAGE_VERSION}"
set_etc_environment_variable "ImageOS" "${IMAGE_OS}"
# Set the ACCEPT_EULA variable to Y value to confirm your acceptance of the End-User Licensing Agreement
set_etc_environment_variable "ACCEPT_EULA" "Y"
# This directory is supposed to be created in $HOME and owned by user(https://github.com/actions/runner-images/issues/491)
mkdir -p /etc/skel/.config/configstore
set_etc_environment_variable "XDG_CONFIG_HOME" '$HOME/.config'
# Change waagent entries to use /mnt for swap file
sed -i 's/ResourceDisk.Format=n/ResourceDisk.Format=y/g' /etc/waagent.conf
sed -i 's/ResourceDisk.EnableSwap=n/ResourceDisk.EnableSwap=y/g' /etc/waagent.conf
sed -i 's/ResourceDisk.SwapSizeMB=0/ResourceDisk.SwapSizeMB=4096/g' /etc/waagent.conf
# Add localhost alias to ::1 IPv6
sed -i 's/::1 ip6-localhost ip6-loopback/::1 localhost ip6-localhost ip6-loopback/g' /etc/hosts
# Prepare directory and env variable for toolcache
AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache
mkdir $AGENT_TOOLSDIRECTORY
set_etc_environment_variable "AGENT_TOOLSDIRECTORY" "${AGENT_TOOLSDIRECTORY}"
set_etc_environment_variable "RUNNER_TOOL_CACHE" "${AGENT_TOOLSDIRECTORY}"
chmod -R 777 $AGENT_TOOLSDIRECTORY
# https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html
# https://www.suse.com/support/kb/doc/?id=000016692
echo 'vm.max_map_count=262144' | tee -a /etc/sysctl.conf
# https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files
echo 'fs.inotify.max_user_watches=655360' | tee -a /etc/sysctl.conf
echo 'fs.inotify.max_user_instances=1280' | tee -a /etc/sysctl.conf
# https://github.com/actions/runner-images/issues/9491
echo 'vm.mmap_rnd_bits=28' | tee -a /etc/sysctl.conf
# https://github.com/actions/runner-images/pull/7860
netfilter_rule='/etc/udev/rules.d/50-netfilter.rules'
rules_directory="$(dirname "${netfilter_rule}")"
mkdir -p $rules_directory
touch $netfilter_rule
echo 'ACTION=="add", SUBSYSTEM=="module", KERNEL=="nf_conntrack", RUN+="/usr/sbin/sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1"' | tee -a $netfilter_rule
# Create symlink for tests running
chmod +x $HELPER_SCRIPTS/invoke-tests.sh
ln -s $HELPER_SCRIPTS/invoke-tests.sh /usr/local/bin/invoke_tests
# Disable motd updates metadata
sed -i 's/ENABLED=1/ENABLED=0/g' /etc/default/motd-news
if [[ -f "/etc/fwupd/daemon.conf" ]]; then
sed -i 's/UpdateMotd=true/UpdateMotd=false/g' /etc/fwupd/daemon.conf
systemctl mask fwupd-refresh.timer
fi
# Disable to load providers
# https://github.com/microsoft/azure-pipelines-agent/issues/3834
if is_ubuntu22; then
sed -i 's/openssl_conf = openssl_init/#openssl_conf = openssl_init/g' /etc/ssl/openssl.cnf
fi
@@ -0,0 +1,32 @@
#!/bin/bash -e
################################################################################
## File: configure-image-data.sh
## Desc: Create a file with image data and documentation links
################################################################################
imagedata_file=$IMAGEDATA_FILE
image_version=$IMAGE_VERSION
image_version_major=${image_version/.*/}
image_version_minor=$(echo $image_version | cut -d "." -f 2)
os_name=$(lsb_release -ds | sed "s/ /\\\n/g")
os_version=$(lsb_release -rs)
image_label="ubuntu-${os_version}"
version_major=${os_version/.*/}
version_wo_dot=${os_version/./}
github_url="https://github.com/actions/runner-images/blob"
software_url="${github_url}/ubuntu${version_major}/${image_version_major}.${image_version_minor}/images/ubuntu/Ubuntu${version_wo_dot}-Readme.md"
releaseUrl="https://github.com/actions/runner-images/releases/tag/ubuntu${version_major}%2F${image_version_major}.${image_version_minor}"
cat <<EOF > $imagedata_file
[
{
"group": "Operating System",
"detail": "${os_name}"
},
{
"group": "Runner Image",
"detail": "Image: ${image_label}\nVersion: ${image_version}\nIncluded Software: ${software_url}\nImage Release: ${releaseUrl}"
}
]
EOF
@@ -0,0 +1,18 @@
#!/bin/bash -e
################################################################################
## File: configure-limits.sh
## Desc: Configure limits
################################################################################
echo 'session required pam_limits.so' >> /etc/pam.d/common-session
echo 'session required pam_limits.so' >> /etc/pam.d/common-session-noninteractive
echo 'DefaultLimitNOFILE=65536' >> /etc/systemd/system.conf
echo 'DefaultLimitSTACK=16M:infinity' >> /etc/systemd/system.conf
# Raise Number of File Descriptors
echo '* soft nofile 65536' >> /etc/security/limits.conf
echo '* hard nofile 65536' >> /etc/security/limits.conf
# Double stack size from default 8192KB
echo '* soft stack 16384' >> /etc/security/limits.conf
echo '* hard stack 16384' >> /etc/security/limits.conf
@@ -0,0 +1,26 @@
#!/bin/bash -e
################################################################################
## File: configure-snap.sh
## Desc: Configure snap
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
# Update /etc/environment to include /snap/bin in PATH
# because /etc/profile.d is ignored by `--norc` shell launch option
prepend_etc_environment_path "/snap/bin"
# Put snapd auto refresh on hold
# as it may generate too much traffic on Canonical's snap server
# when they are rolling a new major update out.
# Hold is calculated as today's date + 60 days
# snapd is started automatically, but during image generation
# a unix socket may die, restart snapd.service (and therefore snapd.socket)
# to make sure the socket is alive.
systemctl restart snapd.socket
systemctl restart snapd
snap set system refresh.hold="$(date --date='today+60 days' +%Y-%m-%dT%H:%M:%S%:z)"
@@ -0,0 +1,40 @@
#!/bin/bash -e
################################################################################
## File: configure-system.sh
## Desc: Post deployment system configuration actions
################################################################################
source $HELPER_SCRIPT_FOLDER/etc-environment.sh
source $HELPER_SCRIPT_FOLDER/os.sh
mv -f /imagegeneration/post-generation /opt
echo "chmod -R 777 /opt"
chmod -R 777 /opt
echo "chmod -R 777 /usr/share"
chmod -R 777 /usr/share
chmod 755 $IMAGE_FOLDER
# Remove quotes around PATH
ENVPATH=$(grep 'PATH=' /etc/environment | head -n 1 | sed -z 's/^PATH=*//')
ENVPATH=${ENVPATH#"\""}
ENVPATH=${ENVPATH%"\""}
replace_etc_environment_variable "PATH" "${ENVPATH}"
echo "Updated /etc/environment: $(cat /etc/environment)"
# Clean yarn and npm cache
if yarn --version > /dev/null; then
yarn cache clean
fi
if npm --version; then
npm cache clean --force
fi
if is_ubuntu24; then
# Prevent needrestart from restarting the provisioner service.
# Currently only happens on Ubuntu 24.04, so make it conditional for the time being
# as configuration is too different between Ubuntu versions.
sed -i '/^\s*};/i \ qr(^runner-provisioner) => 0,' /etc/needrestart/needrestart.conf
fi
@@ -0,0 +1,24 @@
#!/bin/bash -e
################################################################################
## File: install-actions-cache.sh
## Desc: Download latest release from https://github.com/actions/action-versions
## Maintainer: #actions-runtime and @TingluoHuang
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
# Prepare directory and env variable for ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE
ACTION_ARCHIVE_CACHE_DIR=/opt/actionarchivecache
mkdir -p $ACTION_ARCHIVE_CACHE_DIR
chmod -R 777 $ACTION_ARCHIVE_CACHE_DIR
echo "Setting up ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE variable to ${ACTION_ARCHIVE_CACHE_DIR}"
set_etc_environment_variable "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE" "${ACTION_ARCHIVE_CACHE_DIR}"
# Download latest release from github.com/actions/action-versions and untar to /opt/actionarchivecache
download_url=$(resolve_github_release_asset_url "actions/action-versions" "endswith(\"action-versions.tar.gz\")" "latest")
archive_path=$(download_with_retry "$download_url")
tar -xzf "$archive_path" -C $ACTION_ARCHIVE_CACHE_DIR
invoke_tests "ActionArchiveCache"
@@ -0,0 +1,36 @@
#!/bin/bash -e
################################################################################
## File: install-aliyun-cli.sh
## Desc: Install Alibaba Cloud CLI
## Supply chain security: Alibaba Cloud CLI - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
# Install Alibaba Cloud CLI
# Pin tool version on ubuntu20 due to issues with GLIBC_2.32 not available
if is_ubuntu20; then
toolset_version=$(get_toolset_value '.aliyunCli.version')
download_url="https://github.com/aliyun/aliyun-cli/releases/download/v$toolset_version/aliyun-cli-linux-$toolset_version-amd64.tgz"
else
download_url=$(resolve_github_release_asset_url "aliyun/aliyun-cli" "contains(\"aliyun-cli-linux\") and endswith(\"amd64.tgz\")" "latest")
hash_url="https://github.com/aliyun/aliyun-cli/releases/latest/download/SHASUMS256.txt"
fi
archive_path=$(download_with_retry "$download_url")
# Supply chain security - Alibaba Cloud CLI
if is_ubuntu20; then
external_hash=$(get_toolset_value '.aliyunCli.sha256')
else
external_hash=$(get_checksum_from_url "$hash_url" "aliyun-cli-linux.*amd64.tgz" "SHA256")
fi
use_checksum_comparison "$archive_path" "$external_hash"
tar xzf "$archive_path"
mv aliyun /usr/local/bin
invoke_tests "CLI.Tools" "Aliyun CLI"
@@ -0,0 +1,121 @@
#!/bin/bash -e
################################################################################
## File: install-android-sdk.sh
## Desc: Install Android SDK and tools
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
add_filtered_installation_components() {
local minimum_version=$1
shift
local tools_array=("$@")
for item in ${tools_array[@]}; do
# Take the last argument after splitting string by ';'' and '-''
item_version=$(echo "${item##*[-;]}")
# Semver 'comparison'. Add item to components array, if item's version is greater than or equal to minimum version
if [[ "$(printf "${minimum_version}\n${item_version}\n" | sort -V | head -n1)" == "$minimum_version" ]]; then
components+=($item)
fi
done
}
get_full_ndk_version() {
local major_version=$1
ndk_version=$($SDKMANAGER --list | grep "ndk;${major_version}\." | awk '{gsub("ndk;", ""); print $1}' | sort -V | tail -n1)
echo "$ndk_version"
}
# Set env variable for SDK Root (https://developer.android.com/studio/command-line/variables)
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
set_etc_environment_variable "ANDROID_SDK_ROOT" "${ANDROID_SDK_ROOT}"
# ANDROID_HOME is deprecated, but older versions of Gradle rely on it
set_etc_environment_variable "ANDROID_HOME" "${ANDROID_SDK_ROOT}"
# Create android sdk directory
mkdir -p ${ANDROID_SDK_ROOT}
# Download the latest command line tools so that we can accept all of the licenses.
# See https://developer.android.com/studio/#command-tools
cmdline_tools_package=$(get_toolset_value '.android."cmdline-tools"')
if [[ $cmdline_tools_version == "latest" ]]; then
REPOSITORY_XML_URL="https://dl.google.com/android/repository/repository2-1.xml"
repository_xml_file=$(download_with_retry "$REPOSITORY_XML_URL")
cmdline_tools_package=$(
yq -p=xml \
'.sdk-repository.remotePackage[] | select(."+@path" == "cmdline-tools;latest" and .channelRef."+@ref" == "channel-0").archives.archive[].complete.url | select(contains("commandlinetools-linux"))' \
"${repository_xml_file}"
)
if [[ -z $cmdline_tools_package ]]; then
echo "Failed to parse latest command-line tools version"
exit 1
fi
fi
# Install command line tools
archive_path=$(download_with_retry "https://dl.google.com/android/repository/${cmdline_tools_package}")
unzip -qq "$archive_path" -d ${ANDROID_SDK_ROOT}/cmdline-tools
# Command line tools need to be placed in ${ANDROID_SDK_ROOT}/sdk/cmdline-tools/latest to determine SDK root
mv ${ANDROID_SDK_ROOT}/cmdline-tools/cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest
# Check sdk manager installation
if ${SDKMANAGER} --list 1>/dev/null; then
echo "Android SDK manager was installed"
else
echo "Android SDK manager was not installed"
exit 1
fi
# Get toolset values and prepare environment variables
minimum_build_tool_version=$(get_toolset_value '.android.build_tools_min_version')
minimum_platform_version=$(get_toolset_value '.android.platform_min_version')
android_ndk_major_default=$(get_toolset_value '.android.ndk.default')
android_ndk_major_versions=($(get_toolset_value '.android.ndk.versions[]'))
android_ndk_major_latest=(${android_ndk_major_versions[-1]})
ndk_default_full_version=$(get_full_ndk_version $android_ndk_major_default)
ndk_latest_full_version=$(get_full_ndk_version $android_ndk_major_latest)
ANDROID_NDK=${ANDROID_SDK_ROOT}/ndk/${ndk_default_full_version}
# ANDROID_NDK, ANDROID_NDK_HOME, and ANDROID_NDK_ROOT variables should be set as many customer builds depend on them https://github.com/actions/runner-images/issues/5879
set_etc_environment_variable "ANDROID_NDK" "${ANDROID_NDK}"
set_etc_environment_variable "ANDROID_NDK_HOME" "${ANDROID_NDK}"
set_etc_environment_variable "ANDROID_NDK_ROOT" "${ANDROID_NDK}"
set_etc_environment_variable "ANDROID_NDK_LATEST_HOME" "${ANDROID_SDK_ROOT}/ndk/${ndk_latest_full_version}"
# Prepare components for installation
extras=$(get_toolset_value '.android.extra_list[] | "extras;" + .')
addons=$(get_toolset_value '.android.addon_list[] | "add-ons;" + .')
additional=$(get_toolset_value '.android.additional_tools[]')
components=("${extras[@]}" "${addons[@]}" "${additional[@]}")
for ndk_major_version in "${android_ndk_major_versions[@]}"; do
ndk_full_version=$(get_full_ndk_version $ndk_major_version)
components+=("ndk;$ndk_full_version")
done
available_platforms=($($SDKMANAGER --list | sed -n '/Available Packages:/,/^$/p' | grep "platforms;android-[0-9]" | cut -d"|" -f 1))
all_build_tools=($($SDKMANAGER --list | grep "build-tools;" | cut -d"|" -f 1 | sort -u))
available_build_tools=$(echo ${all_build_tools[@]//*rc[0-9]/})
add_filtered_installation_components $minimum_platform_version "${available_platforms[@]}"
add_filtered_installation_components $minimum_build_tool_version "${available_build_tools[@]}"
# Install components
echo "y" | $SDKMANAGER ${components[@]}
# Add required permissions
chmod -R a+rwx ${ANDROID_SDK_ROOT}
reload_etc_environment
invoke_tests "Android"
@@ -0,0 +1,14 @@
#!/bin/bash -e
################################################################################
## File: install-apache.sh
## Desc: Install Apache HTTP Server
################################################################################
# Install Apache
apt-get install apache2
# Disable apache2.service
systemctl is-active --quiet apache2.service && systemctl stop apache2.service
systemctl disable apache2.service
invoke_tests "WebServers" "Apache"
@@ -0,0 +1,18 @@
#!/bin/bash -e
################################################################################
## File: install-apt-common.sh
## Desc: Install basic command line utilities and dev packages
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
common_packages=$(get_toolset_value .apt.common_packages[])
cmd_packages=$(get_toolset_value .apt.cmd_packages[])
for package in $common_packages $cmd_packages; do
echo "Install $package"
apt-get install --no-install-recommends $package
done
invoke_tests "Apt"
@@ -0,0 +1,11 @@
#!/bin/bash -e
################################################################################
## File: install-apt-vital.sh
## Desc: Install vital command line utilities
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
vital_packages=$(get_toolset_value .apt.vital_packages[])
apt-get install --no-install-recommends $vital_packages
@@ -0,0 +1,32 @@
#!/bin/bash -e
################################################################################
## File: install-aws-tools.sh
## Desc: Install the AWS CLI, Session Manager plugin for the AWS CLI, and AWS SAM CLI
## Supply chain security: AWS SAM CLI - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
awscliv2_archive_path=$(download_with_retry "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip")
unzip -qq "$awscliv2_archive_path" -d /tmp
/tmp/aws/install -i /usr/local/aws-cli -b /usr/local/bin
smplugin_deb_path=$(download_with_retry "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb")
apt-get install "$smplugin_deb_path"
# Download the latest aws sam cli release
aws_sam_cli_archive_name="aws-sam-cli-linux-x86_64.zip"
sam_cli_download_url=$(resolve_github_release_asset_url "aws/aws-sam-cli" "endswith(\"$aws_sam_cli_archive_name\")" "latest")
aws_sam_cli_archive_path=$(download_with_retry "$sam_cli_download_url")
# Supply chain security - AWS SAM CLI
aws_sam_cli_hash=$(get_checksum_from_github_release "aws/aws-sam-cli" "${aws_sam_cli_archive_name}.. " "latest" "SHA256")
use_checksum_comparison "$aws_sam_cli_archive_path" "$aws_sam_cli_hash"
# Install the latest aws sam cli release
unzip "$aws_sam_cli_archive_path" -d /tmp
/tmp/install
invoke_tests "CLI.Tools" "AWS"
@@ -0,0 +1,18 @@
#!/bin/bash -e
################################################################################
## File: install-azcopy.sh
## Desc: Install AzCopy
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Install AzCopy10
archive_path=$(download_with_retry "https://aka.ms/downloadazcopy-v10-linux")
tar xzf "$archive_path" --strip-components=1 -C /tmp
install /tmp/azcopy /usr/local/bin/azcopy
# Create azcopy 10 alias for backward compatibility
ln -sf /usr/local/bin/azcopy /usr/local/bin/azcopy10
invoke_tests "Tools" "azcopy"
@@ -0,0 +1,15 @@
#!/bin/bash -e
################################################################################
## File: install-azure-cli.sh
## Desc: Install Azure CLI (az)
################################################################################
# Install Azure CLI (instructions taken from https://docs.microsoft.com/en-us/cli/azure/install-azure-cli)
curl -fsSL https://aka.ms/InstallAzureCLIDeb | sudo bash
echo "azure-cli https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt" >> $HELPER_SCRIPTS/apt-sources.txt
rm -f /etc/apt/sources.list.d/azure-cli.list
rm -f /etc/apt/sources.list.d/azure-cli.list.save
invoke_tests "CLI.Tools" "Azure CLI"
@@ -0,0 +1,18 @@
#!/bin/bash -e
################################################################################
## File: install-azure-devops-cli.sh
## Desc: Install Azure DevOps CLI (az devops)
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
# AZURE_EXTENSION_DIR shell variable defines where modules are installed
# https://docs.microsoft.com/en-us/cli/azure/azure-cli-extensions-overview
export AZURE_EXTENSION_DIR=/opt/az/azcliextensions
set_etc_environment_variable "AZURE_EXTENSION_DIR" "${AZURE_EXTENSION_DIR}"
# install azure devops Cli extension
az extension add -n azure-devops
invoke_tests "CLI.Tools" "Azure DevOps CLI"
@@ -0,0 +1,16 @@
#!/bin/bash -e
################################################################################
## File: install-bazel.sh
## Desc: Install Bazel and Bazelisk (A user-friendly launcher for Bazel)
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Install bazelisk
npm install -g @bazel/bazelisk
# run bazelisk once in order to install /usr/local/bin/bazel binary
sudo -u $SUDO_USER bazel version
invoke_tests "Tools" "Bazel"
@@ -0,0 +1,17 @@
#!/bin/bash -e
################################################################################
## File: install-bicep.sh
## Desc: Install bicep cli
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Install Bicep CLI
download_url=$(resolve_github_release_asset_url "Azure/bicep" "endswith(\"bicep-linux-x64\")" "latest")
bicep_binary_path=$(download_with_retry "${download_url}")
# Mark it as executable
install "$bicep_binary_path" /usr/local/bin/bicep
invoke_tests "Tools" "Bicep"
@@ -0,0 +1,40 @@
#!/bin/bash -e
################################################################################
## File: install-clang.sh
## Desc: Install Clang compiler
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
install_clang() {
local version=$1
echo "Installing clang-$version..."
apt-get install "clang-$version" "lldb-$version" "lld-$version" "clang-format-$version" "clang-tidy-$version"
}
set_default_clang() {
local version=$1
echo "Make Clang ${version} default"
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${version} 100
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${version} 100
update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-${version} 100
update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-${version} 100
update-alternatives --install /usr/bin/run-clang-tidy run-clang-tidy /usr/bin/run-clang-tidy-${version} 100
}
versions=$(get_toolset_value '.clang.versions[]')
default_clang_version=$(get_toolset_value '.clang.default_version')
for version in ${versions[*]}; do
if [[ $version != $default_clang_version ]]; then
install_clang $version
fi
done
install_clang $default_clang_version
set_default_clang $default_clang_version
invoke_tests "Tools" "clang"
@@ -0,0 +1,31 @@
#!/bin/bash -e
################################################################################
## File: install-cmake.sh
## Desc: Install CMake
## Supply chain security: CMake - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Test to see if the software in question is already installed, if not install it
echo "Checking to see if the installer script has already been run"
if command -v cmake; then
echo "cmake is already installed"
else
# Download script to install CMake
download_url=$(resolve_github_release_asset_url "Kitware/CMake" "endswith(\"inux-x86_64.sh\")" "latest")
curl -fsSL "${download_url}" -o cmakeinstall.sh
# Supply chain security - CMake
hash_url=$(resolve_github_release_asset_url "Kitware/CMake" "endswith(\"SHA-256.txt\")" "latest")
external_hash=$(get_checksum_from_url "$hash_url" "linux-x86_64.sh" "SHA256")
use_checksum_comparison "cmakeinstall.sh" "$external_hash"
# Install CMake and remove the install script
chmod +x cmakeinstall.sh \
&& ./cmakeinstall.sh --prefix=/usr/local --exclude-subdir \
&& rm cmakeinstall.sh
fi
invoke_tests "Tools" "Cmake"
@@ -0,0 +1,31 @@
#!/bin/bash -e
################################################################################
## File: install-codeql-bundle.sh
## Desc: Install CodeQL CLI Bundle to the toolcache.
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Retrieve the CLI version of the latest CodeQL bundle.
base_url="$(curl -fsSL https://raw.githubusercontent.com/github/codeql-action/v2/src/defaults.json)"
bundle_version="$(echo "$base_url" | jq -r '.cliVersion')"
bundle_tag_name="codeql-bundle-v$bundle_version"
echo "Downloading CodeQL bundle $bundle_version..."
# Note that this is the all-platforms CodeQL bundle, to support scenarios where customers run
# different operating systems within containers.
codeql_archive=$(download_with_retry "https://github.com/github/codeql-action/releases/download/$bundle_tag_name/codeql-bundle.tar.gz")
codeql_toolcache_path="$AGENT_TOOLSDIRECTORY/CodeQL/$bundle_version/x64"
mkdir -p "$codeql_toolcache_path"
echo "Unpacking the downloaded CodeQL bundle archive..."
tar -xzf "$codeql_archive" -C "$codeql_toolcache_path"
# Touch a file to indicate to the CodeQL Action that this bundle shipped with the toolcache. This is
# to support overriding the CodeQL version specified in defaults.json on GitHub Enterprise.
touch "$codeql_toolcache_path/pinned-version"
# Touch a file to indicate to the toolcache that setting up CodeQL is complete.
touch "$codeql_toolcache_path.complete"
@@ -0,0 +1,45 @@
#!/bin/bash -e
################################################################################
## File: install-container-tools.sh
## Desc: Install container tools: podman, buildah and skopeo onto the image
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
#
# pin podman due to https://github.com/actions/runner-images/issues/7753
# https://bugs.launchpad.net/ubuntu/+source/libpod/+bug/2024394
#
if ! is_ubuntu22; then
install_packages=(podman buildah skopeo)
else
install_packages=(podman=3.4.4+ds1-1ubuntu1 buildah skopeo)
fi
# Packages is available in the official Ubuntu upstream starting from Ubuntu 21
if is_ubuntu20; then
REPO_URL="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$(lsb_release -rs)"
GPG_KEY="/usr/share/keyrings/devel_kubic_libcontainers_stable.gpg"
REPO_PATH="/etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
curl -fsSL "${REPO_URL}/Release.key" | gpg --dearmor -o $GPG_KEY
echo "deb [arch=amd64 signed-by=$GPG_KEY] ${REPO_URL}/ /" > $REPO_PATH
fi
# Install podman, buildah, skopeo container's tools
apt-get update
apt-get install ${install_packages[@]}
mkdir -p /etc/containers
printf "[registries.search]\nregistries = ['docker.io', 'quay.io']\n" | tee /etc/containers/registries.conf
if is_ubuntu20; then
# Remove source repo
rm $GPG_KEY
rm $REPO_PATH
# Document source repo
echo "containers $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt
fi
invoke_tests "Tools" "Containers"
@@ -0,0 +1,107 @@
#!/bin/bash -e
################################################################################
## File: install-docker.sh
## Desc: Install docker onto the image
## Supply chain security: amazon-ecr-credential-helper - dynamic checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
REPO_URL="https://download.docker.com/linux/ubuntu"
GPG_KEY="/usr/share/keyrings/docker.gpg"
REPO_PATH="/etc/apt/sources.list.d/docker.list"
os_codename=$(lsb_release -cs)
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o $GPG_KEY
echo "deb [arch=amd64 signed-by=$GPG_KEY] $REPO_URL ${os_codename} stable" > $REPO_PATH
apt-get update
# Install docker components which available via apt-get
# Using toolsets keep installation order to install dependencies before the package in order to control versions
components=$(get_toolset_value '.docker.components[] .package')
for package in $components; do
version=$(get_toolset_value ".docker.components[] | select(.package == \"$package\") | .version")
if [[ $version == "latest" ]]; then
apt-get install --no-install-recommends "$package"
else
version_string=$(apt-cache madison "$package" | awk '{ print $3 }' | grep "$version" | grep "$os_codename" | head -1)
apt-get install --no-install-recommends "${package}=${version_string}"
fi
done
# Install plugins that are best installed from the GitHub repository
# Be aware that `url` built from github repo name and plugin name because of current repo naming for those plugins
plugins=$(get_toolset_value '.docker.plugins[] .plugin')
for plugin in $plugins; do
version=$(get_toolset_value ".docker.plugins[] | select(.plugin == \"$plugin\") | .version")
filter=$(get_toolset_value ".docker.plugins[] | select(.plugin == \"$plugin\") | .asset")
url=$(resolve_github_release_asset_url "docker/$plugin" "endswith(\"$filter\")" "$version")
binary_path=$(download_with_retry "$url" "/tmp/docker-$plugin")
mkdir -pv "/usr/libexec/docker/cli-plugins"
install "$binary_path" "/usr/libexec/docker/cli-plugins/docker-$plugin"
done
# docker from official repo introduced different GID generation: https://github.com/actions/runner-images/issues/8157
gid=$(cut -d ":" -f 3 /etc/group | grep "^1..$" | sort -n | tail -n 1 | awk '{ print $1+1 }')
groupmod -g "$gid" docker
# Create systemd-tmpfiles configuration for Docker
cat <<EOF | sudo tee /etc/tmpfiles.d/docker.conf
L /run/docker.sock - - - - root docker 0770
EOF
# Reload systemd-tmpfiles to apply the new configuration
systemd-tmpfiles --create /etc/tmpfiles.d/docker.conf
# Enable docker.service
systemctl is-active --quiet docker.service || systemctl start docker.service
systemctl is-enabled --quiet docker.service || systemctl enable docker.service
# Docker daemon takes time to come up after installing
sleep 10
docker info
if [[ "${DOCKERHUB_PULL_IMAGES:-yes}" == "yes" ]]; then
# If credentials are provided, attempt to log into Docker Hub
# with a paid account to avoid Docker Hub's rate limit.
if [[ "${DOCKERHUB_LOGIN}" ]] && [[ "${DOCKERHUB_PASSWORD}" ]]; then
docker login --username "${DOCKERHUB_LOGIN}" --password "${DOCKERHUB_PASSWORD}"
fi
# Pull images
images=$(get_toolset_value '.docker.images[]')
for image in $images; do
docker pull "$image"
done
# Always attempt to logout so we do not leave our credentials on the built
# image. Logout _should_ return a zero exit code even if no credentials were
# stored from earlier.
docker logout
else
echo "Skipping docker images pulling"
fi
# Download amazon-ecr-credential-helper
aws_latest_release_url="https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/releases/latest"
aws_helper_url=$(curl -fsSL "${aws_latest_release_url}" | jq -r '.body' | awk -F'[()]' '/linux-amd64/ {print $2}')
aws_helper_binary_path=$(download_with_retry "$aws_helper_url")
# Supply chain security - amazon-ecr-credential-helper
aws_helper_external_hash=$(get_checksum_from_url "${aws_helper_url}.sha256" "docker-credential-ecr-login" "SHA256")
use_checksum_comparison "$aws_helper_binary_path" "$aws_helper_external_hash"
# Install amazon-ecr-credential-helper
install "$aws_helper_binary_path" "/usr/bin/docker-credential-ecr-login"
# Cleanup custom repositories
rm $GPG_KEY
rm $REPO_PATH
invoke_tests "Tools" "Docker"
if [[ "${DOCKERHUB_PULL_IMAGES:-yes}" == "yes" ]]; then
invoke_tests "Tools" "Docker images"
fi
@@ -0,0 +1,100 @@
#!/bin/bash -e
################################################################################
## File: install-dotnetcore-sdk.sh
## Desc: Install .NET Core SDK
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/os.sh
extract_dotnet_sdk() {
local archive_name=$1
set -e
destination="./tmp-$(basename -s .tar.gz $archive_name)"
echo "Extracting $archive_name to $destination"
mkdir "$destination" && tar -C "$destination" -xzf "$archive_name"
rsync -qav --remove-source-files "$destination/shared/" /usr/share/dotnet/shared/
rsync -qav --remove-source-files "$destination/host/" /usr/share/dotnet/host/
rsync -qav --remove-source-files "$destination/sdk/" /usr/share/dotnet/sdk/
rm -rf "$destination" "$archive_name"
}
# Ubuntu 20 doesn't support EOL versions
latest_dotnet_packages=$(get_toolset_value '.dotnet.aptPackages[]')
dotnet_versions=$(get_toolset_value '.dotnet.versions[]')
dotnet_tools=$(get_toolset_value '.dotnet.tools[].name')
# Disable telemetry
export DOTNET_CLI_TELEMETRY_OPTOUT=1
# Install .NET SDK from apt
# There is a versions conflict, that leads to
# Microsoft <-> Canonical repos dependencies mix up.
# Give Microsoft's repo higher priority to avoid collisions.
# See: https://github.com/dotnet/core/issues/7699
cat << EOF > /etc/apt/preferences.d/dotnet
Package: *net*
Pin: origin packages.microsoft.com
Pin-Priority: 1001
EOF
apt-get update
for latest_package in ${latest_dotnet_packages[@]}; do
echo "Determining if .NET Core ($latest_package) is installed"
if ! dpkg -S $latest_package &> /dev/null; then
echo "Could not find .NET Core ($latest_package), installing..."
apt-get install $latest_package
else
echo ".NET Core ($latest_package) is already installed"
fi
done
rm /etc/apt/preferences.d/dotnet
apt-get update
# Install .NET SDK from home repository
# Get list of all released SDKs from channels which are not end-of-life or preview
sdks=()
for version in ${dotnet_versions[@]}; do
release_url="https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/${version}/releases.json"
releases=$(cat "$(download_with_retry "$release_url")")
if [[ $version == "6.0" ]]; then
sdks=("${sdks[@]}" $(echo "${releases}" | jq -r 'first(.releases[].sdks[]?.version | select(contains("preview") or contains("rc") | not))'))
else
sdks=("${sdks[@]}" $(echo "${releases}" | jq -r '.releases[].sdk.version | select(contains("preview") or contains("rc") | not)'))
sdks=("${sdks[@]}" $(echo "${releases}" | jq -r '.releases[].sdks[]?.version | select(contains("preview") or contains("rc") | not)'))
fi
done
sorted_sdks=$(echo ${sdks[@]} | tr ' ' '\n' | sort -r | uniq -w 5)
# Download/install additional SDKs in parallel
export -f download_with_retry
export -f extract_dotnet_sdk
parallel --jobs 0 --halt soon,fail=1 \
'url="https://dotnetcli.blob.core.windows.net/dotnet/Sdk/{}/dotnet-sdk-{}-linux-x64.tar.gz"; \
download_with_retry $url' ::: "${sorted_sdks[@]}"
find . -name "*.tar.gz" | parallel --halt soon,fail=1 'extract_dotnet_sdk {}'
# NuGetFallbackFolder at /usr/share/dotnet/sdk/NuGetFallbackFolder is warmed up by smoke test
# Additional FTE will just copy to ~/.dotnet/NuGet which provides no benefit on a fungible machine
set_etc_environment_variable DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
set_etc_environment_variable DOTNET_NOLOGO 1
set_etc_environment_variable DOTNET_MULTILEVEL_LOOKUP 0
prepend_etc_environment_path '$HOME/.dotnet/tools'
# Install .Net tools
for dotnet_tool in ${dotnet_tools[@]}; do
echo "Installing dotnet tool $dotnet_tool"
dotnet tool install $dotnet_tool --tool-path '/etc/skel/.dotnet/tools'
done
invoke_tests "DotnetSDK"
@@ -0,0 +1,29 @@
#!/bin/bash -e
################################################################################
## File: install-erlang.sh
## Desc: Install erlang and rebar3
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source_list=/etc/apt/sources.list.d/eslerlang.list
source_key=/usr/share/keyrings/eslerlang.gpg
# Install Erlang
wget -q -O - https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc | gpg --dearmor > $source_key
echo "deb [signed-by=$source_key] https://packages.erlang-solutions.com/ubuntu $(lsb_release -cs) contrib" > $source_list
apt-get update
apt-get install --no-install-recommends esl-erlang
# Install rebar3
rebar3_url=$(resolve_github_release_asset_url "erlang/rebar3" "endswith(\"rebar3\")" "latest")
binary_path=$(download_with_retry "$rebar3_url")
install "$binary_path" /usr/local/bin/rebar3
# Clean up source list
rm $source_list
rm $source_key
invoke_tests "Tools" "erlang"
@@ -0,0 +1,48 @@
#!/bin/bash -e
################################################################################
## File: install-firefox.sh
## Desc: Install Firefox
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
# Mozillateam PPA is added manually because sometimes
# launchpad portal sends empty answer when trying to add it automatically
REPO_URL="http://ppa.launchpad.net/mozillateam/ppa/ubuntu"
GPG_FINGERPRINT="0ab215679c571d1c8325275b9bdb3d89ce49ec21"
GPG_KEY="/etc/apt/trusted.gpg.d/mozillateam_ubuntu_ppa.gpg"
REPO_PATH="/etc/apt/sources.list.d/mozillateam-ubuntu-ppa-focal.list"
# Install Firefox
curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x${GPG_FINGERPRINT}" | sudo gpg --dearmor -o $GPG_KEY
echo "deb $REPO_URL $(lsb_release -cs) main" > $REPO_PATH
apt-get update
apt-get install --target-release 'o=LP-PPA-mozillateam' firefox
rm $REPO_PATH
# Document apt source repo's
echo "mozillateam $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt
# add to global system preferences for firefox locale en_US, because other browsers have en_US local.
# Default firefox local is en_GB
echo 'pref("intl.locale.requested","en_US");' >> "/usr/lib/firefox/browser/defaults/preferences/syspref.js"
# Download and unpack latest release of geckodriver
download_url=$(resolve_github_release_asset_url "mozilla/geckodriver" "test(\"linux64.tar.gz$\")" "latest")
driver_archive_path=$(download_with_retry "$download_url")
GECKODRIVER_DIR="/usr/local/share/gecko_driver"
GECKODRIVER_BIN="$GECKODRIVER_DIR/geckodriver"
mkdir -p $GECKODRIVER_DIR
tar -xzf "$driver_archive_path" -C $GECKODRIVER_DIR
chmod +x $GECKODRIVER_BIN
ln -s "$GECKODRIVER_BIN" /usr/bin/
set_etc_environment_variable "GECKOWEBDRIVER" "${GECKODRIVER_DIR}"
invoke_tests "Browsers" "Firefox"
@@ -0,0 +1,17 @@
#!/bin/bash -e
################################################################################
## File: install-gcc-compilers.sh
## Desc: Install GNU C++ compilers
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
versions=$(get_toolset_value '.gcc.versions[]')
for version in ${versions[*]}; do
echo "Installing $version..."
apt-get install $version
done
invoke_tests "Tools" "gcc"
@@ -0,0 +1,20 @@
#!/bin/bash -e
################################################################################
## File: install-gfortran.sh
## Desc: Install GNU Fortran
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
versions=$(get_toolset_value '.gfortran.versions[]')
for version in ${versions[*]}; do
echo "Installing $version..."
apt-get install $version
done
echo "Install versionless gfortran (latest)"
apt-get install gfortran
invoke_tests "Tools" "gfortran"
@@ -0,0 +1,22 @@
#!/bin/bash -e
################################################################################
## File: install-git-lfs.sh
## Desc: Install Git-lfs
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
GIT_LFS_REPO="https://packagecloud.io/install/repositories/github/git-lfs"
# Install git-lfs
curl -fsSL $GIT_LFS_REPO/script.deb.sh | bash
apt-get install git-lfs
# Remove source repo's
rm /etc/apt/sources.list.d/github_git-lfs.list
# Document apt source repo's
echo "git-lfs $GIT_LFS_REPO" >> $HELPER_SCRIPTS/apt-sources.txt
invoke_tests "Tools" "Git-lfs"
@@ -0,0 +1,36 @@
#!/bin/bash -e
################################################################################
## File: install-git.sh
## Desc: Install Git and Git-FTP
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
GIT_REPO="ppa:git-core/ppa"
## Install git
add-apt-repository $GIT_REPO -y
apt-get update
apt-get install git
# Git version 2.35.2 introduces security fix that breaks action\checkout https://github.com/actions/checkout/issues/760
cat <<EOF >> /etc/gitconfig
[safe]
directory = *
EOF
# Install git-ftp
apt-get install git-ftp
# Remove source repo's
add-apt-repository --remove $GIT_REPO
# Document apt source repo's
echo "git-core $GIT_REPO" >> $HELPER_SCRIPTS/apt-sources.txt
# Add well-known SSH host keys to known_hosts
ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa ssh.dev.azure.com >> /etc/ssh/ssh_known_hosts
invoke_tests "Tools" "Git"
@@ -0,0 +1,24 @@
#!/bin/bash -e
################################################################################
## File: install-github-cli.sh
## Desc: Install GitHub CLI
## Must be run as non-root user after homebrew
## Supply chain security: GitHub CLI - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Download GitHub CLI
gh_cli_url=$(resolve_github_release_asset_url "cli/cli" "contains(\"linux\") and contains(\"amd64\") and endswith(\".deb\")" "latest")
gh_cli_deb_path=$(download_with_retry "$gh_cli_url")
# Supply chain security - GitHub CLI
hash_url=$(resolve_github_release_asset_url "cli/cli" "endswith(\"checksums.txt\")" "latest")
external_hash=$(get_checksum_from_url "$hash_url" "linux_amd64.deb" "SHA256")
use_checksum_comparison "$gh_cli_deb_path" "$external_hash"
# Install GitHub CLI
apt-get install "$gh_cli_deb_path"
invoke_tests "CLI.Tools" "GitHub CLI"
@@ -0,0 +1,86 @@
#!/bin/bash -e
################################################################################
## File: install-google-chrome.sh
## Desc: Install google-chrome, chromedriver and chromium
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
get_chromium_revision() {
local chrome_revision=$1
# Take the first part of the revision variable to search not only for a specific version,
# but also for similar ones, so that we can get a previous one if the required revision is not found
chrome_revision_prefix=${chrome_revision:0:${#chrome_revision}/2+1}
SEARCH_URL="https://www.googleapis.com/storage/v1/b/chromium-browser-snapshots/o?delimiter=/&prefix=Linux_x64"
# Revision can include a hash instead of a number. Need to filter it out https://github.com/actions/runner-images/issues/5256
revisions_available=$(curl -s $SEARCH_URL/${chrome_revision_prefix} | jq -r '.prefixes[]' | grep -E "Linux_x64\/[0-9]+\/"| cut -d "/" -f 2 | sort --version-sort)
# If required Chromium revision is not found in the list
# we should have to decrement the revision number until we find one.
# This is mentioned in the documentation we use for this installation:
# https://www.chromium.org/getting-involved/download-chromium
latest_valid_revision=$(echo $revisions_available | cut -f 1 -d " ")
for revision in $revisions_available; do
if [ "$chrome_revision" -lt "$revision" ]; then
break
fi
latest_valid_revision=$revision
done
echo $latest_valid_revision
}
# Download and install Google Chrome
CHROME_DEB_URL="https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
chrome_deb_path=$(download_with_retry "$CHROME_DEB_URL")
apt-get install "$chrome_deb_path" -f
set_etc_environment_variable "CHROME_BIN" "/usr/bin/google-chrome"
# Remove Google Chrome repo
rm -f /etc/cron.daily/google-chrome /etc/apt/sources.list.d/google-chrome.list /etc/apt/sources.list.d/google-chrome.list.save
# Parse Google Chrome version
full_chrome_version=$(google-chrome --product-version)
chrome_version=${full_chrome_version%.*}
echo "Chrome version is $full_chrome_version"
# Get chrome versions information
CHROME_PLATFORM="linux64"
CHROME_VERSIONS_URL="https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build-with-downloads.json"
chrome_versions_json=$(curl -fsSL "${CHROME_VERSIONS_URL}")
# Download and unpack the latest release of chromedriver
chromedriver_version=$(echo "${chrome_versions_json}" | jq -r '.builds["'"$chrome_version"'"].version')
chromedriver_url=$(echo "${chrome_versions_json}" | jq -r '.builds["'"$chrome_version"'"].downloads.chromedriver[] | select(.platform=="'"${CHROME_PLATFORM}"'").url')
CHROMEDRIVER_DIR="/usr/local/share/chromedriver-linux64"
chromedriver_bin="$CHROMEDRIVER_DIR/chromedriver"
echo "Installing chromedriver version $chromedriver_version"
driver_archive_path=$(download_with_retry "$chromedriver_url")
unzip -qq "$driver_archive_path" -d /usr/local/share
chmod +x $chromedriver_bin
ln -s "$chromedriver_bin" /usr/bin/
set_etc_environment_variable "CHROMEWEBDRIVER" "${CHROMEDRIVER_DIR}"
# Download and unpack Chromium
chrome_revision=$(echo "${chrome_versions_json}" | jq -r '.builds["'"$chrome_version"'"].revision')
chromium_revision=$(get_chromium_revision $chrome_revision)
chromium_url="https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64%2F${chromium_revision}%2Fchrome-linux.zip?alt=media"
CHROMIUM_DIR="/usr/local/share/chromium"
chromium_bin="${CHROMIUM_DIR}/chrome-linux/chrome"
echo "Installing chromium revision $chromium_revision"
chromium_archive_path=$(download_with_retry "$chromium_url")
mkdir $CHROMIUM_DIR
unzip -qq "$chromium_archive_path" -d $CHROMIUM_DIR
ln -s $chromium_bin /usr/bin/chromium
ln -s $chromium_bin /usr/bin/chromium-browser
invoke_tests "Browsers" "Chrome"
invoke_tests "Browsers" "Chromium"
@@ -0,0 +1,22 @@
#!/bin/bash -e
################################################################################
## File: install-google-cloud-cli.sh
## Desc: Install the Google Cloud CLI
################################################################################
REPO_URL="https://packages.cloud.google.com/apt"
# Install the Google Cloud CLI
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] $REPO_URL cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list
wget -qO- https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor > /usr/share/keyrings/cloud.google.gpg
apt-get update
apt-get install google-cloud-cli
# remove apt
rm /etc/apt/sources.list.d/google-cloud-sdk.list
rm /usr/share/keyrings/cloud.google.gpg
# add repo to the apt-sources.txt
echo "google-cloud-sdk $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt
invoke_tests "CLI.Tools" "Google Cloud CLI"
@@ -0,0 +1,44 @@
#!/bin/bash -e
################################################################################
## File: install-haskell.sh
## Desc: Install Haskell, GHCup, Cabal and Stack
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
# Any nonzero value for non-interactive installation
export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
export BOOTSTRAP_HASKELL_INSTALL_NO_STACK_HOOK=1
export GHCUP_INSTALL_BASE_PREFIX=/usr/local
export BOOTSTRAP_HASKELL_GHC_VERSION=0
ghcup_bin=$GHCUP_INSTALL_BASE_PREFIX/.ghcup/bin
set_etc_environment_variable "BOOTSTRAP_HASKELL_NONINTERACTIVE" $BOOTSTRAP_HASKELL_NONINTERACTIVE
set_etc_environment_variable "GHCUP_INSTALL_BASE_PREFIX" $GHCUP_INSTALL_BASE_PREFIX
# Install GHCup
curl --proto '=https' --tlsv1.2 -fsSL https://get-ghcup.haskell.org | sh > /dev/null 2>&1 || true
export PATH="$ghcup_bin:$PATH"
prepend_etc_environment_path $ghcup_bin
available_versions=$(ghcup list -t ghc -r | grep -v "prerelease" | awk '{print $2}')
# Install 2 latest Haskell Major.Minor versions
major_minor_versions=$(echo "$available_versions" | cut -d"." -f 1,2 | uniq | tail -n2)
for major_minor_version in $major_minor_versions; do
full_version=$(echo "$available_versions" | grep "$major_minor_version." | tail -n1)
echo "install ghc version $full_version..."
ghcup install ghc $full_version
ghcup set ghc $full_version
done
echo "install cabal..."
ghcup install cabal latest
chmod -R 777 $GHCUP_INSTALL_BASE_PREFIX/.ghcup
ln -s $GHCUP_INSTALL_BASE_PREFIX/.ghcup /etc/skel/.ghcup
# Install the latest stable release of haskell stack
curl -fsSL https://get.haskellstack.org/ | bash
invoke_tests "Haskell"
@@ -0,0 +1,23 @@
#!/bin/bash -e
################################################################################
## File: install-heroku.sh
## Desc: Install Heroku CLI. Based on instructions found here: https://devcenter.heroku.com/articles/heroku-cli
################################################################################
REPO_URL="https://cli-assets.heroku.com/channels/stable/apt"
GPG_KEY="/usr/share/keyrings/heroku.gpg"
REPO_PATH="/etc/apt/sources.list.d/heroku.list"
# add heroku repository to apt
curl -fsSL "${REPO_URL}/release.key" | gpg --dearmor -o $GPG_KEY
echo "deb [trusted=yes] $REPO_URL ./" > $REPO_PATH
# install heroku
apt-get update
apt-get install heroku
# remove heroku's apt repository
rm $REPO_PATH
rm $GPG_KEY
invoke_tests "Tools" "Heroku"
@@ -0,0 +1,23 @@
#!/bin/bash -e
################################################################################
## File: install-hhvm.sh
## Desc: Install HHVM
################################################################################
REPO_URL="https://dl.hhvm.com/ubuntu"
GPG_KEY="/usr/share/keyrings/hhvm.gpg"
REPO_PATH="/etc/apt/sources.list.d/hhvm.list"
# add HHVM repository to apt
curl -fsSL https://dl.hhvm.com/conf/hhvm.gpg.key | gpg --dearmor -o $GPG_KEY
echo "deb [signed-by=$GPG_KEY] $REPO_URL $(lsb_release -cs) main" > $REPO_PATH
# install HHVM
apt-get update
apt-get install hhvm
# remove HHVM's apt repository
rm $REPO_PATH
rm $GPG_KEY
invoke_tests "Tools" "HHVM"
@@ -0,0 +1,31 @@
#!/bin/bash -e
################################################################################
## File: install-homebrew.sh
## Desc: Install Homebrew on Linux
## Caveat: Brew MUST NOT be used to install any tool during the image build to avoid dependencies, which may come along with the tool
################################################################################
# Source the helpers
source $HELPER_SCRIPTS/etc-environment.sh
source $HELPER_SCRIPTS/install.sh
# Install the Homebrew on Linux
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
# Invoke shellenv to make brew available during running session
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
set_etc_environment_variable HOMEBREW_NO_AUTO_UPDATE 1
set_etc_environment_variable HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS 3650
# Validate the installation ad hoc
echo "Validate the installation reloading /etc/environment"
reload_etc_environment
gfortran=$(brew --prefix)/bin/gfortran
# Remove gfortran symlink, not to conflict with system gfortran
if [[ -e $gfortran ]]; then
rm $gfortran
fi
invoke_tests "Tools" "Homebrew"
@@ -0,0 +1,119 @@
#!/bin/bash -e
################################################################################
## File: install-java-tools.sh
## Desc: Install Java and related tooling (Ant, Gradle, Maven)
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
create_java_environment_variable() {
local java_version=$1
local default=$2
local install_path_pattern="/usr/lib/jvm/temurin-${java_version}-jdk-amd64"
if [[ ${default} == "True" ]]; then
echo "Setting up JAVA_HOME variable to ${install_path_pattern}"
set_etc_environment_variable "JAVA_HOME" "${install_path_pattern}"
echo "Setting up default symlink"
update-java-alternatives -s ${install_path_pattern}
fi
echo "Setting up JAVA_HOME_${java_version}_X64 variable to ${install_path_pattern}"
set_etc_environment_variable "JAVA_HOME_${java_version}_X64" "${install_path_pattern}"
}
install_open_jdk() {
local java_version=$1
# Install Java from PPA repositories.
apt-get -y install temurin-${java_version}-jdk=\*
java_version_path="/usr/lib/jvm/temurin-${java_version}-jdk-amd64"
java_toolcache_path="${AGENT_TOOLSDIRECTORY}/Java_Temurin-Hotspot_jdk"
full_java_version=$(cat "${java_version_path}/release" | grep "^SEMANTIC" | cut -d "=" -f 2 | tr -d "\"" | tr "+" "-")
# If there is no semver in java release, then extract java version from -fullversion
[[ -z ${full_java_version} ]] && full_java_version=$(${java_version_path}/bin/java -fullversion 2>&1 | tr -d "\"" | tr "+" "-" | awk '{print $4}')
# Convert non valid semver like 11.0.14.1-9 -> 11.0.14-9
# https://github.com/adoptium/temurin-build/issues/2248
[[ ${full_java_version} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ ]] && full_java_version=$(echo $full_java_version | sed -E 's/\.[0-9]+-/-/')
# When version string is too short, add extra ".0" to make it valid semver
[[ ${full_java_version} =~ ^[0-9]+- ]] && full_java_version=$(echo $full_java_version | sed -E 's/-/.0-/')
[[ ${full_java_version} =~ ^[0-9]+\.[0-9]+- ]] && full_java_version=$(echo $full_java_version | sed -E 's/-/.0-/')
java_toolcache_version_path="${java_toolcache_path}/${full_java_version}"
echo "Java ${java_version} Toolcache Version Path: ${java_toolcache_version_path}"
mkdir -p "${java_toolcache_version_path}"
# Create a complete file
touch "${java_toolcache_version_path}/x64.complete"
# Create symlink for Java
ln -s ${java_version_path} "${java_toolcache_version_path}/x64"
# add extra permissions to be able execute command without sudo
chmod -R 777 /usr/lib/jvm
}
# Add Adoptium PPA
# apt-key is deprecated, dearmor and add manually
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor > /usr/share/keyrings/adoptium.gpg
echo "deb [signed-by=/usr/share/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb/ $(lsb_release -cs) main" > /etc/apt/sources.list.d/adoptium.list
# Get all the updates from enabled repositories.
apt-get update
# While Ubuntu 24.04 binaries are not released in the Adoptium repo, we will not install Java
defaultVersion=$(get_toolset_value '.java.default')
jdkVersionsToInstall=($(get_toolset_value ".java.versions[]"))
for jdkVersionToInstall in ${jdkVersionsToInstall[@]}; do
install_open_jdk ${jdkVersionToInstall}
if [[ ${jdkVersionToInstall} == ${defaultVersion} ]]
then
create_java_environment_variable ${jdkVersionToInstall} True
else
create_java_environment_variable ${jdkVersionToInstall} False
fi
done
# Install Ant
apt-get install --no-install-recommends ant ant-optional
set_etc_environment_variable "ANT_HOME" "/usr/share/ant"
# Install Maven
mavenVersion=$(get_toolset_value '.java.maven')
mavenDownloadUrl="https://dlcdn.apache.org/maven/maven-3/${mavenVersion}/binaries/apache-maven-${mavenVersion}-bin.zip"
maven_archive_path=$(download_with_retry "$mavenDownloadUrl")
unzip -qq -d /usr/share "$maven_archive_path"
ln -s /usr/share/apache-maven-${mavenVersion}/bin/mvn /usr/bin/mvn
# Install Gradle
# This script founds the latest gradle release from https://services.gradle.org/versions/all
# The release is downloaded, extracted, a symlink is created that points to it, and GRADLE_HOME is set.
gradleJson=$(curl -fsSL https://services.gradle.org/versions/all)
gradleLatestVersion=$(echo ${gradleJson} | jq -r '.[] | select(.version | contains("-") | not).version' | sort -V | tail -n1)
gradleDownloadUrl=$(echo ${gradleJson} | jq -r ".[] | select(.version==\"$gradleLatestVersion\") | .downloadUrl")
echo "gradleUrl=${gradleDownloadUrl}"
echo "gradleVersion=${gradleLatestVersion}"
gradle_archive_path=$(download_with_retry "$gradleDownloadUrl")
unzip -qq -d /usr/share "$gradle_archive_path"
ln -s /usr/share/gradle-"${gradleLatestVersion}"/bin/gradle /usr/bin/gradle
gradle_home_dir=$(find /usr/share -depth -maxdepth 1 -name "gradle*")
set_etc_environment_variable "GRADLE_HOME" "${gradle_home_dir}"
# Delete java repositories and keys
rm -f /etc/apt/sources.list.d/adoptium.list
rm -f /etc/apt/sources.list.d/zulu.list
rm -f /usr/share/keyrings/adoptium.gpg
rm -f /usr/share/keyrings/zulu.gpg
reload_etc_environment
invoke_tests "Java"
@@ -0,0 +1,24 @@
#!/bin/bash -e
################################################################################
## File: install-julia.sh
## Desc: Install Julia and add to the path
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# get the latest julia version
json=$(curl -fsSL "https://julialang-s3.julialang.org/bin/versions.json")
julia_version=$(echo $json | jq -r '.[].files[] | select(.triplet=="x86_64-linux-gnu" and (.version | contains("-") | not)).version' | sort -V | tail -n1)
# download julia archive
julia_tar_url=$(echo $json | jq -r ".[].files[].url | select(endswith(\"julia-${julia_version}-linux-x86_64.tar.gz\"))")
julia_archive_path=$(download_with_retry "$julia_tar_url")
# extract files and make symlink
julia_installation_path="/usr/local/julia${julia_version}"
mkdir -p "${julia_installation_path}"
tar -C "${julia_installation_path}" -xzf "$julia_archive_path" --strip-components=1
ln -s "${julia_installation_path}/bin/julia" /usr/bin/julia
invoke_tests "Tools" "Julia"
@@ -0,0 +1,24 @@
#!/bin/bash -e
################################################################################
## File: install-kotlin.sh
## Desc: Install Kotlin
## Supply chain security: Kotlin - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
KOTLIN_ROOT="/usr/share"
download_url=$(resolve_github_release_asset_url "JetBrains/kotlin" "contains(\"kotlin-compiler\") and endswith(\".zip\")" "latest")
archive_path=$(download_with_retry "$download_url")
# Supply chain security - Kotlin
kotlin_hash_file=$(download_with_retry "${download_url}.sha256")
kotlin_hash=$(cat "$kotlin_hash_file")
use_checksum_comparison "$archive_path" "$kotlin_hash"
unzip -qq "$archive_path" -d $KOTLIN_ROOT
rm $KOTLIN_ROOT/kotlinc/bin/*.bat
ln -sf $KOTLIN_ROOT/kotlinc/bin/* /usr/bin
invoke_tests "Tools" "Kotlin"
@@ -0,0 +1,48 @@
#!/bin/bash -e
################################################################################
## File: install-kubernetes-tools.sh
## Desc: Installs kubectl, helm, kustomize
## Supply chain security: KIND, minikube - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Download KIND
kind_url=$(resolve_github_release_asset_url "kubernetes-sigs/kind" "endswith(\"kind-linux-amd64\")" "latest")
kind_binary_path=$(download_with_retry "${kind_url}")
# Supply chain security - KIND
kind_external_hash=$(get_checksum_from_url "${kind_url}.sha256sum" "kind-linux-amd64" "SHA256")
use_checksum_comparison "${kind_binary_path}" "${kind_external_hash}"
# Install KIND
install "${kind_binary_path}" /usr/local/bin/kind
## Install kubectl
kubectl_minor_version=$(curl -fsSL "https://dl.k8s.io/release/stable.txt" | cut -d'.' -f1,2 )
curl -fsSL https://pkgs.k8s.io/core:/stable:/$kubectl_minor_version/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/'$kubectl_minor_version'/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install kubectl
rm -f /etc/apt/sources.list.d/kubernetes.list
# Install Helm
curl -fsSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
# Download minikube
curl -fsSL -O https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
# Supply chain security - minikube
minikube_hash=$(get_checksum_from_github_release "kubernetes/minikube" "linux-amd64" "latest" "SHA256")
use_checksum_comparison "minikube-linux-amd64" "${minikube_hash}"
# Install minikube
install minikube-linux-amd64 /usr/local/bin/minikube
# Install kustomize
download_url="https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
curl -fsSL "$download_url" | bash
mv kustomize /usr/local/bin
invoke_tests "Tools" "Kubernetes tools"
@@ -0,0 +1,22 @@
#!/bin/bash -e
################################################################################
## File: install-leiningen.sh
## Desc: Install Leiningen
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
LEIN_BIN=/usr/local/bin/lein
curl -fsSL https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > $LEIN_BIN
chmod 0755 $LEIN_BIN
# Run lein to trigger self-install
export LEIN_HOME=/usr/local/lib/lein
lein
LEIN_JAR=$(find $LEIN_HOME -name "leiningen-*-standalone.jar")
set_etc_environment_variable "LEIN_JAR" "${LEIN_JAR}"
set_etc_environment_variable "LEIN_HOME" "${LEIN_HOME}"
invoke_tests "Tools" "Leiningen"
@@ -0,0 +1,50 @@
#!/bin/bash -e
################################################################################
## File: install-microsoft-edge.sh
## Desc: Install Microsoft Edge and WebDriver
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
REPO_URL="https://packages.microsoft.com/repos/edge"
GPG_KEY="/usr/share/keyrings/microsoft-edge.gpg"
REPO_PATH="/etc/apt/sources.list.d/microsoft-edge.list"
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > $GPG_KEY
# Specify an arch as Microsoft repository supports armhf and arm64 as well
echo "deb [arch=amd64 signed-by=$GPG_KEY] $REPO_URL stable main" > $REPO_PATH
apt-get update
apt-get install --no-install-recommends microsoft-edge-stable
rm $GPG_KEY
rm $REPO_PATH
echo "microsoft-edge $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt
# Install Microsoft Edge Webdriver
EDGEDRIVER_DIR="/usr/local/share/edge_driver"
edgedriver_bin="$EDGEDRIVER_DIR/msedgedriver"
mkdir -p $EDGEDRIVER_DIR
edge_version=$(microsoft-edge --version | cut -d' ' -f 3)
edge_version_major=$(echo $edge_version | cut -d'.' -f 1)
edgedriver_version_url="https://msedgedriver.azureedge.net/LATEST_RELEASE_${edge_version_major}_LINUX"
# Convert a resulting file to normal UTF-8
edgedriver_latest_version=$(curl -fsSL "$edgedriver_version_url" | iconv -f utf-16 -t utf-8 | tr -d '\r')
edgedriver_url="https://msedgedriver.azureedge.net/${edgedriver_latest_version}/edgedriver_linux64.zip"
edgedriver_archive_path=$(download_with_retry "$edgedriver_url")
unzip -qq "$edgedriver_archive_path" -d "$EDGEDRIVER_DIR"
chmod +x $edgedriver_bin
ln -s $edgedriver_bin /usr/bin
set_etc_environment_variable "EDGEWEBDRIVER" "${EDGEDRIVER_DIR}"
invoke_tests "Browsers" "Edge"
@@ -0,0 +1,21 @@
#!/bin/bash -e
################################################################################
## File: install-miniconda.sh
## Desc: Install miniconda
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
# Install Miniconda
curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda.sh \
&& chmod +x miniconda.sh \
&& ./miniconda.sh -b -p /usr/share/miniconda \
&& rm miniconda.sh
CONDA=/usr/share/miniconda
set_etc_environment_variable "CONDA" "${CONDA}"
ln -s $CONDA/bin/conda /usr/bin/conda
invoke_tests "Tools" "Conda"
@@ -0,0 +1,30 @@
#!/bin/bash -e
################################################################################
## File: install-mongodb.sh
## Desc: Install Mongo DB
################################################################################
# Source the helpers
source $HELPER_SCRIPTS/install.sh
toolset_version=$(get_toolset_value '.mongodb.version')
REPO_URL="https://repo.mongodb.org/apt/ubuntu"
GPG_KEY="/usr/share/keyrings/mongodb-org-$toolset_version.gpg"
REPO_PATH="/etc/apt/sources.list.d/mongodb-org-$toolset_version.list"
# add Mongo DB repository to apt
curl -fsSL https://www.mongodb.org/static/pgp/server-$toolset_version.asc | gpg --dearmor -o $GPG_KEY
echo "deb [ arch=amd64,arm64 signed-by=$GPG_KEY ] $REPO_URL $(lsb_release -cs)/mongodb-org/$toolset_version multiverse" > $REPO_PATH
# Install Mongo DB
sudo apt-get update
sudo apt-get install mongodb-org
# remove Mongo DB's apt repository
rm $REPO_PATH
rm $GPG_KEY
# Document source repo
echo "mongodb $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt
invoke_tests "Databases" "MongoDB"
@@ -0,0 +1,36 @@
#!/bin/bash -e
################################################################################
## File: install-mono.sh
## Desc: Install Mono
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
os_label=$(lsb_release -cs)
REPO_URL="https://download.mono-project.com/repo/ubuntu"
GPG_KEY="/usr/share/keyrings/mono-official-stable.gpg"
REPO_PATH="/etc/apt/sources.list.d/mono-official-stable.list"
# There are no packages for Ubuntu 22 in the repo, but developers confirmed that packages from Ubuntu 20 should work
if is_ubuntu22; then
os_label="focal"
fi
# Install Mono repo
curl -fsSL https://download.mono-project.com/repo/xamarin.gpg | gpg --dearmor -o $GPG_KEY
echo "deb [signed-by=$GPG_KEY] $REPO_URL stable-$os_label main" > $REPO_PATH
# Install Mono
apt-get update
apt-get install --no-install-recommends apt-transport-https mono-complete nuget
# Remove Mono's apt repo
rm $REPO_PATH
rm -f "${REPO_PATH}.save"
rm $GPG_KEY
# Document source repo
echo "mono https://download.mono-project.com/repo/ubuntu stable-$os_label main" >> $HELPER_SCRIPTS/apt-sources.txt
invoke_tests "Tools" "Mono"
@@ -0,0 +1,16 @@
#!/bin/bash -e
################################################################################
## File: install-ms-repos.sh
## Desc: Install official Microsoft package repos for the distribution
################################################################################
os_label=$(lsb_release -rs)
# Install Microsoft repository
wget https://packages.microsoft.com/config/ubuntu/$os_label/packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb
# update
apt-get install apt-transport-https ca-certificates curl software-properties-common
apt-get update
apt-get dist-upgrade
@@ -0,0 +1,14 @@
#!/bin/bash -e
################################################################################
## File: install-mssql-tools.sh
## Desc: Install MS SQL Server client tools (https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools?view=sql-server-2017)
################################################################################
export ACCEPT_EULA=Y
apt-get update
apt-get install mssql-tools unixodbc-dev
apt-get -f install
ln -s /opt/mssql-tools/bin/* /usr/local/bin/
invoke_tests "Tools" "MSSQLCommandLineTools"
@@ -0,0 +1,30 @@
#!/bin/bash -e
################################################################################
## File: install-mysql.sh
## Desc: Install MySQL Client
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
# Mysql setting up root password
MYSQL_ROOT_PASSWORD=root
echo "mysql-server mysql-server/root_password password $MYSQL_ROOT_PASSWORD" | debconf-set-selections
echo "mysql-server mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD" | debconf-set-selections
export ACCEPT_EULA=Y
# Install MySQL Client
apt-get install mysql-client
# Install MySQL Server
apt-get install mysql-server
# Install MySQL Dev tools
apt-get install libmysqlclient-dev
# Disable mysql.service
systemctl is-active --quiet mysql.service && systemctl stop mysql.service
systemctl disable mysql.service
invoke_tests "Databases" "MySQL"
@@ -0,0 +1,14 @@
#!/bin/bash -e
################################################################################
## File: install-nginx.sh
## Desc: Install Nginx
################################################################################
# Install Nginx
apt-get install nginx
# Disable nginx.service
systemctl is-active --quiet nginx.service && systemctl stop nginx.service
systemctl disable nginx.service
invoke_tests "WebServers" "Nginx"
@@ -0,0 +1,29 @@
#!/bin/bash -e
################################################################################
## File: install-nodejs.sh
## Desc: Install Node.js LTS and related tooling (Gulp, Grunt)
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Install default Node.js
default_version=$(get_toolset_value '.node.default')
curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n -o ~/n
bash ~/n $default_version
# Install node modules
node_modules=$(get_toolset_value '.node_modules[].name')
npm install -g $node_modules
echo "Creating the symlink for [now] command to vercel CLI"
ln -s /usr/local/bin/vercel /usr/local/bin/now
# fix global modules installation as regular user
# related issue https://github.com/actions/runner-images/issues/3727
sudo chmod -R 777 /usr/local/lib/node_modules
sudo chmod -R 777 /usr/local/bin
rm -rf ~/n
invoke_tests "Node" "Node.js"
@@ -0,0 +1,22 @@
#!/bin/bash -e
################################################################################
## File: install-nvm.sh
## Desc: Install Nvm
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
export NVM_DIR="/etc/skel/.nvm"
mkdir $NVM_DIR
nvm_version=$(curl -fsSL https://api.github.com/repos/nvm-sh/nvm/releases/latest | jq -r '.tag_name')
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/$nvm_version/install.sh | bash
set_etc_environment_variable "NVM_DIR" '$HOME/.nvm'
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' | tee -a /etc/skel/.bash_profile
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
invoke_tests "Tools" "nvm"
# set system node.js as default one
nvm alias default system
@@ -0,0 +1,24 @@
#!/bin/bash -e
################################################################################
## File: install-oc-cli.sh
## Desc: Install the OC CLI
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
if is_ubuntu20; then
toolset_version=$(get_toolset_value '.ocCli.version')
download_url="https://mirror.openshift.com/pub/openshift-v4/clients/ocp/$toolset_version/openshift-client-linux-$toolset_version.tar.gz"
else
# Install the oc CLI
download_url="https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-client-linux.tar.gz"
fi
archive_path=$(download_with_retry "$download_url")
tar xzf "$archive_path" -C "/usr/local/bin" oc
invoke_tests "CLI.Tools" "OC CLI"
@@ -0,0 +1,25 @@
#!/bin/bash -e
################################################################################
## File: install-oras-cli.sh
## Desc: Install ORAS CLI
## Supply chain security: ORAS CLI - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Determine latest ORAS CLI version
download_url=$(resolve_github_release_asset_url "oras-project/oras" "endswith(\"linux_amd64.tar.gz\")" "latest")
# Download ORAS CLI
archive_path=$(download_with_retry "$download_url")
# Supply chain security - ORAS CLI
hash_url=$(resolve_github_release_asset_url "oras-project/oras" "endswith(\"checksums.txt\")" "latest")
external_hash=$(get_checksum_from_url "${hash_url}" "linux_amd64.tar.gz" "SHA256")
use_checksum_comparison "$archive_path" "${external_hash}"
# Unzip ORAS CLI
tar xzf "$archive_path" -C /usr/local/bin oras
invoke_tests "CLI.Tools" "Oras CLI"
@@ -0,0 +1,15 @@
#!/bin/bash -e
################################################################################
## File: install-packer.sh
## Desc: Install packer
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Install Packer
download_url=$(curl -fsSL https://api.releases.hashicorp.com/v1/releases/packer/latest | jq -r '.builds[] | select((.arch=="amd64") and (.os=="linux")).url')
archive_path=$(download_with_retry "$download_url")
unzip -o -qq "$archive_path" -d /usr/local/bin
invoke_tests "Tools" "Packer"
@@ -0,0 +1,26 @@
#!/bin/bash -e
################################################################################
## File: install-phantomjs.sh
## Desc: Install PhantomJS
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Install required dependencies
apt-get install chrpath libssl-dev libxft-dev libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev
# Define the version and hash of PhantomJS to be installed
DIR_NAME=phantomjs-2.1.1-linux-x86_64
ARCHIVE_HASH="86dd9a4bf4aee45f1a84c9f61cf1947c1d6dce9b9e8d2a907105da7852460d2f"
# Download the archive and verify its integrity using checksum comparison
download_url="https://bitbucket.org/ariya/phantomjs/downloads/$DIR_NAME.tar.bz2"
archive_path=$(download_with_retry "$download_url")
use_checksum_comparison "$archive_path" "$ARCHIVE_HASH"
# Extract the archive and create a symbolic link to the executable
tar xjf "$archive_path" -C /usr/local/share
ln -sf /usr/local/share/$DIR_NAME/bin/phantomjs /usr/local/bin
invoke_tests "Tools" "Phantomjs"
+113
View File
@@ -0,0 +1,113 @@
#!/bin/bash -e
################################################################################
## File: install-php.sh
## Desc: Install php
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
# add repository for old Ubuntu images
# details in thread: https://github.com/actions/runner-images/issues/6331
if is_ubuntu20; then
apt-add-repository ppa:ondrej/php -y
apt-get update
fi
# Install PHP
php_versions=$(get_toolset_value '.php.versions[]')
for version in $php_versions; do
echo "Installing PHP $version"
apt-get install --no-install-recommends \
php$version \
php$version-amqp \
php$version-apcu \
php$version-bcmath \
php$version-bz2 \
php$version-cgi \
php$version-cli \
php$version-common \
php$version-curl \
php$version-dba \
php$version-dev \
php$version-enchant \
php$version-fpm \
php$version-gd \
php$version-gmp \
php$version-igbinary \
php$version-imagick \
php$version-imap \
php$version-interbase \
php$version-intl \
php$version-ldap \
php$version-mbstring \
php$version-memcache \
php$version-memcached \
php$version-mongodb \
php$version-mysql \
php$version-odbc \
php$version-opcache \
php$version-pgsql \
php$version-phpdbg \
php$version-pspell \
php$version-readline \
php$version-redis \
php$version-snmp \
php$version-soap \
php$version-sqlite3 \
php$version-sybase \
php$version-tidy \
php$version-xdebug \
php$version-xml \
php$version-xsl \
php$version-yaml \
php$version-zip \
php$version-zmq
apt-get install --no-install-recommends php$version-pcov
# Disable PCOV, as Xdebug is enabled by default
# https://github.com/krakjoe/pcov#interoperability
phpdismod -v $version pcov
if [[ $version == "7.2" || $version == "7.3" || $version == "7.4" ]]; then
apt-get install --no-install-recommends php$version-recode
fi
if [[ $version != "8.0" && $version != "8.1" && $version != "8.2" && $version != "8.3" ]]; then
apt-get install --no-install-recommends php$version-xmlrpc php$version-json
fi
done
apt-get install --no-install-recommends php-pear
apt-get install --no-install-recommends snmp
# Install composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === file_get_contents('https://composer.github.io/installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
sudo mv composer.phar /usr/bin/composer
php -r "unlink('composer-setup.php');"
# Add composer bin folder to path
prepend_etc_environment_path '$HOME/.config/composer/vendor/bin'
#Create composer folder for user to preserve folder permissions
mkdir -p /etc/skel/.composer
# Install phpunit (for PHP)
wget -q -O phpunit https://phar.phpunit.de/phpunit-8.phar
install phpunit /usr/local/bin/phpunit
# ubuntu 20.04 libzip-dev is libzip5 based and is not compatible libzip-dev of ppa:ondrej/php
# see https://github.com/actions/runner-images/issues/1084
if is_ubuntu20; then
rm /etc/apt/sources.list.d/ondrej-*.list
apt-get update
fi
invoke_tests "Common" "PHP"
@@ -0,0 +1,25 @@
#!/bin/bash -e
################################################################################
## File: install-pipx-packages.sh
## Desc: Install tools via pipx
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
export PATH="$PATH:/opt/pipx_bin"
pipx_packages=$(get_toolset_value ".pipx[] .package")
for package in $pipx_packages; do
echo "Install $package into default python"
pipx install $package
# https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html
# Install ansible into an existing ansible-core Virtual Environment
if [[ $package == "ansible-core" ]]; then
pipx inject $package ansible
fi
done
invoke_tests "Common" "PipxPackages"
@@ -0,0 +1,37 @@
#!/bin/bash -e
################################################################################
## File: install-postgresql.sh
## Desc: Install PostgreSQL
################################################################################
# Source the helpers
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
REPO_URL="https://apt.postgresql.org/pub/repos/apt/"
# Preparing repo for PostgreSQL
wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /usr/share/keyrings/postgresql.gpg
echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] $REPO_URL $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
# Fetch PostgreSQL version to install from the toolset
toolset_version=$(get_toolset_value '.postgresql.version')
# Install PostgreSQL
echo "Install PostgreSQL"
apt update
apt-get install postgresql-$toolset_version
echo "Install libpq-dev"
apt-get install libpq-dev
# Disable postgresql.service
systemctl is-active --quiet postgresql.service && systemctl stop postgresql.service
systemctl disable postgresql.service
rm /etc/apt/sources.list.d/pgdg.list
rm /usr/share/keyrings/postgresql.gpg
echo "postgresql $REPO_URL" >> $HELPER_SCRIPTS/apt-sources.txt
invoke_tests "Databases" "PostgreSQL"
@@ -0,0 +1,21 @@
#!/bin/bash -e
################################################################################
## File: install-powershell.sh
## Desc: Install PowerShell Core
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/os.sh
pwsh_version=$(get_toolset_value .pwsh.version)
# Install Powershell
if is_ubuntu24; then
dependency_path=$(download_with_retry "http://mirrors.kernel.org/ubuntu/pool/main/i/icu/libicu72_72.1-3ubuntu2_amd64.deb")
sudo dpkg -i "$dependency_path"
package_path=$(download_with_retry "https://github.com/PowerShell/PowerShell/releases/download/v7.4.2/powershell-lts_7.4.2-1.deb_amd64.deb")
sudo dpkg -i "$package_path"
else
apt-get install powershell=$pwsh_version*
fi
@@ -0,0 +1,23 @@
#!/bin/bash -e
################################################################################
## File: install-pulumi.sh
## Desc: Install Pulumi
## Supply chain security: Pulumi - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Dowload Pulumi
version=$(curl -fsSL "https://www.pulumi.com/latest-version")
download_url="https://get.pulumi.com/releases/sdk/pulumi-v${version}-linux-x64.tar.gz"
archive_path=$(download_with_retry "$download_url")
# Supply chain security - Pulumi
external_hash=$(get_checksum_from_url "https://github.com/pulumi/pulumi/releases/download/v${version}/SHA512SUMS" "linux-x64.tar.gz" "SHA512")
use_checksum_comparison "$archive_path" "$external_hash" "512"
# Unzipping Pulumi
tar --strip=1 -xf "$archive_path" -C /usr/local/bin
invoke_tests "Tools" "Pulumi"
@@ -0,0 +1,93 @@
#!/bin/bash -e
################################################################################
## File: install-pypy.sh
## Desc: Install PyPy
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# This function installs PyPy using the specified arguments:
# $1=package_url
install_pypy() {
local package_url=$1
package_tar_name=$(echo "$package_url" | awk -F/ '{print $NF}')
package_name=${package_tar_name/.tar.bz2/}
echo "Downloading tar archive '$package_name'"
package_tar_temp_path=$(download_with_retry $package_url)
echo "Expand '$package_name' to the /tmp folder"
tar xf "$package_tar_temp_path" -C /tmp
# Get Python version
major_version=$(echo ${package_name/pypy/} | cut -d. -f1)
python_major="python$major_version"
if [ $major_version != 2 ]; then
pypy_major="pypy$major_version"
else
pypy_major="pypy"
fi
package_temp_folder="/tmp/$package_name"
python_full_version=$("$package_temp_folder/bin/$pypy_major" -c "import sys;print('{}.{}.{}'.format(sys.version_info[0],sys.version_info[1],sys.version_info[2]))")
pypy_full_version=$("$package_temp_folder/bin/$pypy_major" -c "import sys;print('{}.{}.{}'.format(*sys.pypy_version_info[0:3]))")
echo "Put '$pypy_full_version' to PYPY_VERSION file"
echo $pypy_full_version > "$package_temp_folder/PYPY_VERSION"
# PyPy folder structure
pypy_toolcache_path=$AGENT_TOOLSDIRECTORY/PyPy
pypy_toolcache_version_path=$pypy_toolcache_path/$python_full_version
pypy_toolcache_version_arch_path=$pypy_toolcache_version_path/x64
echo "Check if PyPy hostedtoolcache folder exist..."
if [ ! -d $pypy_toolcache_path ]; then
mkdir -p $pypy_toolcache_path
fi
echo "Create PyPy '$pypy_toolcache_version_path' folder"
mkdir $pypy_toolcache_version_path
echo "Move PyPy '$package_temp_folder' binaries to '$pypy_toolcache_version_arch_path' folder"
mv $package_temp_folder $pypy_toolcache_version_arch_path
echo "Create additional symlinks (Required for UsePythonVersion Azure DevOps task)"
cd $pypy_toolcache_version_arch_path/bin
# Starting from PyPy 7.3.4 these links are already included in the package
[ -f ./$python_major ] || ln -s $pypy_major $python_major
[ -f ./python ] || ln -s $python_major python
chmod +x ./python ./$python_major
echo "Install latest Pip"
./python -m ensurepip
./python -m pip install --ignore-installed pip
echo "Create complete file"
touch $pypy_toolcache_version_path/x64.complete
echo "Remove '$package_tar_temp_path'"
rm -f $package_tar_temp_path
}
# Installation PyPy
pypy_versions_json=$(curl -fsSL https://downloads.python.org/pypy/versions.json)
toolset_versions=$(get_toolset_value '.toolcache[] | select(.name | contains("PyPy")) | .versions[]')
for toolset_version in $toolset_versions; do
latest_major_pypy_version=$(echo $pypy_versions_json |
jq -r --arg toolset_version $toolset_version '.[]
| select((.python_version | startswith($toolset_version)) and .stable == true).files[]
| select(.arch == "x64" and .platform == "linux").download_url' | head -1)
if [[ -z "$latest_major_pypy_version" ]]; then
echo "Failed to get PyPy version '$toolset_version'"
exit 1
fi
install_pypy $latest_major_pypy_version
done
chown -R "$SUDO_USER:$SUDO_USER" "$AGENT_TOOLSDIRECTORY/PyPy"
@@ -0,0 +1,40 @@
#!/bin/bash -e
################################################################################
## File: install-python.sh
## Desc: Install Python 3
################################################################################
set -e
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
source $HELPER_SCRIPTS/os.sh
# Install Python, Python 3, pip, pip3
apt-get install --no-install-recommends python3 python3-dev python3-pip python3-venv
# Install pipx
# Set pipx custom directory
export PIPX_BIN_DIR=/opt/pipx_bin
export PIPX_HOME=/opt/pipx
if is_ubuntu24; then
apt-get install --no-install-recommends pipx
pipx ensurepath
else
python3 -m pip install pipx
python3 -m pipx ensurepath
fi
# Update /etc/environment
set_etc_environment_variable "PIPX_BIN_DIR" $PIPX_BIN_DIR
set_etc_environment_variable "PIPX_HOME" $PIPX_HOME
prepend_etc_environment_path $PIPX_BIN_DIR
# Test pipx
if ! command -v pipx; then
echo "pipx was not installed or not found on PATH"
exit 1
fi
# Adding this dir to PATH will make installed pip commands are immediately available.
prepend_etc_environment_path '$HOME/.local/bin'
invoke_tests "Tools" "Python"
@@ -0,0 +1,19 @@
#!/bin/bash -e
################################################################################
## File: install-rlang.sh
## Desc: Install R
################################################################################
# install R
os_label=$(lsb_release -cs)
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | gpg --dearmor > /usr/share/keyrings/rlang.gpg
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
apt-get update
apt-get install r-base
rm /etc/apt/sources.list.d/rlang.list
rm /usr/share/keyrings/rlang.gpg
invoke_tests "Tools" "R"
@@ -0,0 +1,63 @@
#!/bin/bash -e
################################################################################
## File: install-ruby.sh
## Desc: Install Ruby requirements and ruby gems
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/os.sh
source $HELPER_SCRIPTS/install.sh
apt-get install ruby-full
# temporary fix for fastlane installation https://github.com/sporkmonger/addressable/issues/541
if is_ubuntu20; then
gem install public_suffix -v 5.1.1
fi
# Install ruby gems from toolset
gems_to_install=$(get_toolset_value ".rubygems[] .name")
if [[ -n "$gems_to_install" ]]; then
for gem in $gems_to_install; do
echo "Installing gem $gem"
gem install $gem
done
fi
# Install Ruby requirements
apt-get install libz-dev openssl libssl-dev
echo "Install Ruby from toolset..."
package_tar_names=$(curl -fsSL "https://api.github.com/repos/ruby/ruby-builder/releases/latest" | jq -r '.assets[].name')
toolset_versions=$(get_toolset_value '.toolcache[] | select(.name | contains("Ruby")) | .versions[]')
platform_version=$(get_toolset_value '.toolcache[] | select(.name | contains("Ruby")) | .platform_version')
ruby_path="$AGENT_TOOLSDIRECTORY/Ruby"
echo "Check if Ruby hostedtoolcache folder exist..."
if [[ ! -d $ruby_path ]]; then
mkdir -p $ruby_path
fi
for toolset_version in ${toolset_versions[@]}; do
package_tar_name=$(echo "$package_tar_names" | grep "^ruby-${toolset_version}-ubuntu-${platform_version}.tar.gz$" | sort -V | tail -1)
ruby_version=$(echo "$package_tar_name" | cut -d'-' -f 2)
ruby_version_path="$ruby_path/$ruby_version"
echo "Create Ruby $ruby_version directory..."
mkdir -p $ruby_version_path
echo "Downloading tar archive $package_tar_name"
download_url="https://github.com/ruby/ruby-builder/releases/download/toolcache/${package_tar_name}"
package_archive_path=$(download_with_retry "$download_url")
echo "Expand '$package_tar_name' to the '$ruby_version_path' folder"
tar xf "$package_archive_path" -C $ruby_version_path
complete_file_path="$ruby_version_path/x64.complete"
if [[ ! -f $complete_file_path ]]; then
echo "Create complete file"
touch $complete_file_path
fi
done
invoke_tests "Tools" "Ruby"
@@ -0,0 +1,15 @@
#!/bin/bash -e
################################################################################
## File: install-runner-package.sh
## Desc: Download and Install runner package
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
download_url=$(resolve_github_release_asset_url "actions/runner" 'test("actions-runner-linux-x64-[0-9]+\\.[0-9]{3}\\.[0-9]+\\.tar\\.gz$")' "latest")
archive_name="${download_url##*/}"
archive_path=$(download_with_retry "$download_url")
mkdir -p /opt/runner-cache
mv "$archive_path" "/opt/runner-cache/$archive_name"
@@ -0,0 +1,36 @@
#!/bin/bash -e
################################################################################
## File: install-rust.sh
## Desc: Install Rust
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
source $HELPER_SCRIPTS/os.sh
export RUSTUP_HOME=/etc/skel/.rustup
export CARGO_HOME=/etc/skel/.cargo
curl -fsSL https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal
# Initialize environment variables
source $CARGO_HOME/env
# Install common tools
rustup component add rustfmt clippy
if is_ubuntu22; then
cargo install bindgen-cli cbindgen cargo-audit cargo-outdated
fi
if is_ubuntu20; then
cargo install bindgen-cli cbindgen cargo-audit cargo-outdated
fi
# Cleanup Cargo cache
rm -rf ${CARGO_HOME}/registry/*
# Update /etc/environment
prepend_etc_environment_path '$HOME/.cargo/bin'
invoke_tests "Tools" "Rust"
@@ -0,0 +1,15 @@
#!/bin/bash -e
################################################################################
## File: install-sbt.sh
## Desc: Install sbt
################################################################################
source $HELPER_SCRIPTS/install.sh
# Install latest sbt release
download_url=$(resolve_github_release_asset_url "sbt/sbt" "endswith(\".tgz\")" "latest")
archive_path=$(download_with_retry "$download_url")
tar zxf "$archive_path" -C /usr/share
ln -s /usr/share/sbt/bin/sbt /usr/bin/sbt
invoke_tests "Tools" "Sbt"
@@ -0,0 +1,24 @@
#!/bin/bash -e
################################################################################
## File: install-selenium.sh
## Desc: Install selenium server
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
selenium_major_version=$(get_toolset_value '.selenium.version')
# Download Selenium server
selenium_download_url=$(resolve_github_release_asset_url "SeleniumHQ/selenium" "contains(\"selenium-server-\") and endswith(\".jar\")" "$selenium_major_version\.+" "" "true")
selenium_jar_path=$(download_with_retry "$selenium_download_url" "/usr/share/java/selenium-server.jar")
# Create an empty file to retrieve selenium version
selenium_full_version=$(echo $selenium_download_url | awk -F"selenium-server-|.jar" '{print $2}')
touch "/usr/share/java/selenium-server-$selenium_full_version"
# Add SELENIUM_JAR_PATH environment variable
set_etc_environment_variable "SELENIUM_JAR_PATH" "$selenium_jar_path"
invoke_tests "Tools" "Selenium"
@@ -0,0 +1,29 @@
#!/bin/bash -e
################################################################################
## File: install-sqlpackage.sh
## Desc: Install SqlPackage CLI to DacFx (https://docs.microsoft.com/sql/tools/sqlpackage/sqlpackage-download#get-sqlpackage-net-core-for-linux)
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/os.sh
# Install libssl1.1 dependency
if is_ubuntu22; then
focal_list=/etc/apt/sources.list.d/focal-security.list
echo "deb http://archive.ubuntu.com/ubuntu/ focal-security main" | tee "${focal_list}"
apt-get update --quiet
apt-get install --no-install-recommends libssl1.1
rm "${focal_list}"
apt-get update --quiet
fi
# Install SqlPackage
archive_path=$(download_with_retry "https://aka.ms/sqlpackage-linux")
unzip -qq "$archive_path" -d /usr/local/sqlpackage
chmod +x /usr/local/sqlpackage/sqlpackage
ln -sf /usr/local/sqlpackage/sqlpackage /usr/local/bin
invoke_tests "Tools" "SqlPackage"
@@ -0,0 +1,57 @@
#!/bin/bash -e
################################################################################
## File: install-swift.sh
## Desc: Install Swift
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
source $HELPER_SCRIPTS/etc-environment.sh
# Install
image_label="ubuntu$(lsb_release -rs)"
swift_version=$(curl -fsSL "https://api.github.com/repos/apple/swift/releases/latest" | jq -r '.tag_name | match("[0-9.]+").string')
swift_release_name="swift-${swift_version}-RELEASE-${image_label}"
archive_url="https://swift.org/builds/swift-${swift_version}-release/${image_label//./}/swift-${swift_version}-RELEASE/${swift_release_name}.tar.gz"
archive_path=$(download_with_retry "$archive_url")
# Verifying PGP signature using official Swift PGP key. Referring to https://www.swift.org/install/linux/#Installation-via-Tarball
# Download and import Swift PGP keys
gpg --keyserver hkp://keyserver.ubuntu.com \
--recv-keys \
'7463 A81A 4B2E EA1B 551F FBCF D441 C977 412B 37AD' \
'1BE1 E29A 084C B305 F397 D62A 9F59 7F4D 21A5 6D5F' \
'A3BA FD35 56A5 9079 C068 94BD 63BC 1CFE 91D3 06C6' \
'5E4D F843 FB06 5D7F 7E24 FBA2 EF54 30F0 71E1 B235' \
'8513 444E 2DA3 6B7C 1659 AF4D 7638 F1FB 2B2B 08C4' \
'A62A E125 BBBF BB96 A6E0 42EC 925C C1CC ED3D 1561' \
'8A74 9566 2C3C D4AE 18D9 5637 FAF6 989E 1BC1 6FEA' \
'E813 C892 820A 6FA1 3755 B268 F167 DF1A CF9C E069' \
'52BB 7E3D E28A 71BE 22EC 05FF EF80 A866 B47A 981F'
gpg --keyserver hkp://keyserver.ubuntu.com --refresh-keys Swift
# Download and verify signature
signature_path=$(download_with_retry "${archive_url}.sig")
gpg --verify "$signature_path" "$archive_path"
# Remove Swift PGP public key with temporary keyring
rm -rf ~/.gnupg
# Extract and install swift
tar xzf "$archive_path" -C /tmp
SWIFT_INSTALL_ROOT="/usr/share/swift"
swift_bin_root="$SWIFT_INSTALL_ROOT/usr/bin"
swift_lib_root="$SWIFT_INSTALL_ROOT/usr/lib"
mv "/tmp/${swift_release_name}" $SWIFT_INSTALL_ROOT
mkdir -p /usr/local/lib
ln -s "$swift_bin_root/swift" /usr/local/bin/swift
ln -s "$swift_bin_root/swiftc" /usr/local/bin/swiftc
ln -s "$swift_lib_root/libsourcekitdInProc.so" /usr/local/lib/libsourcekitdInProc.so
set_etc_environment_variable "SWIFT_PATH" "${swift_bin_root}"
invoke_tests "Common" "Swift"
@@ -0,0 +1,14 @@
#!/bin/bash -e
################################################################################
## File: install-terraform.sh
## Desc: Install terraform
################################################################################
source $HELPER_SCRIPTS/install.sh
# Install Terraform
download_url=$(curl -fsSL https://api.releases.hashicorp.com/v1/releases/terraform/latest | jq -r '.builds[] | select((.arch=="amd64") and (.os=="linux")).url')
archive_path=$(download_with_retry "${download_url}")
unzip -qq "$archive_path" -d /usr/local/bin
invoke_tests "Tools" "Terraform"
@@ -0,0 +1,30 @@
#!/bin/bash -e
################################################################################
## File: install-vcpkg.sh
## Desc: Install vcpkg
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/etc-environment.sh
# Set env variable for vcpkg
VCPKG_INSTALLATION_ROOT=/usr/local/share/vcpkg
set_etc_environment_variable "VCPKG_INSTALLATION_ROOT" "${VCPKG_INSTALLATION_ROOT}"
# Install vcpkg
git clone https://github.com/Microsoft/vcpkg $VCPKG_INSTALLATION_ROOT
$VCPKG_INSTALLATION_ROOT/bootstrap-vcpkg.sh
# workaround https://github.com/microsoft/vcpkg/issues/27786
mkdir -p /root/.vcpkg/ $HOME/.vcpkg
touch /root/.vcpkg/vcpkg.path.txt $HOME/.vcpkg/vcpkg.path.txt
$VCPKG_INSTALLATION_ROOT/vcpkg integrate install
chmod 0777 -R $VCPKG_INSTALLATION_ROOT
ln -sf $VCPKG_INSTALLATION_ROOT/vcpkg /usr/local/bin
rm -rf /root/.vcpkg $HOME/.vcpkg
invoke_tests "Tools" "Vcpkg"
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash -e
################################################################################
## File: install-yq.sh
## Desc: Install yq - a command-line YAML, JSON and XML processor
## Supply chain security: yq - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Download yq
yq_url=$(resolve_github_release_asset_url "mikefarah/yq" "endswith(\"yq_linux_amd64\")" "latest")
binary_path=$(download_with_retry "${yq_url}")
# Supply chain security - yq
hash_url=$(resolve_github_release_asset_url "mikefarah/yq" "endswith(\"checksums\")" "latest")
external_hash=$(get_checksum_from_url "${hash_url}" "yq_linux_amd64 " "SHA256" "true" " " "19")
use_checksum_comparison "$binary_path" "$external_hash"
# Install yq
install "$binary_path" /usr/bin/yq
invoke_tests "Tools" "yq"
@@ -0,0 +1,38 @@
#!/bin/bash -e
################################################################################
## File: install-zstd.sh
## Desc: Install zstd
## Supply chain security: zstd - checksum validation
################################################################################
# Source the helpers for use with the script
source $HELPER_SCRIPTS/install.sh
# Download zstd
release_tag=$(curl -fsSL https://api.github.com/repos/facebook/zstd/releases/latest | jq -r '.tag_name')
release_name="zstd-${release_tag//v}"
download_url="https://github.com/facebook/zstd/releases/download/${release_tag}/${release_name}.tar.gz"
archive_path=$(download_with_retry "${download_url}")
# Supply chain security - zstd
external_hash=$(get_checksum_from_url "${download_url}.sha256" "${release_name}.tar.gz" "SHA256")
use_checksum_comparison "$archive_path" "$external_hash"
# Install zstd
apt-get install liblz4-dev
tar xzf "$archive_path" -C /tmp
make -C "/tmp/${release_name}/contrib/pzstd" all
make -C "/tmp/${release_name}" zstd-release
for copyprocess in zstd zstdless zstdgrep; do
cp "/tmp/${release_name}/programs/${copyprocess}" /usr/local/bin/
done
cp "/tmp/${release_name}/contrib/pzstd/pzstd" /usr/local/bin/
for symlink in zstdcat zstdmt unzstd; do
ln -sf /usr/local/bin/zstd /usr/local/bin/${symlink}
done
invoke_tests "Tools" "Zstd"
@@ -0,0 +1,278 @@
using module ./software-report-base/SoftwareReport.psm1
using module ./software-report-base/SoftwareReport.Nodes.psm1
param (
[Parameter(Mandatory)]
[string] $OutputDirectory
)
$global:ErrorActionPreference = "Stop"
$global:ErrorView = "NormalView"
Set-StrictMode -Version Latest
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Android.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Browsers.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.CachedTools.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Common.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Databases.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Helpers.psm1") -DisableNameChecking
Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Java.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Rust.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.Tools.psm1") -DisableNameChecking
Import-Module (Join-Path $PSScriptRoot "SoftwareReport.WebServers.psm1") -DisableNameChecking
# Restore file owner in user profile
sudo chown -R ${env:USER}: $env:HOME
# Software report
$softwareReport = [SoftwareReport]::new("Ubuntu $(Get-OSVersionShort)")
$softwareReport.Root.AddToolVersion("OS Version:", $(Get-OSVersionFull))
$softwareReport.Root.AddToolVersion("Kernel Version:", $(Get-KernelVersion))
$softwareReport.Root.AddToolVersion("Image Version:", $env:IMAGE_VERSION)
$softwareReport.Root.AddToolVersion("Systemd version:", $(Get-SystemdVersion))
$installedSoftware = $softwareReport.Root.AddHeader("Installed Software")
# Language and Runtime
$languageAndRuntime = $installedSoftware.AddHeader("Language and Runtime")
$languageAndRuntime.AddToolVersion("Bash", $(Get-BashVersion))
$languageAndRuntime.AddToolVersionsListInline("Clang", $(Get-ClangToolVersions -ToolName "clang"), "^\d+")
$languageAndRuntime.AddToolVersionsListInline("Clang-format", $(Get-ClangToolVersions -ToolName "clang-format"), "^\d+")
$languageAndRuntime.AddToolVersionsListInline("Clang-tidy", $(Get-ClangTidyVersions), "^\d+")
$languageAndRuntime.AddToolVersion("Dash", $(Get-DashVersion))
if (Test-IsUbuntu20) {
$languageAndRuntime.AddToolVersion("Erlang", $(Get-ErlangVersion))
$languageAndRuntime.AddToolVersion("Erlang rebar3", $(Get-ErlangRebar3Version))
}
$languageAndRuntime.AddToolVersionsListInline("GNU C++", $(Get-CPPVersions), "^\d+")
$languageAndRuntime.AddToolVersionsListInline("GNU Fortran", $(Get-FortranVersions), "^\d+")
$languageAndRuntime.AddToolVersion("Julia", $(Get-JuliaVersion))
$languageAndRuntime.AddToolVersion("Kotlin", $(Get-KotlinVersion))
if (-not $(Test-IsUbuntu24)) {
$languageAndRuntime.AddToolVersion("Mono", $(Get-MonoVersion))
$languageAndRuntime.AddToolVersion("MSBuild", $(Get-MsbuildVersion))
}
$languageAndRuntime.AddToolVersion("Node.js", $(Get-NodeVersion))
$languageAndRuntime.AddToolVersion("Perl", $(Get-PerlVersion))
$languageAndRuntime.AddToolVersion("Python", $(Get-PythonVersion))
$languageAndRuntime.AddToolVersion("Ruby", $(Get-RubyVersion))
$languageAndRuntime.AddToolVersion("Swift", $(Get-SwiftVersion))
# Package Management
$packageManagement = $installedSoftware.AddHeader("Package Management")
$packageManagement.AddToolVersion("cpan", $(Get-CpanVersion))
$packageManagement.AddToolVersion("Helm", $(Get-HelmVersion))
$packageManagement.AddToolVersion("Homebrew", $(Get-HomebrewVersion))
$packageManagement.AddToolVersion("Miniconda", $(Get-MinicondaVersion))
$packageManagement.AddToolVersion("Npm", $(Get-NpmVersion))
if (-not $(Test-IsUbuntu24)) {
$packageManagement.AddToolVersion("NuGet", $(Get-NuGetVersion))
}
$packageManagement.AddToolVersion("Pip", $(Get-PipVersion))
$packageManagement.AddToolVersion("Pip3", $(Get-Pip3Version))
$packageManagement.AddToolVersion("Pipx", $(Get-PipxVersion))
$packageManagement.AddToolVersion("RubyGems", $(Get-GemVersion))
$packageManagement.AddToolVersion("Vcpkg", $(Get-VcpkgVersion))
$packageManagement.AddToolVersion("Yarn", $(Get-YarnVersion))
$packageManagement.AddHeader("Environment variables").AddTable($(Build-PackageManagementEnvironmentTable))
$packageManagement.AddHeader("Homebrew note").AddNote(@'
Location: /home/linuxbrew
Note: Homebrew is pre-installed on image but not added to PATH.
run the eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" command
to accomplish this.
'@)
# Project Management
$projectManagement = $installedSoftware.AddHeader("Project Management")
$projectManagement.AddToolVersion("Ant", $(Get-AntVersion))
$projectManagement.AddToolVersion("Gradle", $(Get-GradleVersion))
$projectManagement.AddToolVersion("Lerna", $(Get-LernaVersion))
$projectManagement.AddToolVersion("Maven", $(Get-MavenVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$projectManagement.AddToolVersion("Sbt", $(Get-SbtVersion))
}
# Tools
$tools = $installedSoftware.AddHeader("Tools")
$tools.AddToolVersion("Ansible", $(Get-AnsibleVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$tools.AddToolVersion("apt-fast", $(Get-AptFastVersion))
}
$tools.AddToolVersion("AzCopy", $(Get-AzCopyVersion))
$tools.AddToolVersion("Bazel", $(Get-BazelVersion))
$tools.AddToolVersion("Bazelisk", $(Get-BazeliskVersion))
$tools.AddToolVersion("Bicep", $(Get-BicepVersion))
$tools.AddToolVersion("Buildah", $(Get-BuildahVersion))
$tools.AddToolVersion("CMake", $(Get-CMakeVersion))
$tools.AddToolVersion("CodeQL Action Bundle", $(Get-CodeQLBundleVersion))
$tools.AddToolVersion("Docker Amazon ECR Credential Helper", $(Get-DockerAmazonECRCredHelperVersion))
$tools.AddToolVersion("Docker Compose v2", $(Get-DockerComposeV2Version))
$tools.AddToolVersion("Docker-Buildx", $(Get-DockerBuildxVersion))
$tools.AddToolVersion("Docker Client", $(Get-DockerClientVersion))
$tools.AddToolVersion("Docker Server", $(Get-DockerServerVersion))
$tools.AddToolVersion("Fastlane", $(Get-FastlaneVersion))
$tools.AddToolVersion("Git", $(Get-GitVersion))
$tools.AddToolVersion("Git LFS", $(Get-GitLFSVersion))
$tools.AddToolVersion("Git-ftp", $(Get-GitFTPVersion))
$tools.AddToolVersion("Haveged", $(Get-HavegedVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$tools.AddToolVersion("Heroku", $(Get-HerokuVersion))
}
if (Test-IsUbuntu20) {
$tools.AddToolVersion("HHVM (HipHop VM)", $(Get-HHVMVersion))
}
$tools.AddToolVersion("jq", $(Get-JqVersion))
$tools.AddToolVersion("Kind", $(Get-KindVersion))
$tools.AddToolVersion("Kubectl", $(Get-KubectlVersion))
$tools.AddToolVersion("Kustomize", $(Get-KustomizeVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$tools.AddToolVersion("Leiningen", $(Get-LeiningenVersion))
}
$tools.AddToolVersion("MediaInfo", $(Get-MediainfoVersion))
$tools.AddToolVersion("Mercurial", $(Get-HGVersion))
$tools.AddToolVersion("Minikube", $(Get-MinikubeVersion))
$tools.AddToolVersion("n", $(Get-NVersion))
$tools.AddToolVersion("Newman", $(Get-NewmanVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$tools.AddToolVersion("nvm", $(Get-NvmVersion))
}
$tools.AddToolVersion("OpenSSL", $(Get-OpensslVersion))
$tools.AddToolVersion("Packer", $(Get-PackerVersion))
$tools.AddToolVersion("Parcel", $(Get-ParcelVersion))
if (Test-IsUbuntu20) {
$tools.AddToolVersion("PhantomJS", $(Get-PhantomJSVersion))
}
$tools.AddToolVersion("Podman", $(Get-PodManVersion))
$tools.AddToolVersion("Pulumi", $(Get-PulumiVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$tools.AddToolVersion("R", $(Get-RVersion))
}
$tools.AddToolVersion("Skopeo", $(Get-SkopeoVersion))
$tools.AddToolVersion("Sphinx Open Source Search Server", $(Get-SphinxVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$tools.AddToolVersion("SVN", $(Get-SVNVersion))
$tools.AddToolVersion("Terraform", $(Get-TerraformVersion))
}
$tools.AddToolVersion("yamllint", $(Get-YamllintVersion))
$tools.AddToolVersion("yq", $(Get-YqVersion))
$tools.AddToolVersion("zstd", $(Get-ZstdVersion))
# CLI Tools
$cliTools = $installedSoftware.AddHeader("CLI Tools")
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$cliTools.AddToolVersion("Alibaba Cloud CLI", $(Get-AlibabaCloudCliVersion))
}
$cliTools.AddToolVersion("AWS CLI", $(Get-AWSCliVersion))
$cliTools.AddToolVersion("AWS CLI Session Manager Plugin", $(Get-AWSCliSessionManagerPluginVersion))
$cliTools.AddToolVersion("AWS SAM CLI", $(Get-AWSSAMVersion))
$cliTools.AddToolVersion("Azure CLI", $(Get-AzureCliVersion))
$cliTools.AddToolVersion("Azure CLI (azure-devops)", $(Get-AzureDevopsVersion))
$cliTools.AddToolVersion("GitHub CLI", $(Get-GitHubCliVersion))
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$cliTools.AddToolVersion("Google Cloud CLI", $(Get-GoogleCloudCLIVersion))
$cliTools.AddToolVersion("Netlify CLI", $(Get-NetlifyCliVersion))
$cliTools.AddToolVersion("OpenShift CLI", $(Get-OCCliVersion))
$cliTools.AddToolVersion("ORAS CLI", $(Get-ORASCliVersion))
$cliTools.AddToolVersion("Vercel CLI", $(Get-VerselCliversion))
}
# Java
$installedSoftware.AddHeader("Java").AddTable($(Get-JavaVersionsTable))
# PHP Tools
$phpTools = $installedSoftware.AddHeader("PHP Tools")
$phpTools.AddToolVersionsListInline("PHP", $(Get-PHPVersions), "^\d+\.\d+")
$phpTools.AddToolVersion("Composer", $(Get-ComposerVersion))
$phpTools.AddToolVersion("PHPUnit", $(Get-PHPUnitVersion))
$phpTools.AddNote("Both Xdebug and PCOV extensions are installed, but only Xdebug is enabled.")
# Haskell Tools
$haskellTools = $installedSoftware.AddHeader("Haskell Tools")
$haskellTools.AddToolVersion("Cabal", $(Get-CabalVersion))
$haskellTools.AddToolVersion("GHC", $(Get-GHCVersion))
$haskellTools.AddToolVersion("GHCup", $(Get-GHCupVersion))
$haskellTools.AddToolVersion("Stack", $(Get-StackVersion))
# Rust Tools
Initialize-RustEnvironment
$rustTools = $installedSoftware.AddHeader("Rust Tools")
$rustTools.AddToolVersion("Cargo", $(Get-CargoVersion))
$rustTools.AddToolVersion("Rust", $(Get-RustVersion))
$rustTools.AddToolVersion("Rustdoc", $(Get-RustdocVersion))
$rustTools.AddToolVersion("Rustup", $(Get-RustupVersion))
# Packages
$rustToolsPackages = $rustTools.AddHeader("Packages")
if ((Test-IsUbuntu20) -or (Test-IsUbuntu22)) {
$rustToolsPackages.AddToolVersion("Bindgen", $(Get-BindgenVersion))
$rustToolsPackages.AddToolVersion("Cargo audit", $(Get-CargoAuditVersion))
$rustToolsPackages.AddToolVersion("Cargo clippy", $(Get-CargoClippyVersion))
$rustToolsPackages.AddToolVersion("Cargo outdated", $(Get-CargoOutdatedVersion))
$rustToolsPackages.AddToolVersion("Cbindgen", $(Get-CbindgenVersion))
}
$rustToolsPackages.AddToolVersion("Rustfmt", $(Get-RustfmtVersion))
# Browsers and Drivers
$browsersTools = $installedSoftware.AddHeader("Browsers and Drivers")
$browsersTools.AddToolVersion("Google Chrome", $(Get-ChromeVersion))
$browsersTools.AddToolVersion("ChromeDriver", $(Get-ChromeDriverVersion))
$browsersTools.AddToolVersion("Chromium", $(Get-ChromiumVersion))
$browsersTools.AddToolVersion("Microsoft Edge", $(Get-EdgeVersion))
$browsersTools.AddToolVersion("Microsoft Edge WebDriver", $(Get-EdgeDriverVersion))
$browsersTools.AddToolVersion("Selenium server", $(Get-SeleniumVersion))
$browsersTools.AddToolVersion("Mozilla Firefox", $(Get-FirefoxVersion))
$browsersTools.AddToolVersion("Geckodriver", $(Get-GeckodriverVersion))
# Environment variables
$browsersTools.AddHeader("Environment variables").AddTable($(Build-BrowserWebdriversEnvironmentTable))
# .NET Tools
$netCoreTools = $installedSoftware.AddHeader(".NET Tools")
$netCoreTools.AddToolVersionsListInline(".NET Core SDK", $(Get-DotNetCoreSdkVersions), "^\d+\.\d+\.\d")
$netCoreTools.AddNodes($(Get-DotnetTools))
# Databases
$databasesTools = $installedSoftware.AddHeader("Databases")
if (Test-IsUbuntu20) {
$databasesTools.AddToolVersion("MongoDB", $(Get-MongoDbVersion))
}
$databasesTools.AddToolVersion("sqlite3", $(Get-SqliteVersion))
$databasesTools.AddNode($(Build-PostgreSqlSection))
$databasesTools.AddNode($(Build-MySQLSection))
if (-not $(Test-IsUbuntu24)) {
$databasesTools.AddNode($(Build-MSSQLToolsSection))
}
# Cached Tools
$cachedTools = $installedSoftware.AddHeader("Cached Tools")
$cachedTools.AddToolVersionsList("Go", $(Get-ToolcacheGoVersions), "^\d+\.\d+")
$cachedTools.AddToolVersionsList("Node.js", $(Get-ToolcacheNodeVersions), "^\d+")
$cachedTools.AddToolVersionsList("Python", $(Get-ToolcachePythonVersions), "^\d+\.\d+")
$cachedTools.AddToolVersionsList("PyPy", $(Get-ToolcachePyPyVersions), "^\d+\.\d+")
if (-not $(Test-IsUbuntu24)) {
$cachedTools.AddToolVersionsList("Ruby", $(Get-ToolcacheRubyVersions), "^\d+\.\d+")
}
# PowerShell Tools
$powerShellTools = $installedSoftware.AddHeader("PowerShell Tools")
$powerShellTools.AddToolVersion("PowerShell", $(Get-PowershellVersion))
$powerShellTools.AddHeader("PowerShell Modules").AddNodes($(Get-PowerShellModules))
$installedSoftware.AddHeader("Web Servers").AddTable($(Build-WebServersTable))
$androidTools = $installedSoftware.AddHeader("Android")
$androidTools.AddTable($(Build-AndroidTable))
$androidTools.AddHeader("Environment variables").AddTable($(Build-AndroidEnvironmentTable))
if (-not $(Test-IsUbuntu24)) {
$installedSoftware.AddHeader("Cached Docker images").AddTable($(Get-CachedDockerImagesTableData))
}
$installedSoftware.AddHeader("Installed apt packages").AddTable($(Get-AptPackages))
$softwareReport.ToJson() | Out-File -FilePath "${OutputDirectory}/software-report.json" -Encoding UTF8NoBOM
$softwareReport.ToMarkdown() | Out-File -FilePath "${OutputDirectory}/software-report.md" -Encoding UTF8NoBOM
@@ -0,0 +1,173 @@
function Split-TableRowByColumns {
param(
[string] $Row
)
return $Row.Split("|") | ForEach-Object { $_.trim() }
}
function Get-AndroidSDKRoot {
return "/usr/local/lib/android/sdk"
}
function Get-AndroidSDKManagerPath {
$androidSDKDir = Get-AndroidSDKRoot
return Join-Path $androidSDKDir "cmdline-tools" "latest" "bin" "sdkmanager"
}
function Get-AndroidInstalledPackages {
$androidSDKManagerPath = Get-AndroidSDKManagerPath
$androidSDKManagerList = Invoke-Expression "$androidSDKManagerPath --list_installed --include_obsolete"
return $androidSDKManagerList
}
function Build-AndroidTable {
$packageInfo = Get-AndroidInstalledPackages
return @(
@{
"Package" = "Android Command Line Tools"
"Version" = Get-AndroidCommandLineToolsVersion
},
@{
"Package" = "Android Emulator"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Android Emulator"
},
@{
"Package" = "Android SDK Build-tools"
"Version" = Get-AndroidBuildToolVersions -PackageInfo $packageInfo
},
@{
"Package" = "Android SDK Platform-Tools"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Android SDK Platform-Tools"
},
@{
"Package" = "Android SDK Platforms"
"Version" = Get-AndroidPlatformVersions -PackageInfo $packageInfo
},
@{
"Package" = "Android Support Repository"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Android Support Repository"
},
@{
"Package" = "CMake"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "cmake"
},
@{
"Package" = "Google APIs"
"Version" = Get-AndroidGoogleAPIsVersions -PackageInfo $packageInfo
},
@{
"Package" = "Google Play services"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Google Play services"
},
@{
"Package" = "Google Repository"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "Google Repository"
},
@{
"Package" = "NDK"
"Version" = Get-AndroidNDKVersions
},
@{
"Package" = "SDK Patch Applier v4"
"Version" = Get-AndroidPackageVersions -PackageInfo $packageInfo -MatchedString "SDK Patch Applier v4"
}
) | Where-Object { $_.Version } | ForEach-Object {
[PSCustomObject] @{
"Package Name" = $_.Package
"Version" = $_.Version
}
}
}
function Get-AndroidPackageVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo,
[Parameter(Mandatory)]
[object] $MatchedString
)
$versions = $PackageInfo | Where-Object { $_ -Match $MatchedString } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
return $packageInfoParts[1]
}
return ($versions -Join "<br>")
}
function Get-AndroidPlatformVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$versions = $PackageInfo | Where-Object { $_ -Match "Android SDK Platform " } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
$revision = $packageInfoParts[1]
$version = $packageInfoParts[0].split(";")[1]
return "$version (rev $revision)"
}
[array]::Reverse($versions)
return ($versions -Join "<br>")
}
function Get-AndroidCommandLineToolsVersion {
$commandLineTools = Get-AndroidSDKManagerPath
(& $commandLineTools --version | Out-String).Trim() -match "(?<version>^(\d+\.){1,}\d+$)" | Out-Null
$commandLineToolsVersion = $Matches.Version
return $commandLineToolsVersion
}
function Get-AndroidBuildToolVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$versions = $PackageInfo | Where-Object { $_ -Match "Android SDK Build-Tools" } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
return $packageInfoParts[1]
}
$groupVersions = @()
$versions | ForEach-Object {
$majorVersion = $_.Split(".")[0]
$groupVersions += $versions | Where-Object { $_.StartsWith($majorVersion) } | Join-String -Separator " "
}
return ($groupVersions | Sort-Object -Descending -Unique | Join-String -Separator "<br>")
}
function Get-AndroidGoogleAPIsVersions {
param (
[Parameter(Mandatory)]
[object] $PackageInfo
)
$versions = $PackageInfo | Where-Object { $_ -Match "Google APIs" } | ForEach-Object {
$packageInfoParts = Split-TableRowByColumns $_
return $packageInfoParts[0].split(";")[1]
}
return ($versions -Join "<br>")
}
function Get-AndroidNDKVersions {
$ndkFolderPath = Join-Path (Get-AndroidSDKRoot) "ndk"
$versions = Get-ChildItem -Path $ndkFolderPath -Name
$ndkDefaultVersion = (Get-ToolsetContent).android.ndk.default
$ndkDefaultFullVersion = Get-ChildItem "$env:ANDROID_HOME/ndk/$ndkDefaultVersion.*" -Name | Select-Object -Last 1
return ($versions | ForEach-Object {
$defaultPostfix = ( $_ -eq $ndkDefaultFullVersion ) ? " (default)" : ""
$_ + $defaultPostfix
} | Join-String -Separator "<br>")
}
function Build-AndroidEnvironmentTable {
$androidVersions = Get-Item env:ANDROID_*
$shouldResolveLink = 'ANDROID_NDK', 'ANDROID_NDK_HOME', 'ANDROID_NDK_ROOT', 'ANDROID_NDK_LATEST_HOME'
return $androidVersions | Sort-Object -Property Name | ForEach-Object {
[PSCustomObject] @{
"Name" = $_.Name
"Value" = if ($shouldResolveLink.Contains($_.Name )) { Get-PathWithLink($_.Value) } else {$_.Value}
}
}
}
@@ -0,0 +1,60 @@
function Get-ChromeVersion {
$googleChromeVersion = google-chrome --version | Get-StringPart -Part 2
return $googleChromeVersion
}
function Get-ChromeDriverVersion {
$chromeDriverVersion = chromedriver --version | Get-StringPart -Part 1
return $chromeDriverVersion
}
function Get-FirefoxVersion {
$firefoxVersion = $(firefox --version) | Get-StringPart -Part 2
return $firefoxVersion
}
function Get-GeckodriverVersion {
$geckodriverVersion = geckodriver --version | Select-Object -First 1 | Get-StringPart -Part 1
return $geckodriverVersion
}
function Get-ChromiumVersion {
$chromiumVersion = chromium-browser --version | Get-StringPart -Part 1
return $chromiumVersion
}
function Get-EdgeVersion {
$edgeVersion = (microsoft-edge --version).Trim() | Get-StringPart -Part 2
return $edgeVersion
}
function Get-EdgeDriverVersion {
$edgeDriverVersion = msedgedriver --version | Get-StringPart -Part 3
return $edgeDriverVersion
}
function Get-SeleniumVersion {
$fullSeleniumVersion = (Get-ChildItem "/usr/share/java/selenium-server-*").Name -replace "selenium-server-"
return $fullSeleniumVersion
}
function Build-BrowserWebdriversEnvironmentTable {
return @(
[PSCustomObject] @{
"Name" = "CHROMEWEBDRIVER"
"Value" = $env:CHROMEWEBDRIVER
},
[PSCustomObject] @{
"Name" = "EDGEWEBDRIVER"
"Value" = $env:EDGEWEBDRIVER
},
[PSCustomObject] @{
"Name" = "GECKOWEBDRIVER"
"Value" = $env:GECKOWEBDRIVER
},
[PSCustomObject] @{
"Name" = "SELENIUM_JAR_PATH"
"Value" = $env:SELENIUM_JAR_PATH
}
)
}
@@ -0,0 +1,29 @@
function Get-ToolcacheRubyVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Ruby"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcachePythonVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "Python"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcachePyPyVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "PyPy"
Get-ChildItem -Path $toolcachePath -Name | Sort-Object { [Version] $_ } | ForEach-Object {
$pypyRootPath = Join-Path $toolcachePath $_ "x64"
[string] $pypyVersionOutput = & "$pypyRootPath/bin/python" -c "import sys;print(sys.version)"
$pypyVersionOutput -match "^([\d\.]+) \(.+\) \[PyPy ([\d\.]+\S*) .+]$" | Out-Null
return "{0} [PyPy {1}]" -f $Matches[1], $Matches[2]
}
}
function Get-ToolcacheNodeVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "node"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
function Get-ToolcacheGoVersions {
$toolcachePath = Join-Path $env:AGENT_TOOLSDIRECTORY "go"
return Get-ChildItem $toolcachePath -Name | Sort-Object { [Version] $_ }
}
@@ -0,0 +1,358 @@
function Get-BashVersion {
$version = bash -c 'echo ${BASH_VERSION}'
return $version
}
function Get-DashVersion {
$version = dpkg-query -W -f '${Version}' dash
return $version
}
function Get-CPPVersions {
$result = Get-CommandResult "apt list --installed" -Multiline
$cppVersions = $result.Output | Where-Object { $_ -match "g\+\+-\d\d\/" } | ForEach-Object {
& $_.Split("/")[0] --version | Select-Object -First 1 | Get-StringPart -Part 3
} | Sort-Object {[Version] $_}
return $cppVersions
}
function Get-FortranVersions {
$result = Get-CommandResult "apt list --installed" -Multiline
$fortranVersions = $result.Output | Where-Object { $_ -match "^gfortran-\d\d\/" } | ForEach-Object {
& $_.Split("/")[0] --version | Select-Object -First 1 | Get-StringPart -Part 4
} | Sort-Object {[Version] $_}
return $fortranVersions
}
function Get-ClangToolVersions {
param (
[Parameter(Mandatory = $true)]
[string] $ToolName,
[string] $VersionLineMatcher = "${ToolName} version",
[string] $VersionPattern = "\d+\.\d+\.\d+)"
)
$result = Get-CommandResult "apt list --installed" -Multiline
$toolVersions = $result.Output | Where-Object { $_ -match "^${ToolName}-\d+" } | ForEach-Object {
$clangCommand = ($_ -Split "/")[0]
Invoke-Expression "$clangCommand --version" | Where-Object { $_ -match "${VersionLineMatcher}" } | ForEach-Object {
$_ -match "${VersionLineMatcher} (?<version>${VersionPattern}" | Out-Null
$Matches.version
}
} | Sort-Object {[Version] $_}
return $toolVersions
}
function Get-ClangTidyVersions {
$clangVersions = Get-ClangToolVersions -ToolName "clang-tidy" -VersionLineMatcher "LLVM version" -VersionPattern "\d+\.\d+\.\d+)"
return $clangVersions
}
function Get-ErlangVersion {
$erlangVersion = (erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), ''OTP_VERSION''])), io:fwrite(Version), halt().' -noshell)
$shellVersion = (erl -eval 'erlang:display(erlang:system_info(version)), halt().' -noshell).Trim('"')
return "$erlangVersion (Eshell $shellVersion)"
}
function Get-ErlangRebar3Version {
$result = Get-CommandResult "rebar3 --version"
$result.Output -match "rebar (?<version>(\d+.){2}\d+)" | Out-Null
return $Matches.version
}
function Get-MonoVersion {
$monoVersion = mono --version | Out-String | Get-StringPart -Part 4
return $monoVersion
}
function Get-MsbuildVersion {
$msbuildVersion = msbuild -version | Select-Object -Last 1
$monoVersion = Get-MonoVersion
return "$msbuildVersion (Mono $monoVersion)"
}
function Get-NuGetVersion {
$nugetVersion = nuget help | Select-Object -First 1 | Get-StringPart -Part 2
return $nugetVersion
}
function Get-NodeVersion {
$nodeVersion = $(node --version).Substring(1)
return $nodeVersion
}
function Get-OpensslVersion {
$opensslVersion = $(dpkg-query -W -f '${Version}' openssl)
return $opensslVersion
}
function Get-PerlVersion {
$version = $(perl -e 'print substr($^V,1)')
return $version
}
function Get-PythonVersion {
$result = Get-CommandResult "python --version"
$version = $result.Output | Get-StringPart -Part 1
return $version
}
function Get-PowershellVersion {
$pwshVersion = $(pwsh --version) | Get-StringPart -Part 1
return $pwshVersion
}
function Get-RubyVersion {
$rubyVersion = ruby --version | Out-String | Get-StringPart -Part 1
return $rubyVersion
}
function Get-SwiftVersion {
$swiftVersion = swift --version | Out-String | Get-StringPart -Part 2
return $swiftVersion
}
function Get-KotlinVersion {
$kotlinVersion = kotlin -version | Out-String | Get-StringPart -Part 2
return $kotlinVersion
}
function Get-JuliaVersion {
$juliaVersion = julia --version | Get-StringPart -Part 2
return $juliaVersion
}
function Get-LernaVersion {
$version = lerna -v
return $version
}
function Get-HomebrewVersion {
$result = Get-CommandResult "/home/linuxbrew/.linuxbrew/bin/brew --version"
$result.Output -match "Homebrew (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-CpanVersion {
$result = Get-CommandResult "cpan --version" -ExpectedExitCode @(25, 255)
$result.Output -match "version (?<version>\d+\.\d+) " | Out-Null
return $Matches.version
}
function Get-GemVersion {
$result = Get-CommandResult "gem --version"
$result.Output -match "(?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-MinicondaVersion {
$condaVersion = conda --version | Get-StringPart -Part 1
return $condaVersion
}
function Get-HelmVersion {
$(helm version) -match 'Version:"v(?<version>\d+\.\d+\.\d+)"' | Out-Null
return $Matches.version
}
function Get-NpmVersion {
$npmVersion = npm --version
return $npmVersion
}
function Get-YarnVersion {
$yarnVersion = yarn --version
return $yarnVersion
}
function Get-ParcelVersion {
$parcelVersion = parcel --version
return $parcelVersion
}
function Get-PipVersion {
$pipVersion = pip --version | Get-StringPart -Part 1
return $pipVersion
}
function Get-Pip3Version {
$pip3Version = pip3 --version | Get-StringPart -Part 1
return $pip3Version
}
function Get-VcpkgVersion {
$commitId = git -C "/usr/local/share/vcpkg" rev-parse --short HEAD
return "(build from commit $commitId)"
}
function Get-AntVersion {
$result = ant -version | Out-String
$result -match "version (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-GradleVersion {
$gradleVersion = (gradle -v) -match "^Gradle \d" | Get-StringPart -Part 1
return $gradleVersion
}
function Get-MavenVersion {
$result = mvn -version | Out-String
$result -match "Apache Maven (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-SbtVersion {
$result = Get-CommandResult "sbt -version"
$result.Output -match "sbt script version: (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-PHPVersions {
$result = Get-CommandResult "apt list --installed" -Multiline
return $result.Output | Where-Object { $_ -match "^php\d+\.\d+/" } | ForEach-Object {
$_ -match "now (\d+:)?(?<version>\d+\.\d+\.\d+)" | Out-Null
$Matches.version
}
}
function Get-ComposerVersion {
$composerVersion = (composer --version) -replace " version" | Get-StringPart -Part 1
return $composerVersion
}
function Get-PHPUnitVersion {
$(phpunit --version | Out-String) -match "PHPUnit (?<version>\d+\.\d+\.\d+)\s" | Out-Null
return $Matches.version
}
function Get-GHCVersion {
$(ghc --version) -match "version (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-GHCupVersion {
$(ghcup --version) -match "version (?<version>\d+(\.\d+){2,})" | Out-Null
return $Matches.version
}
function Get-CabalVersion {
$(cabal --version | Out-String) -match "cabal-install version (?<version>\d+\.\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-StackVersion {
$(stack --version | Out-String) -match "Version (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.version
}
function Get-AzModuleVersions {
$azModuleVersions = Get-ChildItem /usr/share | Where-Object { $_ -match "az_\d+" } | Foreach-Object {
$_.Name.Split("_")[1]
}
$azModuleVersions = $azModuleVersions -join " "
return $azModuleVersions
}
function Get-PowerShellModules {
[Array] $result = @()
[Array] $azureInstalledModules = Get-ChildItem -Path "/usr/share/az_*" -Directory | ForEach-Object { $_.Name.Split("_")[1] }
if ($azureInstalledModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("Az", $azureInstalledModules, "^\d+\.\d+", "Inline")
}
[Array] $azureCachedModules = Get-ChildItem /usr/share/az_*.zip -File | ForEach-Object { $_.Name.Split("_")[1] }
if ($azureCachedModules.Count -gt 0) {
$result += [ToolVersionsListNode]::new("Az (Cached)", $azureCachedModules, "^\d+\.\d+", "Inline")
}
(Get-ToolsetContent).powershellModules.name | ForEach-Object {
$moduleName = $_
$moduleVersions = Get-Module -Name $moduleName -ListAvailable | Select-Object -ExpandProperty Version | Sort-Object -Unique
$result += [ToolVersionsListNode]::new($moduleName, $moduleVersions, "^\d+", "Inline")
}
return $result
}
function Get-DotNetCoreSdkVersions {
$dotNetCoreSdkVersion = dotnet --list-sdks list | ForEach-Object { $_ | Get-StringPart -Part 0 }
return $dotNetCoreSdkVersion
}
function Get-DotnetTools {
$env:PATH = "/etc/skel/.dotnet/tools:$($env:PATH)"
$dotnetTools = (Get-ToolsetContent).dotnet.tools
return $dotnetTools | ForEach-Object {
$version = Invoke-Expression $_.getversion
return [ToolVersionNode]::new($_.name, $version)
}
}
function Get-CachedDockerImages {
$toolsetJson = Get-ToolsetContent
$images = $toolsetJson.docker.images
return $images
}
function Get-CachedDockerImagesTableData {
$allImages = sudo docker images --digests --format "*{{.Repository}}:{{.Tag}}|{{.Digest}} |{{.CreatedAt}}"
$allImages.Split("*") | Where-Object { $_ } | ForEach-Object {
$parts = $_.Split("|")
[PSCustomObject] @{
"Repository:Tag" = $parts[0]
"Digest" = $parts[1]
"Created" = $parts[2].split(' ')[0]
}
} | Sort-Object -Property "Repository:Tag"
}
function Get-AptPackages {
$apt = (Get-ToolsetContent).Apt
$output = @()
ForEach ($pkg in ($apt.vital_packages + $apt.common_packages + $apt.cmd_packages)) {
$version = $(dpkg-query -W -f '${Version}' $pkg)
if ($null -eq $version) {
$version = $(dpkg-query -W -f '${Version}' "$pkg*")
}
$version = $version -replace '~','\~'
$output += [PSCustomObject] @{
Name = $pkg
Version = $version
}
}
return ($output | Sort-Object Name)
}
function Get-PipxVersion {
$result = (Get-CommandResult "pipx --version").Output
$result -match "(?<version>\d+\.\d+\.\d+\.?\d*)" | Out-Null
return $Matches.Version
}
function Build-PackageManagementEnvironmentTable {
return @(
[PSCustomObject] @{
"Name" = "CONDA"
"Value" = $env:CONDA
},
[PSCustomObject] @{
"Name" = "VCPKG_INSTALLATION_ROOT"
"Value" = $env:VCPKG_INSTALLATION_ROOT
}
)
}
function Get-SystemdVersion {
$matchCollection = [regex]::Matches((systemctl --version | head -n 1), "\((.*?)\)")
$result = foreach ($match in $matchCollection) {$match.Groups[1].Value}
return $result
}
@@ -0,0 +1,61 @@
function Get-PostgreSqlVersion {
$postgreSQLVersion = psql --version | Get-StringPart -Part 2
return $postgreSQLVersion
}
function Get-MongoDbVersion {
$mongoDBVersion = mongod --version | Select-Object -First 1 | Get-StringPart -Part 2 -Delimiter "v"
return $mongoDBVersion
}
function Get-SqliteVersion {
$sqliteVersion = sqlite3 --version | Get-StringPart -Part 0
return $sqliteVersion
}
function Get-MySQLVersion {
$mySQLVersion = mysqld --version | Get-StringPart -Part 2
return $mySQLVersion
}
function Get-SQLCmdVersion {
$sqlcmdVersion = sqlcmd -? | Select-String -Pattern "Version" | Get-StringPart -Part 1
return $sqlcmdVersion
}
function Get-SqlPackageVersion {
$sqlPackageVersion = sqlpackage /version
return $sqlPackageVersion
}
function Build-PostgreSqlSection {
$node = [HeaderNode]::new("PostgreSQL")
$node.AddToolVersion("PostgreSQL", $(Get-PostgreSqlVersion))
$node.AddNote(@(
"User: postgres",
"PostgreSQL service is disabled by default.",
"Use the following command as a part of your job to start the service: 'sudo systemctl start postgresql.service'"
) -join "`n")
return $node
}
function Build-MySQLSection {
$node = [HeaderNode]::new("MySQL")
$node.AddToolVersion("MySQL", $(Get-MySQLVersion))
$node.AddNote(@(
"User: root",
"Password: root",
"MySQL service is disabled by default.",
"Use the following command as a part of your job to start the service: 'sudo systemctl start mysql.service'"
) -join "`n")
return $node
}
function Build-MSSQLToolsSection {
$node = [HeaderNode]::new("MS SQL")
$node.AddToolVersion("sqlcmd", $(Get-SQLCmdVersion))
$node.AddToolVersion("SqlPackage", $(Get-SqlPackageVersion))
return $node
}
@@ -0,0 +1,37 @@
function Get-StringPart {
param (
[Parameter(ValueFromPipeline)]
[string] $ToolOutput,
[string] $Delimiter = " ",
[int[]] $Part
)
$parts = $ToolOutput.Split($Delimiter, [System.StringSplitOptions]::RemoveEmptyEntries)
$selectedParts = $parts[$Part]
return [string]::Join($Delimiter, $selectedParts)
}
function Get-PathWithLink {
param (
[string] $InputPath
)
$link = Get-Item $InputPath | Select-Object -ExpandProperty Target
if (-not [string]::IsNullOrEmpty($link)) {
return "${InputPath} -> ${link}"
}
return "${InputPath}"
}
function Get-OSVersionShort {
$(Get-OSVersionFull) | Get-StringPart -Delimiter '.' -Part 0,1
}
function Get-OSVersionFull {
lsb_release -ds | Get-StringPart -Part 1, 2
}
function Get-KernelVersion {
$kernelVersion = uname -r
return $kernelVersion
}
@@ -0,0 +1,17 @@
function Get-JavaVersionsTable {
$javaToolcacheVersions = Get-ChildItem $env:AGENT_TOOLSDIRECTORY/Java*/* -Directory | Sort-Object { [int] $_.Name.Split(".")[0] }
return $javaToolcacheVersions | ForEach-Object {
$majorVersion = $_.Name.split(".")[0]
$fullVersion = $_.Name.Replace("-", "+")
$defaultJavaPath = $env:JAVA_HOME
$javaPath = Get-Item env:JAVA_HOME_${majorVersion}_X64
$defaultPostfix = ($javaPath.Value -eq $defaultJavaPath) ? " (default)" : ""
[PSCustomObject] @{
"Version" = $fullVersion + $defaultPostfix
"Environment Variable" = $javaPath.Name
}
}
}
@@ -0,0 +1,55 @@
function Initialize-RustEnvironment {
$env:PATH = "/etc/skel/.cargo/bin:/etc/skel/.rustup/bin:$($env:PATH)"
$env:RUSTUP_HOME = "/etc/skel/.rustup"
$env:CARGO_HOME = "/etc/skel/.cargo"
}
function Get-RustVersion {
$rustVersion = $(rustc --version) | Get-StringPart -Part 1
return $rustVersion
}
function Get-BindgenVersion {
$bindgenVersion = $(bindgen --version) | Get-StringPart -Part 1
return $bindgenVersion
}
function Get-CargoVersion {
$cargoVersion = $(cargo --version) | Get-StringPart -Part 1
return $cargoVersion
}
function Get-CargoAuditVersion {
$cargoAuditVersion = $(cargo-audit --version) | Get-StringPart -Part 1
return $cargoAuditVersion
}
function Get-CargoOutdatedVersion {
$cargoOutdatedVersion = cargo outdated --version | Get-StringPart -Part 1
return $cargoOutdatedVersion
}
function Get-CargoClippyVersion {
$cargoClippyVersion = $(cargo-clippy --version) | Get-StringPart -Part 1
return $cargoClippyVersion
}
function Get-CbindgenVersion {
$cbindgenVersion = $(cbindgen --version) | Get-StringPart -Part 1
return $cbindgenVersion
}
function Get-RustupVersion {
$rustupVersion = $(rustup --version) | Get-StringPart -Part 1
return $rustupVersion
}
function Get-RustdocVersion {
$rustdocVersion = $(rustdoc --version) | Get-StringPart -Part 1
return $rustdocVersion
}
function Get-RustfmtVersion {
$rustfmtVersion = $(rustfmt --version) | Get-StringPart -Part 1 | Get-StringPart -Part 0 -Delimiter "-"
return $rustfmtVersion
}
@@ -0,0 +1,281 @@
function Get-AnsibleVersion {
$ansibleVersion = (ansible --version)[0] -replace "[^\d.]"
return $ansibleVersion
}
function Get-AptFastVersion {
$versionFileContent = Get-Content (which apt-fast) -Raw
$match = [Regex]::Match($versionFileContent, '# apt-fast v(.+)\n')
return $match.Groups[1].Value
}
function Get-AzCopyVersion {
$azcopyVersion = [string]$(azcopy --version) | Get-StringPart -Part 2
return "$azcopyVersion - available by ``azcopy`` and ``azcopy10`` aliases"
}
function Get-BazelVersion {
$bazelVersion = bazel --version | Select-String "bazel" | Get-StringPart -Part 1
return $bazelVersion
}
function Get-BazeliskVersion {
$result = Get-CommandResult "bazelisk version" -Multiline
$bazeliskVersion = $result.Output | Select-String "Bazelisk version:" | Get-StringPart -Part 2 | Get-StringPart -Part 0 -Delimiter "v"
return $bazeliskVersion
}
function Get-BicepVersion {
(bicep --version | Out-String) -match "bicep cli version (?<version>\d+\.\d+\.\d+)" | Out-Null
return $Matches.Version
}
function Get-CodeQLBundleVersion {
$CodeQLVersionsWildcard = Join-Path $Env:AGENT_TOOLSDIRECTORY -ChildPath "CodeQL" | Join-Path -ChildPath "*"
$CodeQLVersionPath = Get-ChildItem $CodeQLVersionsWildcard | Select-Object -First 1 -Expand FullName
$CodeQLPath = Join-Path $CodeQLVersionPath -ChildPath "x64" | Join-Path -ChildPath "codeql" | Join-Path -ChildPath "codeql"
$CodeQLVersion = & $CodeQLPath version --quiet
return $CodeQLVersion
}
function Get-PodManVersion {
$podmanVersion = podman --version | Get-StringPart -Part 2
return $podmanVersion
}
function Get-BuildahVersion {
$buildahVersion = buildah --version | Get-StringPart -Part 2
return $buildahVersion
}
function Get-SkopeoVersion {
$skopeoVersion = skopeo --version | Get-StringPart -Part 2
return $skopeoVersion
}
function Get-CMakeVersion {
$cmakeVersion = cmake --version | Select-Object -First 1 | Get-StringPart -Part 2
return $cmakeVersion
}
function Get-DockerComposeV2Version {
$composeVersion = docker compose version | Get-StringPart -Part 3 | Get-StringPart -Part 0 -Delimiter "v"
return $composeVersion
}
function Get-DockerClientVersion {
$dockerClientVersion = sudo docker version --format '{{.Client.Version}}'
return $dockerClientVersion
}
function Get-DockerServerVersion {
$dockerServerVersion = sudo docker version --format '{{.Server.Version}}'
return $dockerServerVersion
}
function Get-DockerBuildxVersion {
$buildxVersion = docker buildx version | Get-StringPart -Part 1 | Get-StringPart -Part 0 -Delimiter "v"
return $buildxVersion
}
function Get-DockerAmazonECRCredHelperVersion {
$ecrVersion = docker-credential-ecr-login -v | Select-String "Version:" | Get-StringPart -Part 1
return $ecrVersion
}
function Get-GitVersion {
$gitVersion = git --version | Get-StringPart -Part -1
return $gitVersion
}
function Get-GitLFSVersion {
$result = Get-CommandResult "git-lfs --version"
$gitlfsversion = $result.Output | Get-StringPart -Part 0 | Get-StringPart -Part 1 -Delimiter "/"
return $gitlfsversion
}
function Get-GitFTPVersion {
$gitftpVersion = git-ftp --version | Get-StringPart -Part 2
return $gitftpVersion
}
function Get-GoogleCloudCLIVersion {
return (gcloud --version | Select-Object -First 1) | Get-StringPart -Part 3
}
function Get-HavegedVersion {
$havegedVersion = dpkg-query --showformat='${Version}' --show haveged | Get-StringPart -Part 0 -Delimiter "-"
return $havegedVersion
}
function Get-HerokuVersion {
$herokuVersion = heroku version | Get-StringPart -Part 0 | Get-StringPart -Part 1 -Delimiter "/"
return $herokuVersion
}
function Get-HHVMVersion {
$hhvmVersion = hhvm --version | Select-Object -First 1 | Get-StringPart -Part 2
return $hhvmVersion
}
function Get-SVNVersion {
$svnVersion = svn --version | Select-Object -First 1 | Get-StringPart -Part 2
return $svnVersion
}
function Get-KustomizeVersion {
$kustomizeVersion = kustomize version --short | Get-StringPart -Part 0 | Get-StringPart -Part 1 -Delimiter "v"
return $kustomizeVersion
}
function Get-KindVersion {
$kindVersion = kind version | Get-StringPart -Part 1 | Get-StringPart -Part 0 -Delimiter "v"
return $kindVersion
}
function Get-KubectlVersion {
$kubectlVersion = (kubectl version --client --output=json | ConvertFrom-Json).clientVersion.gitVersion.Replace('v','')
return $kubectlVersion
}
function Get-MinikubeVersion {
$minikubeVersion = minikube version --short | Get-StringPart -Part 0 -Delimiter "v"
return $minikubeVersion
}
function Get-HGVersion {
$hgVersion = hg --version | Select-Object -First 1 | Get-StringPart -Part -1 | Get-StringPart -Part 0 -Delimiter ")"
return $hgVersion
}
function Get-LeiningenVersion {
return "$(lein -v | Get-StringPart -Part 1)"
}
function Get-MediainfoVersion {
$mediainfoVersion = (mediainfo --version | Select-Object -Index 1 | Get-StringPart -Part 2).Replace('v', '')
return $mediainfoVersion
}
function Get-NewmanVersion {
return $(newman --version)
}
function Get-NVersion {
$nVersion = (n --version).Replace('v', '')
return $nVersion
}
function Get-NvmVersion {
$nvmVersion = bash -c "source /etc/skel/.nvm/nvm.sh && nvm --version"
return $nvmVersion
}
function Get-PackerVersion {
$packerVersion = (packer --version | Select-String "^Packer").Line.Replace('v','') | Get-StringPart -Part 1
return $packerVersion
}
function Get-PhantomJSVersion {
$env:OPENSSL_CONF="/etc/ssl"; phantomjs --version
return $(phantomjs --version)
}
function Get-TerraformVersion {
return (terraform version | Select-String "^Terraform").Line.Replace('v','') | Get-StringPart -Part 1
}
function Get-JqVersion {
$jqVersion = jq --version | Get-StringPart -Part 1 -Delimiter "-"
return $jqVersion
}
function Get-AzureCliVersion {
$azcliVersion = (az version | ConvertFrom-Json).'azure-cli'
return $azcliVersion
}
function Get-AzureDevopsVersion {
$azdevopsVersion = (az version | ConvertFrom-Json).extensions.'azure-devops'
return $azdevopsVersion
}
function Get-AlibabaCloudCliVersion {
return $(aliyun version)
}
function Get-AWSCliVersion {
$result = Get-CommandResult "aws --version"
$awsVersion = $result.Output | Get-StringPart -Part 0 | Get-StringPart -Part 1 -Delimiter "/"
return $awsVersion
}
function Get-AWSCliSessionManagerPluginVersion {
$result = (Get-CommandResult "session-manager-plugin --version").Output
return $result
}
function Get-AWSSAMVersion {
return $(sam --version | Get-StringPart -Part -1)
}
function Get-FastlaneVersion {
$fastlaneVersion = fastlane --version | Select-String "^fastlane [0-9]" | Get-StringPart -Part 1
return $fastlaneVersion
}
function Get-GitHubCliVersion {
$ghVersion = gh --version | Select-String "gh version" | Get-StringPart -Part 2
return $ghVersion
}
function Get-NetlifyCliVersion {
$netlifyVersion = netlify --version | Get-StringPart -Part 0 | Get-StringPart -Part 1 -Delimiter "/"
return $netlifyVersion
}
function Get-OCCliVersion {
$ocVersion = oc version -o=json | jq -r '.releaseClientVersion'
return $ocVersion
}
function Get-ORASCliVersion {
$orasVersion = oras version | Select-String "^Version:" | Get-StringPart -Part 1
return $orasVersion
}
function Get-VerselCliversion {
$result = Get-CommandResult "vercel --version" -Multiline
return $result.Output | Select-Object -Skip 1 -First 1
}
function Get-PulumiVersion {
$pulumiVersion = pulumi version | Get-StringPart -Part 0 -Delimiter "v"
return $pulumiVersion
}
function Get-RVersion {
$rVersion = (Get-CommandResult "R --version | grep 'R version'").Output | Get-StringPart -Part 2
return $rVersion
}
function Get-SphinxVersion {
$sphinxVersion = searchd -h | Select-Object -First 1 | Get-StringPart -Part 1 | Get-StringPart -Part 0 -Delimiter "-"
return $sphinxVersion
}
function Get-YamllintVersion {
return $(yamllint --version) | Get-StringPart -Part 1
}
function Get-ZstdVersion {
$zstdVersion = zstd --version | Get-StringPart -Part 1 -Delimiter "v" | Get-StringPart -Part 0 -Delimiter ","
return "$zstdVersion"
}
function Get-YqVersion {
$yqVersion = $(yq -V) | Get-StringPart -Part 3
return $yqVersion.TrimStart("v").Trim()
}
@@ -0,0 +1,55 @@
function Get-ApacheVersion {
$name = "apache2"
$port = 80
$version = bash -c "apache2 -v | grep -Po 'Apache/(\d+.){2}\d+'" | Get-StringPart -Part 1 -Delimiter "/"
$serviceStatus = systemctl status apache2 | grep "Active:" | Get-StringPart -Part 1
$configFile = "/etc/apache2/apache2.conf"
return [PsCustomObject]@{
"Name" = $name
"Version" = $version
"ConfigFile" = $configFile
"ServiceStatus" = $serviceStatus
"ListenPort" = $port
}
}
function Get-NginxVersion {
$name = "nginx"
$port = 80
$version = (dpkg-query --showformat='${Version}' --show nginx).Split('-')[0]
$serviceStatus = systemctl status nginx | grep "Active:" | Get-StringPart -Part 1
$configFile = "/etc/nginx/nginx.conf"
return [PsCustomObject]@{
"Name" = $name
"Version" = $version
"ConfigFile" = $configFile
"ServiceStatus" = $serviceStatus
"ListenPort" = $port
}
}
function Get-Xsp4Version {
$name = "mono-xsp4"
$port = (grep '^port=' /etc/default/mono-xsp4).Split('=')[1]
$version = (dpkg-query --showformat='${Version}' --show mono-xsp4).Split('-')[0]
$serviceStatus = systemctl show -p ActiveState --value mono-xsp4
$configFile = "/etc/default/mono-xsp4"
return [PsCustomObject]@{
"Name" = $name
"Version" = $version
"ConfigFile" = $configFile
"ServiceStatus" = $serviceStatus
"ListenPort" = $port
}
}
function Build-WebServersTable {
$servers = @()
$servers += (Get-ApacheVersion)
if (Test-IsUbuntu20) {
$servers += (Get-Xsp4Version)
}
$servers += (Get-NginxVersion)
return $servers
}
@@ -0,0 +1,156 @@
function Get-CommandResult {
<#
.SYNOPSIS
Runs a command in bash and returns the output and exit code.
.DESCRIPTION
Function runs a provided command in bash and returns the output and exit code as hashtable.
.PARAMETER Command
The command to run.
.PARAMETER ExpectedExitCode
The expected exit code. If the actual exit code does not match, an exception is thrown.
.PARAMETER Multiline
If true, the output is returned as an array of strings. Otherwise, the output is returned as a single string.
.PARAMETER ValidateExitCode
If true, the actual exit code is compared to the expected exit code.
.EXAMPLE
$result = Get-CommandResult "ls -la"
This command runs "ls -la" in bash and returns the output and exit code as hashtable.
#>
param(
[Parameter(Mandatory=$true)]
[string] $Command,
[int[]] $ExpectedExitCode = 0,
[switch] $Multiline,
[bool] $ValidateExitCode = $true
)
# Bash trick to suppress and show error output because some commands write to stderr (for example, "python --version")
$stdout = & bash -c "$Command 2>&1"
$exitCode = $LASTEXITCODE
if ($ValidateExitCode) {
if ($ExpectedExitCode -notcontains $exitCode) {
try {
throw "StdOut: '$stdout' ExitCode: '$exitCode'"
} catch {
Write-Host $_.Exception.Message
Write-Host $_.ScriptStackTrace
exit $LASTEXITCODE
}
}
}
return @{
Output = If ($Multiline -eq $true) { $stdout } else { [string] $stdout }
ExitCode = $exitCode
}
}
function Test-IsUbuntu20 {
return (lsb_release -rs) -eq "20.04"
}
function Test-IsUbuntu22 {
return (lsb_release -rs) -eq "22.04"
}
function Test-IsUbuntu24 {
return (lsb_release -rs) -eq "24.04"
}
function Get-ToolsetContent {
<#
.SYNOPSIS
Retrieves the content of the toolset.json file.
.DESCRIPTION
This function reads the toolset.json in path provided by INSTALLER_SCRIPT_FOLDER
environment variable and returns the content as a PowerShell object.
#>
$toolsetPath = Join-Path $env:INSTALLER_SCRIPT_FOLDER "toolset.json"
$toolsetJson = Get-Content -Path $toolsetPath -Raw
ConvertFrom-Json -InputObject $toolsetJson
}
function Invoke-DownloadWithRetry {
<#
.SYNOPSIS
Downloads a file from a given URL with retry functionality.
.DESCRIPTION
The Invoke-DownloadWithRetry function downloads a file from the specified URL
to the specified path. It includes retry functionality in case the download fails.
.PARAMETER Url
The URL of the file to download.
.PARAMETER Path
The path where the downloaded file will be saved. If not provided, a temporary path
will be used.
.EXAMPLE
Invoke-DownloadWithRetry -Url "https://example.com/file.zip" -Path "/usr/local/bin"
Downloads the file from the specified URL and saves it to the specified path.
.EXAMPLE
Invoke-DownloadWithRetry -Url "https://example.com/file.zip"
Downloads the file from the specified URL and saves it to a temporary path.
.OUTPUTS
The path where the downloaded file is saved.
#>
param(
[Parameter(Mandatory)]
[string] $Url,
[Alias("Destination")]
[string] $DestinationPath
)
if (-not $DestinationPath) {
$invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''
$re = "[{0}]" -f [RegEx]::Escape($invalidChars)
$fileName = [IO.Path]::GetFileName($Url) -replace $re
if ([String]::IsNullOrEmpty($fileName)) {
$fileName = [System.IO.Path]::GetRandomFileName()
}
$DestinationPath = Join-Path -Path "/tmp" -ChildPath $fileName
}
Write-Host "Downloading package from $Url to $DestinationPath..."
$interval = 30
$downloadStartTime = Get-Date
for ($retries = 20; $retries -gt 0; $retries--) {
try {
$attemptStartTime = Get-Date
(New-Object System.Net.WebClient).DownloadFile($Url, $DestinationPath)
$attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2)
Write-Host "Package downloaded in $attemptSeconds seconds"
break
} catch {
$attemptSeconds = [math]::Round(($(Get-Date) - $attemptStartTime).TotalSeconds, 2)
Write-Warning "Package download failed in $attemptSeconds seconds"
Write-Warning $_.Exception.Message
}
if ($retries -eq 0) {
$totalSeconds = [math]::Round(($(Get-Date) - $downloadStartTime).TotalSeconds, 2)
throw "Package download failed after $totalSeconds seconds"
}
Write-Warning "Waiting $interval seconds before retrying (retries left: $retries)..."
Start-Sleep -Seconds $interval
}
return $DestinationPath
}
@@ -0,0 +1,89 @@
#!/bin/bash -e
################################################################################
## File: etc-environment.sh
## Desc: Helper functions for source and modify /etc/environment
################################################################################
# NB: sed expression use '%' as a delimiter in order to simplify handling
# values containg slashes (i.e. directory path)
# The values containing '%' will break the functions
get_etc_environment_variable() {
local variable_name=$1
# remove `variable_name=` and possible quotes from the line
grep "^${variable_name}=" /etc/environment | sed -E "s%^${variable_name}=\"?([^\"]+)\"?.*$%\1%"
}
add_etc_environment_variable() {
local variable_name=$1
local variable_value=$2
echo "${variable_name}=${variable_value}" | sudo tee -a /etc/environment
}
replace_etc_environment_variable() {
local variable_name=$1
local variable_value=$2
# modify /etc/environemnt in place by replacing a string that begins with variable_name
sudo sed -i -e "s%^${variable_name}=.*$%${variable_name}=${variable_value}%" /etc/environment
}
set_etc_environment_variable() {
local variable_name=$1
local variable_value=$2
if grep "^${variable_name}=" /etc/environment > /dev/null; then
replace_etc_environment_variable $variable_name $variable_value
else
add_etc_environment_variable $variable_name $variable_value
fi
}
prepend_etc_environment_variable() {
local variable_name=$1
local element=$2
# TODO: handle the case if the variable does not exist
existing_value=$(get_etc_environment_variable "${variable_name}")
set_etc_environment_variable "${variable_name}" "${element}:${existing_value}"
}
append_etc_environment_variable() {
local variable_name=$1
local element=$2
# TODO: handle the case if the variable does not exist
existing_value=$(get_etc_environment_variable "${variable_name}")
set_etc_environment_variable "${variable_name}" "${existing_value}:${element}"
}
prepend_etc_environment_path() {
local element=$1
prepend_etc_environment_variable PATH "${element}"
}
append_etc_environment_path() {
local element=$1
append_etc_environment_variable PATH "${element}"
}
# Process /etc/environment as if it were shell script with `export VAR=...` expressions
# The PATH variable is handled specially in order to do not override the existing PATH
# variable. The value of PATH variable read from /etc/environment is added to the end
# of value of the exiting PATH variable exactly as it would happen with real PAM app read
# /etc/environment
#
# TODO: there might be the others variables to be processed in the same way as "PATH" variable
# ie MANPATH, INFOPATH, LD_*, etc. In the current implementation the values from /etc/evironments
# replace the values of the current environment
reload_etc_environment() {
# add `export ` to every variable of /etc/environemnt except PATH and eval the result shell script
eval $(grep -v '^PATH=' /etc/environment | sed -e 's%^%export %')
# handle PATH specially
etc_path=$(get_etc_environment_variable PATH)
export PATH="$PATH:$etc_path"
}
+242
View File
@@ -0,0 +1,242 @@
#!/bin/bash -e
################################################################################
## File: install.sh
## Desc: Helper functions for installing tools
################################################################################
download_with_retry() {
local url=$1
local download_path=$2
if [ -z "$download_path" ]; then
download_path="/tmp/$(basename "$url")"
fi
echo "Downloading package from $url to $download_path..." >&2
interval=30
download_start_time=$(date +%s)
for ((retries=20; retries>0; retries--)); do
attempt_start_time=$(date +%s)
if http_code=$(curl -4sSLo "$download_path" "$url" -w '%{http_code}'); then
attempt_seconds=$(($(date +%s) - attempt_start_time))
if [ "$http_code" -eq 200 ]; then
echo "Package downloaded in $attempt_seconds seconds" >&2
break
else
echo "Received HTTP status code $http_code after $attempt_seconds seconds" >&2
fi
else
attempt_seconds=$(($(date +%s) - attempt_start_time))
echo "Package download failed in $attempt_seconds seconds" >&2
fi
if [ "$retries" -le 1 ]; then
total_seconds=$(($(date +%s) - download_start_time))
echo "Package download failed after $total_seconds seconds" >&2
exit 1
fi
echo "Waiting $interval seconds before retrying (retries left: $retries)..." >&2
sleep $interval
done
echo "$download_path"
}
get_toolset_value() {
local toolset_path="${INSTALLER_SCRIPT_FOLDER}/toolset.json"
local query=$1
echo "$(jq -r "$query" $toolset_path)"
}
get_github_releases_by_version() {
local repo=$1
local version=${2:-".+"}
local allow_pre_release=${3:-false}
local with_assets_only=${4:-false}
page_size="100"
json=$(curl -fsSL "https://api.github.com/repos/${repo}/releases?per_page=${page_size}")
if [[ -z "$json" ]]; then
echo "Failed to get releases" >&2
exit 1
fi
if [[ $with_assets_only == "true" ]]; then
json=$(echo $json | jq -r '.[] | select(.assets | length > 0)')
else
json=$(echo $json | jq -r '.[]')
fi
if [[ $allow_pre_release == "true" ]]; then
json=$(echo $json | jq -r '.')
else
json=$(echo $json | jq -r '. | select(.prerelease==false)')
fi
# Filter out rc/beta/etc releases, convert to numeric version and sort
json=$(echo $json | jq '. | select(.tag_name | test(".*-[a-z]|beta") | not)' | jq '.tag_name |= gsub("[^\\d.]"; "")' | jq -s 'sort_by(.tag_name | split(".") | map(tonumber))')
# Select releases matching version
if [[ $version == "latest" ]]; then
json_filtered=$(echo $json | jq .[-1])
elif [[ $version == *"+"* ]] || [[ $version == *"*"* ]]; then
json_filtered=$(echo $json | jq --arg version $version '.[] | select(.tag_name | test($version))')
else
json_filtered=$(echo $json | jq --arg version $version '.[] | select(.tag_name | contains($version))')
fi
if [[ -z "$json_filtered" ]]; then
echo "Failed to get releases from ${repo} matching version ${version}" >&2
echo "Available versions: $(echo "$json" | jq -r '.tag_name')" >&2
exit 1
fi
echo $json_filtered
}
resolve_github_release_asset_url() {
local repo=$1
local url_filter=$2
local version=${3:-".+"}
local allow_pre_release=${4:-false}
local allow_multiple_matches=${5:-false}
matching_releases=$(get_github_releases_by_version "${repo}" "${version}" "${allow_pre_release}" "true")
matched_url=$(echo $matching_releases | jq -r ".assets[].browser_download_url | select(${url_filter})")
if [[ -z "$matched_url" ]]; then
echo "Found no download urls matching pattern: ${url_filter}" >&2
echo "Available download urls: $(echo "$matching_releases" | jq -r '.assets[].browser_download_url')" >&2
exit 1
fi
if [[ "$(echo "$matched_url" | wc -l)" -gt 1 ]]; then
if [[ $allow_multiple_matches == "true" ]]; then
matched_url=$(echo "$matched_url" | tail -n 1)
else
echo "Multiple matches found for ${version} version and ${url_filter} URL filter. Please make filters more specific" >&2
exit 1
fi
fi
echo $matched_url
}
get_checksum_from_github_release() {
local repo=$1
local file_name=$2
local version=${3:-".+"}
local hash_type=$4
local allow_pre_release=${5:-false}
if [[ -z "$file_name" ]]; then
echo "File name is not specified." >&2
exit 1
fi
if [[ "$hash_type" == "SHA256" ]]; then
hash_pattern="[A-Fa-f0-9]{64}"
elif [[ "$hash_type" == "SHA512" ]]; then
hash_pattern="[A-Fa-f0-9]{128}"
else
echo "Unknown hash type: ${hash_type}" >&2
exit 1
fi
matching_releases=$(get_github_releases_by_version "${repo}" "${version}" "${allow_pre_release}" "true")
matched_line=$(printf "$(echo $matching_releases | jq '.body')\n" | grep "$file_name")
if [[ -z "$matched_line" ]]; then
echo "File name ${file_name} not found in release body" >&2
exit 1
fi
if [[ "$(echo "$matched_line" | wc -l)" -gt 1 ]]; then
echo "Multiple matches found for ${file_name} in release body: ${matched_line}" >&2
exit 1
fi
hash=$(echo $matched_line | grep -oP "$hash_pattern")
if [[ -z "$hash" ]]; then
echo "Found ${file_name} in body of release, but failed to get hash from it: ${matched_line}" >&2
exit 1
fi
echo "$hash"
}
get_checksum_from_url() {
local url=$1
local file_name=$2
local hash_type=$3
local use_custom_search_pattern=${4:-false}
local delimiter=${5:-' '}
local word_number=${6:-1}
if [[ "$hash_type" == "SHA256" ]]; then
hash_pattern="[A-Fa-f0-9]{64}"
elif [[ "$hash_type" == "SHA512" ]]; then
hash_pattern="[A-Fa-f0-9]{128}"
else
echo "Unknown hash type: ${hash_type}" >&2
exit 1
fi
checksums_file_path=$(download_with_retry "$url")
checksums=$(cat "$checksums_file_path")
rm "$checksums_file_path"
matched_line=$(printf "$checksums\n" | grep "$file_name")
if [[ "$(echo "$matched_line" | wc -l)" -gt 1 ]]; then
echo "Found multiple lines matching file name ${file_name} in checksum file." >&2
exit 1
fi
if [[ -z "$matched_line" ]]; then
echo "File name ${file_name} not found in checksum file." >&2
exit 1
fi
if [[ $use_custom_search_pattern == "true" ]]; then
hash=$(echo "$matched_line" | sed 's/ */ /g' | cut -d "$delimiter" -f "$word_number" | tr -d -c '[:alnum:]')
else
hash=$(echo $matched_line | grep -oP "$hash_pattern")
fi
if [[ -z "$hash" ]]; then
echo "Found ${file_name} in checksum file, but failed to get hash from it: ${matched_line}" >&2
exit 1
fi
echo "$hash"
}
use_checksum_comparison() {
local file_path=$1
local checksum=$2
local sha_type=${3:-"256"}
echo "Performing checksum verification"
if [[ ! -f "$file_path" ]]; then
echo "File not found: $file_path"
exit 1
fi
local_file_hash=$(shasum --algorithm "$sha_type" "$file_path" | awk '{print $1}')
if [[ "$local_file_hash" != "$checksum" ]]; then
echo "Checksum verification failed. Expected hash: $checksum; Actual hash: $local_file_hash."
exit 1
else
echo "Checksum verification passed"
fi
}
@@ -0,0 +1,8 @@
#!/bin/bash -e
################################################################################
## File: invoke-tests.sh
## Desc: Helper function for invoking tests
################################################################################
pwsh -Command "Import-Module '$HELPER_SCRIPTS/../tests/Helpers.psm1' -DisableNameChecking
Invoke-PesterTests -TestFile \"$1\" -TestName \"$2\""
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash -e
################################################################################
## File: os.sh
## Desc: Helper functions for OS releases
################################################################################
is_ubuntu20() {
lsb_release -rs | grep -q '20.04'
}
is_ubuntu22() {
lsb_release -rs | grep -q '22.04'
}
is_ubuntu24() {
lsb_release -rs | grep -q '24.04'
}
@@ -0,0 +1,18 @@
Describe "ActionArchiveCache" {
BeforeDiscovery {
$actionArchiveCachePath = "/opt/actionarchivecache"
$tarballTestCases = Get-ChildItem -Path "$actionArchiveCachePath/*.tar.gz" -Recurse | ForEach-Object { @{ ActionTarball = $_.FullName } }
}
Context "Action archive cache directory not empty" {
It "<ActionArchiveCachepath> not empty" -TestCases @{ ActionArchiveCachepath = $actionArchiveCachePath } {
(Get-ChildItem -Path "$ActionArchiveCachepath/*.tar.gz" -Recurse).Count | Should -BeGreaterThan 0
}
}
Context "Action tarball not empty" {
It "<ActionTarball>" -TestCases $tarballTestCases {
(Get-Item "$ActionTarball").Length | Should -BeGreaterThan 0
}
}
}

Some files were not shown because too many files have changed in this diff Show More