Skip to content

Commit 19076f0

Browse files
authored
[GV-115] Enable multiple engines in CI with Example Project (#76)
Enables multiple engine versions to be tested simultaneously in CI, by reusing the GDK's unreal-engine.version file.
1 parent d0fa4ce commit 19076f0

File tree

6 files changed

+193
-88
lines changed

6 files changed

+193
-88
lines changed

.buildkite/nightly.steps.yaml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
script_runner: &script_runner
2+
agents:
3+
- "agent_count=8"
4+
- "capable_of_building=platform"
5+
- "environment=production"
6+
- "machine_type=quarter"
7+
- "permission_set=builder"
8+
- "platform=linux"
9+
- "queue=${CI_LINUX_BUILDER_QUEUE:-v3-1572524284-e64831bf1e88b227-------z}"
10+
- "scaler_version=2"
11+
- "working_hours_time_zone=london"
12+
113
common: &common
214
agents:
315
- "agent_count=1"
@@ -7,7 +19,7 @@ common: &common
719
- "permission_set=builder"
820
- "platform=windows"
921
- "scaler_version=2"
10-
- "queue=${CI_WINDOWS_BUILDER_QUEUE:-v3-1572610922-3d03d5c2f13b7fa4-------z}" # Has FASTbuild disabled
22+
- "queue=${CI_WINDOWS_BUILDER_QUEUE:-v4-2019-11-07-bk3700-fbffad576b9676d7}" # Has FASTbuild disabled
1123
timeout_in_minutes: 60 # TODO(ENG-548): reduce timeout once agent-cold-start is optimised.
1224
retry:
1325
automatic:
@@ -17,9 +29,21 @@ common: &common
1729
plugins:
1830
- ca-johnson/taskkill#v4.1: ~
1931

32+
# NOTE: step labels turn into commit-status names like {org}/{repo}/{pipeline}/{step-label}, lower-case and hyphenated.
33+
# These are then relied on to have stable names by other things, so once named, please beware renaming has consequences.
34+
2035
steps:
21-
- label: "build-and-deploy-:windows:"
22-
command: powershell -NoProfile -NonInteractive -InputFormat Text -Command ./ci/setup-and-build.ps1
36+
- label: "generate-pipeline-steps"
37+
commands:
38+
- "chmod -R +rwx ci"
39+
- "ci/generate-pipeline-steps.sh"
40+
env:
41+
ENGINE_VERSION: "${ENGINE_VERSION}"
42+
<<: *script_runner
43+
44+
- wait
45+
46+
- label: "slack-notify"
47+
if: build.env("SLACK_NOTIFY") == "true" || build.branch == "master"
48+
command: "powershell -NoProfile -NonInteractive -InputFormat Text -Command ./ci/slack-notify.ps1"
2349
<<: *common # This folds the YAML named anchor into this step. Overrides, if any, should follow, not precede.
24-
artifact_paths:
25-
- "UnrealEngine/Engine/Programs/AutomationTool/Saved/Logs/*"

ci/deploy.ps1

Lines changed: 7 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ param(
88
Start-Event "deploy-game" "build-unreal-gdk-example-project-:windows:"
99
# Use the shortened commit hash gathered during GDK plugin clone and the current date and time to distinguish the deployment
1010
$date_and_time = Get-Date -Format "MMdd_HHmm"
11-
$deployment_name = "exampleproject_${date_and_time}_$($gdk_commit_hash)"
11+
$deployment_name = "exampleproject$($env:STEP_NUMBER)_${date_and_time}_$($gdk_commit_hash)"
1212
$assembly_name = "$($deployment_name)_asm"
1313

1414
pushd "spatial"
@@ -66,96 +66,21 @@ pushd "spatial"
6666
"--snapshot=$deployment_snapshot_path", `
6767
"--cluster_region=$deployment_cluster_region", `
6868
"--log_level=debug", `
69-
"--tags=ttl_1_hours"
69+
"--tags=ttl_1_hours", `
70+
"--deployment_description=`"Engine commit: $($env:ENGINE_COMMIT_HASH)`"" `
7071
)
7172

7273
if ($launch_deployment_process.ExitCode -ne 0) {
7374
Write-Log "Failed to launch a Spatial cloud deployment. Error: $($launch_deployment_process.ExitCode)"
7475
Throw "Deployment launch failed"
7576
}
77+
78+
buildkite-agent meta-data set "deployment-name-$($env:STEP_NUMBER)" "$deployment_name"
79+
buildkite-agent meta-data set "project-name" "$project_name"
80+
buildkite-agent meta-data set "gdk-commit-hash" "$gdk_commit_hash)"
7681
} else {
7782
Write-Log "Deployment will not be launched as you have passed in an argument specifying that it should not be (START_DEPLOYMENT=${launch_deployment}). Remove it to have your build launch a deployment."
7883
}
79-
80-
if ($env:BUILDKITE_BRANCH -eq "master" -or $env:BUILDKITE_SLACK_NOTIFY -eq "true") {
81-
# Send a Slack notification with a link to the new deployment and to the build.
82-
83-
# Build Slack text
84-
if ($env:BUILDKITE_NIGHTLY_BUILD -eq "true") {
85-
$slack_text = ":night_with_stars: Nightly build of *Example Project* succeeded."
86-
} else {
87-
$slack_text = "*Example Project* build by $env:BUILDKITE_BUILD_CREATOR succeeded."
88-
}
89-
90-
# Read Slack webhook secret from the vault and extract the Slack webhook URL from it.
91-
$slack_webhook_secret = "$(imp-ci secrets read --environment=production --buildkite-org=improbable --secret-type=slack-webhook --secret-name=unreal-gdk-slack-web-hook)"
92-
$slack_webhook_url = $slack_webhook_secret | ConvertFrom-Json | %{$_.url}
93-
94-
$deployment_url = "https://console.improbable.io/projects/${project_name}/deployments/${deployment_name}/overview"
95-
$gdk_commit_url = "https://github.com/spatialos/UnrealGDK/commit/${gdk_commit_hash}"
96-
$project_commit_url = "https://github.com/spatialos/UnrealGDKExampleProject/commit/$env:BUILDKITE_COMMIT"
97-
$build_url = "$env:BUILDKITE_BUILD_URL"
98-
$json_message = [ordered]@{
99-
text = "$slack_text"
100-
attachments= @(
101-
@{
102-
fallback = "Find build here: $build_url and potential deployment here: $deployment_url"
103-
color = "good"
104-
fields = @(
105-
@{
106-
title = "Build Message"
107-
value = "$env:BUILDKITE_MESSAGE".Substring(0, [System.Math]::Min(64, "$env:BUILDKITE_MESSAGE".Length))
108-
short = "true"
109-
}
110-
@{
111-
title = "Example Project branch"
112-
value = "$env:BUILDKITE_BRANCH"
113-
short = "true"
114-
}
115-
@{
116-
title = "GDK branch"
117-
value = "$gdk_branch_name"
118-
short = "true"
119-
}
120-
)
121-
actions = @(
122-
@{
123-
type = "button"
124-
text = ":github: Project commit"
125-
url = "$project_commit_url"
126-
style = "primary"
127-
}
128-
@{
129-
type = "button"
130-
text = ":github: GDK commit"
131-
url = "$gdk_commit_url"
132-
style = "primary"
133-
}
134-
@{
135-
type = "button"
136-
text = ":buildkite: BK build"
137-
url = "$build_url"
138-
style = "primary"
139-
}
140-
)
141-
}
142-
)
143-
}
144-
145-
if ($launch_deployment -eq "true") {
146-
$deployment_button = @{
147-
type = "button"
148-
text = ":cloud: Deployment"
149-
url = "$deployment_url"
150-
style = "primary"
151-
}
152-
$json_message["attachments"][0]["actions"] += ($deployment_button)
153-
}
154-
155-
$json_request = $json_message | ConvertTo-Json -Depth 10
156-
157-
Invoke-WebRequest -UseBasicParsing "$slack_webhook_url" -ContentType "application/json" -Method POST -Body "$json_request"
158-
}
15984
Finish-Event "launch-deployment" "deploy-unreal-gdk-example-project-:windows:"
16085

