Skip to content

Commit

Permalink
Use vcpkg to install Windows dependencies
Browse files Browse the repository at this point in the history
It looks like vcpkg is a most correct way to install Postgres packages
in Windows. There are 4 steps to install packages via vcpkg:

1- Create a base Windows image which has dependencies to run vcpkg.

2- Install packages via vcpkg and save & upload the vcpkg cache. Reuse
that cache on the next install.

3- Create a Windows image from the base image (step #1). While
installing packages via vcpkg, use cache from step anarazel#2.

4- Delete Windows base image.

Important note: After this PR is merged, extra_*_dirs needs to be
removed from Windows task in Postgres.
  • Loading branch information
nbyavuz committed Jun 7, 2024
1 parent 79e6763 commit 588a285
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 143 deletions.
108 changes: 90 additions & 18 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ env:
# GCP_REGION
# GCP_REPO

# It is easier to manage VCKPG_PACKAGES in a single place
VCPKG_PACKAGES: |
gettext icu libxml2 libxslt lz4 openssl pkgconf python3 tcl zlib zstd
# central definition for the tasks interacting with gcp

Expand Down Expand Up @@ -101,36 +105,43 @@ task:
name: 'Building VM Image: ${IMAGE_NAME}'
alias: vmbuild-${TASK_NAME}
matrix:
- env:
TASK_NAME: freebsd-13
PACKERFILE: packer/freebsd.pkr.hcl

- env:
PACKERFILE: packer/linux_debian.pkr.hcl
SCRIPTS: scripts/linux_debian_*

- depends_on: cleanup-leftover-running
matrix:
- env:
TASK_NAME: bookworm
- env:
TASK_NAME: bullseye
- env:
TASK_NAME: sid
TASK_NAME: freebsd-13
PACKERFILE: packer/freebsd.pkr.hcl

- env:
TASK_NAME: sid-newkernel
PACKERFILE: packer/linux_debian.pkr.hcl
SCRIPTS: scripts/linux_debian_*

matrix:
- env:
TASK_NAME: bookworm
- env:
TASK_NAME: bullseye
- env:
TASK_NAME: sid
- env:
TASK_NAME: sid-newkernel
- env:
TASK_NAME: sid-newkernel-uring

- env:
TASK_NAME: sid-newkernel-uring
PACKERFILE: packer/windows_base.pkr.hcl
TASK_NAME: windows-base
SCRIPTS: scripts/windows_install_vs_2019.ps1

- env:
# build-vcpkg-cache task already depends on cleanup-leftover-running task
- depends_on: build-vcpkg-cache
env:
PACKERFILE: packer/windows.pkr.hcl
SCRIPTS: scripts/windows*
TASK_NAME: windows-ci

env:
IMAGE_NAME: ${PREFIX}-${TASK_NAME}

depends_on: cleanup-leftover-running

container:
dockerfile: docker/linux_debian_packer
cpu: 0.5
Expand Down Expand Up @@ -172,6 +183,67 @@ task:
${IMAGE_NAME}-${DATE}
task:
name: 'Build VCPKG Cache'
alias: build-vcpkg-cache
depends_on: vmbuild-windows-base

env:
VCPKG_PATH: ${CIRRUS_WORKING_DIR}\vcpkg
VCPKG_CACHE: ${VCPKG_PATH}\binary_cache
CIRRUS_SHELL: powershell
ErrorActionPreference: Stop

compute_engine_instance:
image_project: $GCP_PROJECT
image: family/pg-ci-windows-base
platform: windows
cpu: 4
disk: 50

sysinfo_script: |
chcp
systeminfo
get-psdrive -psprovider filesystem
Get-ChildItem -Path Env:
clone_vcpkg_script:
git clone --depth 1 https://github.com/Microsoft/vcpkg.git ${Env:VCPKG_PATH}

vcpkg_cache:
folder: ${VCPKG_CACHE}

install_vcpkg_packages_script: |
cd ${Env:VCPKG_PATH}
.\bootstrap-vcpkg.bat -disableMetrics
.\vcpkg.exe install --debug --binarysource=files,${Env:VCPKG_CACHE},readwrite ${Env:VCPKG_PACKAGES} --triplet=x64-windows
if (!$?) { throw 'cmdfail' }
upload_caches: vcpkg

zip_vcpkg_cache_script: |
7z.exe a -r vcpkg_cache.zip ${Env:VCPKG_CACHE}\*
vcpkg_cache_zip_artifacts:
path: vcpkg_cache.zip


task:
name: Clean up Windows base images
depends_on: vmbuild-windows-ci

container:
dockerfile: docker/linux_debian_packer
cpu: 0.5
memory: 256Mi

<<: *gcp_auth_unix

# There could be leftover windows-base images, so delete all of them
cleanup_windows_base_images_script: |
export IMAGES=$(gcloud compute images list --project $GCP_PROJECT --format='object value(name)' --no-standard-images | grep "$PREFIX-windows-base")
gcloud compute images delete --quiet --project $GCP_PROJECT $IMAGES
task:
name: 'Building VM Image: ${IMAGE_NAME}'
alias: vmbuild-${TASK_NAME}
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ pre-commit:
-var "image_date=$(IMAGE_DATE)" \
-var "image_name=bookworm" \
packer/linux_debian.pkr.hcl
# Windows Base VM
packer validate \
-var gcp_project=pg-ci-images-dev \
-var "image_date=$(IMAGE_DATE)" \
-var "image_name=windows-ci-base" \
packer/windows_base.pkr.hcl
# Windows VM
packer validate \
-var gcp_project=pg-ci-images-dev \
Expand Down
74 changes: 22 additions & 52 deletions packer/windows.pkr.hcl
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
variable "image_name" { type = string }
variable "image_date" { type = string }

variable "build_type" {
type = string
default = "googlecompute"
variable "cirrus_build_id" {
default = env("CIRRUS_BUILD_ID")
}

variable "VCPKG_PACKAGES" {
default = env("VCPKG_PACKAGES")
}

# Packer doesn't capture errors correctly when default execute command is used.
Expand All @@ -23,7 +26,6 @@ locals {
image_identity = "${var.image_name}-${var.image_date}"

perl_version = "5.26.3.1"
python_version = "3.10.6"

windows_gcp_images = [
{
Expand All @@ -36,7 +38,7 @@ source "googlecompute" "windows" {
disk_size = "50"
disk_type = "pd-ssd"
project_id = var.gcp_project
source_image_family = "windows-2022"
source_image_family = "pg-ci-windows-base"
image_name = local.image_identity
zone = "us-west1-a"
machine_type = "t2d-standard-4"
Expand All @@ -59,38 +61,17 @@ build {
# so we can easily combine the packer invocations later
dynamic "source" {
for_each = local.windows_gcp_images
labels = ["source.${var.build_type}.windows"]
labels = ["source.googlecompute.windows"]
iterator = tag

content {
name = tag.value.task_name
}
}

### base installations
# googlecompute only
provisioner "powershell" {
execute_command = var.execute_command
inline = [
"$ErrorActionPreference = 'Stop'",
# disable antivirus
"Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable",

# install choco
"Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))",

"choco install -y --no-progress 7zip",
"choco install -y --no-progress git --parameters=\"/GitAndUnixToolsOnPath\"",
]
}

provisioner "powershell" {
execute_command = var.execute_command
inline = [
"$ErrorActionPreference = 'Stop'",
# contains useful utilities, including a diff we can use
"[Environment]::SetEnvironmentVariable('PATH', 'C:\\Program Files\\Git\\usr\\bin;' + [Environment]::GetEnvironmentVariable('PATH', 'Machine'), 'Machine')",

# set IMAGE_IDENTITY to distinguish images on CI runs
"[Environment]::SetEnvironmentVariable('IMAGE_IDENTITY', '${local.image_identity}', 'Machine')",
]
Expand All @@ -102,19 +83,25 @@ build {
script = "scripts/windows_install_dbg.ps1"
}

# install python
### vs-2019 installations
provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_install_winflexbison.ps1"
}

provisioner "powershell" {
execute_command = var.execute_command
environment_vars = ["TEMP_PYTHON_VERSION=${local.python_version}"]
script = "scripts/windows_install_python.ps1"
environment_vars = ["CIRRUS_BUILD_ID=${var.cirrus_build_id}",
"VCPKG_PACKAGES=${var.VCPKG_PACKAGES}"]
script = "scripts/windows_install_pg_deps.ps1"
}

# install meson and ninja
provisioner "powershell" {
execute_command = var.execute_command
inline = [
"$ErrorActionPreference = 'Stop'",
"py -m pip install meson ninja"
"python3 -m ensurepip",
"python3 -m pip install meson ninja"
]
}

Expand All @@ -134,13 +121,7 @@ build {
"[Environment]::SetEnvironmentVariable('PATH', \"C:\\strawberry\\${local.perl_version}\\perl\\bin;\" + [Environment]::GetEnvironmentVariable('PATH', 'Machine'), 'Machine')",
]
}

# install openssl
provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_install_openssl.ps1"
}
### end of base installations
### end of vs-2019 installations

### mingw installations
provisioner "powershell" {
Expand Down Expand Up @@ -178,20 +159,9 @@ build {
}
### end of mingw installations

### vs-2019 installations
# clean unnecessary files
provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_install_winflexbison.ps1"
script = "scripts/windows_clean_unnecessary_files.ps1"
}

provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_install_pg_deps.ps1"
}

provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_install_vs_2019.ps1"
}
### end of vs-2019 installations
}
77 changes: 77 additions & 0 deletions packer/windows_base.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
variable "image_name" { type = string }
variable "image_date" { type = string }
variable "gcp_project" {type = string}

# Packer doesn't capture errors correctly when default execute command is used.
# See $ErrorActionPreference = 'Stop' in the new execute_command.
# So, use new execute_command to handle VM errors correctly
variable "execute_command" {
type = string
default = "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'}; $ErrorActionPreference = 'Stop' ;. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }\""
}

locals {
image_identity = "${var.image_name}-${var.image_date}"
}

source "googlecompute" "windows-base" {
disk_size = "50"
disk_type = "pd-ssd"
project_id = var.gcp_project
source_image_family = "windows-2022"
image_name = local.image_identity
zone = "us-west1-a"
machine_type = "t2d-standard-4"
instance_name = "build-${local.image_identity}"
communicator = "winrm"
winrm_username = "packer_user"
winrm_insecure = true
winrm_use_ssl = true
winrm_timeout = "10m"
state_timeout = "10m"
metadata = {
windows-startup-script-cmd = "winrm quickconfig -quiet & net user /add packer_user & net localgroup administrators packer_user /add & winrm set winrm/config/service/auth @{Basic=\"true\"}"
}
}

build {
sources = ["googlecompute.windows-base"]

provisioner "powershell" {
execute_command = var.execute_command
inline = [
"$ErrorActionPreference = 'Stop'",
# disable antivirus
"Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable",

# install choco
"Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))",

"choco install -y --no-progress 7zip",
"choco install -y --no-progress git --parameters=\"/GitAndUnixToolsOnPath\"",
]
}

provisioner "powershell" {
execute_command = var.execute_command
inline = [
"$ErrorActionPreference = 'Stop'",
# contains useful utilities, including a diff we can use
"[Environment]::SetEnvironmentVariable('PATH', 'C:\\Program Files\\Git\\usr\\bin;' + [Environment]::GetEnvironmentVariable('PATH', 'Machine'), 'Machine')",

# set BASE_IMAGE_IDENTITY to distinguish images on CI runs
"[Environment]::SetEnvironmentVariable('BASE_IMAGE_IDENTITY', '${local.image_identity}', 'Machine')",
]
}

provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_install_vs_2019.ps1"
}

# clean unnecessary files
provisioner "powershell" {
execute_command = var.execute_command
script = "scripts/windows_clean_unnecessary_files.ps1"
}
}
7 changes: 7 additions & 0 deletions scripts/windows_clean_unnecessary_files.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Do not error out if files do not exist
$ErrorActionPreference = "SilentlyContinue"

cd c:\
Remove-Item C:\t -Force -Recurse
Remove-Item -Force -Recurse ${Env:TEMP}\*
Remove-Item -Force -Recurse "${Env:ProgramData}\Package Cache"
Loading

0 comments on commit 588a285

Please sign in to comment.