diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..5f60bbaf --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,296 @@ +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\\openSEE" + } + + stages { + stage('Prepare Environment') { + steps { + script { + // Set current Version + def fileContent = powershell(returnStdout: true, script: ''' + Get-Content -Path "./scripts/OpenSEE.version" -Raw + ''').trim() + env.openSEEVersion = fileContent + println("openSEE version: ${env.openSEEVersion}") + } + 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 v2.0.0") + env.LAST_RELEASE_TAG = "v2.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('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/OpenSEE.version' -Commit false" + bat(script: "@git add scripts/OpenSEE.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 './src/Directory.Build.props'" + powershell "powershell.exe -File .\\scripts\\CreateDependencyPR.ps1 -GithubToken '${github_pat}' -DevelopmentBranchName '${devBranch}'" + script { + bat(script: "@git add src/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('src/OpenSEE') { + bat(script: 'npm run build') + powershell """ + \$uiFile = '.\\wwwroot\\Scripts\\OpenSee.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.openSEEDockerTag = env.CHANGE_BRANCH == "${env.devBranch}" ? "${env.openSEEVersion}a" : env.openSEEVersion + println("Building openSEE Docker image tag: opensee:${env.openSEEDockerTag}") + } + + powershell "msbuild /t:Publish /p:DeployOnBuild=true';'Configuration=Release';'PublishProfile='Docker Release Profile openSEE' './src/OpenSEE/OpenSEE.csproj' /nodeReuse:false -restore" + powershell "docker build --build-arg CONFIGURATION=Release -f .\\openSEE.dockerfile -t opensee:${env.openSEEDockerTag} ." + } + } + + 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 '.\\src\\OpenSEE\\OpenSEE.csproj' ` + -c Release ` + -r win-x64 ` + --self-contained true ` + -o '${env.publishDirectory}' + if (\$LASTEXITCODE -ne 0) { + throw 'dotnet publish failed.' + } + + \$requiredFiles = @( + '${env.publishDirectory}\\OpenSEE.exe', + '${env.publishDirectory}\\OpenSEE.dll', + '${env.publishDirectory}\\wwwroot\\Scripts\\OpenSee.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}" ? + "openSEE_v${env.openSEEVersion}.zip" : + "openSEE_v${env.openSEEVersion}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 openSEE v${env.openSEEVersion}a is available.' ` + -BranchName '${env.devBranch}' ` + -GithubToken '${github_pat}' ` + -RepoOwner 'GridProtectionAlliance' ` + -RepoName 'openSEE' + """ + } + } + + 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 env.openSEEVersion != 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.openSEEVersion} -m 'Version ${env.openSEEVersion} release'" + powershell "git push origin --tags" + } + } + } +} diff --git a/openSEE.dockerfile b/openSEE.dockerfile new file mode 100644 index 00000000..b5dcdd4f --- /dev/null +++ b/openSEE.dockerfile @@ -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 /openSEE + +# Copy openSEE from the local published folder to the container +COPY ./[Bb]uild/${CONFIGURATION}/Applications/openSEE/net9.0/publish/linux-x64/ /openSEE/ + +ENV ASPNETCORE_HTTP_PORTS=50951 + +# Set permissions for all copied folders and files +RUN chmod -R 777 /openSEE + +# Ensure the application is executable +RUN chmod +x /openSEE/OpenSEE + +# Expose the webserver port +EXPOSE 50951 + +# Define the entry point to run +ENTRYPOINT ["sh", "-c", "exec /openSEE/OpenSEE"] diff --git a/scripts/BuildNightly.bat b/scripts/BuildNightly.bat deleted file mode 100644 index 7d0c3a71..00000000 --- a/scripts/BuildNightly.bat +++ /dev/null @@ -1,27 +0,0 @@ -::******************************************************************************************************* -:: BuildNightly.bat - Gbtc -:: -:: Tennessee Valley Authority, 2009 -:: No copyright is claimed pursuant to 17 USC § 105. All Other Rights Reserved. -:: -:: This software is made freely available under the TVA Open Source Agreement (see below). -:: -:: Code Modification History: -:: ----------------------------------------------------------------------------------------------------- -:: 10/20/2009 - Pinal C. Patel -:: Generated original version of source code. -:: 09/14/2010 - Mihir Brahmbhatt -:: Change Framework path from v3.5 to v4.0 -:: 10/03/2010 - Pinal C. Patel -:: Updated to use MSBuild 4.0. -:: -::******************************************************************************************************* - -@ECHO OFF - -SetLocal - -IF NOT "%1" == "" SET logflag=/l:FileLogger,Microsoft.Build.Engine;logfile=%1 - -ECHO BuildNightly: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe OpenSEE.buildproj /p:ForceBuild=false %logflag% -"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" OpenSEE.buildproj /p:ForceBuild=false %logflag% \ No newline at end of file diff --git a/scripts/BuildTSX.ps1 b/scripts/BuildTSX.ps1 deleted file mode 100644 index 79eaaa16..00000000 --- a/scripts/BuildTSX.ps1 +++ /dev/null @@ -1,46 +0,0 @@ -# Call the script with the path to the project directory as an argument: -# .\build-panel.ps1 "C:\Projects\SystemCenter\Source\Applications\SystemCenter" - -# Uncomment the following line to hardcode the project directory for testing -#$projectDir = "D:\Projects\SystemCenter\Source\Applications\SystemCenter\" - -param( - [string]$projectDir, - [string]$buildConfig = "Release" -) - -# Validate script parameters -if ([string]::IsNullOrWhiteSpace($projectDir)) { - throw "projectDir parameter was not provided, script terminated." -} - -function Install-NPM { - "Installing NPM" - npm install - "Installed NPM Succesfully" -} - -function Build-TS { - "Building TypeScript" - $mode = $buildConfig - if ($mode = "release") { - $mode = "production" - } - "Build set to mode $mode" - .\node_modules\.bin\webpack --mode=$mode - - "Built TypeScript" -} - -function Remove-NPM { - "Remove NPM" - mkdir "tmp" - robocopy /MIR .\tmp .\node_modules > NULL - Remove-Item '.\node_modules' -Recurse - Remove-Item '.\tmp' -Recurse -} - -Set-Location "$projectDir" -Install-NPM -Build-TS -Remove-NPM \ No newline at end of file diff --git a/scripts/CreateDependencyPR.ps1 b/scripts/CreateDependencyPR.ps1 new file mode 100644 index 00000000..a316bfb0 --- /dev/null +++ b/scripts/CreateDependencyPR.ps1 @@ -0,0 +1,135 @@ +param( + [string]$GithubToken, + [string]$DevelopmentBranchName = "development" +) + +$headers = @{ + "Authorization" = "token $GithubToken" + "Accept" = "application/vnd.github.v3+json" +} + +#Count Changes in Dev vs Master +function CountChanges { + param( + [string]$Repository, + [string]$mainBranch + ) + + # Check if Development Branch exists + $branchURL = "https://api.github.com/repos/$Repository/branches/development" + + Write-Host "Checking for development branch in $branchURL" + + try { + $prs = Invoke-RestMethod -Uri $branchURL -Headers $headers -Method Get -ErrorAction Stop + } + catch { + # Generate a development Branch on top of main if it doesn't exist + $refUrl = "https://api.github.com/repos/$Repository/git/ref/heads/$mainBranch" + + $baseRef = Invoke-RestMethod -Uri $refUrl -Headers $headers -Method Get + $baseSha = $baseRef.object.sha + + $body = @{ + ref = "refs/heads/development" + sha = $baseSha + } | ConvertTo-Json + + $newRefUrl = "https://api.github.com/repos/$Repository/git/refs" + + Invoke-RestMethod -Uri $newRefUrl ` + -Headers $headers ` + -Method Post ` + -Body $body ` + -ContentType "application/json" + + Write-Host "No development branch found for $Repository. Generated development branch based on $mainBranch" + return 0; + } + + + $branchURL = "https://api.github.com/repos/$Repository/compare/$mainBranch...development" + Write-Host "Checking for diff branch in $branchURL" + + $prs = Invoke-RestMethod -Uri $branchURL -Headers $headers -Method Get + + return $prs.ahead_by +} + +function GeneratePR { + param( + [string]$Repository, + [string]$Title, + [string]$Body, + [string]$mainBranch, + [string]$organization + ) + + # Check if PR already exists + $url = "https://api.github.com/repos/$Repository/pulls?state=open&head=${organization}:development&base=$mainBranch" + $prs = Invoke-RestMethod -Uri $url -Headers $headers -Method Get + + if ($prs.Count -gt 0) { + Write-Host "PR Already exists" + return $prs[0].html_url + } + + $url = "https://api.github.com/repos/$Repository/pulls" + + $body = @{ + title = "$Title" + head = "development" + base = "$mainBranch" + body = "$Body" + } | ConvertTo-Json + + $response = Invoke-RestMethod -Uri $url ` + -Headers $headers ` + -Method Post ` + -Body $body ` + -ContentType "application/json" ` + + return $response.html_url + +} + +# Get all Gemstone Repos +$repoFileURL = "https://raw.githubusercontent.com/gemstone/root-dev/refs/heads/master/repos.txt" +$gemstoneRepos = Invoke-WebRequest -Uri $repoFileURL -UseBasicParsing | Select-Object -ExpandProperty Content +$gemstoneRepos = $gemstoneRepos -split "`n" | Where-Object { -not $_.Trim().StartsWith("::") } + +# Separate repos names from project names +for ($i = 0; $i -lt $gemstoneRepos.Length; $i++){ + $parts = $gemstoneRepos[$i].Trim().Split('/'); + + if ($parts.Length -eq 2) { + $gemstoneRepos[$i] = $parts[0].Trim() + } + else { + $gemstoneRepos[$i] = "" + } +} + +$gemstoneRepos = $gemstoneRepos | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } + +$prs = @() + +foreach ($repo in $gemstoneRepos) { + $changes = CountChanges -Repository "Gemstone/$repo" -mainBranch "master" + if ($changes -gt 0) { + Write-Host "There are $changes changes in $repo." + $prLink = GeneratePR -Repository "Gemstone/$repo" -Title "Release Update" -Body "This PR was Generated by a release of openSEE" -mainBranch "master" -organization "Gemstone" + $prs += $prLink + } +} + +# Add Comments to the PR with the Open PRs in the openSEE Repo +if ($prs.Count -gt 0) { + $commentBody = "The following PRs have been generated for the dependencies: `n" + foreach ($pr in $prs) { + $commentBody += "- [ ] $pr `n" + } + +& "$PSScriptRoot\GithubComment.ps1" -Comment $commentBody -BranchName "$DevelopmentBranchName" -GithubToken $GithubToken -RepoOwner "GridProtectionAlliance" -RepoName "openSEE" + +} diff --git a/scripts/GemstoneUpdates.ps1 b/scripts/GemstoneUpdates.ps1 new file mode 100644 index 00000000..dafe7d7c --- /dev/null +++ b/scripts/GemstoneUpdates.ps1 @@ -0,0 +1,79 @@ +param( + [string]$VersionFile +) + +#Compare Versions +function CompareVersions { + param( + [string]$Version1, + [string]$Version2 + ) + + $array1 = $Version1.Split(".") + $array2 = $Version2.Split(".") + + $i = 0 + while ($i -lt [Math]::Max($array1.Count, $array2.Count)) { + if ($i -ge $array1.Count) { + $v1 = 0 + } else { + $v1 = [int]$array1[$i] + } + if ($i -ge $array2.Count) { + $v2 = 0 + } else { + $v2 = [int]$array2[$i] + } + if ($v1 -gt $v2) { + return 1 + } + if ($v2 -gt $v1) { + return -1 + } + $i++ + } + return 0 +} + +#Write Version +function UpdateVersion { + param( + [string]$VersionFile, + [string]$Version, + [string]$VariableName + ) + + $content = Get-Content -LiteralPath $VersionFile -Raw -Encoding UTF8 + + $pattern = "(<$VariableName>)([^<]+)()" + $newContent = [regex]::Replace($content, $pattern, "`${1}$version`${3}") + + if ($newContent -eq $content) { + return 0; + } + + Set-Content -LiteralPath $VersionFile -Value $newContent -Encoding UTF8 -NoNewline + return 1 +} + +$changedFiles = 0; +# Find all CSProje Files +$currentConsolePath = Get-Location +$savePath = Join-Path -Path $currentConsolePath -ChildPath $SlnFolder + + +#Update all Gemstone References + +#Get Latest Version on Github +$RepoState = git ls-remote --sort='version:refname' --tags https://github.com/gemstone/common.git | Select-Object -Last 1 +$regex = [regex]".+refs\/tags\/v([0-9]+\.[0-9]+\.[0-9]+)" + +$matchesCollection = $regex.Matches($RepoState) + +$latestVersion = $matchesCollection[0].Groups[1].Value + +echo "Found Lastest Common Gemstone Version on GitHub: $latestVersion" + +$changedFiles = UpdateVersion -VersionFile $VersionFile -VariableName "GemstoneVersion" -Version $latestVersion + +echo "Updated $changedFiles Dependecies in $VersionFile" diff --git a/scripts/GithubComment.ps1 b/scripts/GithubComment.ps1 new file mode 100644 index 00000000..48f125f0 --- /dev/null +++ b/scripts/GithubComment.ps1 @@ -0,0 +1,36 @@ +param( + [string]$Comment, + [string]$BranchName, + [string]$GithubToken, + [string]$RepoOwner, + [string]$RepoName +) + +# Configuration +# Find PR by branch name +$headers = @{ + "Authorization" = "token $GithubToken" + "Accept" = "application/vnd.github.v3+json" +} + +# Search for open PRs with the specified head branch +$prsUrl = "https://api.github.com/repos/$RepoOwner/$RepoName/pulls?state=open&head=${RepoOwner}:${BranchName}" +$prs = Invoke-RestMethod -Uri $prsUrl -Headers $headers -Method Get + +if ($prs.Count -eq 0) { + Write-Host "No open PR found for branch: $BranchName" + exit 1 +} + +# Get the first PR (assuming one PR per branch) +$prNumber = $prs[0].number +Write-Host "Found PR #$prNumber for branch: $BranchName" + +# Add comment to the PR +$commentUrl = "https://api.github.com/repos/$RepoOwner/$RepoName/issues/$prNumber/comments" +$body = @{ + body = $Comment +} | ConvertTo-Json + +$response = Invoke-RestMethod -Uri $commentUrl -Headers $headers -Method Post -Body $body -ContentType "application/json" +Write-Host "Comment added successfully to PR #$prNumber" diff --git a/scripts/MasterBuild.buildproj b/scripts/MasterBuild.buildproj deleted file mode 100644 index 2207de15..00000000 --- a/scripts/MasterBuild.buildproj +++ /dev/null @@ -1,510 +0,0 @@ - - - - - - - - - - - - - - - - - - $(GitServer) - - $(LocalFolder) - - - - $(BuildFlavor) - - $(BuildTarget) - - $(BuildOutputFolder) - - $(BuildDeployFolder) - - $(BuildInteractive) - - - - - - - - - - - - $(GitClient) - - $(GitBranch) - - $(MSTest) - - $(SandcastleBuilder) - - $(ForceBuild) - - $(SkipVersioning) - - $(DoNotPush) - - $(SkipUnitTest) - - - - - - - - - - - - - - - - - - $(PublishApp) - - $(PublishProfile) - - - - - - PrepareSettings; - CheckEnvironment; - CreateWorkspace; - - - - UpdateRepository; - VersionSource; - BuildProjects; - ExecuteUnitTests; - - - - CleanBuild; - DeployBuild; - PushToServer; - - - - BeforeCheckEnvironment; - CoreCheckEnvironment; - AfterCheckEnvironment; - - - - BeforePrepareSettings; - CorePrepareSettings; - AfterPrepareSettings; - - - BeforeCreateWorkspace; - CoreCreateWorkspace; - AfterCreateWorkspace; - - - - BeforeUpdateRepository; - CoreUpdateRepository; - AfterUpdateRepository; - - - - BeforeVersionSource; - CoreVersionSource; - AfterVersionSource; - - - - BeforeBuildProjects; - CoreBuildProjects; - AfterBuildProjects; - - - - BeforeExecuteUnitTests; - CoreExecuteUnitTests; - AfterExecuteUnitTests; - - - - BeforeCleanBuild; - CoreCleanBuild; - AfterCleanBuild; - - - - BeforeDeployBuild; - CoreDeployBuild; - AfterDeployBuild; - - - - BeforePushToServer; - CorePushToServer; - AfterPushToServer; - - - - - - - - - (?'BeforeVersion')(?'CoreVersion')(?'AfterVersion') - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(MSBuildProgramFiles32) - $(ProgramFiles) - $(ProgramW6432) - $(ProgramFiles) - $([System.IO.Path]::GetFullPath('$(TEMP)\MSBuild\$(ProjectName)')) - Release - Any CPU - True - $(LocalFolder)\Build\Output\$(BuildFlavor) - true - $(LocalFolder)\Build\Scripts\$(ProjectName).version - $(ProgramFiles64)\NuGet\nuget.exe - $(ProgramFiles32)\Git\cmd\git.exe - master - True - $(VS140COMNTOOLS)\..\IDE\mstest.exe - - false - false - false - false - $(LocalFolder)\$(ProjectName).Binaries.zip - $(LocalFolder)\$(ProjectName).Installs.zip - $(LocalFolder)\$(ProjectName).Scripts.zip - $(LocalFolder)\$(ProjectName).Source.zip - $(LocalFolder)\Archives\Binaries - $(LocalFolder)\Archives\Installs - $(LocalFolder)\Archives\Scripts - $(LocalFolder)\Archives\Source - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - - - - - - - - - - - - - - - - - - - - - v$(Major).$(Minor).$(Build).$(Revision)-$(GitBranch) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/scripts/OpenSEE.buildproj b/scripts/OpenSEE.buildproj deleted file mode 100644 index acbdfddc..00000000 --- a/scripts/OpenSEE.buildproj +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - OpenSee - $(LocalFolder)\src\$(ProjectName).sln - - None - None - Increment - None - $(LocalFolder)\scripts\$(ProjectName).version - - - git@github.com:GridProtectionAlliance/OpenSEE.git - true - $(LocalFolder)\scripts\PublishProfile.pubxml - - - - - - - - - - (?'BeforeVersion'AssemblyVersion\(%22)(?'CoreVersion'(\*|\d+)\.)+(\*|\d+)(?'AfterVersion'%22\)) - 4 - - - (?'BeforeVersion'AssemblyFileVersion\(%22)(?'CoreVersion'(\*|\d+)\.)+(\*|\d+)(?'AfterVersion'%22\)) - 4 - - - - - - - %WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/scripts/OpenSEE.version b/scripts/OpenSEE.version index 0732b43a..778bf95c 100644 --- a/scripts/OpenSEE.version +++ b/scripts/OpenSEE.version @@ -1 +1 @@ -3.0.11.1 \ No newline at end of file +3.0.11 diff --git a/scripts/PublishProfile.pubxml b/scripts/PublishProfile.pubxml deleted file mode 100644 index b41ee906..00000000 --- a/scripts/PublishProfile.pubxml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - FileSystem - False - .\Publish - True - - diff --git a/scripts/Targets/Inline/GitHistory.targets b/scripts/Targets/Inline/GitHistory.targets deleted file mode 100644 index 957140a0..00000000 --- a/scripts/Targets/Inline/GitHistory.targets +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - m_output; - private string m_errorMessage; - - public GitHistory() - { - // Initialize member variables. - m_output = new List(); - } - - public string GitClient - { - get { return m_gitClient; } - set { m_gitClient = value; } - } - - public string LocalPath - { - get { return m_localPath; } - set { m_localPath = value; } - } - - public string VersionTag - { - get { return m_versionTag; } - set { m_versionTag = value; } - } - - [Output()] - public int TotalChanges - { - get { return m_totalChanges; } - } - - public override bool Execute() - { - try - { - // Launch Git Client and wait for it to complete. - using (Process p = new Process()) - { - p.StartInfo.FileName = m_gitClient; - p.StartInfo.Arguments = string.Format(@"log --pretty=oneline ""{0}..""", m_versionTag); - p.StartInfo.WorkingDirectory = m_localPath; - p.StartInfo.UseShellExecute = false; - p.StartInfo.RedirectStandardOutput = true; - p.StartInfo.RedirectStandardError = true; - p.OutputDataReceived += OnOutputDataReceived; - p.ErrorDataReceived += OnErrorDataReceived; - p.Start(); - p.BeginOutputReadLine(); - p.BeginErrorReadLine(); - p.WaitForExit(); - } - - // Check if the command encountered an error. - if (!string.IsNullOrEmpty(m_errorMessage)) - throw new Exception(m_errorMessage); - - // Count the number of changes returned by the query. - m_totalChanges = m_output.Count; - - return true; - } - catch (Exception ex) - { - // Notify about the exception. - m_totalChanges = -1; - Log.LogError(ex.Message); - - return false; - } - } - - private void OnOutputDataReceived(object sender, DataReceivedEventArgs e) - { - // Accumulate the output for processing. - if (!string.IsNullOrEmpty(e.Data)) - m_output.Add(e.Data); - } - - private void OnErrorDataReceived(object sender, DataReceivedEventArgs e) - { - // Capture the encountered error. - if (!string.IsNullOrEmpty(e.Data)) - m_errorMessage = e.Data; - } - } - ]]> - - - - - \ No newline at end of file diff --git a/scripts/Targets/MSBuild Community Tasks/ICSharpCode.SharpZipLib.dll b/scripts/Targets/MSBuild Community Tasks/ICSharpCode.SharpZipLib.dll deleted file mode 100644 index 77bafe8b..00000000 Binary files a/scripts/Targets/MSBuild Community Tasks/ICSharpCode.SharpZipLib.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Community Tasks/MSBuild.Community.Tasks.Targets b/scripts/Targets/MSBuild Community Tasks/MSBuild.Community.Tasks.Targets deleted file mode 100644 index c38506ea..00000000 --- a/scripts/Targets/MSBuild Community Tasks/MSBuild.Community.Tasks.Targets +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - MSBuild.Community.Tasks.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/Targets/MSBuild Community Tasks/MSBuild.Community.Tasks.dll b/scripts/Targets/MSBuild Community Tasks/MSBuild.Community.Tasks.dll deleted file mode 100644 index 15f51c95..00000000 Binary files a/scripts/Targets/MSBuild Community Tasks/MSBuild.Community.Tasks.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/Interop.COMAdmin.dll b/scripts/Targets/MSBuild Extension Pack/Interop.COMAdmin.dll deleted file mode 100644 index b9383304..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/Interop.COMAdmin.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/Interop.IWshRuntimeLibrary.dll b/scripts/Targets/MSBuild Extension Pack/Interop.IWshRuntimeLibrary.dll deleted file mode 100644 index 2400e761..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/Interop.IWshRuntimeLibrary.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.BizTalk.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.BizTalk.dll deleted file mode 100644 index 0a559238..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.BizTalk.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Iis7.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Iis7.dll deleted file mode 100644 index bf90d151..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Iis7.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.JSharp.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.JSharp.dll deleted file mode 100644 index 57d8129d..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.JSharp.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sql2005.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sql2005.dll deleted file mode 100644 index b96b9a4a..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sql2005.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sql2008.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sql2008.dll deleted file mode 100644 index f966cc0b..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sql2008.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.StyleCop.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.StyleCop.dll deleted file mode 100644 index 14f72e5d..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.StyleCop.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sync.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sync.dll deleted file mode 100644 index fa1fce69..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Sync.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Tfs.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Tfs.dll deleted file mode 100644 index ccce3dc7..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.Tfs.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.dll b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.dll deleted file mode 100644 index c630fae3..00000000 Binary files a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.dll and /dev/null differ diff --git a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.tasks b/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.tasks deleted file mode 100644 index 7576541c..00000000 --- a/scripts/Targets/MSBuild Extension Pack/MSBuild.ExtensionPack.tasks +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/Versioning.ps1 b/scripts/Versioning.ps1 new file mode 100644 index 00000000..f2f62c4a --- /dev/null +++ b/scripts/Versioning.ps1 @@ -0,0 +1,81 @@ +param( + [string]$VersionFile, + [string]$Commit +) + +#Compare Versions +function CompareVersions { + param( + [string]$Version1, + [string]$Version2 + ) + + $array1 = $Version1.Split(".") + $array2 = $Version2.Split(".") + + $i = 0 + while ($i -lt [Math]::Max($array1.Count, $array2.Count)) { + if ($i -ge $array1.Count) { + $v1 = 0 + } else { + $v1 = [int]$array1[$i] + } + if ($i -ge $array2.Count) { + $v2 = 0 + } else { + $v2 = [int]$array2[$i] + } + if ($v1 -gt $v2) { + return 1 + } + if ($v2 -gt $v1) { + return -1 + } + $i++ + } + return 0 +} + +#Increment Version +function IncrementVersion { + param( + [string]$prevVersion + ) + $array = $prevVersion.Split(".") + $array[$array.Count - 1] = [int]$array[$array.Count - 1] + 1 + return $array -join '.' +} + +$Commit = [System.Convert]::ToBoolean($Commit) + +#Get Latest Version on Github +git fetch origin master:refs/remotes/origin/master +$commit = git rev-parse origin/master +$tag = git describe --tags --abbrev=0 $commit + +if ([String]::IsNullOrEmpty($tag)) { + echo "No previous tag found" + $tag = "v3.0.0" +} + +$tag = $tag.TrimStart("v") + +echo "Last Published Version Found: $tag" + + +# Get Current Version +$currentVersion = $([System.IO.File]::ReadAllText($VersionFile).Trim()) +echo "Current Version in Repository: $currentVersion" + +# Check if Update is needed +if ((CompareVersions -Version1 $currentVersion -Version2 $tag) -gt 0) { + echo "No Version update neccesarry" + return; +} + +# Update Version +$updatedVersion = IncrementVersion -prevVersion $tag + +echo "Updating to $updatedVersion" + +[System.IO.File]::WriteAllText($VersionFile, $updatedVersion) diff --git a/scripts/openSee.output b/scripts/openSee.output deleted file mode 100644 index e69de29b..00000000 diff --git a/src/OpenSEE-dev.slnx b/src/OpenSEE-dev.slnx index fab4fbb0..8fa4b08a 100644 --- a/src/OpenSEE-dev.slnx +++ b/src/OpenSEE-dev.slnx @@ -5,10 +5,18 @@ + + - + + + + + + + @@ -25,4 +33,5 @@ + diff --git a/src/OpenSEE/OpenSEE.csproj b/src/OpenSEE/OpenSEE.csproj index 3822643b..354cebdf 100644 --- a/src/OpenSEE/OpenSEE.csproj +++ b/src/OpenSEE/OpenSEE.csproj @@ -5,9 +5,15 @@ true latest net9.0 + OpenSee + OpenSee + Copyright © 2020-2023 Debug;Development;Release bin\ - false + $(MSBuildProjectDirectory)\..\..\scripts\OpenSEE.version + $([System.IO.File]::ReadAllText('$(VersionFile)').Trim()) + $(Version) + $(Version) true diff --git a/src/OpenSEE/Pages/Shared/Index.cshtml b/src/OpenSEE/Pages/Shared/Index.cshtml index d5b06600..5a5b7393 100644 --- a/src/OpenSEE/Pages/Shared/Index.cshtml +++ b/src/OpenSEE/Pages/Shared/Index.cshtml @@ -96,6 +96,6 @@ @*@Scripts.Render("~/Scripts/OpenSEE")*@ - + \ No newline at end of file diff --git a/src/OpenSEE/Program.cs b/src/OpenSEE/Program.cs index eeae81c0..158c41e9 100644 --- a/src/OpenSEE/Program.cs +++ b/src/OpenSEE/Program.cs @@ -142,6 +142,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) diff --git a/src/OpenSEE/Properties/AssemblyInfo.cs b/src/OpenSEE/Properties/AssemblyInfo.cs deleted file mode 100644 index e774c8f7..00000000 --- a/src/OpenSEE/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("OpenSee")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("OpenSee")] -[assembly: AssemblyCopyright("Copyright © 2020-2023")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("845f68f7-4094-4fe6-95e3-1b113bbfad3f")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("3.0.12.0")] -[assembly: AssemblyFileVersion("3.0.12.0")] diff --git a/src/OpenSEE/Properties/PublishProfiles/Development Profile openSEE.pubxml b/src/OpenSEE/Properties/PublishProfiles/Development Profile openSEE.pubxml new file mode 100644 index 00000000..c46fc03f --- /dev/null +++ b/src/OpenSEE/Properties/PublishProfiles/Development Profile openSEE.pubxml @@ -0,0 +1,24 @@ + + + + + ;IS_PUBLISH + Custom + Development + Any CPU + f2f40586-a967-ff65-5db4-30d9e460b8b5 + + + Development + Any CPU + ..\..\build\Development\Applications\openSEE\net9.0\publish\win-x64\ + FileSystem + <_TargetId>Folder + net9.0 + win-x64 + true + false + true + false + + \ No newline at end of file diff --git a/src/OpenSEE/Properties/PublishProfiles/Docker Development Profile openSEE.pubxml b/src/OpenSEE/Properties/PublishProfiles/Docker Development Profile openSEE.pubxml new file mode 100644 index 00000000..bc02cb01 --- /dev/null +++ b/src/OpenSEE/Properties/PublishProfiles/Docker Development Profile openSEE.pubxml @@ -0,0 +1,23 @@ + + + + + ;IS_PUBLISH;IS_DOCKER + Custom + Development + Any CPU + f2f40586-a967-ff65-5db4-30d9e460b8b5 + + + Development + Any CPU + ..\..\build\Development\Applications\openSEE\net9.0\publish\linux-x64\ + FileSystem + <_TargetId>Folder + net9.0 + linux-x64 + true + false + false + + \ No newline at end of file diff --git a/src/OpenSEE/Properties/PublishProfiles/Docker Release Profile openSEE.pubxml b/src/OpenSEE/Properties/PublishProfiles/Docker Release Profile openSEE.pubxml new file mode 100644 index 00000000..90858ba9 --- /dev/null +++ b/src/OpenSEE/Properties/PublishProfiles/Docker Release Profile openSEE.pubxml @@ -0,0 +1,23 @@ + + + + + ;IS_PUBLISH;IS_DOCKER + Custom + Release + Any CPU + f2f40586-a967-ff65-5db4-30d9e460b8b5 + + + Release + Any CPU + ..\..\build\Release\Applications\openSEE\net9.0\publish\linux-x64\ + FileSystem + <_TargetId>Folder + net9.0 + linux-x64 + true + false + false + + \ No newline at end of file diff --git a/src/OpenSEE/Properties/PublishProfiles/Release Profile openSEE.pubxml b/src/OpenSEE/Properties/PublishProfiles/Release Profile openSEE.pubxml new file mode 100644 index 00000000..8ace05c2 --- /dev/null +++ b/src/OpenSEE/Properties/PublishProfiles/Release Profile openSEE.pubxml @@ -0,0 +1,24 @@ + + + + + ;IS_PUBLISH + Custom + Release + Any CPU + f2f40586-a967-ff65-5db4-30d9e460b8b5 + + + Release + Any CPU + ..\..\build\Release\Applications\openSEE\net9.0\publish\win-x64\ + FileSystem + <_TargetId>Folder + net9.0 + win-x64 + true + false + true + false + + \ No newline at end of file diff --git a/src/OpenSEE/Security/SkipAuthenticationMiddleware.cs b/src/OpenSEE/Security/SkipAuthenticationMiddleware.cs new file mode 100644 index 00000000..91e8245c --- /dev/null +++ b/src/OpenSEE/Security/SkipAuthenticationMiddleware.cs @@ -0,0 +1,54 @@ +//****************************************************************************************************** +// SkipAuthenticationMiddleware.cs - Gbtc +// +// Copyright © 2026, Grid Protection Alliance. All Rights Reserved. +// +// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See +// the NOTICE file distributed with this work for additional information regarding copyright ownership. +// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this +// file except in compliance with the License. You may obtain a copy of the License at: +// +// http://opensource.org/licenses/MIT +// +// Unless agreed to in writing, the subject software distributed under the License is distributed on an +// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the +// License for the specific language governing permissions and limitations. +// +// Code Modification History: +// ---------------------------------------------------------------------------------------------------- +// 07/29/2026 - Preston Crawford +// Generated original version of source code. +// +//****************************************************************************************************** + +using Gemstone.Security.AccessControl; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace OpenSEE.Security; + +public class SkipAuthenticationMiddleware +{ + private readonly RequestDelegate m_next; + + public SkipAuthenticationMiddleware(RequestDelegate next) + { + m_next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + ClaimsIdentity identity = new("SkipAuthentication"); + identity.AddClaim(new(ClaimTypes.Name, "SkipAuthenticationUser")); + identity.AddClaim(new("Gemstone.ProviderIdentity", "SkipAuthentication")); + identity.AddClaim(new("Gemstone.ResourceAccess.Default", ResourceAccessType.Create.ToString())); + identity.AddClaim(new("Gemstone.ResourceAccess.Default", ResourceAccessType.Read.ToString())); + identity.AddClaim(new("Gemstone.ResourceAccess.Default", ResourceAccessType.Update.ToString())); + identity.AddClaim(new("Gemstone.ResourceAccess.Default", ResourceAccessType.Delete.ToString())); + context.User = new(identity); + await context.SignInAsync(context.User); + await m_next(context); + } +} \ No newline at end of file diff --git a/src/OpenSEE/Startup.cs b/src/OpenSEE/Startup.cs index 4ea090c7..a7df84ae 100644 --- a/src/OpenSEE/Startup.cs +++ b/src/OpenSEE/Startup.cs @@ -155,6 +155,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseGemstoneAuthentication(); + dynamic options = Settings.Instance[Program.DefaultWebHostingCategory]; + + if (options.DisableAuthentication ?? false) + app.UseMiddleware(); + app.UseStaticFiles(WebExtensions.StaticFileEmbeddedResources()); app.UseStaticFiles(); diff --git a/src/OpenSEE/package.json b/src/OpenSEE/package.json index b8bb8ea7..1980a98e 100644 --- a/src/OpenSEE/package.json +++ b/src/OpenSEE/package.json @@ -47,6 +47,7 @@ }, "scripts": { "build": "npm prune && npm ci && webpack --mode=production", + "buildrelease": "npm run build", "builddev": "npm install && webpack --mode=development", "watch": "webpack --watch --color --mode=development", "update": "npx npm-check-updates",