16186
popd

ci/generate-pipeline-steps.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# Download the unreal-engine.version file from the GDK repo so we can run the example project builds on the same versions the GDK was run against
5+
# This is not the pinnacle of engineering, as we rely on GitHub's web interface to download the file, but it seems like GitHub disallows git archive
6+
# which would be our other option for downloading a single file
7+
GDK_BRANCH_LOCAL="${GDK_BRANCH:-master}"
8+
NUMBER_OF_TRIES=0
9+
while [ $NUMBER_OF_TRIES -lt 5 ]; do
10+
CURL_TIMEOUT=$((10<<NUMBER_OF_TRIES))
11+
NUMBER_OF_TRIES=$((NUMBER_OF_TRIES+1))
12+
echo "Trying to download unreal-engine.version from GitHub's UnrealGDK repository, try: $NUMBER_OF_TRIES, timeout: $CURL_TIMEOUT seconds ..."
13+
curl -L -m $CURL_TIMEOUT https://raw.githubusercontent.com/spatialos/UnrealGDK/$GDK_BRANCH_LOCAL/ci/unreal-engine.version -o ci/unreal-engine.version
14+
if [ $? -eq 0 ]; then
15+
break
16+
fi
17+
done
18+
19+
# This script generates BuildKite steps for each engine version we want to test against.
20+
# We retrieve these engine versions from the unreal-engine.version file in the UnrealGDK repository.
21+
# The steps are based on the template in nightly.template.steps.yaml.
22+
23+
if [ -z "${ENGINE_VERSION}" ]; then
24+
echo "Generating build steps for each engine version listed in unreal-engine.version"
25+
STEP_NUMBER=1
26+
IFS=$'\n'
27+
for commit_hash in $(cat < ci/unreal-engine.version); do
28+
REPLACE_STRING="s|ENGINE_COMMIT_HASH_PLACEHOLDER|$commit_hash|g; s|STEP_NUMBER_PLACEHOLDER|$STEP_NUMBER|g"
29+
sed $REPLACE_STRING ci/nightly.template.steps.yaml | buildkite-agent pipeline upload
30+
STEP_NUMBER=$((STEP_NUMBER+1))
31+
done
32+
# We generate one build step for each engine version, which is one line in the unreal-engine.version file.
33+
# The number of engine versions we are dealing with is therefore the counting variable from the above loop minus one.
34+
STEP_NUMBER=$((STEP_NUMBER-1))
35+
buildkite-agent meta-data set "engine-version-count" "$STEP_NUMBER"
36+
else
37+
echo "Generating steps for the specified engine version: $ENGINE_VERSION"
38+
sed "s|ENGINE_COMMIT_HASH_PLACEHOLDER|$ENGINE_VERSION|g" ci/nightly.template.steps.yaml | buildkite-agent pipeline upload
39+
fi

