diff --git a/.github/workflows/analyze-reusable.yml b/.github/workflows/analyze-reusable.yml
index 3ef564eba90..8ace8be0742 100644
--- a/.github/workflows/analyze-reusable.yml
+++ b/.github/workflows/analyze-reusable.yml
@@ -41,13 +41,13 @@ jobs:
with:
fetch-depth: '0'
- - uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
+ - uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
global-json-file: ./global.json
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v3.29.5
+ uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -74,4 +74,4 @@ jobs:
shell: pwsh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v3.29.5
+ uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5
diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml
index 27ceac59bbd..3391afa0749 100644
--- a/.github/workflows/labels.yml
+++ b/.github/workflows/labels.yml
@@ -22,7 +22,7 @@ jobs:
- name: Verify PR has label starting with 'cl-'
id: verify-labels
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const labels = context.payload.pull_request.labels.map(label => label.name.toLowerCase());
diff --git a/.github/workflows/macos-ci.yml b/.github/workflows/macos-ci.yml
index f89ce8caa83..141dffb6e89 100644
--- a/.github/workflows/macos-ci.yml
+++ b/.github/workflows/macos-ci.yml
@@ -172,7 +172,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1000
- - uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
+ - uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
global-json-file: ./global.json
- name: Bootstrap packaging
@@ -231,7 +231,7 @@ jobs:
testResultsFolder: "${{ runner.workspace }}/testResults"
- name: Upload package artifact
if: always()
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: macos-package
path: "*.pkg"
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 935c8ff93bb..7ac6df36ccb 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v3.29.5
+ uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5
with:
sarif_file: results.sarif
diff --git a/.github/workflows/windows-packaging-reusable.yml b/.github/workflows/windows-packaging-reusable.yml
index 8d0255d4443..119e5c158f2 100644
--- a/.github/workflows/windows-packaging-reusable.yml
+++ b/.github/workflows/windows-packaging-reusable.yml
@@ -64,7 +64,7 @@ jobs:
shell: pwsh
- name: Setup .NET
- uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
global-json-file: ./global.json
@@ -84,7 +84,7 @@ jobs:
- name: Upload Build Artifacts
if: always()
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: windows-packaging-${{ matrix.architecture }}-${{ matrix.channel }}
path: |
diff --git a/.github/workflows/xunit-tests.yml b/.github/workflows/xunit-tests.yml
index c643917edd0..87c9dad9edc 100644
--- a/.github/workflows/xunit-tests.yml
+++ b/.github/workflows/xunit-tests.yml
@@ -28,7 +28,7 @@ jobs:
fetch-depth: 1000
- name: Setup .NET
- uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
global-json-file: ./global.json
@@ -49,7 +49,7 @@ jobs:
Write-Host "Completed xUnit test run."
- name: Upload xUnit results
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: ${{ inputs.test_results_artifact_name }}
diff --git a/.pipelines/MSIXBundle-vPack-Official.yml b/.pipelines/MSIXBundle-vPack-Official.yml
index 996991c22a0..420a96c3017 100644
--- a/.pipelines/MSIXBundle-vPack-Official.yml
+++ b/.pipelines/MSIXBundle-vPack-Official.yml
@@ -22,6 +22,26 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- R1
- Netlock
default: "R1"
+- name: IsEarlyAccess
+ type: boolean
+ default: false
+- name: EarlyAccessFeed
+ displayName: Early Access Feed
+ type: string
+ default: 'net11'
+ values:
+ - 'net8'
+ - 'net9'
+ - 'net10'
+ - 'net11'
+- name: DOTNET_RUNTIME_VERSION
+ displayName: Runtime version of early access build
+ type: string
+ default: ' '
+- name: DOTNET_SDK_VERSION
+ displayName: SDK version of early access build
+ type: string
+ default: ' '
name: msixbundle_vPack_$(Build.SourceBranchName)_Prod.True_Create.${{ parameters.createVPack }}_$(date:yyyyMMdd).$(rev:rr)
@@ -48,9 +68,19 @@ variables:
value: ${{ parameters.ReleaseTagVar }}
- name: netiso
value: ${{ parameters.netiso }}
+ - name: IsEarlyAccess
+ value: ${{ parameters.IsEarlyAccess }}
+ - name: EARLY_ACCESS_FEED
+ value: ${{ parameters.EarlyAccessFeed }}
+ - name: DOTNET_RUNTIME_VERSION
+ value: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ - name: DOTNET_SDK_VERSION
+ value: ${{ parameters.DOTNET_SDK_VERSION }}
- group: certificate_logical_to_actual # used within signing task
- group: MSIXSigningProfile
- group: msixTools
+ - ${{ if eq(parameters.IsEarlyAccess, true) }}:
+ - group: DotNetPrivateBuildAccess
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
@@ -95,9 +125,33 @@ extends:
tsaOptionsFile: .config/tsaoptions.json
stages:
+ - stage: prep
+ displayName: 'Prepare early access .NET'
+ dependsOn: []
+ jobs:
+ - ${{ if eq(parameters.IsEarlyAccess, true) }}:
+ - template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
+ parameters:
+ DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
+ - ${{ else }}:
+ - job: skip_download_dotnet_early_access
+ displayName: 'Skip early access .NET download'
+ pool:
+ type: windows
+ variables:
+ - name: ob_outputDirectory
+ value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
+ - name: ob_signing_setup_enabled
+ value: false
+ - name: ob_sdl_codeSignValidation_enabled
+ value: false
+ steps:
+ - pwsh: Write-Host 'IsEarlyAccess is false; skipping early access .NET download.'
+
- stage: Build_MSIX_Package
displayName: 'Build and create MSIX packages'
- dependsOn: []
+ dependsOn: [prep]
jobs:
- job: Build
pool:
@@ -114,6 +168,10 @@ extends:
ArtifactPlatform: 'windows'
ob_outputDirectory: '$(BUILD.SOURCESDIRECTORY)\out'
ob_artifactBaseName: drop_build_$(Architecture)
+ IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
+ EARLY_ACCESS_FEED: ${{ parameters.EarlyAccessFeed }}
+ DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
steps:
- checkout: self
@@ -210,6 +268,9 @@ extends:
Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration"
displayName: 'Build Windows Universal - $(Architecture)-$(BuildConfiguration) Symbols folder'
env:
+ ${{ if eq(parameters.IsEarlyAccess, true) }}:
+ __DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
+ VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
# Add CodeQL Finalize task right after your 'Build' step.
diff --git a/.pipelines/NonOfficial/PowerShell-Coordinated_Packages-NonOfficial.yml b/.pipelines/NonOfficial/PowerShell-Coordinated_Packages-NonOfficial.yml
index 2ffa0b94513..353e2f6e854 100644
--- a/.pipelines/NonOfficial/PowerShell-Coordinated_Packages-NonOfficial.yml
+++ b/.pipelines/NonOfficial/PowerShell-Coordinated_Packages-NonOfficial.yml
@@ -13,6 +13,7 @@ parameters:
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: ReleaseTagVar
displayName: Release Tag
type: string
diff --git a/.pipelines/NonOfficial/PowerShell-Packages-NonOfficial.yml b/.pipelines/NonOfficial/PowerShell-Packages-NonOfficial.yml
index 29d209df7bb..aa42fb19dac 100644
--- a/.pipelines/NonOfficial/PowerShell-Packages-NonOfficial.yml
+++ b/.pipelines/NonOfficial/PowerShell-Packages-NonOfficial.yml
@@ -38,6 +38,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
diff --git a/.pipelines/NonOfficial/PowerShell-Release-NonOfficial.yml b/.pipelines/NonOfficial/PowerShell-Release-NonOfficial.yml
index fb1c5af40e2..c2d71b7a633 100644
--- a/.pipelines/NonOfficial/PowerShell-Release-NonOfficial.yml
+++ b/.pipelines/NonOfficial/PowerShell-Release-NonOfficial.yml
@@ -36,6 +36,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: IsEarlyAccess
type: boolean
default: false
diff --git a/.pipelines/PowerShell-Coordinated_Packages-Official.yml b/.pipelines/PowerShell-Coordinated_Packages-Official.yml
index 6d41528af66..9fb94c4c208 100644
--- a/.pipelines/PowerShell-Coordinated_Packages-Official.yml
+++ b/.pipelines/PowerShell-Coordinated_Packages-Official.yml
@@ -40,6 +40,7 @@ parameters:
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
@@ -121,4 +122,3 @@ extends:
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
-
diff --git a/.pipelines/PowerShell-Packages-Official.yml b/.pipelines/PowerShell-Packages-Official.yml
index 7cade8188a0..d8223676e81 100644
--- a/.pipelines/PowerShell-Packages-Official.yml
+++ b/.pipelines/PowerShell-Packages-Official.yml
@@ -38,6 +38,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
@@ -120,4 +121,3 @@ extends:
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
-
diff --git a/.pipelines/PowerShell-Release-Official.yml b/.pipelines/PowerShell-Release-Official.yml
index 0f403b6e7d3..10ad7f7677a 100644
--- a/.pipelines/PowerShell-Release-Official.yml
+++ b/.pipelines/PowerShell-Release-Official.yml
@@ -36,6 +36,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: IsEarlyAccess
type: boolean
default: false
diff --git a/.pipelines/PowerShell-vPack-Official.yml b/.pipelines/PowerShell-vPack-Official.yml
index 48d63a81e20..8afdf11eef6 100644
--- a/.pipelines/PowerShell-vPack-Official.yml
+++ b/.pipelines/PowerShell-vPack-Official.yml
@@ -29,6 +29,26 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- R1
- Netlock
default: "R1"
+- name: IsEarlyAccess
+ type: boolean
+ default: false
+- name: EarlyAccessFeed
+ displayName: Early Access Feed
+ type: string
+ default: 'net11'
+ values:
+ - 'net8'
+ - 'net9'
+ - 'net10'
+ - 'net11'
+- name: DOTNET_RUNTIME_VERSION
+ displayName: Runtime version of early access build
+ type: string
+ default: ' '
+- name: DOTNET_SDK_VERSION
+ displayName: SDK version of early access build
+ type: string
+ default: ' '
name: vPack_$(Build.SourceBranchName)_Prod_Create.${{ parameters.createVPack }}_Name.${{ parameters.vPackName}}_$(date:yyyyMMdd).$(rev:rr)
@@ -38,6 +58,10 @@ variables:
debug: ${{ parameters.debug }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
netiso: ${{ parameters.netiso }}
+ IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
+ EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
+ DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
resources:
repositories:
@@ -85,3 +109,7 @@ extends:
parameters:
createVPack: ${{ parameters.createVPack }}
vPackName: ${{ parameters.vPackName }}
+ IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
+ EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
+ DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
diff --git a/.pipelines/apiscan-gen-notice.yml b/.pipelines/apiscan-gen-notice.yml
index 629e8387a4f..63786ada233 100644
--- a/.pipelines/apiscan-gen-notice.yml
+++ b/.pipelines/apiscan-gen-notice.yml
@@ -15,6 +15,7 @@ parameters:
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
diff --git a/.pipelines/templates/insert-nuget-config-azfeed.yml b/.pipelines/templates/insert-nuget-config-azfeed.yml
index b40b0872edf..e724acb8659 100644
--- a/.pipelines/templates/insert-nuget-config-azfeed.yml
+++ b/.pipelines/templates/insert-nuget-config-azfeed.yml
@@ -68,6 +68,7 @@ steps:
'net8' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-8-early-access/nuget/v3/index.json' }
'net9' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-9-early-access/nuget/v3/index.json' }
'net10' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-10-early-access/nuget/v3/index.json' }
+ 'net11' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-11-early-access/nuget/v3/index.json' }
default { throw "Unknown early access feed URL: $earlyAccessFeed" }
}
$powerShellRepoUri = 'https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/PowerShell/nuget/v3/index.json'
diff --git a/.pipelines/templates/release-validate-sdk.yml b/.pipelines/templates/release-validate-sdk.yml
index f0a253e5ccd..4d097aca3b7 100644
--- a/.pipelines/templates/release-validate-sdk.yml
+++ b/.pipelines/templates/release-validate-sdk.yml
@@ -99,6 +99,7 @@ jobs:
'net8' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-8-early-access/nuget/v3/index.json' }
'net9' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-9-early-access/nuget/v3/index.json' }
'net10' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-10-early-access/nuget/v3/index.json' }
+ 'net11' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-11-early-access/nuget/v3/index.json' }
default { throw "Unknown early access feed URL: $earlyAccessFeed" }
}
}
diff --git a/.pipelines/templates/stages/PowerShell-Release-Stages.yml b/.pipelines/templates/stages/PowerShell-Release-Stages.yml
index d922b224b97..f48f9ea5321 100644
--- a/.pipelines/templates/stages/PowerShell-Release-Stages.yml
+++ b/.pipelines/templates/stages/PowerShell-Release-Stages.yml
@@ -71,6 +71,7 @@ stages:
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
+ EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
dotnetArch: 'osx-x64'
- template: /.pipelines/templates/release-validate-sdk.yml@self
@@ -82,6 +83,7 @@ stages:
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
+ EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
dotnetArch: 'linux-x64'
- stage: gbltool
diff --git a/.pipelines/templates/stages/PowerShell-vPack-Stages.yml b/.pipelines/templates/stages/PowerShell-vPack-Stages.yml
index 404936440f8..bf493192b81 100644
--- a/.pipelines/templates/stages/PowerShell-vPack-Stages.yml
+++ b/.pipelines/templates/stages/PowerShell-vPack-Stages.yml
@@ -3,9 +3,45 @@ parameters:
type: boolean
- name: vPackName
type: string
+ - name: IsEarlyAccess
+ type: boolean
+ default: false
+ - name: EarlyAccessFeed
+ type: string
+ default: 'net11'
+ - name: DOTNET_RUNTIME_VERSION
+ type: string
+ default: ' '
+ - name: DOTNET_SDK_VERSION
+ type: string
+ default: ' '
stages:
+- stage: prep
+ displayName: 'Prepare early access .NET'
+ jobs:
+ - ${{ if eq(parameters.IsEarlyAccess, true) }}:
+ - template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
+ parameters:
+ DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
+ - ${{ else }}:
+ - job: skip_download_dotnet_early_access
+ displayName: 'Skip early access .NET download'
+ pool:
+ type: windows
+ variables:
+ - name: ob_outputDirectory
+ value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
+ - name: ob_signing_setup_enabled
+ value: false
+ - name: ob_sdl_codeSignValidation_enabled
+ value: false
+ steps:
+ - pwsh: Write-Host 'IsEarlyAccess is false; skipping early access .NET download.'
+
- stage: BuildStage
+ dependsOn: [prep]
jobs:
- job: BuildJob
pool:
@@ -41,6 +77,10 @@ stages:
ob_createvpack_verbose: true
ob_createvpack_packagename: '${{ parameters.vPackName }}.$(architecture)'
ob_createvpack_description: PowerShell $(architecture) $(version)
+ IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
+ EARLY_ACCESS_FEED: ${{ parameters.EarlyAccessFeed }}
+ DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
# Some official-build adapters force the injected validator on despite templateContext.
# Exclude this payload from that validator; it is validated below with the tools-only policy.
ob_sdl_codeSignValidation_excludes: '-|**\*.ps1;-|**\*.psm1;-|**\*.ps1xml;-|**\*.psd1;-|**\*.exe;-|**\*.dll'
@@ -147,13 +187,18 @@ stages:
AnalyzeInPipeline: false # Do not upload results
Language: csharp
- - task: UseDotNet@2
- displayName: 'Install .NET based on global.json'
- inputs:
- useGlobalJson: true
- workingDirectory: $(repoRoot)
- env:
- ob_restore_phase: true
+ - ${{ if eq(parameters.IsEarlyAccess, true) }}:
+ - template: /.pipelines/templates/install-dotnet.yml@self
+ parameters:
+ architecture: win-x64
+ - ${{ else }}:
+ - task: UseDotNet@2
+ displayName: 'Install .NET based on global.json'
+ inputs:
+ useGlobalJson: true
+ workingDirectory: $(repoRoot)
+ env:
+ ob_restore_phase: true
- pwsh: |
# Need to set PowerShellRoot variable for obp-file-signing template
@@ -204,6 +249,8 @@ stages:
displayName: Build Windows Universal - $(Architecture) -$(BuildConfiguration) Symbols folder
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
+ ${{ if eq(parameters.IsEarlyAccess, true) }}:
+ VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
- task: CodeQL3000Finalize@0 # Add CodeQL Finalize task right after your 'Build' step.
diff --git a/.pipelines/templates/variables/PowerShell-Coordinated_Packages-Variables.yml b/.pipelines/templates/variables/PowerShell-Coordinated_Packages-Variables.yml
index d87334aef44..f61a41f40b8 100644
--- a/.pipelines/templates/variables/PowerShell-Coordinated_Packages-Variables.yml
+++ b/.pipelines/templates/variables/PowerShell-Coordinated_Packages-Variables.yml
@@ -9,6 +9,7 @@ parameters:
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: ReleaseTagVar
type: string
default: 'fromBranch'
diff --git a/.pipelines/templates/variables/PowerShell-Packages-Variables.yml b/.pipelines/templates/variables/PowerShell-Packages-Variables.yml
index a9849a14252..c4b26637dd9 100644
--- a/.pipelines/templates/variables/PowerShell-Packages-Variables.yml
+++ b/.pipelines/templates/variables/PowerShell-Packages-Variables.yml
@@ -18,6 +18,7 @@ parameters:
- 'net8'
- 'net9'
- 'net10'
+ - 'net11'
- name: IsEarlyAccess
type: boolean
default: false
diff --git a/.pipelines/templates/variables/PowerShell-vPack-Variables.yml b/.pipelines/templates/variables/PowerShell-vPack-Variables.yml
index 7f00a5e0e2a..ad5d5ed6095 100644
--- a/.pipelines/templates/variables/PowerShell-vPack-Variables.yml
+++ b/.pipelines/templates/variables/PowerShell-vPack-Variables.yml
@@ -8,6 +8,23 @@ parameters:
- name: netiso
type: string
default: 'R1'
+ - name: IsEarlyAccess
+ type: boolean
+ default: false
+ - name: EarlyAccessFeed
+ type: string
+ default: 'net11'
+ values:
+ - 'net8'
+ - 'net9'
+ - 'net10'
+ - 'net11'
+ - name: DOTNET_RUNTIME_VERSION
+ type: string
+ default: ' '
+ - name: DOTNET_SDK_VERSION
+ type: string
+ default: ' '
variables:
- name: CDP_DEFINITION_BUILD_COUNT
@@ -30,6 +47,14 @@ variables:
value: none
- name: ReleaseTagVar
value: ${{ parameters.ReleaseTagVar }}
+ - name: IsEarlyAccess
+ value: ${{ parameters.IsEarlyAccess }}
+ - name: EARLY_ACCESS_FEED
+ value: ${{ parameters.EarlyAccessFeed }}
+ - name: DOTNET_RUNTIME_VERSION
+ value: ${{ parameters.DOTNET_RUNTIME_VERSION }}
+ - name: DOTNET_SDK_VERSION
+ value: ${{ parameters.DOTNET_SDK_VERSION }}
- group: Azure Blob variable group
- group: certificate_logical_to_actual # used within signing task
- group: DotNetPrivateBuildAccess
diff --git a/build.psm1 b/build.psm1
index 1c9a602e5c1..bcf625e681e 100644
--- a/build.psm1
+++ b/build.psm1
@@ -959,6 +959,7 @@ function Switch-PSNugetConfig {
'net8' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-8-early-access/nuget/v3/index.json' }
'net9' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-9-early-access/nuget/v3/index.json' }
'net10' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-10-early-access/nuget/v3/index.json' }
+ 'net11' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-11-early-access/nuget/v3/index.json' }
default { throw "Unknown early access feed URL: $earlyAccess" }
}
diff --git a/src/System.Management.Automation/resources/cs/PSConfigurationStrings.cs.resx b/src/System.Management.Automation/resources/cs/PSConfigurationStrings.cs.resx
index 900b72e9fc1..3b9b822587c 100644
--- a/src/System.Management.Automation/resources/cs/PSConfigurationStrings.cs.resx
+++ b/src/System.Management.Automation/resources/cs/PSConfigurationStrings.cs.resx
@@ -120,4 +120,10 @@
PowerShell přestal fungovat kvůli problému se zabezpečením: Konfigurační soubor nejde přečíst: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/de/PSConfigurationStrings.de.resx b/src/System.Management.Automation/resources/de/PSConfigurationStrings.de.resx
index 73dd8f23625..af7f81cc1e6 100644
--- a/src/System.Management.Automation/resources/de/PSConfigurationStrings.de.resx
+++ b/src/System.Management.Automation/resources/de/PSConfigurationStrings.de.resx
@@ -120,4 +120,10 @@
PowerShell funktioniert aufgrund eines Sicherheitsproblems nicht mehr: Die Konfigurationsdatei kann nicht gelesen werden: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/es/PSConfigurationStrings.es.resx b/src/System.Management.Automation/resources/es/PSConfigurationStrings.es.resx
index 7c833695182..11845c0604a 100644
--- a/src/System.Management.Automation/resources/es/PSConfigurationStrings.es.resx
+++ b/src/System.Management.Automation/resources/es/PSConfigurationStrings.es.resx
@@ -120,4 +120,10 @@
PowerShell ha dejado de funcionar debido a un problema de seguridad: no se puede leer el archivo de configuración: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/fr/PSConfigurationStrings.fr.resx b/src/System.Management.Automation/resources/fr/PSConfigurationStrings.fr.resx
index 30ee6c66a25..675c35d2797 100644
--- a/src/System.Management.Automation/resources/fr/PSConfigurationStrings.fr.resx
+++ b/src/System.Management.Automation/resources/fr/PSConfigurationStrings.fr.resx
@@ -120,4 +120,10 @@
PowerShell a cessé de fonctionner en raison d’un problème de sécurité : impossible de lire le fichier de configuration : {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/it/PSConfigurationStrings.it.resx b/src/System.Management.Automation/resources/it/PSConfigurationStrings.it.resx
index dceea43e1d5..0ac300af31f 100644
--- a/src/System.Management.Automation/resources/it/PSConfigurationStrings.it.resx
+++ b/src/System.Management.Automation/resources/it/PSConfigurationStrings.it.resx
@@ -120,4 +120,10 @@
PowerShell ha smesso di funzionare a causa di un problema di sicurezza: non è possibile leggere il file di configurazione: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/ja/PSConfigurationStrings.ja.resx b/src/System.Management.Automation/resources/ja/PSConfigurationStrings.ja.resx
index 15fd480ced2..8f1f04ca6aa 100644
--- a/src/System.Management.Automation/resources/ja/PSConfigurationStrings.ja.resx
+++ b/src/System.Management.Automation/resources/ja/PSConfigurationStrings.ja.resx
@@ -120,4 +120,10 @@
PowerShell はセキュリティ上の問題により動作を停止しました: 構成ファイル {0} を読み取れません
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/ko/PSConfigurationStrings.ko.resx b/src/System.Management.Automation/resources/ko/PSConfigurationStrings.ko.resx
index 5cc6ae88f91..99e19d62223 100644
--- a/src/System.Management.Automation/resources/ko/PSConfigurationStrings.ko.resx
+++ b/src/System.Management.Automation/resources/ko/PSConfigurationStrings.ko.resx
@@ -120,4 +120,10 @@
보안 문제로 인해 PowerShell이 작동을 중지했습니다. 구성 파일을 읽을 수 없습니다. {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/pl/PSConfigurationStrings.pl.resx b/src/System.Management.Automation/resources/pl/PSConfigurationStrings.pl.resx
index e7b5611cdb7..97cbc5d2c5e 100644
--- a/src/System.Management.Automation/resources/pl/PSConfigurationStrings.pl.resx
+++ b/src/System.Management.Automation/resources/pl/PSConfigurationStrings.pl.resx
@@ -120,4 +120,10 @@
Program PowerShell przestał działać z powodu problemu z zabezpieczeniami: nie można odczytać pliku konfiguracji: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/pt-BR/PSConfigurationStrings.pt-BR.resx b/src/System.Management.Automation/resources/pt-BR/PSConfigurationStrings.pt-BR.resx
index 45b469db758..2789312d804 100644
--- a/src/System.Management.Automation/resources/pt-BR/PSConfigurationStrings.pt-BR.resx
+++ b/src/System.Management.Automation/resources/pt-BR/PSConfigurationStrings.pt-BR.resx
@@ -120,4 +120,10 @@
PowerShell has stopped working because of a security issue: Cannot read the configuration file: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/ru/PSConfigurationStrings.ru.resx b/src/System.Management.Automation/resources/ru/PSConfigurationStrings.ru.resx
index 93bdaf35be1..2bd071f89e4 100644
--- a/src/System.Management.Automation/resources/ru/PSConfigurationStrings.ru.resx
+++ b/src/System.Management.Automation/resources/ru/PSConfigurationStrings.ru.resx
@@ -120,4 +120,10 @@
Windows PowerShell перестал работать из-за проблемы безопасности: Не удается прочитать файл конфигурации: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/tr/PSConfigurationStrings.tr.resx b/src/System.Management.Automation/resources/tr/PSConfigurationStrings.tr.resx
index 63176ae2286..dc9dd515352 100644
--- a/src/System.Management.Automation/resources/tr/PSConfigurationStrings.tr.resx
+++ b/src/System.Management.Automation/resources/tr/PSConfigurationStrings.tr.resx
@@ -120,4 +120,10 @@
PowerShell, bir güvenlik sorunu nedeniyle çalışmayı durdurdu: Yapılandırma dosyası okunamıyor: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/zh-Hans/PSConfigurationStrings.zh-Hans.resx b/src/System.Management.Automation/resources/zh-Hans/PSConfigurationStrings.zh-Hans.resx
index bcff924d325..190d5dc53d3 100644
--- a/src/System.Management.Automation/resources/zh-Hans/PSConfigurationStrings.zh-Hans.resx
+++ b/src/System.Management.Automation/resources/zh-Hans/PSConfigurationStrings.zh-Hans.resx
@@ -120,4 +120,10 @@
由于安全问题,PowerShell 已停止工作: 无法读取配置文件: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/resources/zh-Hant/PSConfigurationStrings.zh-Hant.resx b/src/System.Management.Automation/resources/zh-Hant/PSConfigurationStrings.zh-Hant.resx
index 3cc5246e898..b5660495fee 100644
--- a/src/System.Management.Automation/resources/zh-Hant/PSConfigurationStrings.zh-Hant.resx
+++ b/src/System.Management.Automation/resources/zh-Hant/PSConfigurationStrings.zh-Hant.resx
@@ -120,4 +120,10 @@
PowerShell 已因安全性問題而停止運作: 無法讀取設定檔: {0}
+
+ Cannot read the PowerShell configuration file '{0}': {1}. Falling back to default settings.
+
+
+ Cannot read setting '{0}' from PowerShell configuration file '{1}': {2}. Falling back to default for this setting.
+
\ No newline at end of file
diff --git a/src/System.Management.Automation/utils/Telemetry.cs b/src/System.Management.Automation/utils/Telemetry.cs
index fbb7f588283..79f73e3777d 100644
--- a/src/System.Management.Automation/utils/Telemetry.cs
+++ b/src/System.Management.Automation/utils/Telemetry.cs
@@ -1009,15 +1009,31 @@ private static Guid GetUniqueIdentifier()
try
{
// CreateUniqueIdentifierAndFile shouldn't throw, but the mutex might
- using var m = new Mutex(true, "CreateUniqueUserId");
- m.WaitOne();
+ using var mutex = new Mutex(initiallyOwned: false, name: "CreateUniqueUserId");
+ bool mutexAcquired = false;
try
{
- return CreateUniqueIdentifierAndFile(s_uuidPath);
+ try
+ {
+ mutexAcquired = mutex.WaitOne(millisecondsTimeout: 200);
+ }
+ catch (AbandonedMutexException)
+ {
+ // WaitOne transfers ownership before throwing for an abandoned mutex.
+ mutexAcquired = true;
+ }
+
+ if (mutexAcquired)
+ {
+ return CreateUniqueIdentifierAndFile(s_uuidPath);
+ }
}
finally
{
- m.ReleaseMutex();
+ if (mutexAcquired)
+ {
+ mutex.ReleaseMutex();
+ }
}
}
catch (Exception)
diff --git a/test/powershell/dsc/dsc.profileresource.Tests.ps1 b/test/powershell/dsc/dsc.profileresource.Tests.ps1
index cb357c7350b..4f89a8a1377 100644
--- a/test/powershell/dsc/dsc.profileresource.Tests.ps1
+++ b/test/powershell/dsc/dsc.profileresource.Tests.ps1
@@ -3,6 +3,13 @@
Describe "DSC PowerShell Profile Resource Tests" -Tag "CI" {
BeforeAll {
+
+ $isMsix = $pshome -like '*WindowsApps*'
+ if ($isMsix) {
+ Write-Verbose "Running in MSIX context. Marking tests as pending." -Verbose
+ return
+ }
+
$DSC_ROOT = $env:DSC_ROOT
$skipCleanup = $false
@@ -46,6 +53,10 @@ Describe "DSC PowerShell Profile Resource Tests" -Tag "CI" {
return
}
+ if ($isMsix) {
+ return
+ }
+
# Restore original profile
$testProfilePathCurrentUserCurrentHost = $PROFILE.CurrentUserCurrentHost
if (Test-Path "$TestDrive/currentuser-currenthost-profile.bak") {
@@ -69,6 +80,12 @@ Describe "DSC PowerShell Profile Resource Tests" -Tag "CI" {
}
It 'DSC resource is located at $PSHome' {
+
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$resourceFile = Join-Path -Path $PSHome -ChildPath 'pwsh.profile.resource.ps1'
$resourceFile | Should -Exist
@@ -77,16 +94,31 @@ Describe "DSC PowerShell Profile Resource Tests" -Tag "CI" {
}
It 'DSC resource can be found' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
(& $dscExe resource list -o json | ConvertFrom-Json | Select-Object -Property type).type | Should -Contain 'Microsoft.PowerShell/Profile'
}
It 'DSC resource can set current user current host profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$setOutput = (& $dscExe config set --file $PSScriptRoot/psprofile_currentuser_currenthost.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - CurrentUserCurrentHost!'"
$setOutput.results.result.afterState.content | Should -BeExactly $expectedContent
}
It 'DSC resource can get current user current host profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$getOutput = (& $dscExe config get --file $PSScriptRoot/psprofile_currentuser_currenthost.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - CurrentUserCurrentHost!'"
$getOutput.results.result.actualState.content | Should -BeExactly $expectedContent
@@ -98,18 +130,33 @@ Describe "DSC PowerShell Profile Resource Tests" -Tag "CI" {
}
It 'DSC resource can set current user all hosts profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$setOutput = (& $dscExe config set --file $PSScriptRoot/psprofile_currentuser_allhosts.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - CurrentUserAllHosts!'"
$setOutput.results.result.afterState.content | Should -BeExactly $expectedContent
}
It 'DSC resource can get current user all hosts profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$getOutput = (& $dscExe config get --file $PSScriptRoot/psprofile_currentuser_allhosts.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - CurrentUserAllHosts!'"
$getOutput.results.result.actualState.content | Should -BeExactly $expectedContent
}
It 'DSC resource can export all profiles' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$exportOutput = (& $dscExe config export --file $PSScriptRoot/psprofile_export.dsc.yaml -o json) | ConvertFrom-Json
$exportOutput.resources | Should -HaveCount 4
@@ -123,6 +170,12 @@ Describe "DSC PowerShell Profile Resource Tests" -Tag "CI" {
Describe "DSC PowerShell Profile resource elevated tests" -Tag "CI", 'RequireAdminOnWindows', 'RequireSudoOnUnix' {
BeforeAll {
+ $isMsix = $pshome -like '*WindowsApps*'
+ if ($isMsix) {
+ Write-Verbose "Running in MSIX context. Marking tests as pending." -Verbose
+ return
+ }
+
$DSC_ROOT = $env:DSC_ROOT
$skipCleanup = $false
@@ -166,6 +219,10 @@ Describe "DSC PowerShell Profile resource elevated tests" -Tag "CI", 'RequireAdm
return
}
+ if ($isMsix) {
+ return
+ }
+
$env:PATH = $originalPath
$testProfilePathAllUsersCurrentHost = $PROFILE.AllUsersCurrentHost
@@ -189,24 +246,44 @@ Describe "DSC PowerShell Profile resource elevated tests" -Tag "CI", 'RequireAdm
}
It 'DSC resource can set all users all hosts profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$setOutput = (& $dscExe config set --file $PSScriptRoot/psprofile_alluser_allhost.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - AllUsersAllHosts!'"
$setOutput.results.result.afterState.content | Should -BeExactly $expectedContent
}
It 'DSC resource can get all users all hosts profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$getOutput = (& $dscExe config get --file $PSScriptRoot/psprofile_alluser_allhost.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - AllUsersAllHosts!'"
$getOutput.results.result.actualState.content | Should -BeExactly $expectedContent
}
It 'DSC resource can set all users current hosts profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$setOutput = (& $dscExe config set --file $PSScriptRoot/psprofile_allusers_currenthost.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - AllUsersCurrentHost!'"
$setOutput.results.result.afterState.content | Should -BeExactly $expectedContent
}
It 'DSC resource can get all users current hosts profile' {
+ if ($isMsix) {
+ Set-ItResult -Pending -Because "Running in MSIX context. Skipping test."
+ return
+ }
+
$getOutput = (& $dscExe config get --file $PSScriptRoot/psprofile_allusers_currenthost.dsc.yaml -o json) | ConvertFrom-Json
$expectedContent = "Write-Host 'Welcome to your PowerShell profile - AllUsersCurrentHost!'"
$getOutput.results.result.actualState.content | Should -BeExactly $expectedContent
diff --git a/test/powershell/engine/Basic/Telemetry.Tests.ps1 b/test/powershell/engine/Basic/Telemetry.Tests.ps1
index 0da08316a56..7b6b21885d5 100644
--- a/test/powershell/engine/Basic/Telemetry.Tests.ps1
+++ b/test/powershell/engine/Basic/Telemetry.Tests.ps1
@@ -65,6 +65,22 @@ Describe "Telemetry for shell startup" -Tag CI {
$PWSH = (Get-Process -Id $PID).MainModule.FileName
$telemetrySet = Test-Path -Path env:POWERSHELL_TELEMETRY_OPTOUT
$SendingTelemetry = $env:POWERSHELL_TELEMETRY_OPTOUT
+
+ function Invoke-TelemetryTestProcess {
+ param(
+ [Parameter(Mandatory)]
+ [string[]] $Argument
+ )
+
+ $startInfo = [System.Diagnostics.ProcessStartInfo]::new()
+ $startInfo.FileName = $PWSH
+ $startInfo.UseShellExecute = $false
+ foreach ($argumentValue in $Argument) {
+ $startInfo.ArgumentList.Add($argumentValue)
+ }
+
+ return [System.Diagnostics.Process]::Start($startInfo)
+ }
}
AfterAll {
@@ -108,6 +124,101 @@ Describe "Telemetry for shell startup" -Tag CI {
$uuidPath | Should -Exist
}
+ It "Should not block concurrent telemetry-enabled shell startup when the uuid file is missing" {
+ $env:POWERSHELL_TELEMETRY_OPTOUT = "no"
+ $holderReadyPath = Join-Path -Path $TestDrive -ChildPath "telemetry-holder.ready"
+ $holderStopPath = Join-Path -Path $TestDrive -ChildPath "telemetry-holder.stop"
+ $holderScriptPath = Join-Path -Path $TestDrive -ChildPath "telemetry-holder.ps1"
+ @'
+param($ReadyPath, $StopPath)
+
+[void][Microsoft.PowerShell.Telemetry.ApplicationInsightsTelemetry]::CanSendTelemetry
+[System.IO.File]::WriteAllText($ReadyPath, "")
+while (-not [System.IO.File]::Exists($StopPath)) {
+ Start-Sleep -Milliseconds 100
+}
+'@ | Set-Content -LiteralPath $holderScriptPath
+
+ $holderProcess = $null
+ $childProcess = $null
+ try {
+ $holderProcess = Invoke-TelemetryTestProcess -Argument @(
+ "-NoProfile",
+ "-File",
+ $holderScriptPath,
+ $holderReadyPath,
+ $holderStopPath
+ )
+
+ Wait-UntilTrue -sb { Test-Path -LiteralPath $holderReadyPath } -TimeoutInMilliseconds 15000 -IntervalInMilliseconds 100 |
+ Should -BeTrue
+ $uuidPath | Should -Exist
+ Remove-Item -LiteralPath $uuidPath
+
+ $childProcess = Invoke-TelemetryTestProcess -Argument @("-NoProfile", "-Command", "exit")
+ $childProcess.WaitForExit(15000) | Should -BeTrue
+ $childProcess.ExitCode | Should -Be 0
+ $uuidPath | Should -Exist
+ }
+ finally {
+ if ($childProcess -and -not $childProcess.HasExited) {
+ $childProcess.Kill($true)
+ $childProcess.WaitForExit()
+ }
+
+ if ($childProcess) {
+ $childProcess.Dispose()
+ }
+
+ [System.IO.File]::WriteAllText($holderStopPath, "")
+ if ($holderProcess -and -not $holderProcess.WaitForExit(5000)) {
+ $holderProcess.Kill($true)
+ $holderProcess.WaitForExit()
+ }
+
+ if ($holderProcess) {
+ $holderProcess.Dispose()
+ }
+ }
+ }
+
+ It "Should stop creating the uuid file when the telemetry mutex times out" {
+ $env:POWERSHELL_TELEMETRY_OPTOUT = "no"
+ $mutex = [System.Threading.Mutex]::new($false, "CreateUniqueUserId")
+ $mutexAcquired = $false
+ $childProcess = $null
+ try {
+ try {
+ $mutexAcquired = $mutex.WaitOne(5000)
+ }
+ catch [System.Threading.AbandonedMutexException] {
+ $mutexAcquired = $true
+ }
+
+ $mutexAcquired | Should -BeTrue -Because "the test must own the mutex to force the child to time out"
+ $childProcess = Invoke-TelemetryTestProcess -Argument @("-NoProfile", "-Command", "exit")
+ $childProcess.WaitForExit(15000) | Should -BeTrue
+ $childProcess.ExitCode | Should -Be 0
+ $uuidPath | Should -Not -Exist
+ }
+ finally {
+ if ($childProcess -and -not $childProcess.HasExited) {
+ $childProcess.Kill($true)
+ $childProcess.WaitForExit()
+ }
+
+ if ($childProcess) {
+ $childProcess.Dispose()
+ }
+
+ if ($mutexAcquired) {
+ $mutex.ReleaseMutex()
+ }
+
+ $mutex.Dispose()
+ }
+ }
+
It "Should create a uuid file by default" {
if ( Test-Path env:POWERSHELL_TELEMETRY_OPTOUT ) { Remove-Item -Path env:POWERSHELL_TELEMETRY_OPTOUT }
& $PWSH -NoProfile -Command "exit"