Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ publish/
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
!SEBrowser/Properties/PublishProfiles/Development Profile SEBrowser.pubxml
!SEBrowser/Properties/PublishProfiles/Release Profile SEBrowser.pubxml
!SEBrowser/Properties/PublishProfiles/Docker Development Profile SEBrowser.pubxml
!SEBrowser/Properties/PublishProfiles/Docker Release Profile SEBrowser.pubxml
*.publishproj

# NuGet Packages
Expand Down
314 changes: 314 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
import hudson.model.Result
import jenkins.model.CauseOfInterruption
import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException

def haltBuildWithSuccess() {
currentBuild.rawBuild.@result = Result.SUCCESS
def cause = new CauseOfInterruption.UserInterruption("Build halted programmatically with SUCCESS status")
throw new FlowInterruptedException(Result.SUCCESS, false, cause)
}

pipeline {
agent any

environment {
github_pat = credentials('github-pat')
devBranch = "development"
mainBranch = "master"
NUGET_PACKAGES = "D:\\NuGetCache"
publishDirectory = "${WORKSPACE}\\build\\Jenkins\\publish"
artifactDirectory = "${WORKSPACE}\\build\\Jenkins\\artifacts"
deliveryDirectory = "\\\\webhostfiles\\Delivery\\SEBrowser"
}

stages {
stage('Prepare Environment') {
steps {
script {
// Set current Version
def fileContent = powershell(returnStdout: true, script: '''
Get-Content -Path "./Scripts/SEBrowser.version" -Raw
''').trim()
env.seBrowserVersion = fileContent
println("SEBrowser version: ${env.seBrowserVersion}")
}
script {
// Set current UI Version
def fileContent = powershell(returnStdout: true, script: '''
(Get-Content -Path "./SEBrowser/package.json" -Raw | ConvertFrom-Json).version
''').trim()
env.uiVersion = fileContent
println("SEBrowser UI version: ${env.uiVersion}")
}
script {
//Set current Commit
env.GIT_COMMIT = bat(script: '@git rev-parse HEAD', returnStdout: true).trim()
println("Current Git Commit: ${env.GIT_COMMIT}")
}
script {
//Get last release from git tags
bat( script: "@git fetch origin ${env.mainBranch}:refs/remotes/origin/${env.mainBranch}")
def mainCommit = bat(script: "@git rev-parse origin/${env.mainBranch}", returnStdout: true).trim()

try {
env.LAST_RELEASE_TAG = bat(script: "@git describe --tags --abbrev=0 ${mainCommit}", returnStdout: true).trim()
}
catch (Exception ex) {
println("No tags found, setting LAST_RELEASE_TAG to v3.0.0")
env.LAST_RELEASE_TAG = "v3.0.0"
}
println("Last Release Tag: ${env.LAST_RELEASE_TAG}")
}
}
}

stage('Check Conditions') {
when {
anyOf {
not {
anyOf {
expression { env.BRANCH_NAME.startsWith("PR") }
expression { env.BRANCH_NAME == "${env.mainBranch}" }
}
}
allOf {
expression { env.BRANCH_NAME.startsWith("PR") }
expression { env.CHANGE_BRANCH != "${env.devBranch}" }
}
allOf {
expression { env.BRANCH_NAME.startsWith("PR") }
expression { env.CHANGE_TARGET != "${env.mainBranch}" }
}
}
}
steps {
haltBuildWithSuccess()
}
}

stage('Checkout Master Branch') {
when {
expression {
return env.BRANCH_NAME == "${env.mainBranch}"
}
}
steps {
script {
bat(script: "@git fetch origin ${env.BRANCH_NAME}:refs/remotes/origin/${env.BRANCH_NAME}")
bat(script: "@git checkout origin/${env.BRANCH_NAME}")
}
}
}

stage('Checkout Development Branch') {
when {
expression {
return env.CHANGE_BRANCH == "${env.devBranch}"
}
}
steps {
script {
bat(script: "@git fetch origin ${env.CHANGE_BRANCH}:refs/remotes/origin/${env.CHANGE_BRANCH}")
bat(script: "@git checkout origin/${env.CHANGE_BRANCH}")
}
}
}

stage('Checkout Submodules') {
steps {
bat(script: '@git submodule sync --recursive')
bat(script: '@git submodule update --init --recursive')
bat(script: '@git submodule status --recursive')
}
}

stage('Application Version') {
when {
expression {
return env.BRANCH_NAME != "${env.mainBranch}"
}
}
steps {
script {
env.GIT_COMMIT = bat(script: '@git rev-parse HEAD', returnStdout: true).trim()
}
powershell "powershell.exe -File .\\Scripts\\Versioning.ps1 -VersionFile './Scripts/SEBrowser.version' -Commit false"
bat(script: "@git add Scripts/SEBrowser.version")
bat(script: "git diff --cached --quiet || git commit -m \"Updated Version Number\"")
}
}

stage('Gemstone Updates') {
when {
expression {
return env.BRANCH_NAME != "${env.mainBranch}"
}
}
steps {
powershell "powershell.exe -File .\\Scripts\\GemstoneUpdates.ps1 -VersionFile './Directory.Build.props'"
powershell "powershell.exe -File .\\Scripts\\CreateDependencyPR.ps1 -GithubToken '${github_pat}' -DevelopmentBranchName '${devBranch}'"
script {
bat(script: "@git add Directory.Build.props")
bat(script: "git diff --cached --quiet || git commit -m \"Updated Dependencies\"")
}
}
}

stage('Push Changes') {
when {
allOf {
expression {
return env.BRANCH_NAME != "${env.mainBranch}"
}
expression {
return bat(script: '@git rev-parse HEAD', returnStdout: true).trim() != env.GIT_COMMIT
}
}
}
steps {
powershell "git push origin HEAD:${env.devBranch}"
haltBuildWithSuccess()
}
}

stage('Build Production UI') {
steps {
dir('SEBrowser') {
bat(script: 'npm run build')
powershell """
\$uiFile = '.\\wwwroot\\Scripts\\SEBrowser.${env.uiVersion}.js'
if (-not (Test-Path -LiteralPath \$uiFile -PathType Leaf) -or
(Get-Item -LiteralPath \$uiFile).Length -eq 0) {
throw 'Production UI was not generated.'
}
"""
}
}
}

stage('Build Docker Images') {
when {
anyOf {
expression {
return env.CHANGE_BRANCH == "${env.devBranch}"
}
expression {
return env.BRANCH_NAME == "${env.mainBranch}"
}
}
}
steps {
script {
env.seBrowserDockerTag = env.CHANGE_BRANCH == "${env.devBranch}" ? "${env.seBrowserVersion}a" : env.seBrowserVersion
println("Building SEBrowser Docker image tag: sebrowser:${env.seBrowserDockerTag}")
}

powershell "msbuild /t:Publish /p:DeployOnBuild=true';'Configuration=Release';'PublishProfile='Docker Release Profile SEBrowser' './SEBrowser/SEBrowser.csproj' /nodeReuse:false -restore"
powershell "docker build --build-arg CONFIGURATION=Release -f .\\SEBrowser.dockerfile -t sebrowser:${env.seBrowserDockerTag} ."
}
}

stage('Publish Application') {
steps {
powershell """
if (Test-Path -LiteralPath '${env.publishDirectory}') {
Remove-Item -LiteralPath '${env.publishDirectory}' -Recurse -Force
}
New-Item -ItemType Directory -Path '${env.publishDirectory}' -Force | Out-Null
dotnet publish '.\\SEBrowser\\SEBrowser.csproj' `
-c Release `
-r win-x64 `
--self-contained true `
-o '${env.publishDirectory}'
if (\$LASTEXITCODE -ne 0) {
throw 'dotnet publish failed.'
}

\$requiredFiles = @(
'${env.publishDirectory}\\SEBrowser.exe',
'${env.publishDirectory}\\SEBrowser.dll',
'${env.publishDirectory}\\package.json',
'${env.publishDirectory}\\wwwroot\\Scripts\\SEBrowser.${env.uiVersion}.js'
)
foreach (\$requiredFile in \$requiredFiles) {
if (-not (Test-Path -LiteralPath \$requiredFile -PathType Leaf) -or
(Get-Item -LiteralPath \$requiredFile).Length -eq 0) {
throw "Required publish output is missing: \$requiredFile"
}
}
"""
}
}

stage('Package Application') {
steps {
script {
env.archiveName = env.BRANCH_NAME == "${env.mainBranch}" ?
"SEBrowser_v${env.seBrowserVersion}.zip" :
"SEBrowser_v${env.seBrowserVersion}a.zip"
}
powershell """
if (Test-Path -LiteralPath '${env.artifactDirectory}') {
Remove-Item -LiteralPath '${env.artifactDirectory}' -Recurse -Force
}
New-Item -ItemType Directory -Path '${env.artifactDirectory}' -Force | Out-Null

Compress-Archive `
-Path '${env.publishDirectory}\\*' `
-DestinationPath '${env.artifactDirectory}\\${env.archiveName}' `
-Force
if (-not (Test-Path -LiteralPath '${env.artifactDirectory}\\${env.archiveName}' -PathType Leaf)) {
throw 'Release archive was not created.'
}
"""
}
}

stage('Comment Prerelease') {
when {
expression {
return env.CHANGE_BRANCH == "${env.devBranch}"
}
}
steps {
powershell """
powershell.exe -File .\\Scripts\\GithubComment.ps1 `
-Comment 'Prerelease SEBrowser v${env.seBrowserVersion}a is available.' `
-BranchName '${env.devBranch}' `
-GithubToken '${github_pat}' `
-RepoOwner 'GridProtectionAlliance' `
-RepoName 'SEBrowser'
"""
}
}

stage('Deploy Prerelease') {
when {
expression {
return env.CHANGE_BRANCH == "${env.devBranch}"
}
}
steps {
powershell "Move-Item -Path '${env.artifactDirectory}\\${env.archiveName}' -Destination '${env.deliveryDirectory}\\PreRelease\\${env.archiveName}' -Force"
}
}

stage('Deploy Release') {
when {
allOf {
expression {
return env.BRANCH_NAME == "${env.mainBranch}"
}
expression {
return "v${env.seBrowserVersion}" != env.LAST_RELEASE_TAG
}
}
}
steps {
powershell "Move-Item -Path '${env.artifactDirectory}\\${env.archiveName}' -Destination '${env.deliveryDirectory}\\${env.archiveName}' -Force"
powershell "git tag -a v${env.seBrowserVersion} -m 'Version ${env.seBrowserVersion} release'"
powershell "git push origin --tags"
}
}
}
}
11 changes: 11 additions & 0 deletions SEBrowser-dev.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
<BuildType Name="Development" />
<BuildType Name="Release" />
</Configurations>
<Folder Name="/Solution Items/">
<File Path="Jenkinsfile" />
<File Path="SEBrowser.dockerfile" />
</Folder>
<Folder Name="/Scripts/">
<File Path="Scripts/CreateDependencyPR.ps1" />
<File Path="Scripts/GemstoneUpdates.ps1" />
<File Path="Scripts/GithubComment.ps1" />
<File Path="Scripts/SEBrowser.version" />
<File Path="Scripts/Versioning.ps1" />
</Folder>
<Project Path="SEBrowser/SEBrowser.csproj" />
<Folder Name="/Libraries/">
<Project Path="Libraries/FaultAlgorithms/FaultAlgorithms.csproj" />
Expand Down
23 changes: 23 additions & 0 deletions SEBrowser.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Use the official .NET 9.0 runtime as the base image
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
ARG CONFIGURATION="Development"

# Set the working directory inside the container
WORKDIR /SEBrowser

# Copy SEBrowser from the local published folder to the container
COPY ./[Bb]uild/${CONFIGURATION}/Applications/SEBrowser/net9.0/publish/linux-x64/ /SEBrowser/

ENV ASPNETCORE_HTTP_PORTS=8001

# Set permissions for all copied folders and files
RUN chmod -R 777 /SEBrowser

# Ensure the application is executable
RUN chmod +x /SEBrowser/SEBrowser

# Expose the webserver port
EXPOSE 8001

# Define the entry point to run
ENTRYPOINT ["sh", "-c", "exec /SEBrowser/SEBrowser"]
1 change: 1 addition & 0 deletions SEBrowser/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ private static void DefineWebHotSettings(Settings settings)

section.AuthenticationTicketTimeout = (24.0D, "Expiration of the authentication ticket relative to its creation time, in hours");
section.AuthenticationSessionTimeout = (15.0D, "Expiration of the user's session relative to the last time it was accessed, in minutes");
section.DisableAuthentication = (false, "Disables authentication for the web server");
}

private static void DefineAdditionalSystemSettings(Settings settings, string settingsCatergory = Settings.SystemSettingsCategory)
Expand Down
Loading