ci/nightly.template.steps.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
common: &common
2+
agents:
3+
- "agent_count=1"
4+
- "capable_of_building=gdk-for-unreal"
5+
- "environment=production"
6+
- "machine_type=quad"
7+
- "permission_set=builder"
8+
- "platform=windows"
9+
- "scaler_version=2"
10+
- "queue=${CI_WINDOWS_BUILDER_QUEUE:-v4-2019-11-07-bk3700-fbffad576b9676d7}" # Has FASTbuild disabled
11+
timeout_in_minutes: 60 # TODO(ENG-548): reduce timeout once agent-cold-start is optimised.
12+
retry:
13+
automatic:
14+
# This is designed to trap and retry failures because agent lost connection. Agent exits with -1 in this case.
15+
- exit_status: -1
16+
limit: 3
17+
plugins:
18+
- ca-johnson/taskkill#v4.1: ~
19+
20+
steps:
21+
- label: "build-and-deploy-:windows:-ENGINE_COMMIT_HASH_PLACEHOLDER"
22+
command: "powershell -NoProfile -NonInteractive -InputFormat Text -Command ./ci/setup-and-build.ps1"
23+
<<: *common # This folds the YAML named anchor into this step. Overrides, if any, should follow, not precede.
24+
artifact_paths:
25+
- "UnrealEngine/Engine/Programs/AutomationTool/Saved/Logs/*"
26+
env:
27+
ENGINE_COMMIT_HASH: "ENGINE_COMMIT_HASH_PLACEHOLDER"
28+
STEP_NUMBER: "STEP_NUMBER_PLACEHOLDER"

ci/setup-and-build.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pushd "$exampleproject_home"
3535
Start-Event "get-gdk-head-commit" "build-unreal-gdk-example-project-:windows:"
3636
pushd $gdk_home
3737
# Get the short commit hash of this gdk build for later use in assembly name
38-
$gdk_commit_hash = (git rev-parse HEAD).Substring(0,7)
38+
$gdk_commit_hash = (git rev-parse HEAD).Substring(0,6)
3939
Write-Log "GDK at commit: $gdk_commit_hash on branch $gdk_branch_name"
4040
popd
4141
Finish-Event "get-gdk-head-commit" "build-unreal-gdk-example-project-:windows:"

