Skip to content

Commit a950367

Browse files
authored
[7.17] [buildkite] Add Windows packaging and platform support tests to periodic pipeline (#98072) (#98329)
* [buildkite] Add Windows packaging and platform support tests to periodic pipeline (#98072) (cherry picked from commit dfadca8)
1 parent 97d53db commit a950367

File tree

8 files changed

+299
-25
lines changed

8 files changed

+299
-25
lines changed

.buildkite/hooks/pre-command.bat

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@ECHO OFF
2+
3+
FOR /F "tokens=* eol=#" %%i in ('type .ci\java-versions.properties') do set %%i
4+
5+
SET JAVA_HOME=%USERPROFILE%\.java\%ES_BUILD_JAVA%
6+
SET JAVA11_HOME=%USERPROFILE%\.java\java11
7+
SET JAVA16_HOME=%USERPROFILE%\.java\openjdk16
8+
9+
SET GRADLEW=./gradlew --parallel --no-daemon --scan --build-cache --no-watch-fs -Dorg.elasticsearch.build.cache.url=https://gradle-enterprise.elastic.co/cache/
10+
SET GRADLEW_BAT=./gradlew.bat --parallel --no-daemon --scan --build-cache --no-watch-fs -Dorg.elasticsearch.build.cache.url=https://gradle-enterprise.elastic.co/cache/
11+
12+
(if not exist "%USERPROFILE%/.gradle" mkdir "%USERPROFILE%/.gradle") && (echo. >> "%USERPROFILE%/.gradle/gradle.properties" && echo org.gradle.daemon=false >> "%USERPROFILE%/.gradle/gradle.properties")
13+
14+
set WORKSPACE=%cd%
15+
set BUILD_NUMBER=%BUILDKITE_BUILD_NUMBER%
16+
set COMPOSE_HTTP_TIMEOUT=120
17+
set JOB_BRANCH=%BUILDKITE_BRANCH%
18+
19+
set GRADLE_BUILD_CACHE_USERNAME=vault read -field=username secret/ci/elastic-elasticsearch/migrated/gradle-build-cache
20+
set GRADLE_BUILD_CACHE_PASSWORD=vault read -field=password secret/ci/elastic-elasticsearch/migrated/gradle-build-cache
21+
22+
exit /b 0

.buildkite/pipelines/periodic.yml

+43
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,46 @@ steps:
4545
buildDirectory: /dev/shm/bk
4646
env:
4747
ES_RUNTIME_JAVA: "{{matrix.ES_RUNTIME_JAVA}}"
48+
- group: packaging-tests-windows
49+
steps:
50+
- label: "{{matrix.image}} / packaging-tests-windows"
51+
command: |
52+
.\.buildkite\scripts\run-script.ps1 .\.ci\scripts\packaging-test.ps1
53+
timeout_in_minutes: 180
54+
matrix:
55+
setup:
56+
image:
57+
- windows-2016
58+
- windows-2019
59+
- windows-2022
60+
agents:
61+
provider: gcp
62+
image: family/elasticsearch-{{matrix.image}}
63+
machineType: custom-32-98304
64+
diskType: pd-ssd
65+
diskSizeGb: 350
66+
env: {}
67+
- group: platform-support-windows
68+
steps:
69+
- label: "{{matrix.image}} / {{matrix.GRADLE_TASK}} / platform-support-windows"
70+
command: |
71+
.\.buildkite\scripts\run-script.ps1 bash .buildkite/scripts/windows-run-gradle.sh
72+
timeout_in_minutes: 360
73+
matrix:
74+
setup:
75+
image:
76+
- windows-2016
77+
- windows-2019
78+
- windows-2022
79+
GRADLE_TASK:
80+
- checkPart1
81+
- checkPart2
82+
- bwcTestSnapshots
83+
agents:
84+
provider: gcp
85+
image: family/elasticsearch-{{matrix.image}}
86+
machineType: custom-32-98304
87+
diskType: pd-ssd
88+
diskSizeGb: 350
89+
env:
90+
GRADLE_TASK: "{{matrix.GRADLE_TASK}}"

.buildkite/scripts/run-script.ps1

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Usage: .buildkite/scripts/run-script.ps1 <script-or-simple-command>
2+
# Example: .buildkite/scripts/run-script.ps1 bash .buildkite/scripts/tests.sh
3+
# Example: .buildkite/scripts/run-script.ps1 .buildkite/scripts/other-tests.ps1
4+
#
5+
# NOTE: Apparently passing arguments in powershell is a nightmare, so you shouldn't do it unless it's really simple. Just use the wrapper to call a script instead.
6+
# See: https://stackoverflow.com/questions/6714165/powershell-stripping-double-quotes-from-command-line-arguments
7+
# and: https://github.com/PowerShell/PowerShell/issues/3223#issuecomment-487975049
8+
#
9+
# See here: https://github.com/buildkite/agent/issues/2202
10+
# Background processes after the buildkite step script finishes causes the job to hang.
11+
# So, until this is fixed/changed in buildkite-agent (if ever), we can use this wrapper.
12+
13+
# This wrapper:
14+
# - Creates a Windows job object (which is like a process group)
15+
# - Sets JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, which means that when the job object is closed, all processes in the job object are killed
16+
# - Starts running your given script, and assigns it to the job object
17+
# - Now, any child processes created by your script will also end up in the job object
18+
# - Waits for your script (and only your script, not child processes) to finish
19+
# - Closes the job object, which kills all processes in the job object (including any leftover child processes)
20+
# - Exits with the exit status from your script
21+
22+
Add-Type -TypeDefinition @'
23+
using Microsoft.Win32.SafeHandles;
24+
using System;
25+
using System.ComponentModel;
26+
using System.Runtime.InteropServices;
27+
28+
public class NativeMethods
29+
{
30+
public enum JOBOBJECTINFOCLASS
31+
{
32+
AssociateCompletionPortInformation = 7,
33+
BasicLimitInformation = 2,
34+
BasicUIRestrictions = 4,
35+
EndOfJobTimeInformation = 6,
36+
ExtendedLimitInformation = 9,
37+
SecurityLimitInformation = 5,
38+
GroupInformation = 11
39+
}
40+
41+
[StructLayout(LayoutKind.Sequential)]
42+
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
43+
{
44+
public Int64 PerProcessUserTimeLimit;
45+
public Int64 PerJobUserTimeLimit;
46+
public UInt32 LimitFlags;
47+
public UIntPtr MinimumWorkingSetSize;
48+
public UIntPtr MaximumWorkingSetSize;
49+
public UInt32 ActiveProcessLimit;
50+
public Int64 Affinity;
51+
public UInt32 PriorityClass;
52+
public UInt32 SchedulingClass;
53+
}
54+
55+
[StructLayout(LayoutKind.Sequential)]
56+
struct IO_COUNTERS
57+
{
58+
public UInt64 ReadOperationCount;
59+
public UInt64 WriteOperationCount;
60+
public UInt64 OtherOperationCount;
61+
public UInt64 ReadTransferCount;
62+
public UInt64 WriteTransferCount;
63+
public UInt64 OtherTransferCount;
64+
}
65+
66+
[StructLayout(LayoutKind.Sequential)]
67+
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
68+
{
69+
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
70+
public IO_COUNTERS IoInfo;
71+
public UIntPtr ProcessMemoryLimit;
72+
public UIntPtr JobMemoryLimit;
73+
public UIntPtr PeakProcessMemoryUsed;
74+
public UIntPtr PeakJobMemoryUsed;
75+
}
76+
77+
[DllImport("Kernel32.dll", EntryPoint = "AssignProcessToJobObject", SetLastError = true)]
78+
private static extern bool NativeAssignProcessToJobObject(SafeHandle hJob, SafeHandle hProcess);
79+
80+
public static void AssignProcessToJobObject(SafeHandle job, SafeHandle process)
81+
{
82+
if (!NativeAssignProcessToJobObject(job, process))
83+
throw new Win32Exception();
84+
}
85+
86+
[DllImport(
87+
"Kernel32.dll",
88+
CharSet = CharSet.Unicode,
89+
EntryPoint = "CreateJobObjectW",
90+
SetLastError = true
91+
)]
92+
private static extern SafeFileHandle NativeCreateJobObjectW(
93+
IntPtr lpJobAttributes,
94+
string lpName
95+
);
96+
97+
[DllImport("Kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)]
98+
private static extern bool NativeCloseHandle(SafeHandle hJob);
99+
100+
[DllImport("kernel32.dll")]
101+
public static extern bool SetInformationJobObject(
102+
SafeHandle hJob,
103+
JOBOBJECTINFOCLASS JobObjectInfoClass,
104+
IntPtr lpJobObjectInfo,
105+
uint cbJobObjectInfoLength
106+
);
107+
108+
private const UInt32 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;
109+
110+
public static SafeHandle CreateJobObjectW(string name)
111+
{
112+
SafeHandle job = NativeCreateJobObjectW(IntPtr.Zero, name);
113+
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
114+
info.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
115+
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo =
116+
new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
117+
extendedInfo.BasicLimitInformation = info;
118+
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
119+
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
120+
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
121+
SetInformationJobObject(
122+
job,
123+
JOBOBJECTINFOCLASS.ExtendedLimitInformation,
124+
extendedInfoPtr,
125+
(uint)length
126+
);
127+
if (job.IsInvalid)
128+
throw new Win32Exception();
129+
return job;
130+
}
131+
132+
public static void CloseHandle(SafeHandle job)
133+
{
134+
if (!NativeCloseHandle(job))
135+
throw new Win32Exception();
136+
}
137+
}
138+
139+
'@
140+
141+
$guid = [guid]::NewGuid().Guid
142+
Write-Output "Creating job object with name $guid"
143+
$job = [NativeMethods]::CreateJobObjectW($guid)
144+
$process = Start-Process -PassThru -NoNewWindow powershell -ArgumentList "$args"
145+
[NativeMethods]::AssignProcessToJobObject($job, $process.SafeHandle)
146+
147+
try {
148+
Write-Output "Waiting for process $($process.Id) to complete..."
149+
$process | Wait-Process
150+
Write-Output "Process finished with exit code $($process.ExitCode), terminating job and exiting..."
151+
} finally {
152+
[NativeMethods]::CloseHandle($job)
153+
exit $process.ExitCode
154+
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
.ci/scripts/run-gradle.sh -Dbwc.checkout.align=true $GRADLE_TASK

.ci/scripts/packaging-test.ps1

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,22 @@ $env:ES_BUILD_JAVA=$AppProps.ES_BUILD_JAVA
1212
$env:JAVA_TOOL_OPTIONS=''
1313

1414
$ErrorActionPreference="Stop"
15-
$gradleInit = "C:\Users\$env:username\.gradle\init.d\"
15+
$gradleInit = "$env:USERPROFILE\.gradle\init.d\"
1616
echo "Remove $gradleInit"
1717
Remove-Item -Recurse -Force $gradleInit -ErrorAction Ignore
1818
New-Item -ItemType directory -Path $gradleInit
1919
echo "Copy .ci/init.gradle to $gradleInit"
2020
Copy-Item .ci/init.gradle -Destination $gradleInit
2121

2222
[Environment]::SetEnvironmentVariable("JAVA_HOME", $null, "Machine")
23-
$env:PATH="C:\Users\jenkins\.java\$env:ES_BUILD_JAVA\bin\;$env:PATH"
23+
$env:PATH="$env:USERPROFILE\.java\$env:ES_BUILD_JAVA\bin\;$env:PATH"
2424
$env:JAVA_HOME=$null
25-
$env:SYSTEM_JAVA_HOME="C:\Users\jenkins\.java\java8"
25+
$env:SYSTEM_JAVA_HOME="$env:USERPROFILE\.java\java8"
2626
Remove-Item -Recurse -Force \tmp -ErrorAction Ignore
2727
New-Item -ItemType directory -Path \tmp
2828

2929
$ErrorActionPreference="Continue"
30-
& .\gradlew.bat -g "C:\Users\$env:username\.gradle" --parallel --no-daemon --scan --console=plain $GradleTasks
30+
Add-Content -Path $profile.AllUsersAllHosts -Value '$ErrorActionPreference="Continue"'
31+
& .\gradlew.bat -g "$env:USERPROFILE\.gradle" --parallel --no-daemon --scan --console=plain $GradleTasks
3132

3233
exit $LastExitCode

.ci/scripts/run-gradle.sh

+27-20
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
#!/bin/bash
2-
# drop page cache and kernel slab objects on linux
3-
[[ -x /usr/local/sbin/drop-caches ]] && sudo /usr/local/sbin/drop-caches
42

53
rm -Rfv ~/.gradle/init.d
64
mkdir -p ~/.gradle/init.d && cp -v $WORKSPACE/.ci/init.gradle ~/.gradle/init.d
7-
if [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then
8-
MAX_WORKERS=16
9-
elif [ -f /proc/cpuinfo ]; then
10-
MAX_WORKERS=`grep '^cpu\scores' /proc/cpuinfo | uniq | sed 's/\s\+//g' | cut -d':' -f 2`
11-
else
12-
if [[ "$OSTYPE" == "darwin"* ]]; then
13-
MAX_WORKERS=`sysctl -n hw.physicalcpu | sed 's/\s\+//g'`
14-
else
15-
echo "Unsupported OS Type: $OSTYPE"
16-
exit 1
17-
fi
18-
fi
19-
if pwd | grep -v -q ^/dev/shm ; then
20-
echo "Not running on a ramdisk, reducing number of workers"
21-
MAX_WORKERS=$(($MAX_WORKERS*2/3))
22-
fi
235

24-
# Export glibc version as environment variable since some BWC tests are incompatible with later versions
25-
export GLIBC_VERSION=$(ldd --version | grep '^ldd' | sed 's/.* \([1-9]\.[0-9]*\).*/\1/')
6+
MAX_WORKERS=4
7+
8+
# Don't run this stuff on Windows
9+
if ! uname -a | grep -q MING; then
10+
# drop page cache and kernel slab objects on linux
11+
[[ -x /usr/local/sbin/drop-caches ]] && sudo /usr/local/sbin/drop-caches
12+
13+
if [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then
14+
MAX_WORKERS=16
15+
elif [ -f /proc/cpuinfo ]; then
16+
MAX_WORKERS=`grep '^cpu\scores' /proc/cpuinfo | uniq | sed 's/\s\+//g' | cut -d':' -f 2`
17+
else
18+
if [[ "$OSTYPE" == "darwin"* ]]; then
19+
MAX_WORKERS=`sysctl -n hw.physicalcpu | sed 's/\s\+//g'`
20+
else
21+
echo "Unsupported OS Type: $OSTYPE"
22+
exit 1
23+
fi
24+
fi
25+
if pwd | grep -v -q ^/dev/shm ; then
26+
echo "Not running on a ramdisk, reducing number of workers"
27+
MAX_WORKERS=$(($MAX_WORKERS*2/3))
28+
fi
29+
30+
# Export glibc version as environment variable since some BWC tests are incompatible with later versions
31+
export GLIBC_VERSION=$(ldd --version | grep '^ldd' | sed 's/.* \([1-9]\.[0-9]*\).*/\1/')
32+
fi
2633

2734
set -e
2835
$GRADLEW -S --max-workers=$MAX_WORKERS $@

build-tools-internal/src/main/groovy/elasticsearch.build-scan.gradle

+42
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ long startTime = project.gradle.services.get(BuildRequestMetaData).getStartTime(
1717

1818
buildScan {
1919
URL jenkinsUrl = System.getenv('JENKINS_URL') ? new URL(System.getenv('JENKINS_URL')) : null
20+
String buildKiteUrl = System.getenv('BUILDKITE_BUILD_URL') ? System.getenv('BUILDKITE_BUILD_URL') : null
2021

2122
// Automatically publish scans from Elasticsearch CI
2223
if (jenkinsUrl?.host?.endsWith('elastic.co') || jenkinsUrl?.host?.endsWith('elastic.dev') || System.getenv('BUILDKITE') == 'true') {
@@ -98,6 +99,47 @@ buildScan {
9899
value 'Git Commit ID', BuildParams.gitRevision
99100
link 'Source', "https://github.com/elastic/elasticsearch/tree/${BuildParams.gitRevision}"
100101
}
102+
} else if (buildKiteUrl) { //Buildkite-specific build scan metadata
103+
// Disable async upload in CI to ensure scan upload completes before CI agent is terminated
104+
uploadInBackground = false
105+
106+
def branch = System.getenv('BUILDKITE_BRANCH')
107+
def repoMatcher = System.getenv('BUILDKITE_REPO') =~ /(https:\/\/github\.com\/|git@github\.com:)(\S+)\.git/
108+
def repository = repoMatcher.matches() ? repoMatcher.group(2) : "<unknown>"
109+
tag 'CI'
110+
link 'CI Build', buildKiteUrl
111+
value 'Job Number', System.getenv('BUILDKITE_BUILD_NUMBER')
112+
113+
114+
// Add SCM information
115+
def prId = System.getenv('BUILDKITE_PULL_REQUEST')
116+
if (prId != 'false') {
117+
def prBaseUrl = (System.getenv('BUILDKITE_PULL_REQUEST_REPO') - ".git")
118+
value 'Git Commit ID', System.getenv('BUILDKITE_COMMIT')
119+
tag "pr/${prId}"
120+
tag 'pull-request'
121+
link 'Source', "${prBaseUrl}/tree/${System.getenv('BUILDKITE_COMMIT')}"
122+
link 'Pull Request', "https://github.com/${repository}/pull/${prId}"
123+
} else {
124+
value 'Git Commit ID', BuildParams.gitRevision
125+
link 'Source', "https://github.com/${repository}/tree/${BuildParams.gitRevision}"
126+
tag branch
127+
}
128+
129+
buildScanPublished { scan ->
130+
// Attach build scan link as build metadata
131+
// See: https://buildkite.com/docs/pipelines/build-meta-data
132+
new ProcessBuilder('buildkite-agent', 'meta-data', 'set', "build-scan-${System.getenv('BUILDKITE_JOB_ID')}", "${scan.buildScanUri}")
133+
.start()
134+
.waitFor()
135+
136+
// Add a build annotation
137+
// See: https://buildkite.com/docs/agent/v3/cli-annotate
138+
def body = """<div class="mb3"><span class="p1 border rounded">${System.getenv('BUILDKITE_LABEL')}</span> :gradle: build ran: <a href="${scan.buildScanUri}"><code>gradle ${gradle.startParameter.taskNames.join(' ')}</code></a></div>"""
139+
new ProcessBuilder('buildkite-agent', 'annotate', '--context', 'gradle-build-scans', '--append', '--style', 'info', body)
140+
.start()
141+
.waitFor()
142+
}
101143
} else {
102144
tag 'LOCAL'
103145
}

build-tools/src/main/java/org/elasticsearch/gradle/ReaperService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public abstract class ReaperService implements BuildService<ReaperService.Params
4141
*/
4242
public void registerPid(String serviceId, long pid) {
4343
String[] killPidCommand = OS.<String[]>conditional()
44-
.onWindows(() -> new String[] { "Taskkill", "/F", "/PID", String.valueOf(pid) })
44+
.onWindows(() -> new String[] { "Taskkill", "/F", "/T", "/PID", String.valueOf(pid) })
4545
.onUnix(() -> new String[] { "kill", "-9", String.valueOf(pid) })
4646
.supply();
4747
registerCommand(serviceId, killPidCommand);

0 commit comments

Comments
 (0)