From 02c6191019f3923e45691d3eeeef4cd589b5071b Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Fri, 23 Aug 2024 16:48:48 +0000 Subject: [PATCH 01/14] Set up CI with Start Right Set up CI with Start Right made pipeline file based on Jim's texteditor now building with net8.0 added tsa json added dependabot fixed yml to sign code. revert dotnet back to 8.0 revert back to privateassets for PowerShellStandardLibrary revert back to privateassets for PowerShellStandardLibrary fixed build.psm1 and yml to fix code signing error Deleted Microsoft.PowerShell.Threadjob.csproj Revert "Deleted Microsoft.PowerShell.Threadjob.csproj" This reverts commit cdc5061c98f2927e9f114ca4a188fab3d72c7f18. Deleted Microsoft.PowerShell.ThreadJob.csproj debugging build... Merged PR 32351: Revert "Deleted Microsoft.PowerShell.ThreadJob.csproj" Revert "Deleted Microsoft.PowerShell.ThreadJob.csproj" Reverted commit `d1f649d9`. debugging build Updated nuget.config fixing powershellget import with netlock Deleted Microsoft.PowerShell.Threadjob.csproj trying to install PSResourceGet Trying to import PSReousrceGet updated yml updated yml and moved install of psresourceget to build updated yml fixed Install-Module line updated yml fixed version to MinimumVersion added settings for linux testing csproj powershel.sdk for unix testing csproj powershel.sdk for unix add dll in a separate folder. Fixed issues with relfection. removed the local dll reference and the unix condition. conditionally added SMA.Security added conditional fomatting using reflection for Security Policy removed dependency to SMA target framework netstandard2.0 updated pipeline with new build command netstandard2.0 fixed an issue with reflection. Abstracted the assembly to a method. Need to figure out a way to not run a process every time and save the SMA dll path. Added DeployBoxProducts release pipeline update edits to deploybox pipeline edits to release pipeline moved manual validation to a separate stage removed nuget task and changed to PublishExtension@5 task Updated threadjobs-official.yml removed download Updated threadjobs-official.yml fixed dependsOn changed method of grabbing location of SMA Updated versions to 3.0.0. Added proxy module and edited build scripts to publish both. replaced periods with _ in stage name removed spaces from stage name added two separate boolean parameters for proxy and official in the onebranch yaml fixed error in parameters removed spaces from stage name added import threadjob for psd1 required module Added test module manifest to pipeline changed import module from dll to entire mdoule Install-Module instead of import Copied the Microsoft.PowerShell.ThreadJob module to env:PSModule path fixed signing. added archive for ThreadJob Trying to add tfx fixed indentation Revert "fixed signing. added archive for ThreadJob" This reverts commit c3ec1253a09bdba601739f4510ec9ea168130def. trying nugetcommand Trying Publish-PSResource trying task: powershell@2 fixed signing again. git revert error changed gallery api to 2. added verbose messages to release added error actions for release pwsh script commands trying to add dotnet sdk dotnet version 8.x added pwsh true changed os to linux added sudo force install psresourceget and Register-PSRepositroy -Default instead of -Name PSGallery fixed official release to Default and removed source location removed PSGallery registration added variable group for api key trying to debug variable group mapping from env trying version trying package.version moved version variable to job scope and added build as dependson in release added download current trying templateContext to pass nupkg artifact to release stage removed download:current's removed publish task. trying to find pukg trying to find nupkg just checking pipeline.workspace found the nupkgs uploading morudle folder and not the jupkg because probably -NupkgPath isn't available yet outputtig GalleryPAT for validation gallerypat output trying runtime expression moved variable group to stage variable should work now added var group as a job variable added name value for variable apikey fixed indentation issue with stage variables switch version order removed - in group trying to output env trying to add it as a stage variable got rid of ob release environment moved everything to stage vars. left group only in job vars removed Gallery[PAT] installing Microsoft.PowerShell.ThreadJob to machine before publishing added verbose statements and copy-item verbose and test-module manifest for threadjob.psd1 PSModulePath separator is : in linux ; in windows. Changed version numbers --- .config/tsaoptions.json | 8 + .github/dependabot.yml | 16 ++ .gitignore | 2 + .pipelines/threadjobs-official.yml | 248 ++++++++++++++++++ build.ps1 | 9 +- buildtools.psm1 | 35 ++- doBuild.ps1 | 40 ++- global.json | 6 + nuget.config | 8 +- package.config.json | 1 + src/Microsoft.PowerShell.ThreadJob.psd1 | 6 +- src/ThreadJob/ThreadJob.psd1 | 41 +++ src/ThreadJob/ThreadJob.psm1 | 6 + src/code/Microsoft.PowerShell.ThreadJob.cs | 38 ++- .../Microsoft.PowerShell.ThreadJob.csproj | 19 +- 15 files changed, 416 insertions(+), 67 deletions(-) create mode 100644 .config/tsaoptions.json create mode 100644 .github/dependabot.yml create mode 100644 .pipelines/threadjobs-official.yml create mode 100644 global.json create mode 100644 src/ThreadJob/ThreadJob.psd1 create mode 100644 src/ThreadJob/ThreadJob.psm1 diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 0000000..e4c65c4 --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,8 @@ +{ + "instanceUrl": "https://msazure.visualstudio.com", + "projectName": "One", + "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell\\PowerShell Core\\ThreadJob", + "codebaseName": "TFSMSAzure_ThreadJob", + "notificationAliases": [ "chungjustin@microsoft.com", "slee@microsoft.com" ], + "tools": [ "CredScan", "PoliCheck", "BinSkim" ] +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a5ba660 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: "nuget" # See documentation for possible values + directory: "/src/code" # Location of package manifests + schedule: + interval: "daily" + + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: nuget + directory: / + schedule: + interval: daily \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9587ceb..80167f7 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ xhtml/ **/.vscode/** **/out/** **/bin/** +.vs/**/* +**/*.sln \ No newline at end of file diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml new file mode 100644 index 0000000..86ce7e3 --- /dev/null +++ b/.pipelines/threadjobs-official.yml @@ -0,0 +1,248 @@ +name: ThreadJob-ModuleBuild-$(Build.BuildId) +trigger: none +pr: none + +schedules: +- cron: '0 3 * * 1' + displayName: Weekly Build + branches: + include: + - onebranch-pipelines + always: true + +parameters: + - name: 'publishOfficialToPowerShellGallery' + displayName: 'Publish official module to PowerShell gallery' + type: boolean + default: false + - name : 'publishProxyToPowerShellGallery' + displayName: 'Publish proxy module to PowerShell gallery' + type: boolean + default: false + +variables: + BuildConfiguration: Release + DOTNET_NOLOGO: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + POWERSHELL_TELEMETRY_OPTOUT: 1 + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + WindowsContainerImage: onebranch.azurecr.io/windows/ltsc2022/vse2022:latest + +resources: + repositories: + - repository: templates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +extends: + # https://aka.ms/obpipelines/templates + template: v2/OneBranch.Official.CrossPlat.yml@templates + parameters: + release: + category: NonAzure + featureFlags: + WindowsHostVersion: + Version: 2022 + Network: Netlock + globalSdl: # https://aka.ms/obpipelines/sdl + asyncSdl: + enabled: true + forStages: [build] + #credscan: + # enabled: true + # scanfolder: $(Build.SourcesDirectory) + # suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json + stages: + - stage: build + jobs: + - job: main + displayName: Build package + pool: + type: windows + variables: + - name: ob_outputDirectory + value: $(Build.SourcesDirectory)/out + #- name: ob_sdl_credscan_suppressionsFile + # value: $(Build.SourcesDirectory)\.config\suppress.json + steps: + - pwsh: | + Write-Verbose -Verbose ((Get-Item $(Build.SourcesDirectory)).FullName) + Get-ChildItem $(Build.SourcesDirectory) -Recurse -File -Name | Write-Verbose -Verbose + $manifestData = Import-PowerShellDataFile -Path src/Microsoft.PowerShell.ThreadJob.psd1 + $moduleVersion = $manifestData.ModuleVersion + Write-Host "##vso[task.setvariable variable=version;isOutput=true]$moduleVersion" + if ($manifestData.PrivateData.PsData.Prerelease) { + $prerel = $manifestData.PrivateData.PSData.Prerelease + $nupkgVersion = "${moduleVersion}-${prerel}" + } else { + $nupkgVersion = $moduleVersion + } + Write-Host "##vso[task.setvariable variable=nupkgversion;isOutput=true]$nupkgVersion" + name: package + displayName: Get version from project properties + - task: onebranch.pipeline.version@1 + displayName: Set OneBranch version + inputs: + system: Custom + customVersion: $(package.version) + - task: UseDotNet@2 + displayName: Use .NET SDK + inputs: + packageType: sdk + useGlobalJson: true + - pwsh: | + Get-ChildItem | Write-Verbose -Verbose + Register-PSRepository -Name CFS -SourceLocation "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/nuget/v2" -InstallationPolicy Trusted + Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 + .\build.ps1 -clean -Build -BuildConfiguration Release -BuildFramework netstandard2.0 + displayName: Build + - task: onebranch.pipeline.signing@1 + displayName: Sign 1st-party files + inputs: + command: sign + signing_profile: external_distribution + search_root: $(Build.SourcesDirectory)/out + files_to_sign: | + **/*.psd1; + **/*.ps1xml; + **/*.psm1; + **/Microsoft.PowerShell.*.dll; + - task: ArchiveFiles@2 + displayName: Zip module + inputs: + rootFolderOrFile: $(Build.SourcesDirectory)/out/Microsoft.PowerShell.ThreadJob + includeRootFolder: false + archiveType: zip + archiveFile: out/Microsoft.PowerShell.ThreadJob-v$(package.version).zip + - task: ArchiveFiles@2 + displayName: Zip module + inputs: + rootFolderOrFile: $(Build.SourcesDirectory)/out/ThreadJob + includeRootFolder: false + archiveType: zip + archiveFile: out/ThreadJob-v$(package.version).zip + - pwsh: | + Get-ChildItem | Write-Verbose -Verbose + Write-Verbose -Verbose -Message "Install Microsoft.PowerShell.ThreadJob module" + Copy-Item -Path $(Build.SourcesDirectory)/out/Microsoft.PowerShell.ThreadJob -Destination ($env:PSModulePath -split ';')[0] -Recurse -Force + Write-Verbose -Verbose -Message "Test ThreadJob module manifest" + Test-ModuleManifest -Path $(Build.SourcesDirectory)/out/ThreadJob/ThreadJob.psd1 + .\build.ps1 -Publish + Write-Verbose -Verbose ((Get-Item .).FullName) + Write-Verbose -Verbose ((Get-Item $(Build.SourcesDirectory)).FullName) + Get-ChildItem $(Build.SourcesDirectory) -Recurse -File -Name | Write-Verbose -Verbose + displayName: Package module + - task: onebranch.pipeline.signing@1 + displayName: Sign NuGet package + inputs: + command: sign + signing_profile: external_distribution + search_root: $(Build.SourcesDirectory) + files_to_sign: "**/*.nupkg" + - stage: manual + dependsOn: build + jobs: + - job: validation + displayName: Manual validation + pool: + type: agentless + timeoutInMinutes: 1440 + steps: + - task: ManualValidation@0 + displayName: Wait 24 hours for validation + inputs: + notifyUsers: $(Build.RequestedForEmail) + instructions: Please validate the release and then publish it! + timeoutInMinutes: 1440 + - stage: release_official_MicrosoftPowerShellThreadJob_module + displayName: release official + variables: + ob_release_environment: PPE + drop: $(Pipeline.Workspace)/drop_build_main + version: $[ stageDependencies.build.main.outputs['package.version'] ] + dependsOn: [build, manual] + condition: ${{ parameters.publishOfficialToPowerShellGallery }} + jobs: + - job: publish + templateContext: + inputs: + - input: pipelineArtifact + artifactName: drop_build_main + displayName: Publish to PowerShell Gallery + pool: + type: release + os: linux + variables: + - group: ThreadJob_Gallery_API + steps: + - task: Bash@3 + inputs: + targetType: inline + script: | + sudo tdnf install -y powershell + displayName: Install PowerShell + - task: powershell@2 + inputs: + pwsh: true + targetType: inline + script: | + Write-Verbose -Verbose ((Get-Item $(Pipeline.Workspace)).FullName) + Get-ChildItem $(Pipeline.Workspace) -Recurse -File -Name | Write-Verbose -Verbose + Write-Verbose -Verbose -Message "Set up CFS repository" + Register-PSRepository -Name CFS -SourceLocation "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/nuget/v2" -InstallationPolicy Trusted -ErrorAction Continue + Write-Verbose -Verbose -Message "Install PSResourceGet module" + Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force + Write-Verbose -Verbose -Message "Publish module to PSGallery" + Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob + env: + GalleryPAT: $(ChungJustinAPIKey) + displayName: Publish to PowerShell Gallery + - stage: release_proxy_ThreadJob_module + displayName: release proxy + variables: + ob_release_environment: PPE + drop: $(Pipeline.Workspace)/drop_build_main + version: $[ stageDependencies.build.main.outputs['package.version'] ] + dependsOn: [build, manual] + condition: ${{ parameters.publishProxyToPowerShellGallery }} + jobs: + - job: publish + templateContext: + inputs: + - input: pipelineArtifact + artifactName: drop_build_main + displayName: Publish to PowerShell Gallery + pool: + type: release + os: linux + variables: + - group: ThreadJob_Gallery_API + steps: + - task: Bash@3 + inputs: + targetType: inline + script: | + sudo tdnf install -y powershell + displayName: Install PowerShell + - task: powershell@2 + inputs: + pwsh: true + targetType: inline + script: | + Write-Verbose -Verbose ((Get-Item $(Pipeline.Workspace)).FullName) + Get-ChildItem $(Pipeline.Workspace) -Recurse -File -Name | Write-Verbose -Verbose + Write-Verbose -Verbose -Message "Set up CFS repository" + Register-PSRepository -Name CFS -SourceLocation "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/nuget/v2" -InstallationPolicy Trusted -ErrorAction Continue + Write-Verbose -Verbose -Message "Install PSResourceGet module" + Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force + Write-Verbose -Verbose -Message "Install Microsoft.PowerShell.ThreadJob module" + Copy-Item -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob -Destination ($env:PSModulePath -split ':')[0] -Recurse -Force -Verbose + Write-Verbose -Verbose -Message "Test ThreadJob module manifest" + Test-ModuleManifest -Path $(Pipeline.Workspace)/ThreadJob/ThreadJob.psd1 + Write-Verbose -Verbose -Message "Publish module to PSGallery" + Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob + env: + GalleryPAT: $(ChungJustinAPIKey) + displayName: Publish to PowerShell Gallery \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 898920a..51cfbd1 100644 --- a/build.ps1 +++ b/build.ps1 @@ -22,8 +22,8 @@ param ( [ValidateSet("Debug", "Release")] [string] $BuildConfiguration = "Debug", - [ValidateSet("net461")] - [string] $BuildFramework = "net461" + [ValidateSet("netstandard2.0")] + [string] $BuildFramework = "netstandard2.0" ) Import-Module -Name "$PSScriptRoot/buildtools.psd1" -Force @@ -31,8 +31,10 @@ Import-Module -Name "$PSScriptRoot/buildtools.psd1" -Force $config = Get-BuildConfiguration -ConfigPath $PSScriptRoot $script:ModuleName = $config.ModuleName +$script:ProxyModuleName = $config.ProxyModuleName $script:SrcPath = $config.SourcePath $script:OutDirectory = $config.BuildOutputPath +$script:ProxyOutDirectory = $config.BuildOutputPath $script:SignedDirectory = $config.SignedOutputPath $script:TestPath = $config.TestPath @@ -53,7 +55,7 @@ if ($env:TF_BUILD) { Write-Host "##$vstsCommandString" } -. $PSScriptRoot/dobuild.ps1 +. $PSScriptRoot/doBuild.ps1 if ($Clean -and (Test-Path $OutDirectory)) { @@ -73,6 +75,7 @@ if ($Clean -and (Test-Path $OutDirectory)) if (-not (Test-Path $OutDirectory)) { $script:OutModule = New-Item -ItemType Directory -Path (Join-Path $OutDirectory $ModuleName) + $script:ProxyOutModule = New-Item -itemType Directory -Path (Join-Path $OutDirectory $ProxyModuleName) } else { diff --git a/buildtools.psm1 b/buildtools.psm1 index 686e1d5..c64c151 100644 --- a/buildtools.psm1 +++ b/buildtools.psm1 @@ -2,7 +2,7 @@ # Licensed under the MIT License. $ConfigurationFileName = 'package.config.json' -Import-Module -Name PowerShellGet -MinimumVersion 3.0.18 +Import-Module -Name Microsoft.PowerShell.PSResourceGet -Force function Get-BuildConfiguration { [CmdletBinding()] @@ -36,6 +36,7 @@ function Get-BuildConfiguration { $configObj.TestPath = Join-Path $projectRoot -ChildPath $configObj.TestPath $configObj.HelpPath = Join-Path $projectRoot -ChildPath $configObj.HelpPath $configObj.BuildOutputPath = Join-Path $projectRoot -ChildPath $configObj.BuildOutputPath + if ($configObj.SignedOutputPath) { $configObj.SignedOutputPath = Join-Path $projectRoot -ChildPath $configObj.SignedOutputPath } @@ -69,32 +70,28 @@ function Publish-ModulePackage ) Write-Verbose -Verbose -Message "Creating new local package repo" + $config = Get-BuildConfiguration $localRepoName = 'packagebuild-local-repo' - $localRepoLocation = Join-Path -Path ([System.io.path]::GetTempPath()) -ChildPath $localRepoName - if (Test-Path -Path $localRepoLocation) { - Remove-Item -Path $localRepoLocation -Recurse -Force -ErrorAction Ignore - } - $null = New-Item -Path $localRepoLocation -ItemType Directory -Force + $localRepoLocation = $config.BuildOutputPath Write-Verbose -Verbose -Message "Registering local package repo: $localRepoName" Register-PSResourceRepository -Name $localRepoName -Uri $localRepoLocation -Trusted -Force Write-Verbose -Verbose -Message "Publishing package to local repo: $localRepoName" - $config = Get-BuildConfiguration - if (! $Signed.IsPresent) { - $modulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ModuleName - } else { - $modulePath = Join-Path -Path $config.SignedOutputPath -ChildPath $config.ModuleName - } + $modulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ModuleName + + # Proxy module + Write-Verbose -Verbose -Message "Publishing proxy module to local repo: $localRepoName" + $proxyModulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ProxyModuleName + Publish-PSResource -Path $proxyModulePath -Repository $localRepoName -SkipDependenciesCheck -Confirm:$false -Verbose + + # Official module + Write-Verbose -Verbose -Message "Publishing official module to local repo: $localRepoName" Publish-PSResource -Path $modulePath -Repository $localRepoName -SkipDependenciesCheck -Confirm:$false -Verbose - if ($env:TF_BUILD) { - Write-Verbose -Verbose -Message "Uploading module nuget package artifact to AzDevOps" - $artifactName = "nupkg" - $artifactPath = (Get-ChildItem -Path $localRepoLocation -Filter "$($config.ModuleName)*.nupkg").FullName - $artifactPath = Resolve-Path -Path $artifactPath - Write-Host "##vso[artifact.upload containerfolder=$artifactName;artifactname=$artifactName;]$artifactPath" - } + $artifactPath = (Get-ChildItem -Path $localRepoLocation -Filter "$($config.ModuleName)*.nupkg").FullName + $artifactPath = Resolve-Path -Path $artifactPath + Write-Verbose -Verbose -Message "ArtifactPath: $artifactPath" Write-Verbose -Verbose -Message "Unregistering local package repo: $localRepoName" Unregister-PSResourceRepository -Name $localRepoName -Confirm:$false diff --git a/doBuild.ps1 b/doBuild.ps1 index 5b8057f..0af7900 100644 --- a/doBuild.ps1 +++ b/doBuild.ps1 @@ -13,6 +13,10 @@ function DoBuild $BuildOutPath = "${OutDirectory}/${ModuleName}" Write-Verbose -Verbose -Message "Module output file path: '$BuildOutPath'" + # Proxy module out path + $ProxyOutPath = "${OutDirectory}/${ProxyModuleName}" + Write-Verbose -Verbose -Message "Module output file path: '$ProxyOutPath'" + # Module build source path $BuildSrcPath = "bin/${BuildConfiguration}/${BuildFramework}/publish" Write-Verbose -Verbose -Message "Module build source path: '$BuildSrcPath'" @@ -21,6 +25,11 @@ function DoBuild Write-Verbose -Verbose "Copy-Item ${SrcPath}/${ModuleName}.psd1 to $BuildOutPath" Copy-Item "${SrcPath}/${ModuleName}.psd1" "$BuildOutPath" + # Copy Proxy psd1 and psm1 file + Write-Verbose -Verbose -Message "Copying proxy module files to '$ProxyOutPath'" + Copy-Item "${SrcPath}/${ProxyModuleName}/${ProxyModuleName}.psd1" "$ProxyOutPath" + Copy-Item "${SrcPath}/${ProxyModuleName}/${ProxyModuleName}.psm1" "$ProxyOutPath" + # Copy help Write-Verbose -Verbose -Message "Copying help files to '$BuildOutPath'" copy-item -Recurse "${HelpPath}/${Culture}" "$BuildOutPath" @@ -43,8 +52,19 @@ function DoBuild # Check for dotnet for Windows (we only build on Windows platforms). if ($null -eq $dotnetCommand) { - Write-Verbose -Verbose -Message "dotnet.exe cannot be found in current path. Looking in ProgramFiles path." - $dotnetCommandPath = Join-Path -Path $env:ProgramFiles -ChildPath "dotnet\dotnet.exe" + if ($IsWindows) { + Write-Verbose -Verbose -Message "dotnet.exe cannot be found in current path. Looking in ProgramFiles path." + $dotnetCommandPath = Join-Path -Path $env:ProgramFiles -ChildPath "dotnet\dotnet.exe" + } elseif ($IsLinux) { + Write-Verbose -Verbose -Message "dotnet cannot be found in current path. Looking in /usr/share/dotnet path." + $dotnetCommandPath = "/usr/share/dotnet/dotnet" + } elseif ($IsMaxOS) { + Write-Verbose -Verbose -Message "dotnet cannot be found in current path. Looking in /usr/local/share/dotnet path." + $dotnetCommandPath = "/usr/local/share/dotnet/dotnet" + } else { + throw "Unsupported operating system." + } + $dotnetCommand = Get-Command -Name $dotnetCommandPath -ErrorAction Ignore if ($null -eq $dotnetCommand) { throw "Dotnet.exe cannot be found: $dotnetCommandPath is unavailable for build." @@ -60,18 +80,20 @@ function DoBuild Write-Verbose -Verbose -Message "Building location: PSScriptRoot: $PSScriptRoot, PWD: $pwd" $buildCommand = "$($dotnetCommand.Name) publish --configuration $BuildConfiguration --framework $BuildFramework --output $BuildSrcPath" Write-Verbose -Verbose -Message "Starting dotnet build command: $buildCommand" - Invoke-Expression -Command $buildCommand + # Capture the output and error streams + $output = Invoke-Expression -Command $buildCommand 2>&1 + Write-Verbose -Verbose -Message "Build output: $output" - # Dump build source output directory - # $outResultsPath = (Resolve-Path -Path ".").ProviderPath - # Write-Verbose -Verbose -Message "Dumping expected results output path: $outResultsPath" - # $outResults = Get-ChildItem -Path $outResultsPath -Recurse | Out-String - # Write-Verbose -Verbose -Message $outResults + #Dump build source output directory + $outResultsPath = (Resolve-Path -Path ".").ProviderPath + Write-Verbose -Verbose -Message "Dumping expected results output path: $outResultsPath" + $outResults = Get-ChildItem -Path $outResultsPath -Recurse | Out-String + Write-Verbose -Verbose -Message $outResults # Place build results if (! (Test-Path -Path "$BuildSrcPath/${ModuleName}.dll")) { - throw "Expected binary was not created: $BuildSrcPath/${ModuleName}.dll" + # throw "Expected binary was not created: $BuildSrcPath/${ModuleName}.dll" } Write-Verbose -Verbose -Message "Copying implementation assembly $BuildSrcPath/${ModuleName}.dll to $BuildOutPath" diff --git a/global.json b/global.json new file mode 100644 index 0000000..ef01b10 --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.401" + } +} + \ No newline at end of file diff --git a/nuget.config b/nuget.config index 6548586..a8fdae0 100644 --- a/nuget.config +++ b/nuget.config @@ -2,9 +2,7 @@ - + + - - - - + \ No newline at end of file diff --git a/package.config.json b/package.config.json index 0ae6b35..c84e587 100644 --- a/package.config.json +++ b/package.config.json @@ -1,5 +1,6 @@ { "ModuleName": "Microsoft.PowerShell.ThreadJob", + "ProxyModuleName" : "ThreadJob", "Culture": "en-US", "BuildOutputPath": "out", "SignedOutputPath": "signed", diff --git a/src/Microsoft.PowerShell.ThreadJob.psd1 b/src/Microsoft.PowerShell.ThreadJob.psd1 index 5e214f2..c46accb 100644 --- a/src/Microsoft.PowerShell.ThreadJob.psd1 +++ b/src/Microsoft.PowerShell.ThreadJob.psd1 @@ -8,7 +8,7 @@ RootModule = '.\Microsoft.PowerShell.ThreadJob.dll' # Version number of this module. -ModuleVersion = '2.1.1' +ModuleVersion = '2.2.0' # ID used to uniquely identify this module GUID = 'a84b375d-c1d6-4a1c-bcb7-8059bc28cd98' @@ -42,8 +42,6 @@ number of jobs drops below the throttle limit. # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '5.1' -DotNetFrameworkVersion = '4.6.1' -CLRVersion = '4.0.0' # Cmdlets to export from this module CmdletsToExport = 'Start-ThreadJob' @@ -80,6 +78,4 @@ PrivateData = @{ } # End of PrivateData hashtable -HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=2113345' - } diff --git a/src/ThreadJob/ThreadJob.psd1 b/src/ThreadJob/ThreadJob.psd1 new file mode 100644 index 0000000..b88f523 --- /dev/null +++ b/src/ThreadJob/ThreadJob.psd1 @@ -0,0 +1,41 @@ +# +# Module manifest for module 'ThreadJob' +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = '.\ThreadJob.psm1' + +# Version number of this module. +ModuleVersion = '2.0.4' + +# ID used to uniquely identify this module +GUID = '0e7b895d-2fec-43f7-8cae-11e8d16f6e40' + +Author = 'Microsoft Corporation' +CompanyName = 'Microsoft Corporation' +Copyright = '(c) Microsoft Corporation. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'ThreadJob module has been renamed to Microsoft.PowerShell.ThreadJob.' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '5.1' + +RequiredModules = @('Microsoft.PowerShell.ThreadJob') +FunctionsToExport = @() + +# Cmdlets to export from this module +CmdletsToExport = @() +AliasesToExport = @('Start-ThreadJob', 'ThreadJob\Start-ThreadJob') + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + PSData = @{ + LicenseUri = 'https://github.com/PowerShell/ThreadJob/blob/master/LICENSE' + ProjectUri = 'https://github.com/PowerShell/ThreadJob' + } +} # End of PrivateData hashtable + +} \ No newline at end of file diff --git a/src/ThreadJob/ThreadJob.psm1 b/src/ThreadJob/ThreadJob.psm1 new file mode 100644 index 0000000..539c54c --- /dev/null +++ b/src/ThreadJob/ThreadJob.psm1 @@ -0,0 +1,6 @@ +Write-Warning -Message "The ThreadJob module has been renamed to Microsoft.PowerShell.ThreadJob. The ThreadJob module will no longer be included with PowerShell as of 7.6 and above." + +Set-Alias -Name Start-ThreadJob -Value Microsoft.PowerShell.ThreadJob\Start-ThreadJob +Set-Alias -Name ThreadJob\Start-ThreadJob -Value Microsoft.PowerShell.ThreadJob\Start-ThreadJob + +Export-ModuleMember -Alias Start-ThreadJob, ThreadJob\Start-ThreadJob \ No newline at end of file diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 6bfe042..88c8ddf 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -11,9 +11,11 @@ using System.Management.Automation.Host; using System.Management.Automation.Language; using System.Management.Automation.Runspaces; -using System.Management.Automation.Security; using System.Text; using System.Threading; +using System.Reflection; +using System.Diagnostics; +using SMA = System.Management.Automation; namespace Microsoft.PowerShell.ThreadJob { @@ -283,11 +285,11 @@ public override void RemoveJob(Job2 job) #endregion } - internal sealed class ThreadJobDebugger : Debugger + internal sealed class ThreadJobDebugger : SMA.Debugger { #region Members - private Debugger _wrappedDebugger; + private SMA.Debugger _wrappedDebugger; private string _jobName; #endregion @@ -297,7 +299,7 @@ internal sealed class ThreadJobDebugger : Debugger private ThreadJobDebugger() { } public ThreadJobDebugger( - Debugger debugger, + SMA.Debugger debugger, string jobName) { if (debugger == null) @@ -380,7 +382,7 @@ public override DebuggerStopEventArgs GetDebuggerStopArgs() /// PowerShell host. /// Current path. public override void SetParent( - Debugger parent, + SMA.Debugger parent, IEnumerable breakPoints, DebuggerResumeAction? startAction, PSHost host, @@ -473,7 +475,7 @@ public sealed class ThreadJob : Job2, IJobDebugger private PSDataCollection _output; private bool _runningInitScript; private PSHost _streamingHost; - private Debugger _jobDebugger; + private SMA.Debugger _jobDebugger; private string _currentLocationPath; private const string VERBATIM_ARGUMENT = "--%"; @@ -595,11 +597,21 @@ public ThreadJob( WarningRecord lockdownWarning = null; if (Environment.OSVersion.Platform.ToString().Equals("Win32NT", StringComparison.OrdinalIgnoreCase)) { - bool enforceLockdown = (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce); + Assembly assembly = Assembly.LoadFrom(typeof(PSObject).Assembly.Location); + Type systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); + MethodInfo getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); + object lockdownPolicy = getSystemLockdownPolicy.Invoke(null, null); + + Type systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); + FieldInfo enforce = systemEnforcementMode.GetField("Enforce"); + object enforceValue = enforce.GetValue(null); + + bool enforceLockdown = lockdownPolicy.Equals(enforceValue); if (enforceLockdown && !string.IsNullOrEmpty(_filePath)) { // If script source is a file, check to see if it is trusted by the lock down policy - enforceLockdown = (SystemPolicy.GetLockdownPolicy(_filePath, null) == SystemEnforcementMode.Enforce); + lockdownPolicy = getSystemLockdownPolicy.Invoke(null, new object[] { _filePath, null }); + enforceLockdown = lockdownPolicy.Equals(enforceValue); if (!enforceLockdown && (_initSb != null)) { @@ -639,11 +651,11 @@ public ThreadJob( break; case PSInvocationState.Stopped: - SetJobState(JobState.Stopped, newStateInfo.Reason, disposeRunspace:true); + SetJobState(JobState.Stopped, newStateInfo.Reason, disposeRunspace: true); break; case PSInvocationState.Failed: - SetJobState(JobState.Failed, newStateInfo.Reason, disposeRunspace:true); + SetJobState(JobState.Failed, newStateInfo.Reason, disposeRunspace: true); break; case PSInvocationState.Completed: @@ -655,7 +667,7 @@ public ThreadJob( } else { - SetJobState(JobState.Completed, newStateInfo.Reason, disposeRunspace:true); + SetJobState(JobState.Completed, newStateInfo.Reason, disposeRunspace: true); } break; } @@ -1001,7 +1013,7 @@ public override void UnblockJob() /// /// Job Debugger /// - public Debugger Debugger + public SMA.Debugger Debugger { get { @@ -1087,7 +1099,7 @@ private ScriptBlock GetScriptBlockFromFile(string filePath, PSCmdlet psCmdlet) private void SetJobState(JobState jobState, Exception reason, bool disposeRunspace = false) { - base.SetJobState(jobState, reason); + base.SetJobState(jobState); if (disposeRunspace) { _rs.Dispose(); diff --git a/src/code/Microsoft.PowerShell.ThreadJob.csproj b/src/code/Microsoft.PowerShell.ThreadJob.csproj index b1c8d40..f6ffa2c 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.csproj +++ b/src/code/Microsoft.PowerShell.ThreadJob.csproj @@ -5,21 +5,14 @@ Library Microsoft.PowerShell.ThreadJob Microsoft.PowerShell.ThreadJob - 2.1.1.0 - 2.1.1 - 2.1.1 - net461 + 2.2.0.0 + 2.2.0 + 2.2.0 + netstandard2.0 - - - - False - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll - - - + - + From dabbc1120129bf2ee7c833072eb74bc1167ec593 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Fri, 4 Oct 2024 15:07:28 -0500 Subject: [PATCH 02/14] reflected SetJobState --- src/code/Microsoft.PowerShell.ThreadJob.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 88c8ddf..30d3adf 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -1099,7 +1099,21 @@ private ScriptBlock GetScriptBlockFromFile(string filePath, PSCmdlet psCmdlet) private void SetJobState(JobState jobState, Exception reason, bool disposeRunspace = false) { - base.SetJobState(jobState); + // Using Reflection here because this method is using a newer SetJobState method overload that takes in jobstate and reason. + Assembly assembly = Assembly.LoadFrom(typeof(PSObject).Assembly.Location); + Type job2Type = assembly.GetType("System.Management.Automation.Job2"); + + if (job2Type == null) + { + throw new InvalidOperationException("Job2 type not found in the specified assembly."); + } + + MethodInfo setJobStateMethod = job2Type.GetMethod("SetJobState", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(JobState), typeof(Exception) }, null); + if (setJobStateMethod != null) + { + setJobStateMethod.Invoke(this, new object[] { jobState, reason }); + } + if (disposeRunspace) { _rs.Dispose(); From 8a0ca1fccfd2de6a0c2c09a20b12d1202f0e0c70 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Mon, 7 Oct 2024 14:38:37 -0500 Subject: [PATCH 03/14] fixed CL test failure --- src/code/Microsoft.PowerShell.ThreadJob.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 30d3adf..3a156b4 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -16,6 +16,7 @@ using System.Reflection; using System.Diagnostics; using SMA = System.Management.Automation; +using System.Runtime.InteropServices; namespace Microsoft.PowerShell.ThreadJob { @@ -610,7 +611,9 @@ public ThreadJob( if (enforceLockdown && !string.IsNullOrEmpty(_filePath)) { // If script source is a file, check to see if it is trusted by the lock down policy - lockdownPolicy = getSystemLockdownPolicy.Invoke(null, new object[] { _filePath, null }); + MethodInfo[] methods = systemPolicy.GetMethods(BindingFlags.Public | BindingFlags.Static); + MethodInfo getLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); + lockdownPolicy = getLockdownPolicy.Invoke(null, new object[] { _filePath, null }); enforceLockdown = lockdownPolicy.Equals(enforceValue); if (!enforceLockdown && (_initSb != null)) From b0c1aa2f625aa4f4eafa26b8c486635e3123b4c9 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Mon, 10 Feb 2025 11:31:03 -0600 Subject: [PATCH 04/14] Update pwsh 7 install method thru PSPackagesOfficial --- .github/dependabot.yml | 3 +- .gitignore | 2 +- .pipelines/threadjobs-official.yml | 103 +++++++++++++++++++++++------ 3 files changed, 85 insertions(+), 23 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a5ba660..75e50ad 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,4 +13,5 @@ updates: - package-ecosystem: nuget directory: / schedule: - interval: daily \ No newline at end of file + interval: daily + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 80167f7..9f80330 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,4 @@ xhtml/ **/out/** **/bin/** .vs/**/* -**/*.sln \ No newline at end of file +**/*.sln diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index 86ce7e3..560986a 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -36,6 +36,10 @@ resources: name: OneBranch.Pipelines/GovernedTemplates ref: refs/heads/main + pipelines: + - pipeline: PSPackagesOfficial + source: 'PowerShell-Packages-Official' + extends: # https://aka.ms/obpipelines/templates template: v2/OneBranch.Official.CrossPlat.yml@templates @@ -73,13 +77,9 @@ extends: $manifestData = Import-PowerShellDataFile -Path src/Microsoft.PowerShell.ThreadJob.psd1 $moduleVersion = $manifestData.ModuleVersion Write-Host "##vso[task.setvariable variable=version;isOutput=true]$moduleVersion" - if ($manifestData.PrivateData.PsData.Prerelease) { - $prerel = $manifestData.PrivateData.PSData.Prerelease - $nupkgVersion = "${moduleVersion}-${prerel}" - } else { - $nupkgVersion = $moduleVersion - } - Write-Host "##vso[task.setvariable variable=nupkgversion;isOutput=true]$nupkgVersion" + $proxyManifestData = Import-PowerShellDataFile -Path src/ThreadJob/ThreadJob.psd1 + $proxyModuleVersion = $proxyManifestData.ModuleVersion + Write-Host "##vso[task.setvariable variable=proxyVersion;isOutput=true]$proxyModuleVersion" name: package displayName: Get version from project properties - task: onebranch.pipeline.version@1 @@ -122,7 +122,7 @@ extends: rootFolderOrFile: $(Build.SourcesDirectory)/out/ThreadJob includeRootFolder: false archiveType: zip - archiveFile: out/ThreadJob-v$(package.version).zip + archiveFile: out/ThreadJob-v$(package.proxyVersion).zip - pwsh: | Get-ChildItem | Write-Verbose -Verbose Write-Verbose -Verbose -Message "Install Microsoft.PowerShell.ThreadJob module" @@ -170,20 +170,49 @@ extends: inputs: - input: pipelineArtifact artifactName: drop_build_main + - input: pipelineArtifact + pipeline: PSPackagesOfficial + artifactName: drop_upload_upload_packages displayName: Publish to PowerShell Gallery pool: type: release - os: linux + os: windows variables: - group: ThreadJob_Gallery_API steps: - - task: Bash@3 + - task: PowerShell@2 + inputs: + targetType: inline + script: | + $localInstallerPath = Get-ChildItem -Path "$(Pipeline.Workspace)/GitHubPackages" -Filter '*win-x64.msi' | Select-Object -First 1 -ExpandProperty FullName + if (Test-Path -Path $localInstallerPath) { + Write-Verbose -Verbose "Installer found at $localInstallerPath" + } else { + throw "Installer not found" + } + Write-Verbose -Verbose "Installing PowerShell via msiexec" + Start-Process -FilePath msiexec -ArgumentList "/package $localInstallerPath /quiet REGISTER_MANIFEST=1" -Wait -NoNewWindow + $pwshPath = Get-ChildItem -Directory -Path 'C:\Program Files\PowerShell\7*' | Select-Object -First 1 -ExpandProperty FullName + if (Test-Path -Path $pwshPath) { + Write-Verbose -Verbose "PowerShell installed at $pwshPath" + Write-Verbose -Verbose "Adding pwsh to env:PATH" + Write-Host "##vso[task.prependpath]$pwshPath" + } else { + throw "PowerShell not installed" + } + displayName: Install pwsh 7 + - task: PowerShell@2 inputs: targetType: inline + pwsh: true script: | - sudo tdnf install -y powershell - displayName: Install PowerShell - - task: powershell@2 + Write-Verbose -Verbose "Pwsh 7 Installed" + Write-Verbose -Verbose "env:Path: " + $env:PATH -split ';' | ForEach-Object { + Write-Verbose -Verbose $_ + } + displayName: Check pwsh 7 installation + - task: Powershell@2 inputs: pwsh: true targetType: inline @@ -195,7 +224,7 @@ extends: Write-Verbose -Verbose -Message "Install PSResourceGet module" Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force Write-Verbose -Verbose -Message "Publish module to PSGallery" - Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob + Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg env: GalleryPAT: $(ChungJustinAPIKey) displayName: Publish to PowerShell Gallery @@ -204,7 +233,7 @@ extends: variables: ob_release_environment: PPE drop: $(Pipeline.Workspace)/drop_build_main - version: $[ stageDependencies.build.main.outputs['package.version'] ] + version: $[ stageDependencies.build.main.outputs['package.proxyVersion'] ] dependsOn: [build, manual] condition: ${{ parameters.publishProxyToPowerShellGallery }} jobs: @@ -213,24 +242,54 @@ extends: inputs: - input: pipelineArtifact artifactName: drop_build_main + - input: pipelineArtifact + pipeline: PSPackagesOfficial + artifactName: drop_upload_upload_packages displayName: Publish to PowerShell Gallery pool: type: release - os: linux + os: windows variables: - group: ThreadJob_Gallery_API steps: - - task: Bash@3 + - task: PowerShell@2 + inputs: + targetType: inline + script: | + $localInstallerPath = Get-ChildItem -Path "$(Pipeline.Workspace)/GitHubPackages" -Filter '*win-x64.msi' | Select-Object -First 1 -ExpandProperty FullName + if (Test-Path -Path $localInstallerPath) { + Write-Verbose -Verbose "Installer found at $localInstallerPath" + } else { + throw "Installer not found" + } + Write-Verbose -Verbose "Installing PowerShell via msiexec" + Start-Process -FilePath msiexec -ArgumentList "/package $localInstallerPath /quiet REGISTER_MANIFEST=1" -Wait -NoNewWindow + $pwshPath = Get-ChildItem -Directory -Path 'C:\Program Files\PowerShell\7*' | Select-Object -First 1 -ExpandProperty FullName + if (Test-Path -Path $pwshPath) { + Write-Verbose -Verbose "PowerShell installed at $pwshPath" + Write-Verbose -Verbose "Adding pwsh to env:PATH" + Write-Host "##vso[task.prependpath]$pwshPath" + } else { + throw "PowerShell not installed" + } + displayName: Install pwsh 7 + - task: PowerShell@2 inputs: targetType: inline + pwsh: true script: | - sudo tdnf install -y powershell - displayName: Install PowerShell - - task: powershell@2 + Write-Verbose -Verbose "Pwsh 7 Installed" + Write-Verbose -Verbose "env:Path: " + $env:PATH -split ';' | ForEach-Object { + Write-Verbose -Verbose $_ + } + displayName: Check pwsh 7 installation + - task: Powershell@2 inputs: pwsh: true targetType: inline script: | + Write-Verbose -Verbose -Message (Get-Module | Out-String) Write-Verbose -Verbose ((Get-Item $(Pipeline.Workspace)).FullName) Get-ChildItem $(Pipeline.Workspace) -Recurse -File -Name | Write-Verbose -Verbose Write-Verbose -Verbose -Message "Set up CFS repository" @@ -242,7 +301,9 @@ extends: Write-Verbose -Verbose -Message "Test ThreadJob module manifest" Test-ModuleManifest -Path $(Pipeline.Workspace)/ThreadJob/ThreadJob.psd1 Write-Verbose -Verbose -Message "Publish module to PSGallery" - Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob + # Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob + Write-Verbose -Verbose -Message (Get-Module | Out-String) + Write-Verbose -Verbose -Message ((Get-Command Publish-PSResource).Parameters.Keys) env: GalleryPAT: $(ChungJustinAPIKey) displayName: Publish to PowerShell Gallery \ No newline at end of file From 902e4ada5ecac2eabff2b042829dd02aa3dba69a Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Mon, 10 Feb 2025 11:33:40 -0600 Subject: [PATCH 05/14] Change release environment to Production --- .pipelines/threadjobs-official.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index 560986a..8bcf572 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -159,7 +159,7 @@ extends: - stage: release_official_MicrosoftPowerShellThreadJob_module displayName: release official variables: - ob_release_environment: PPE + ob_release_environment: Production drop: $(Pipeline.Workspace)/drop_build_main version: $[ stageDependencies.build.main.outputs['package.version'] ] dependsOn: [build, manual] @@ -231,7 +231,7 @@ extends: - stage: release_proxy_ThreadJob_module displayName: release proxy variables: - ob_release_environment: PPE + ob_release_environment: Production drop: $(Pipeline.Workspace)/drop_build_main version: $[ stageDependencies.build.main.outputs['package.proxyVersion'] ] dependsOn: [build, manual] From d2bec3df8b8d664a30a2cd42d9670211fdd7fff5 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Mon, 10 Feb 2025 12:39:16 -0600 Subject: [PATCH 06/14] Address all issues from first review --- .pipelines/threadjobs-official.yml | 15 ++++----- build.ps1 | 10 ------ buildtools.psd1 | 2 +- buildtools.psm1 | 36 ---------------------- doBuild.ps1 | 4 +-- global.json | 1 - nuget.config | 3 +- src/ThreadJob/ThreadJob.psd1 | 6 ++-- src/ThreadJob/ThreadJob.psm1 | 2 +- src/code/Microsoft.PowerShell.ThreadJob.cs | 24 +++++++-------- 10 files changed, 25 insertions(+), 78 deletions(-) diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index 8bcf572..d34d031 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -72,7 +72,7 @@ extends: # value: $(Build.SourcesDirectory)\.config\suppress.json steps: - pwsh: | - Write-Verbose -Verbose ((Get-Item $(Build.SourcesDirectory)).FullName) + Write-Verbose -Verbose $(Build.SourcesDirectory) Get-ChildItem $(Build.SourcesDirectory) -Recurse -File -Name | Write-Verbose -Verbose $manifestData = Import-PowerShellDataFile -Path src/Microsoft.PowerShell.ThreadJob.psd1 $moduleVersion = $manifestData.ModuleVersion @@ -131,7 +131,7 @@ extends: Test-ModuleManifest -Path $(Build.SourcesDirectory)/out/ThreadJob/ThreadJob.psd1 .\build.ps1 -Publish Write-Verbose -Verbose ((Get-Item .).FullName) - Write-Verbose -Verbose ((Get-Item $(Build.SourcesDirectory)).FullName) + Write-Verbose -Verbose $(Build.SourcesDirectory) Get-ChildItem $(Build.SourcesDirectory) -Recurse -File -Name | Write-Verbose -Verbose displayName: Package module - task: onebranch.pipeline.signing@1 @@ -224,9 +224,7 @@ extends: Write-Verbose -Verbose -Message "Install PSResourceGet module" Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force Write-Verbose -Verbose -Message "Publish module to PSGallery" - Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg - env: - GalleryPAT: $(ChungJustinAPIKey) + Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg displayName: Publish to PowerShell Gallery - stage: release_proxy_ThreadJob_module displayName: release proxy @@ -301,9 +299,8 @@ extends: Write-Verbose -Verbose -Message "Test ThreadJob module manifest" Test-ModuleManifest -Path $(Pipeline.Workspace)/ThreadJob/ThreadJob.psd1 Write-Verbose -Verbose -Message "Publish module to PSGallery" - # Publish-PSResource -ApiKey $env:GalleryPAT -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob + # Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob Write-Verbose -Verbose -Message (Get-Module | Out-String) Write-Verbose -Verbose -Message ((Get-Command Publish-PSResource).Parameters.Keys) - env: - GalleryPAT: $(ChungJustinAPIKey) - displayName: Publish to PowerShell Gallery \ No newline at end of file + displayName: Publish to PowerShell Gallery + \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 51cfbd1..cfbd7af 100644 --- a/build.ps1 +++ b/build.ps1 @@ -15,10 +15,6 @@ param ( [switch] $Publish, - [Parameter(ParameterSetName="publish")] - [switch] - $Signed, - [ValidateSet("Debug", "Release")] [string] $BuildConfiguration = "Debug", @@ -34,7 +30,6 @@ $script:ModuleName = $config.ModuleName $script:ProxyModuleName = $config.ProxyModuleName $script:SrcPath = $config.SourcePath $script:OutDirectory = $config.BuildOutputPath -$script:ProxyOutDirectory = $config.BuildOutputPath $script:SignedDirectory = $config.SignedOutputPath $script:TestPath = $config.TestPath @@ -87,8 +82,3 @@ if ($Build.IsPresent) $sb = (Get-Item Function:DoBuild).ScriptBlock Invoke-ModuleBuild -BuildScript $sb } - -if ($Publish.IsPresent) -{ - Publish-ModulePackage -Signed:$Signed.IsPresent -} diff --git a/buildtools.psd1 b/buildtools.psd1 index 6542e45..588ab64 100644 --- a/buildtools.psd1 +++ b/buildtools.psd1 @@ -41,7 +41,7 @@ # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @( - 'Get-BuildConfiguration', 'Invoke-ModuleBuild', 'Publish-ModulePackage', 'Install-ModulePackageForTest', 'Invoke-ModuleTests') + 'Get-BuildConfiguration', 'Invoke-ModuleBuild', 'Install-ModulePackageForTest', 'Invoke-ModuleTests') # Variables to export from this module VariablesToExport = '*' diff --git a/buildtools.psm1 b/buildtools.psm1 index c64c151..dd52f49 100644 --- a/buildtools.psm1 +++ b/buildtools.psm1 @@ -61,42 +61,6 @@ function Invoke-ModuleBuild { Write-Verbose -Verbose -Message "Finished invoking build script" } -function Publish-ModulePackage -{ - [CmdletBinding()] - param ( - [Parameter()] - [Switch] $Signed - ) - - Write-Verbose -Verbose -Message "Creating new local package repo" - $config = Get-BuildConfiguration - $localRepoName = 'packagebuild-local-repo' - $localRepoLocation = $config.BuildOutputPath - - Write-Verbose -Verbose -Message "Registering local package repo: $localRepoName" - Register-PSResourceRepository -Name $localRepoName -Uri $localRepoLocation -Trusted -Force - - Write-Verbose -Verbose -Message "Publishing package to local repo: $localRepoName" - $modulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ModuleName - - # Proxy module - Write-Verbose -Verbose -Message "Publishing proxy module to local repo: $localRepoName" - $proxyModulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ProxyModuleName - Publish-PSResource -Path $proxyModulePath -Repository $localRepoName -SkipDependenciesCheck -Confirm:$false -Verbose - - # Official module - Write-Verbose -Verbose -Message "Publishing official module to local repo: $localRepoName" - Publish-PSResource -Path $modulePath -Repository $localRepoName -SkipDependenciesCheck -Confirm:$false -Verbose - - $artifactPath = (Get-ChildItem -Path $localRepoLocation -Filter "$($config.ModuleName)*.nupkg").FullName - $artifactPath = Resolve-Path -Path $artifactPath - Write-Verbose -Verbose -Message "ArtifactPath: $artifactPath" - - Write-Verbose -Verbose -Message "Unregistering local package repo: $localRepoName" - Unregister-PSResourceRepository -Name $localRepoName -Confirm:$false -} - function Install-ModulePackageForTest { [CmdletBinding()] param ( diff --git a/doBuild.ps1 b/doBuild.ps1 index 0af7900..b0e6f6b 100644 --- a/doBuild.ps1 +++ b/doBuild.ps1 @@ -11,11 +11,11 @@ function DoBuild # Module build out path $BuildOutPath = "${OutDirectory}/${ModuleName}" - Write-Verbose -Verbose -Message "Module output file path: '$BuildOutPath'" + Write-Verbose -Verbose -Message "Official Module output file path: '$BuildOutPath'" # Proxy module out path $ProxyOutPath = "${OutDirectory}/${ProxyModuleName}" - Write-Verbose -Verbose -Message "Module output file path: '$ProxyOutPath'" + Write-Verbose -Verbose -Message "Proxy Module output file path: '$ProxyOutPath'" # Module build source path $BuildSrcPath = "bin/${BuildConfiguration}/${BuildFramework}/publish" diff --git a/global.json b/global.json index ef01b10..7d7a1c7 100644 --- a/global.json +++ b/global.json @@ -3,4 +3,3 @@ "version": "8.0.401" } } - \ No newline at end of file diff --git a/nuget.config b/nuget.config index a8fdae0..f003b0f 100644 --- a/nuget.config +++ b/nuget.config @@ -2,7 +2,6 @@ - - \ No newline at end of file + diff --git a/src/ThreadJob/ThreadJob.psd1 b/src/ThreadJob/ThreadJob.psd1 index b88f523..73c9bad 100644 --- a/src/ThreadJob/ThreadJob.psd1 +++ b/src/ThreadJob/ThreadJob.psd1 @@ -5,7 +5,7 @@ @{ # Script module or binary module file associated with this manifest. -RootModule = '.\ThreadJob.psm1' +RootModule = 'ThreadJob.psm1' # Version number of this module. ModuleVersion = '2.0.4' @@ -18,7 +18,7 @@ CompanyName = 'Microsoft Corporation' Copyright = '(c) Microsoft Corporation. All rights reserved.' # Description of the functionality provided by this module -Description = 'ThreadJob module has been renamed to Microsoft.PowerShell.ThreadJob.' +Description = "The ThreadJob module is now deprecated. Please use the 'Microsoft.PowerShell.ThreadJob' module instead." # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '5.1' @@ -38,4 +38,4 @@ PrivateData = @{ } } # End of PrivateData hashtable -} \ No newline at end of file +} diff --git a/src/ThreadJob/ThreadJob.psm1 b/src/ThreadJob/ThreadJob.psm1 index 539c54c..ddf22f2 100644 --- a/src/ThreadJob/ThreadJob.psm1 +++ b/src/ThreadJob/ThreadJob.psm1 @@ -3,4 +3,4 @@ Write-Warning -Message "The ThreadJob module has been renamed to Microsoft.Power Set-Alias -Name Start-ThreadJob -Value Microsoft.PowerShell.ThreadJob\Start-ThreadJob Set-Alias -Name ThreadJob\Start-ThreadJob -Value Microsoft.PowerShell.ThreadJob\Start-ThreadJob -Export-ModuleMember -Alias Start-ThreadJob, ThreadJob\Start-ThreadJob \ No newline at end of file +Export-ModuleMember -Alias Start-ThreadJob, ThreadJob\Start-ThreadJob diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 3a156b4..a3681fe 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -14,8 +14,6 @@ using System.Text; using System.Threading; using System.Reflection; -using System.Diagnostics; -using SMA = System.Management.Automation; using System.Runtime.InteropServices; namespace Microsoft.PowerShell.ThreadJob @@ -286,11 +284,11 @@ public override void RemoveJob(Job2 job) #endregion } - internal sealed class ThreadJobDebugger : SMA.Debugger + internal sealed class ThreadJobDebugger : Debugger { #region Members - private SMA.Debugger _wrappedDebugger; + private Debugger _wrappedDebugger; private string _jobName; #endregion @@ -300,7 +298,7 @@ internal sealed class ThreadJobDebugger : SMA.Debugger private ThreadJobDebugger() { } public ThreadJobDebugger( - SMA.Debugger debugger, + Debugger debugger, string jobName) { if (debugger == null) @@ -383,7 +381,7 @@ public override DebuggerStopEventArgs GetDebuggerStopArgs() /// PowerShell host. /// Current path. public override void SetParent( - SMA.Debugger parent, + Debugger parent, IEnumerable breakPoints, DebuggerResumeAction? startAction, PSHost host, @@ -476,7 +474,7 @@ public sealed class ThreadJob : Job2, IJobDebugger private PSDataCollection _output; private bool _runningInitScript; private PSHost _streamingHost; - private SMA.Debugger _jobDebugger; + private Debugger _jobDebugger; private string _currentLocationPath; private const string VERBATIM_ARGUMENT = "--%"; @@ -596,25 +594,25 @@ public ThreadJob( // Determine session language mode for Windows platforms WarningRecord lockdownWarning = null; - if (Environment.OSVersion.Platform.ToString().Equals("Win32NT", StringComparison.OrdinalIgnoreCase)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Assembly assembly = Assembly.LoadFrom(typeof(PSObject).Assembly.Location); + Assembly assembly = typeof(PSObject).Assembly; Type systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); MethodInfo getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); - object lockdownPolicy = getSystemLockdownPolicy.Invoke(null, null); + object lockdownPolicy = getSystemLockdownPolicy.Invoke(null, Array.Empty()); Type systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); FieldInfo enforce = systemEnforcementMode.GetField("Enforce"); object enforceValue = enforce.GetValue(null); - bool enforceLockdown = lockdownPolicy.Equals(enforceValue); + bool enforceLockdown = enforceValue.Equals(lockdownPolicy); if (enforceLockdown && !string.IsNullOrEmpty(_filePath)) { // If script source is a file, check to see if it is trusted by the lock down policy MethodInfo[] methods = systemPolicy.GetMethods(BindingFlags.Public | BindingFlags.Static); MethodInfo getLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); lockdownPolicy = getLockdownPolicy.Invoke(null, new object[] { _filePath, null }); - enforceLockdown = lockdownPolicy.Equals(enforceValue); + enforceLockdown = enforceValue.Equals(lockdownPolicy); if (!enforceLockdown && (_initSb != null)) { @@ -1016,7 +1014,7 @@ public override void UnblockJob() /// /// Job Debugger /// - public SMA.Debugger Debugger + public Debugger Debugger { get { From fdad7be9ebe59b1bfc229b75fcca318b599d7d62 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Tue, 11 Feb 2025 11:47:08 -0600 Subject: [PATCH 07/14] Fix reflection issue with SetJobState --- src/code/Microsoft.PowerShell.ThreadJob.cs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index a3681fe..75d7337 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -1100,20 +1100,16 @@ private ScriptBlock GetScriptBlockFromFile(string filePath, PSCmdlet psCmdlet) private void SetJobState(JobState jobState, Exception reason, bool disposeRunspace = false) { + // base.SetJobState(jobState, reason); // Using Reflection here because this method is using a newer SetJobState method overload that takes in jobstate and reason. - Assembly assembly = Assembly.LoadFrom(typeof(PSObject).Assembly.Location); - Type job2Type = assembly.GetType("System.Management.Automation.Job2"); - - if (job2Type == null) - { - throw new InvalidOperationException("Job2 type not found in the specified assembly."); - } - - MethodInfo setJobStateMethod = job2Type.GetMethod("SetJobState", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(JobState), typeof(Exception) }, null); - if (setJobStateMethod != null) - { - setJobStateMethod.Invoke(this, new object[] { jobState, reason }); - } + MethodInfo s_setJobStateDelegate = typeof(Job2).GetMethod( + "SetJobState", + BindingFlags.Instance | BindingFlags.NonPublic, + binder: null, + new Type[] { typeof(JobState), typeof(Exception) }, + null); + + s_setJobStateDelegate.Invoke(this, new object[] { jobState, reason }); if (disposeRunspace) { From a060d2c21d7a1ff95ea081cd60b81a25464c92bb Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Tue, 11 Feb 2025 12:24:27 -0600 Subject: [PATCH 08/14] Testing pipeline --- .pipelines/threadjobs-official.yml | 4 ++-- build.ps1 | 6 +++++ buildtools.psd1 | 4 ++-- buildtools.psm1 | 36 ++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index d34d031..2129548 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -224,7 +224,7 @@ extends: Write-Verbose -Verbose -Message "Install PSResourceGet module" Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force Write-Verbose -Verbose -Message "Publish module to PSGallery" - Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg + # Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg displayName: Publish to PowerShell Gallery - stage: release_proxy_ThreadJob_module displayName: release proxy @@ -295,7 +295,7 @@ extends: Write-Verbose -Verbose -Message "Install PSResourceGet module" Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force Write-Verbose -Verbose -Message "Install Microsoft.PowerShell.ThreadJob module" - Copy-Item -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob -Destination ($env:PSModulePath -split ':')[0] -Recurse -Force -Verbose + Copy-Item -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob -Destination ($env:PSModulePath -split ';')[0] -Recurse -Force -Verbose Write-Verbose -Verbose -Message "Test ThreadJob module manifest" Test-ModuleManifest -Path $(Pipeline.Workspace)/ThreadJob/ThreadJob.psd1 Write-Verbose -Verbose -Message "Publish module to PSGallery" diff --git a/build.ps1 b/build.ps1 index cfbd7af..1742207 100644 --- a/build.ps1 +++ b/build.ps1 @@ -82,3 +82,9 @@ if ($Build.IsPresent) $sb = (Get-Item Function:DoBuild).ScriptBlock Invoke-ModuleBuild -BuildScript $sb } + +if ($Publish.IsPresent) +{ + Publish-ModulePackage -Signed:$Signed.IsPresent +} + diff --git a/buildtools.psd1 b/buildtools.psd1 index 588ab64..fc65756 100644 --- a/buildtools.psd1 +++ b/buildtools.psd1 @@ -41,8 +41,8 @@ # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @( - 'Get-BuildConfiguration', 'Invoke-ModuleBuild', 'Install-ModulePackageForTest', 'Invoke-ModuleTests') - + 'Get-BuildConfiguration', 'Invoke-ModuleBuild', 'Publish-ModulePackage', 'Install-ModulePackageForTest', 'Invoke-ModuleTests') + # Variables to export from this module VariablesToExport = '*' diff --git a/buildtools.psm1 b/buildtools.psm1 index dd52f49..c64c151 100644 --- a/buildtools.psm1 +++ b/buildtools.psm1 @@ -61,6 +61,42 @@ function Invoke-ModuleBuild { Write-Verbose -Verbose -Message "Finished invoking build script" } +function Publish-ModulePackage +{ + [CmdletBinding()] + param ( + [Parameter()] + [Switch] $Signed + ) + + Write-Verbose -Verbose -Message "Creating new local package repo" + $config = Get-BuildConfiguration + $localRepoName = 'packagebuild-local-repo' + $localRepoLocation = $config.BuildOutputPath + + Write-Verbose -Verbose -Message "Registering local package repo: $localRepoName" + Register-PSResourceRepository -Name $localRepoName -Uri $localRepoLocation -Trusted -Force + + Write-Verbose -Verbose -Message "Publishing package to local repo: $localRepoName" + $modulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ModuleName + + # Proxy module + Write-Verbose -Verbose -Message "Publishing proxy module to local repo: $localRepoName" + $proxyModulePath = Join-Path -Path $config.BuildOutputPath -ChildPath $config.ProxyModuleName + Publish-PSResource -Path $proxyModulePath -Repository $localRepoName -SkipDependenciesCheck -Confirm:$false -Verbose + + # Official module + Write-Verbose -Verbose -Message "Publishing official module to local repo: $localRepoName" + Publish-PSResource -Path $modulePath -Repository $localRepoName -SkipDependenciesCheck -Confirm:$false -Verbose + + $artifactPath = (Get-ChildItem -Path $localRepoLocation -Filter "$($config.ModuleName)*.nupkg").FullName + $artifactPath = Resolve-Path -Path $artifactPath + Write-Verbose -Verbose -Message "ArtifactPath: $artifactPath" + + Write-Verbose -Verbose -Message "Unregistering local package repo: $localRepoName" + Unregister-PSResourceRepository -Name $localRepoName -Confirm:$false +} + function Install-ModulePackageForTest { [CmdletBinding()] param ( From 4a4366139a85e1577e0895ab91d2aac320959cd2 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Tue, 11 Feb 2025 13:16:37 -0600 Subject: [PATCH 09/14] Fix pipeline Issues --- .pipelines/threadjobs-official.yml | 38 +++++++++--------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index 2129548..e257c78 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -67,7 +67,9 @@ extends: type: windows variables: - name: ob_outputDirectory - value: $(Build.SourcesDirectory)/out + value: '$(Build.ArtifactStagingDirectory)' + - name: ob_sdl_sbom_enabled + value: true #- name: ob_sdl_credscan_suppressionsFile # value: $(Build.SourcesDirectory)\.config\suppress.json steps: @@ -98,31 +100,6 @@ extends: Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 .\build.ps1 -clean -Build -BuildConfiguration Release -BuildFramework netstandard2.0 displayName: Build - - task: onebranch.pipeline.signing@1 - displayName: Sign 1st-party files - inputs: - command: sign - signing_profile: external_distribution - search_root: $(Build.SourcesDirectory)/out - files_to_sign: | - **/*.psd1; - **/*.ps1xml; - **/*.psm1; - **/Microsoft.PowerShell.*.dll; - - task: ArchiveFiles@2 - displayName: Zip module - inputs: - rootFolderOrFile: $(Build.SourcesDirectory)/out/Microsoft.PowerShell.ThreadJob - includeRootFolder: false - archiveType: zip - archiveFile: out/Microsoft.PowerShell.ThreadJob-v$(package.version).zip - - task: ArchiveFiles@2 - displayName: Zip module - inputs: - rootFolderOrFile: $(Build.SourcesDirectory)/out/ThreadJob - includeRootFolder: false - archiveType: zip - archiveFile: out/ThreadJob-v$(package.proxyVersion).zip - pwsh: | Get-ChildItem | Write-Verbose -Verbose Write-Verbose -Verbose -Message "Install Microsoft.PowerShell.ThreadJob module" @@ -141,6 +118,14 @@ extends: signing_profile: external_distribution search_root: $(Build.SourcesDirectory) files_to_sign: "**/*.nupkg" + - pwsh: | + Get-ChildItem -Path $(Build.SourcesDirectory)/out -Filter '*.nupkg' -Recurse + | ForEach-Object { + Write-Verbose -Verbose "Copying $($_.FullName) to $(ob_outputDirectory)" + Copy-Item -Path $_.FullName -Destination $(ob_outputDirectory) -Force + } + Get-ChildItem -Path $(ob_outputDirectory) -Recurse -File -Name | Write-Verbose -Verbose + displayName: Upload Signed Nupkgs - stage: manual dependsOn: build jobs: @@ -217,7 +202,6 @@ extends: pwsh: true targetType: inline script: | - Write-Verbose -Verbose ((Get-Item $(Pipeline.Workspace)).FullName) Get-ChildItem $(Pipeline.Workspace) -Recurse -File -Name | Write-Verbose -Verbose Write-Verbose -Verbose -Message "Set up CFS repository" Register-PSRepository -Name CFS -SourceLocation "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/nuget/v2" -InstallationPolicy Trusted -ErrorAction Continue From f6934dcbd3734b7cb84df30205462021754d8247 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Tue, 11 Feb 2025 17:39:21 -0600 Subject: [PATCH 10/14] Remove installing PSReourceGet --- .pipelines/threadjobs-official.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index e257c78..6dc7410 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -202,11 +202,6 @@ extends: pwsh: true targetType: inline script: | - Get-ChildItem $(Pipeline.Workspace) -Recurse -File -Name | Write-Verbose -Verbose - Write-Verbose -Verbose -Message "Set up CFS repository" - Register-PSRepository -Name CFS -SourceLocation "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/nuget/v2" -InstallationPolicy Trusted -ErrorAction Continue - Write-Verbose -Verbose -Message "Install PSResourceGet module" - Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force Write-Verbose -Verbose -Message "Publish module to PSGallery" # Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg displayName: Publish to PowerShell Gallery @@ -271,20 +266,11 @@ extends: pwsh: true targetType: inline script: | - Write-Verbose -Verbose -Message (Get-Module | Out-String) - Write-Verbose -Verbose ((Get-Item $(Pipeline.Workspace)).FullName) - Get-ChildItem $(Pipeline.Workspace) -Recurse -File -Name | Write-Verbose -Verbose - Write-Verbose -Verbose -Message "Set up CFS repository" - Register-PSRepository -Name CFS -SourceLocation "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/powershell/nuget/v2" -InstallationPolicy Trusted -ErrorAction Continue - Write-Verbose -Verbose -Message "Install PSResourceGet module" - Install-Module -Repository CFS -Name Microsoft.PowerShell.PSResourceGet -MinimumVersion 1.0.5 -ErrorAction Continue -Force Write-Verbose -Verbose -Message "Install Microsoft.PowerShell.ThreadJob module" Copy-Item -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob -Destination ($env:PSModulePath -split ';')[0] -Recurse -Force -Verbose Write-Verbose -Verbose -Message "Test ThreadJob module manifest" Test-ModuleManifest -Path $(Pipeline.Workspace)/ThreadJob/ThreadJob.psd1 Write-Verbose -Verbose -Message "Publish module to PSGallery" # Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob - Write-Verbose -Verbose -Message (Get-Module | Out-String) - Write-Verbose -Verbose -Message ((Get-Command Publish-PSResource).Parameters.Keys) displayName: Publish to PowerShell Gallery \ No newline at end of file From 1342de8888d24ac102e0abf60063db03b853e4ed Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Tue, 11 Feb 2025 17:48:21 -0600 Subject: [PATCH 11/14] Remove usage of Signed parameter --- .ci/ci_auto.yml | 2 +- build.ps1 | 7 +------ buildtools.psm1 | 13 ------------- package.config.json | 1 - 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/.ci/ci_auto.yml b/.ci/ci_auto.yml index f9a72d7..7e18486 100644 --- a/.ci/ci_auto.yml +++ b/.ci/ci_auto.yml @@ -124,7 +124,7 @@ stages: } else { - $(Build.SourcesDirectory)/build.ps1 -Publish -Signed + $(Build.SourcesDirectory)/build.ps1 -Publish } displayName: Publish module nuget package and upload package artifact condition: succeeded() diff --git a/build.ps1 b/build.ps1 index 1742207..5e7ff30 100644 --- a/build.ps1 +++ b/build.ps1 @@ -30,7 +30,6 @@ $script:ModuleName = $config.ModuleName $script:ProxyModuleName = $config.ProxyModuleName $script:SrcPath = $config.SourcePath $script:OutDirectory = $config.BuildOutputPath -$script:SignedDirectory = $config.SignedOutputPath $script:TestPath = $config.TestPath $script:ModuleRoot = $PSScriptRoot @@ -44,10 +43,6 @@ if ($env:TF_BUILD) { $vstsCommandString = "vso[task.setvariable variable=BUILD_OUTPUT_PATH]$OutDirectory" Write-Host ("sending " + $vstsCommandString) Write-Host "##$vstsCommandString" - - $vstsCommandString = "vso[task.setvariable variable=SIGNED_OUTPUT_PATH]$SignedDirectory" - Write-Host ("sending " + $vstsCommandString) - Write-Host "##$vstsCommandString" } . $PSScriptRoot/doBuild.ps1 @@ -85,6 +80,6 @@ if ($Build.IsPresent) if ($Publish.IsPresent) { - Publish-ModulePackage -Signed:$Signed.IsPresent + Publish-ModulePackage } diff --git a/buildtools.psm1 b/buildtools.psm1 index c64c151..5d84cde 100644 --- a/buildtools.psm1 +++ b/buildtools.psm1 @@ -37,13 +37,6 @@ function Get-BuildConfiguration { $configObj.HelpPath = Join-Path $projectRoot -ChildPath $configObj.HelpPath $configObj.BuildOutputPath = Join-Path $projectRoot -ChildPath $configObj.BuildOutputPath - if ($configObj.SignedOutputPath) { - $configObj.SignedOutputPath = Join-Path $projectRoot -ChildPath $configObj.SignedOutputPath - } - else { - $configObj | Add-Member -MemberType NoteProperty -Name SignedOutputPath -Value (Join-Path $projectRoot -ChildPath 'signed') - } - return $configObj } @@ -63,12 +56,6 @@ function Invoke-ModuleBuild { function Publish-ModulePackage { - [CmdletBinding()] - param ( - [Parameter()] - [Switch] $Signed - ) - Write-Verbose -Verbose -Message "Creating new local package repo" $config = Get-BuildConfiguration $localRepoName = 'packagebuild-local-repo' diff --git a/package.config.json b/package.config.json index c84e587..12c3666 100644 --- a/package.config.json +++ b/package.config.json @@ -3,7 +3,6 @@ "ProxyModuleName" : "ThreadJob", "Culture": "en-US", "BuildOutputPath": "out", - "SignedOutputPath": "signed", "HelpPath": "help", "TestPath": "test", "SourcePath": "src" From bd34f792336618bd9ffb757123a7363ebaf82670 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Tue, 18 Feb 2025 16:09:24 -0600 Subject: [PATCH 12/14] Improved reflection processes by caching it in the static constructor --- doBuild.ps1 | 2 +- nuget.config | 3 ++ src/ThreadJob/ThreadJob.psd1 | 2 +- src/ThreadJob/ThreadJob.psm1 | 3 +- src/code/Microsoft.PowerShell.ThreadJob.cs | 38 ++++++++++++---------- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/doBuild.ps1 b/doBuild.ps1 index b0e6f6b..cbb005b 100644 --- a/doBuild.ps1 +++ b/doBuild.ps1 @@ -93,7 +93,7 @@ function DoBuild # Place build results if (! (Test-Path -Path "$BuildSrcPath/${ModuleName}.dll")) { - # throw "Expected binary was not created: $BuildSrcPath/${ModuleName}.dll" + throw "Expected binary was not created: $BuildSrcPath/${ModuleName}.dll" } Write-Verbose -Verbose -Message "Copying implementation assembly $BuildSrcPath/${ModuleName}.dll to $BuildOutPath" diff --git a/nuget.config b/nuget.config index f003b0f..5c704bf 100644 --- a/nuget.config +++ b/nuget.config @@ -4,4 +4,7 @@ + + + diff --git a/src/ThreadJob/ThreadJob.psd1 b/src/ThreadJob/ThreadJob.psd1 index 73c9bad..aa4bf4c 100644 --- a/src/ThreadJob/ThreadJob.psd1 +++ b/src/ThreadJob/ThreadJob.psd1 @@ -8,7 +8,7 @@ RootModule = 'ThreadJob.psm1' # Version number of this module. -ModuleVersion = '2.0.4' +ModuleVersion = '2.1.0' # ID used to uniquely identify this module GUID = '0e7b895d-2fec-43f7-8cae-11e8d16f6e40' diff --git a/src/ThreadJob/ThreadJob.psm1 b/src/ThreadJob/ThreadJob.psm1 index ddf22f2..a02343b 100644 --- a/src/ThreadJob/ThreadJob.psm1 +++ b/src/ThreadJob/ThreadJob.psm1 @@ -1,6 +1,5 @@ Write-Warning -Message "The ThreadJob module has been renamed to Microsoft.PowerShell.ThreadJob. The ThreadJob module will no longer be included with PowerShell as of 7.6 and above." Set-Alias -Name Start-ThreadJob -Value Microsoft.PowerShell.ThreadJob\Start-ThreadJob -Set-Alias -Name ThreadJob\Start-ThreadJob -Value Microsoft.PowerShell.ThreadJob\Start-ThreadJob -Export-ModuleMember -Alias Start-ThreadJob, ThreadJob\Start-ThreadJob +Export-ModuleMember -Alias Start-ThreadJob diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 75d7337..6a31912 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -476,6 +476,13 @@ public sealed class ThreadJob : Job2, IJobDebugger private PSHost _streamingHost; private Debugger _jobDebugger; private string _currentLocationPath; + private static readonly MethodInfo getSystemLockdownPolicy; + private static readonly Assembly assembly; + private static readonly Type systemPolicy; + private static readonly Type systemEnforcementMode; + private static readonly FieldInfo enforce; + private static readonly MethodInfo getFileLockdownPolicy; + private static readonly MethodInfo s_setJobStateDelegate; private const string VERBATIM_ARGUMENT = "--%"; @@ -502,6 +509,18 @@ public JobDefinition ThreadJobDefinition static ThreadJob() { s_JobQueue = new ThreadJobQueue(5); + assembly = typeof(PSObject).Assembly; + systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); + getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); + systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); + enforce = systemEnforcementMode.GetField("Enforce"); + getFileLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); + s_setJobStateDelegate = typeof(Job2).GetMethod( + "SetJobState", + BindingFlags.Instance | BindingFlags.NonPublic, + binder: null, + new Type[] { typeof(JobState), typeof(Exception) }, + null); } private ThreadJob() @@ -596,22 +615,14 @@ public ThreadJob( WarningRecord lockdownWarning = null; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Assembly assembly = typeof(PSObject).Assembly; - Type systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); - MethodInfo getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); object lockdownPolicy = getSystemLockdownPolicy.Invoke(null, Array.Empty()); - - Type systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); - FieldInfo enforce = systemEnforcementMode.GetField("Enforce"); object enforceValue = enforce.GetValue(null); - bool enforceLockdown = enforceValue.Equals(lockdownPolicy); + if (enforceLockdown && !string.IsNullOrEmpty(_filePath)) { // If script source is a file, check to see if it is trusted by the lock down policy - MethodInfo[] methods = systemPolicy.GetMethods(BindingFlags.Public | BindingFlags.Static); - MethodInfo getLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); - lockdownPolicy = getLockdownPolicy.Invoke(null, new object[] { _filePath, null }); + lockdownPolicy = getFileLockdownPolicy.Invoke(null, new object[] { _filePath, null }); enforceLockdown = enforceValue.Equals(lockdownPolicy); if (!enforceLockdown && (_initSb != null)) @@ -1102,13 +1113,6 @@ private void SetJobState(JobState jobState, Exception reason, bool disposeRunspa { // base.SetJobState(jobState, reason); // Using Reflection here because this method is using a newer SetJobState method overload that takes in jobstate and reason. - MethodInfo s_setJobStateDelegate = typeof(Job2).GetMethod( - "SetJobState", - BindingFlags.Instance | BindingFlags.NonPublic, - binder: null, - new Type[] { typeof(JobState), typeof(Exception) }, - null); - s_setJobStateDelegate.Invoke(this, new object[] { jobState, reason }); if (disposeRunspace) From dc3f87cb578ff01b0718d080909b4dcafa118dce Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Wed, 19 Feb 2025 16:51:33 -0600 Subject: [PATCH 13/14] Rework reflection cache, helpInfoURI, and fixed a tests. --- .pipelines/threadjobs-official.yml | 4 +- src/Microsoft.PowerShell.ThreadJob.psd1 | 3 ++ src/ThreadJob/ThreadJob.psd1 | 2 +- src/code/Microsoft.PowerShell.ThreadJob.cs | 49 ++++++++++--------- test/Microsoft.PowerShell.ThreadJob.Tests.ps1 | 4 +- 5 files changed, 35 insertions(+), 27 deletions(-) diff --git a/.pipelines/threadjobs-official.yml b/.pipelines/threadjobs-official.yml index 6dc7410..18848ce 100644 --- a/.pipelines/threadjobs-official.yml +++ b/.pipelines/threadjobs-official.yml @@ -203,7 +203,7 @@ extends: targetType: inline script: | Write-Verbose -Verbose -Message "Publish module to PSGallery" - # Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg + Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/Microsoft.PowerShell.ThreadJob.($version).nupkg displayName: Publish to PowerShell Gallery - stage: release_proxy_ThreadJob_module displayName: release proxy @@ -271,6 +271,6 @@ extends: Write-Verbose -Verbose -Message "Test ThreadJob module manifest" Test-ModuleManifest -Path $(Pipeline.Workspace)/ThreadJob/ThreadJob.psd1 Write-Verbose -Verbose -Message "Publish module to PSGallery" - # Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob + Publish-PSResource -ApiKey $(GalleryKey) -Repository PSGallery -Path $(Pipeline.Workspace)/ThreadJob displayName: Publish to PowerShell Gallery \ No newline at end of file diff --git a/src/Microsoft.PowerShell.ThreadJob.psd1 b/src/Microsoft.PowerShell.ThreadJob.psd1 index c46accb..d805d27 100644 --- a/src/Microsoft.PowerShell.ThreadJob.psd1 +++ b/src/Microsoft.PowerShell.ThreadJob.psd1 @@ -60,6 +60,9 @@ PrivateData = @{ # A URL to the main website for this project. ProjectUri = 'https://github.com/Powershell/ThreadJob' + # A URL to get more information about this module + HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=2305300' + # A URL to an icon representing this module. # IconUri = '' diff --git a/src/ThreadJob/ThreadJob.psd1 b/src/ThreadJob/ThreadJob.psd1 index aa4bf4c..4bf812c 100644 --- a/src/ThreadJob/ThreadJob.psd1 +++ b/src/ThreadJob/ThreadJob.psd1 @@ -28,7 +28,7 @@ FunctionsToExport = @() # Cmdlets to export from this module CmdletsToExport = @() -AliasesToExport = @('Start-ThreadJob', 'ThreadJob\Start-ThreadJob') +AliasesToExport = @('Start-ThreadJob') # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. PrivateData = @{ diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 6a31912..27178d7 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -476,13 +476,15 @@ public sealed class ThreadJob : Job2, IJobDebugger private PSHost _streamingHost; private Debugger _jobDebugger; private string _currentLocationPath; - private static readonly MethodInfo getSystemLockdownPolicy; - private static readonly Assembly assembly; - private static readonly Type systemPolicy; - private static readonly Type systemEnforcementMode; - private static readonly FieldInfo enforce; - private static readonly MethodInfo getFileLockdownPolicy; + + /// + /// Reflection members for setting job state. + /// + private static readonly MethodInfo s_getSystemLockdownPolicy; + private static readonly FieldInfo s_enforce; + private static readonly MethodInfo s_getFileLockdownPolicy; private static readonly MethodInfo s_setJobStateDelegate; + private static readonly object s_enforceValue; private const string VERBATIM_ARGUMENT = "--%"; @@ -509,18 +511,22 @@ public JobDefinition ThreadJobDefinition static ThreadJob() { s_JobQueue = new ThreadJobQueue(5); - assembly = typeof(PSObject).Assembly; - systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); - getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); - systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); - enforce = systemEnforcementMode.GetField("Enforce"); - getFileLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assembly assembly = typeof(PSObject).Assembly; + Type systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); + s_getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); + Type systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); + s_enforce = systemEnforcementMode.GetField("Enforce"); + s_enforceValue = s_enforce.GetValue(null); + s_getFileLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); + } s_setJobStateDelegate = typeof(Job2).GetMethod( - "SetJobState", - BindingFlags.Instance | BindingFlags.NonPublic, - binder: null, - new Type[] { typeof(JobState), typeof(Exception) }, - null); + "SetJobState", + BindingFlags.Instance | BindingFlags.NonPublic, + binder: null, + new Type[] { typeof(JobState), typeof(Exception) }, + null); } private ThreadJob() @@ -615,15 +621,14 @@ public ThreadJob( WarningRecord lockdownWarning = null; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - object lockdownPolicy = getSystemLockdownPolicy.Invoke(null, Array.Empty()); - object enforceValue = enforce.GetValue(null); - bool enforceLockdown = enforceValue.Equals(lockdownPolicy); + object lockdownPolicy = s_getSystemLockdownPolicy.Invoke(null, Array.Empty()); + bool enforceLockdown = s_enforceValue.Equals(lockdownPolicy); if (enforceLockdown && !string.IsNullOrEmpty(_filePath)) { // If script source is a file, check to see if it is trusted by the lock down policy - lockdownPolicy = getFileLockdownPolicy.Invoke(null, new object[] { _filePath, null }); - enforceLockdown = enforceValue.Equals(lockdownPolicy); + lockdownPolicy = s_getFileLockdownPolicy.Invoke(null, new object[] { _filePath, null }); + enforceLockdown = s_enforceValue.Equals(lockdownPolicy); if (!enforceLockdown && (_initSb != null)) { diff --git a/test/Microsoft.PowerShell.ThreadJob.Tests.ps1 b/test/Microsoft.PowerShell.ThreadJob.Tests.ps1 index c69b598..1b58596 100644 --- a/test/Microsoft.PowerShell.ThreadJob.Tests.ps1 +++ b/test/Microsoft.PowerShell.ThreadJob.Tests.ps1 @@ -13,7 +13,7 @@ function Wait-ForJobRunning $iteration = 10 Do { - Start-Sleep -Milliseconds 100 + Start-Sleep -Milliseconds 1000 } Until (($job.State -match "Running|Completed|Failed") -or (--$iteration -eq 0)) @@ -373,7 +373,7 @@ Describe 'Basic ThreadJob Tests' -Tags 'CI' { It 'ThreadJob jobs should run in the current working directory' { $threadJobCurrentLocation = Start-ThreadJob -ScriptBlock { $pwd } | Wait-Job | Receive-Job - $threadJobCurrentLocation.Path | Should -BeExactly $pwd.Path + $threadJobCurrentLocation.Path.Trim() | Should -BeExactly $pwd.ToString().Trim() } } From 59615f8e5f8df386fe37a52f6d4c693ee12dad26 Mon Sep 17 00:00:00 2001 From: Justin Chung Date: Fri, 21 Feb 2025 15:54:52 -0600 Subject: [PATCH 14/14] Remove unnecessary caching, rename a method, and fix indentation --- src/Microsoft.PowerShell.ThreadJob.psd1 | 6 +++--- src/code/Microsoft.PowerShell.ThreadJob.cs | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.PowerShell.ThreadJob.psd1 b/src/Microsoft.PowerShell.ThreadJob.psd1 index d805d27..7b127d4 100644 --- a/src/Microsoft.PowerShell.ThreadJob.psd1 +++ b/src/Microsoft.PowerShell.ThreadJob.psd1 @@ -60,9 +60,6 @@ PrivateData = @{ # A URL to the main website for this project. ProjectUri = 'https://github.com/Powershell/ThreadJob' - # A URL to get more information about this module - HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=2305300' - # A URL to an icon representing this module. # IconUri = '' @@ -81,4 +78,7 @@ PrivateData = @{ } # End of PrivateData hashtable +# A URL to get more information about this module +HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=2305300' + } diff --git a/src/code/Microsoft.PowerShell.ThreadJob.cs b/src/code/Microsoft.PowerShell.ThreadJob.cs index 27178d7..3d9c7f9 100644 --- a/src/code/Microsoft.PowerShell.ThreadJob.cs +++ b/src/code/Microsoft.PowerShell.ThreadJob.cs @@ -481,9 +481,8 @@ public sealed class ThreadJob : Job2, IJobDebugger /// Reflection members for setting job state. /// private static readonly MethodInfo s_getSystemLockdownPolicy; - private static readonly FieldInfo s_enforce; private static readonly MethodInfo s_getFileLockdownPolicy; - private static readonly MethodInfo s_setJobStateDelegate; + private static readonly MethodInfo s_setJobState; private static readonly object s_enforceValue; private const string VERBATIM_ARGUMENT = "--%"; @@ -517,16 +516,17 @@ static ThreadJob() Type systemPolicy = assembly.GetType("System.Management.Automation.Security.SystemPolicy"); s_getSystemLockdownPolicy = systemPolicy.GetMethod("GetSystemLockdownPolicy", BindingFlags.Public | BindingFlags.Static); Type systemEnforcementMode = assembly.GetType("System.Management.Automation.Security.SystemEnforcementMode"); - s_enforce = systemEnforcementMode.GetField("Enforce"); - s_enforceValue = s_enforce.GetValue(null); + FieldInfo enforce = systemEnforcementMode.GetField("Enforce"); + s_enforceValue = enforce.GetValue(null); s_getFileLockdownPolicy = systemPolicy.GetMethod("GetLockdownPolicy", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(SafeHandle) }, null); } - s_setJobStateDelegate = typeof(Job2).GetMethod( - "SetJobState", - BindingFlags.Instance | BindingFlags.NonPublic, - binder: null, - new Type[] { typeof(JobState), typeof(Exception) }, - null); + + s_setJobState = typeof(Job2).GetMethod( + "SetJobState", + BindingFlags.Instance | BindingFlags.NonPublic, + binder: null, + new Type[] { typeof(JobState), typeof(Exception) }, + null); } private ThreadJob() @@ -1118,7 +1118,7 @@ private void SetJobState(JobState jobState, Exception reason, bool disposeRunspa { // base.SetJobState(jobState, reason); // Using Reflection here because this method is using a newer SetJobState method overload that takes in jobstate and reason. - s_setJobStateDelegate.Invoke(this, new object[] { jobState, reason }); + s_setJobState.Invoke(this, new object[] { jobState, reason }); if (disposeRunspace) {