ci/slack-notify.ps1

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
. "$PSScriptRoot\common.ps1"
2+
3+
$gdk_branch_name = Get-Env-Variable-Value-Or-Default -environment_variable_name "GDK_BRANCH" -default_value "master"
4+
$launch_deployment = Get-Env-Variable-Value-Or-Default -environment_variable_name "START_DEPLOYMENT" -default_value "true"
5+
$engine_version_count = buildkite-agent meta-data get "engine-version-count"
6+
$project_name = buildkite-agent meta-data get "project-name"
7+
$gdk_commit_hash = buildkite-agent meta-data get "gdk_commit_hash"
8+
9+
# Send a Slack notification with a link to the new deployment and to the build.
10+
Start-Event "slack-notify" "slack-notify"
11+
# Build Slack text
12+
if ($env:BUILDKITE_NIGHTLY_BUILD -eq "true") {
13+
$slack_text = ":night_with_stars: Nightly build of *Example Project* succeeded."
14+
} else {
15+
$slack_text = "*Example Project* build by $env:BUILDKITE_BUILD_CREATOR succeeded."
16+
}
17+
18+
# Read Slack webhook secret from the vault and extract the Slack webhook URL from it.
19+
$slack_webhook_secret = "$(imp-ci secrets read --environment=production --buildkite-org=improbable --secret-type=slack-webhook --secret-name=unreal-gdk-slack-web-hook)"
20+
$slack_webhook_url = $slack_webhook_secret | ConvertFrom-Json | %{$_.url}
21+
22+
$gdk_commit_url = "https://github.com/spatialos/UnrealGDK/commit/${gdk_commit_hash}"
23+
$project_commit_url = "https://github.com/spatialos/UnrealGDKExampleProject/commit/$env:BUILDKITE_COMMIT"
24+
$build_url = "$env:BUILDKITE_BUILD_URL"
25+
$json_message = [ordered]@{
26+
text = "$slack_text"
27+
attachments= @(
28+
@{
29+
fallback = "Find build here: $build_url."
30+
color = "good"
31+
fields = @(
32+
@{
33+
title = "Build Message"
34+
value = "$env:BUILDKITE_MESSAGE".Substring(0, [System.Math]::Min(64, "$env:BUILDKITE_MESSAGE".Length))
35+
short = "true"
36+
}
37+
@{
38+
title = "Example Project branch"
39+
value = "$env:BUILDKITE_BRANCH"
40+
short = "true"
41+
}
42+
@{
43+
title = "GDK branch"
44+
value = "$gdk_branch_name"
45+
short = "true"
46+
}
47+
)
48+
actions = @(
49+
@{
50+
type = "button"
51+
text = ":github: Project commit"
52+
url = "$project_commit_url"
53+
style = "primary"
54+
}
55+
@{
56+
type = "button"
57+
text = ":github: GDK commit"
58+
url = "$gdk_commit_url"
59+
style = "primary"
60+
}
61+
@{
62+
type = "button"
63+
text = ":buildkite: BK build"
64+
url = "$build_url"
65+
style = "primary"
66+
}
67+
)
68+
}
69+
)
70+
}
71+
72+
if ($launch_deployment -eq "true") {
73+
for ($i = 0; $i -lt $engine_version_count; $i++){
74+
$deployment_name = buildkite-agent meta-data get "deployment-name-$($i+1)"
75+
$deployment_url = "https://console.improbable.io/projects/${project_name}/deployments/${deployment_name}/overview"
76+
$deployment_button = @{
77+
type = "button"
78+
text = ":cloud: Deployment $($i+1)"
79+
url = "$deployment_url"
80+
style = "primary"
81+
}
82+
$json_message["attachments"][0]["actions"] += ($deployment_button)
83+
}
84+
}
85+
86+
$json_request = $json_message | ConvertTo-Json -Depth 10
87+
88+
Invoke-WebRequest -UseBasicParsing "$slack_webhook_url" -ContentType "application/json" -Method POST -Body "$json_request"
89+
Finish-Event "slack-notify" "slack-notify"

0 commit comments

Comments
 (0)