diff --git a/.gitignore b/.gitignore index fcab916ac..77189a7fa 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..0028715ec --- /dev/null +++ b/Jenkinsfile @@ -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" + } + } + } +} diff --git a/SEBrowser-dev.slnx b/SEBrowser-dev.slnx index ab2cbf626..69e06e14b 100644 --- a/SEBrowser-dev.slnx +++ b/SEBrowser-dev.slnx @@ -4,6 +4,17 @@ + + + + + + + + + + + diff --git a/SEBrowser.dockerfile b/SEBrowser.dockerfile new file mode 100644 index 000000000..68a3b4b98 --- /dev/null +++ b/SEBrowser.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 /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"] diff --git a/SEBrowser/Program.cs b/SEBrowser/Program.cs index cf2963e85..52bb647b1 100644 --- a/SEBrowser/Program.cs +++ b/SEBrowser/Program.cs @@ -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) diff --git a/SEBrowser/Properties/AssemblyInfo.cs b/SEBrowser/Properties/AssemblyInfo.cs deleted file mode 100644 index 0ac6d41fa..000000000 --- a/SEBrowser/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -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("SEBrowser")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("GridProtectionAlliance")] -[assembly: AssemblyProduct("SEBrowser")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[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.1.5")] -[assembly: AssemblyFileVersion("3.0.1.5")] diff --git a/SEBrowser/Properties/PublishProfiles/Development Profile SEBrowser.pubxml b/SEBrowser/Properties/PublishProfiles/Development Profile SEBrowser.pubxml new file mode 100644 index 000000000..d7c1941e1 --- /dev/null +++ b/SEBrowser/Properties/PublishProfiles/Development Profile SEBrowser.pubxml @@ -0,0 +1,23 @@ + + + + + $(DefineConstants);IS_PUBLISH + Custom + Development + Any CPU + + + Development + Any CPU + ..\build\Development\Applications\SEBrowser\net9.0\publish\win-x64\ + FileSystem + <_TargetId>Folder + net9.0 + win-x64 + true + false + true + false + + diff --git a/SEBrowser/Properties/PublishProfiles/Docker Development Profile SEBrowser.pubxml b/SEBrowser/Properties/PublishProfiles/Docker Development Profile SEBrowser.pubxml new file mode 100644 index 000000000..9a6144dfd --- /dev/null +++ b/SEBrowser/Properties/PublishProfiles/Docker Development Profile SEBrowser.pubxml @@ -0,0 +1,22 @@ + + + + + $(DefineConstants);IS_PUBLISH;IS_DOCKER + Custom + Development + Any CPU + + + Development + Any CPU + ..\build\Development\Applications\SEBrowser\net9.0\publish\linux-x64\ + FileSystem + <_TargetId>Folder + net9.0 + linux-x64 + true + false + false + + diff --git a/SEBrowser/Properties/PublishProfiles/Docker Release Profile SEBrowser.pubxml b/SEBrowser/Properties/PublishProfiles/Docker Release Profile SEBrowser.pubxml new file mode 100644 index 000000000..08d86adcc --- /dev/null +++ b/SEBrowser/Properties/PublishProfiles/Docker Release Profile SEBrowser.pubxml @@ -0,0 +1,22 @@ + + + + + $(DefineConstants);IS_PUBLISH;IS_DOCKER + Custom + Release + Any CPU + + + Release + Any CPU + ..\build\Release\Applications\SEBrowser\net9.0\publish\linux-x64\ + FileSystem + <_TargetId>Folder + net9.0 + linux-x64 + true + false + false + + diff --git a/SEBrowser/Properties/PublishProfiles/Release Profile SEBrowser.pubxml b/SEBrowser/Properties/PublishProfiles/Release Profile SEBrowser.pubxml new file mode 100644 index 000000000..73c1117b8 --- /dev/null +++ b/SEBrowser/Properties/PublishProfiles/Release Profile SEBrowser.pubxml @@ -0,0 +1,23 @@ + + + + + $(DefineConstants);IS_PUBLISH + Custom + Release + Any CPU + + + Release + Any CPU + ..\build\Release\Applications\SEBrowser\net9.0\publish\win-x64\ + FileSystem + <_TargetId>Folder + net9.0 + win-x64 + true + false + true + false + + diff --git a/SEBrowser/SEBrowser.csproj b/SEBrowser/SEBrowser.csproj index b1484c53c..854b5faf2 100644 --- a/SEBrowser/SEBrowser.csproj +++ b/SEBrowser/SEBrowser.csproj @@ -1,10 +1,18 @@ - - net9.0 - Debug;Development;Release - $(DefineConstants);IS_GEMSTONE - false - + + net9.0 + SEBrowser + + GridProtectionAlliance + SEBrowser + Copyright © 2020 + Debug;Development;Release + $(DefineConstants);IS_GEMSTONE + $(MSBuildProjectDirectory)\..\Scripts\SEBrowser.version + $([System.IO.File]::ReadAllText('$(VersionFile)').Trim()) + $(Version) + $(Version) + diff --git a/SEBrowser/Security/SkipAuthenticationMiddleware.cs b/SEBrowser/Security/SkipAuthenticationMiddleware.cs new file mode 100644 index 000000000..e93597a21 --- /dev/null +++ b/SEBrowser/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: +// ---------------------------------------------------------------------------------------------------- +// 08/04/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 SEBrowser.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); + } +} diff --git a/SEBrowser/Startup.cs b/SEBrowser/Startup.cs index aa063c6e5..31427a084 100644 --- a/SEBrowser/Startup.cs +++ b/SEBrowser/Startup.cs @@ -170,6 +170,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseGemstoneAuthentication(); + dynamic options = Settings.Instance[Program.DefaultWebHostingCategory]; + + if (options.DisableAuthentication ?? false) + app.UseMiddleware(); + app.UseStaticFiles(Gemstone.Web.WebExtensions.StaticFileEmbeddedResources()); app.UseStaticFiles(); diff --git a/Scripts/BuildNightly.bat b/Scripts/BuildNightly.bat deleted file mode 100644 index 86c8912c5..000000000 --- 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 SEBrowser.buildproj /p:ForceBuild=false %logflag% -"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" SEBrowser.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 79eaaa165..000000000 --- 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 000000000..91bcb9ebb --- /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 SEBrowser" -mainBranch "master" -organization "Gemstone" + $prs += $prLink + } +} + +# Add Comments to the PR with the Open PRs in the SEBrowser 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 "SEBrowser" + +} diff --git a/Scripts/GemstoneUpdates.ps1 b/Scripts/GemstoneUpdates.ps1 new file mode 100644 index 000000000..2ddc12423 --- /dev/null +++ b/Scripts/GemstoneUpdates.ps1 @@ -0,0 +1,46 @@ +param( + [string]$VersionFile +) + +#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 000000000..2355b67a5 --- /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" \ No newline at end of file diff --git a/Scripts/MasterBuild.buildproj b/Scripts/MasterBuild.buildproj deleted file mode 100644 index 2207de156..000000000 --- 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/PublishProfile.pubxml b/Scripts/PublishProfile.pubxml deleted file mode 100644 index b41ee9068..000000000 --- a/Scripts/PublishProfile.pubxml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - FileSystem - False - .\Publish - True - - diff --git a/Scripts/SEBrowser.buildproj b/Scripts/SEBrowser.buildproj deleted file mode 100644 index b8fa86516..000000000 --- a/Scripts/SEBrowser.buildproj +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - SEBrowser - $(LocalFolder)\$(ProjectName).sln - - None - None - None - Increment - $(LocalFolder)\Scripts\$(ProjectName).version - - git@github.com:GridProtectionAlliance/SEBrowser.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/SEBrowser.output b/Scripts/SEBrowser.output deleted file mode 100644 index e69de29bb..000000000 diff --git a/Scripts/SEBrowser.version b/Scripts/SEBrowser.version index 48ade0390..94ff29cc4 100644 --- a/Scripts/SEBrowser.version +++ b/Scripts/SEBrowser.version @@ -1 +1 @@ -3.0.1.5 \ No newline at end of file +3.1.1 diff --git a/Scripts/Targets/Inline/GitHistory.targets b/Scripts/Targets/Inline/GitHistory.targets deleted file mode 100644 index 957140a02..000000000 --- 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 77bafe8ba..000000000 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 c38506ea7..000000000 --- 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 15f51c955..000000000 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 b93833040..000000000 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 2400e7613..000000000 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 0a5592383..000000000 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 bf90d1511..000000000 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 57d8129d4..000000000 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 b96b9a4a3..000000000 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 f966cc0b1..000000000 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 14f72e5dc..000000000 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 fa1fce69e..000000000 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 ccce3dc73..000000000 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 c630fae37..000000000 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 7576541c4..000000000 --- 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 000000000..f2f62c4a9 --- /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)