-
Notifications
You must be signed in to change notification settings - Fork 2
Unreal Engine Pipeline
Tim Rademaker edited this page Dec 4, 2022
·
13 revisions
A pipeline for Unreal Engine that runs the project's tests, builds and packages the project, deploys the build to Steam and notifies your team of the pipeline's result through a Discord webhook.
Run the pipeline once after creating it to set up the parameters.
library(identifier: 'JenkinsPipelineUtilities@master', retriever: modernSCM([$class: 'GitSCMSource', credentialsId: '', remote: 'https://github.com/timrademaker/JenkinsPipelineUtilities.git']))
pipeline {
parameters {
// Project
string(defaultValue: params.CONFIGURATION ? params.CONFIGURATION : 'Development', description: 'The build configuration for this project. Options: Development, Shipping.', name: 'CONFIGURATION', trim: true)
string(defaultValue: params.TARGET_PLATFORM ? params.TARGET_PLATFORM : 'Win64', description: 'The target platform to build the project for. Options: Win32, Win64, HoloLens, Mac, XboxOne, PS4, IOS, Android, Linux, LinuxAArch64, AllDesktop, TVOS, Switch, Quail, Lumin.', name: 'TARGET_PLATFORM', trim: true)
string(defaultValue: params.TEST_FILTERS ? params.TEST_FILTERS : '', description: 'The test filters to use when running tests. Separate different filters with a \';\', or leave empty to not run any tests.', name: 'TEST_FILTERS', trim: true)
// Discord
credentials(credentialType: 'org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl', defaultValue: params.DISCORD_WEBHOOK ? params.DISCORD_WEBHOOK : '', description: 'The webhook to use to notify the team of build results.', name: 'DISCORD_WEBHOOK', required: false)
// Shipping
booleanParam(defaultValue: params.SHOULD_DEPLOY ? params.SHOULD_DEPLOY : false, description: 'True if the build should be deployed.', name: 'SHOULD_DEPLOY')
booleanParam(defaultValue: params.DEPLOY_UNSTABLE_BUILD ? params.DEPLOY_UNSTABLE_BUILD : false, description: 'True if the build should be deployed even if it is marked as unstable.', name: 'DEPLOY_UNSTABLE_BUILD')
credentials(credentialType: 'com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl', defaultValue: params.STEAM_CREDS ? params.STEAM_CREDS : '', description: 'Login credentials for Steam.', name: 'STEAM_CREDS', required: true)
string(defaultValue: params.STEAM_DEPLOYMENTBRANCH ? params.STEAM_DEPLOYMENTBRANCH : '', description: 'The branch to which this game should automatically be deployed. Can\'t be \'default\'.', name: 'STEAM_DEPLOYMENTBRANCH', trim: true)
booleanParam(defaultValue: params.IS_PREVIEW ? params.IS_PREVIEW : false, description: 'True if this build is a preview (i.e. should not actually be deployed).', name: 'IS_PREVIEW')
}
agent {
node {
label ""
customWorkspace "C:/Jenkins/${env.JOB_NAME}"
}
}
options {
timeout(time: 45, unit: 'MINUTES')
}
environment {
// Perforce
P4_CREDENTIALS = 'Tim180112_P4' // The ID of the Perforce credentials to use
P4_WORKSPACE_FORMAT = 'Tim180112-Jenkins-${JOB_BASE_NAME}'
P4_WORKSPACE_TEMPLATE = 'Tim180112-Jenkins' // The Perforce workspace to use as template
// Project
PROJECT_NAME = 'ExampleProject' // The name of the project file (without '.uproject')
PROJECT_DIRECTORY = 'ExampleProject' // Project directory, relative to the workspace root
BUILD_OUT_DIR = "${env.WORKSPACE}/out/build" // The folder in which to output the build
// Steam
STEAM_APPID = '1000' // The app ID of the game to ship to Steam.
STEAM_DEPOTID = '1001' // The depot ID of the games's depot.
// Unreal Engine base directory
UE_DIR = 'C:/Program Files/Epic Games/UE_4.25';
}
stages {
stage('Setup') {
steps {
script {
p4.init(env.P4_CREDENTIALS, env.P4_WORKSPACE_FORMAT, env.P4_WORKSPACE_TEMPLATE)
p4.pull();
unreal.init(env.UE_DIR, '4', params.TARGET_PLATFORM, params.CONFIGURATION);
if(params.SHOULD_DEPLOY) {
steam.setup();
}
}
}
}
stage('Build') {
when {
expression {
fileExists("${env.WORKSPACE}/${env.PROJECT_DIRECTORY}/Source/${env.PROJECT_NAME}.Target.cs")
}
}
steps {
script {
unreal.build("${env.WORKSPACE}/${env.PROJECT_DIRECTORY}", env.PROJECT_NAME);
}
}
}
stage('Run Tests') {
steps {
script {
if(params.TEST_FILTERS) {
unreal.runTestsNamed("${env.WORKSPACE}/${env.PROJECT_DIRECTORY}", env.PROJECT_NAME, params.TEST_FILTERS.split(';') as List<String>);
}
}
}
}
stage('Package') {
steps {
script {
unreal.packageProject("${env.WORKSPACE}/${env.PROJECT_DIRECTORY}", env.PROJECT_NAME, env.BUILD_OUT_DIR);
}
}
}
stage('Deploy') {
when {
expression {
params.SHOULD_DEPLOY &&
(currentBuild.result != 'UNSTABLE' || params.DEPLOY_UNSTABLE_BUILD)
}
}
steps {
script {
platformName = params.TARGET_PLATFORM;
if(params.TARGET_PLATFORM.toLowerCase() in ['win64', 'win32']) {
platformName = 'Windows';
}
contentRoot = "${env.BUILD_OUT_DIR}/${platformName}NoEditor";
steam.createDepotManifest(env.STEAM_DEPOTID, contentRoot);
appManifest = steam.createAppManifest(env.STEAM_APPID, env.STEAM_DEPOTID, contentRoot, "${env.JOB_BASE_NAME}-${env.BUILD_NUMBER}", params.STEAM_DEPLOYMENTBRANCH, "${env.WORKSPACE}/SteamBuild", params.IS_PREVIEW);
steam.tryDeploy(params.STEAM_CREDS, appManifest);
}
}
}
}
post {
success {
script {
if(params.DISCORD_WEBHOOK) {
withCredentials([string(credentialsId: params.DISCORD_WEBHOOK, variable: 'WEBHOOK_URL')]) {
discord.sendEmbed(env.WEBHOOK_URL, "Ran Jenkins Pipeline for ${env.JOB_BASE_NAME}", "[Build #${env.BUILD_NUMBER}](${env.BUILD_URL})", '3066993', [['**Build Result**', ':white_check_mark: Build succeeded!']]);
}
}
}
}
unsuccessful {
script {
if(params.DISCORD_WEBHOOK) {
withCredentials([string(credentialsId: params.DISCORD_WEBHOOK, variable: 'WEBHOOK_URL')]) {
discord.sendEmbed(env.WEBHOOK_URL, "Ran Jenkins Pipeline for ${env.JOB_BASE_NAME}", "[Build #${env.BUILD_NUMBER}](${env.BUILD_URL})", '15158332', [['**Build Result**', ':x: Build failed!']]);
}
}
}
}
unstable {
script {
if(params.DISCORD_WEBHOOK) {
withCredentials([string(credentialsId: params.DISCORD_WEBHOOK, variable: 'WEBHOOK_URL')]) {
discord.sendEmbed(env.WEBHOOK_URL, "Ran Jenkins Pipeline for ${env.JOB_BASE_NAME}", "[Build #${env.BUILD_NUMBER}](${env.BUILD_URL})", '16776960', [['**Build Result**', ':warning: Build unstable!']]);
}
}
}
}
always {
script {
log.parse();
}
}
cleanup {
script {
file.delete("${env.WORKSPACE}/out");
file.delete("${env.WORKSPACE}/temp");
}
}
}
}
- Source Control
- Building and Testing
- Messaging
- Shipping
- Miscellaneous
- Example Pipelines