Skip to content

Commit 3e8d335

Browse files
authored
Merge the 1.0.0-preview.4 release branch back to main (#379)
- Update version info for the `1.0.0-preview.4` release. - Use deploy box and `GitHubRelease` task to create the GitHub draft release. - Make sure the `Runspace` is available when importing the `AIShell` module and throw otherwise. - When validating packages, I found there were rare cases where the `Runspace` instance passed to the constructor of `AIShell.Integration.Channel` is `null`. The constructor is used only in the public static method `CreateSingleton` which is called from `AIShell.psm1` to create a singleton of the `Channel` type upon importing the `AIShell` module. - In `AIShell.psm1`, we call `CreateSingleton` with `$host.Runspace` to pass in the `Runspace` instance, and the module's manifest defines `PowerShellHostName = 'ConsoleHost'`, so in theory, `$host.Runspace` should never be null, but that just happened. - I'm guessing it could be related to the `CompletionPredictor` module loaded from my profile, which attempts to sync with the modules loaded in the default session from a separate `Runspace` -- somehow, the `Channel` singleton got created from that separate `Runspace` instead of the default session -- but I cannot prove it. - To address this issue, I added restricted checks in both `AIShell.psm1` and the constructor of `Channel` type, to make sure that a `Channel` singleton can be created only if the `Runspace` instance is available. Related changes are in this commit: a447dee.
2 parents fa0948b + 1d048da commit 3e8d335

9 files changed

+161
-86
lines changed

.pipelines/Release-Official.yml

+2
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ extends:
111111
- stage: PublishGitHubRelease
112112
displayName: Publish GitHub Release
113113
dependsOn: UpdateChangeLog
114+
variables:
115+
ob_release_environment: Production
114116
jobs:
115117
- template: /.pipelines/templates/release-publish-github.yml@self
116118
parameters:

.pipelines/templates/linux-package.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
value: true
2020
- group: DotNetPrivateBuildAccess
2121
- name: ob_sdl_sbom_enabled
22-
value: false
22+
value: true
2323
- name: ob_sdl_codeql_compiled_enabled
2424
value: false
2525
- name: ob_outputDirectory

.pipelines/templates/mac-package.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
value: true
2525
- group: DotNetPrivateBuildAccess
2626
- name: ob_sdl_sbom_enabled
27-
value: false
27+
value: true
2828
- name: ob_sdl_codeql_compiled_enabled
2929
value: false
3030
- name: ob_outputDirectory

.pipelines/templates/module-package.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
try {
8282
$RepoName = "PSRLLocal"
8383
Register-PSResourceRepository -Name $RepoName -Uri $nugetPath -Trusted
84-
Publish-PSResource -Repository $RepoName -Path $moduleFolder
84+
Publish-PSResource -Repository $RepoName -Path $moduleFolder -SkipModuleManifestValidate
8585
} finally {
8686
Unregister-PSResourceRepository -Name $RepoName -ErrorAction SilentlyContinue
8787
}

.pipelines/templates/release-publish-github.yml

+145-80
Original file line numberDiff line numberDiff line change
@@ -8,101 +8,166 @@ jobs:
88
displayName: Create GitHub Release Draft
99
condition: succeeded()
1010
pool:
11-
type: windows
11+
type: release
12+
os: windows
13+
templateContext:
14+
inputs:
15+
- input: pipelineArtifact
16+
pipeline: AIShellPackagePipeline
17+
artifactName: drop_windows_package_arm64
18+
- input: pipelineArtifact
19+
pipeline: AIShellPackagePipeline
20+
artifactName: drop_windows_package_x64
21+
- input: pipelineArtifact
22+
pipeline: AIShellPackagePipeline
23+
artifactName: drop_windows_package_x86
24+
- input: pipelineArtifact
25+
pipeline: AIShellPackagePipeline
26+
artifactName: drop_linux_package_arm64
27+
- input: pipelineArtifact
28+
pipeline: AIShellPackagePipeline
29+
artifactName: drop_linux_package_x64
30+
- input: pipelineArtifact
31+
pipeline: AIShellPackagePipeline
32+
artifactName: macos-pkgs
1233
variables:
13-
- group: 'mscodehub-code-read-akv'
14-
- group: 'Azure Blob variable group'
15-
- group: 'GitHubTokens'
1634
- name: ob_outputDirectory
1735
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
1836
- name: ob_sdl_tsa_configFile
1937
value: $(Build.SourcesDirectory)\AIShell\.config\tsaoptions.json
2038

2139
steps:
22-
- checkout: self
23-
clean: true
24-
25-
- pwsh: |
26-
Get-ChildItem Env:
40+
- task: PowerShell@2
41+
inputs:
42+
targetType: inline
43+
script: |
44+
Get-ChildItem Env: | Out-String -Width 500
2745
displayName: 'Capture Environment Variables'
2846

29-
- download: AIShellPackagePipeline
30-
artifact: drop_windows_package_arm64
31-
displayName: Download win-arm64 zip
32-
patterns: '**/*.zip'
33-
34-
- download: AIShellPackagePipeline
35-
artifact: drop_windows_package_x64
36-
displayName: Download win-x64 zip
37-
patterns: '**/*.zip'
38-
39-
- download: AIShellPackagePipeline
40-
artifact: drop_windows_package_x86
41-
displayName: Download win-x86 zip
42-
patterns: '**/*.zip'
43-
44-
- download: AIShellPackagePipeline
45-
artifact: drop_linux_package_arm64
46-
displayName: Download linux-arm64 tar.gz
47-
patterns: '**/*.tar.gz'
48-
49-
- download: AIShellPackagePipeline
50-
artifact: drop_linux_package_x64
51-
displayName: Download linux-x64 tar.gz
52-
patterns: '**/*.tar.gz'
53-
54-
- download: AIShellPackagePipeline
55-
artifact: macos-pkgs
56-
displayName: Download macOS tar.gz
57-
patterns: '**/*.tar.gz'
58-
59-
- pwsh: |
60-
$packagesRoot = '$(Pipeline.Workspace)/release'
61-
$null = New-Item -ItemType Directory -Path $packagesRoot
62-
Get-ChildItem -Path '$(Pipeline.Workspace)\AIShellPackagePipeline' -Include *.zip,*.tar.gz -Recurse |
63-
Copy-Item -Destination $packagesRoot -Force -Verbose
64-
65-
Write-Verbose -Verbose "List all packages to be published to GitHub release page:"
66-
Get-ChildItem -Path $packagesRoot | Out-String -Width 500 -Stream
67-
68-
$vstsCommandString = "vso[task.setvariable variable=PackagesRoot]$packagesRoot"
69-
Write-Host "sending " + $vstsCommandString
70-
Write-Host "##$vstsCommandString"
47+
- task: PowerShell@2
48+
inputs:
49+
targetType: inline
50+
script: |
51+
$packagesRoot = '$(Pipeline.Workspace)/release'
52+
$null = New-Item -ItemType Directory -Path $packagesRoot
53+
Get-ChildItem -Path '$(Pipeline.Workspace)/*' -Include *.zip,*.tar.gz |
54+
Copy-Item -Destination $packagesRoot -Force -Verbose
55+
56+
Write-Verbose -Verbose "List all packages to be published to GitHub release page:"
57+
Get-ChildItem -Path $packagesRoot | Out-String -Width 500
58+
59+
$vstsCommandString = "vso[task.setvariable variable=PackagesRoot]$packagesRoot"
60+
Write-Host "sending " + $vstsCommandString
61+
Write-Host "##$vstsCommandString"
7162
displayName: Capture downloaded artifacts
7263

73-
- pwsh: |
74-
$macX64File = (Get-Item "$(PackagesRoot)\AIShell-*-osx-x64.tar.gz").Name
75-
$releaseVersion = $macX64File.Replace("AIShell-", "").Replace("-osx-x64.tar.gz", "")
76-
77-
$vstsCommandString = "vso[task.setvariable variable=ReleaseVersion]$releaseVersion"
78-
Write-Host "sending " + $vstsCommandString
79-
Write-Host "##$vstsCommandString"
64+
- task: PowerShell@2
65+
inputs:
66+
targetType: inline
67+
script: |
68+
$hashPath = Join-Path $(PackagesRoot) 'hashes.sha256'
69+
$checksums = Get-ChildItem -Path $(PackagesRoot) |
70+
ForEach-Object {
71+
$packageName = $_.Name
72+
$fullPath = $_.FullName
73+
Write-Verbose -Verbose "Generating checksum for $fullPath"
74+
$hash = (Get-FileHash -Path $fullPath -Algorithm SHA256).Hash.ToLower()
75+
# the '*' before the packagename signifies it is a binary
76+
"$hash *$packageName"
77+
}
78+
$checksums | Out-File -FilePath $hashPath -Force
79+
Get-Content -Path $hashPath -Raw | Out-String -Width 500
80+
displayName: Add sha256 hashes
81+
82+
- task: PowerShell@2
83+
inputs:
84+
targetType: inline
85+
script: |
86+
$macX64File = (Get-Item "$(PackagesRoot)/AIShell-*-osx-x64.tar.gz").Name
87+
$releaseVersion = $macX64File.Replace("AIShell-", "").Replace("-osx-x64.tar.gz", "")
88+
89+
$vstsCommandString = "vso[task.setvariable variable=ReleaseVersion]$releaseVersion"
90+
Write-Host "sending " + $vstsCommandString
91+
Write-Host "##$vstsCommandString"
8092
displayName: 'Set release version'
8193

82-
- pwsh: |
83-
git clone https://$(mscodehubCodeReadPat)@mscodehub.visualstudio.com/PowerShellCore/_git/Internal-PowerShellTeam-Tools '$(Pipeline.Workspace)\tools'
84-
displayName: Clone Internal-Tools repository
85-
86-
- pwsh: |
87-
Import-module '$(Pipeline.Workspace)\tools\Scripts\GitHubRelease.psm1'
88-
$releaseTag = 'v$(ReleaseVersion)'
89-
$description = '<!-- TODO: Generate release notes on GitHub! -->'
90-
Publish-ReleaseDraft -Tag $releaseTag -Name "$releaseTag Release of AIShell" -Description $description -User PowerShell -Repository AIShell -PackageFolder $(PackagesRoot) -Token $(GitHubReleasePat)
91-
displayName: Publish Release Draft
94+
- task: PowerShell@2
95+
inputs:
96+
targetType: inline
97+
script: |
98+
$content = '<!-- TODO: Generate release notes on GitHub! -->'
99+
$StringBuilder = [System.Text.StringBuilder]::new($content, $content.Length + 2kb)
100+
$StringBuilder.AppendLine().AppendLine() > $null
101+
$StringBuilder.AppendLine("#### SHA256 Hashes of the release artifacts").AppendLine() > $null
102+
Get-ChildItem -Path $(PackagesRoot) -File | ForEach-Object {
103+
$PackageName = $_.Name
104+
$SHA256 = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash
105+
$StringBuilder.AppendLine("- $PackageName").AppendLine(" - $SHA256") > $null
106+
}
107+
108+
$content = $StringBuilder.ToString()
109+
Write-Verbose -Verbose "Selected content: `n$content"
110+
$releaseNotesFilePath = "$(Pipeline.Workspace)/release-notes.md"
111+
$content | Out-File -FilePath $releaseNotesFilePath -Encoding utf8
112+
Write-Host "##vso[task.setvariable variable=ReleaseNotesFilePath;]$releaseNotesFilePath"
113+
114+
# If it's prelease then make prerelease true as a variable
115+
if ('$(ReleaseVersion)' -like '*-*') {
116+
Write-Host "##vso[task.setvariable variable=IsPreRelease;]true"
117+
} else {
118+
Write-Host "##vso[task.setvariable variable=IsPreRelease;]false"
119+
}
120+
displayName: Set variables for GitHub release task
121+
122+
- task: PowerShell@2
123+
inputs:
124+
targetType: inline
125+
script: |
126+
Write-Host "ReleaseNotes content:"
127+
Get-Content $(ReleaseNotesFilePath) | Out-String -width 500
128+
displayName: Verify Release Notes
129+
130+
- task: GitHubRelease@1
131+
displayName: 'Publish Release Draft'
92132
condition: and(ne('${{ parameters.publish }}', 'false'), succeeded())
133+
inputs:
134+
gitHubConnection: ReleaseToAIShellRepo
135+
repositoryName: PowerShell/AIShell
136+
target: main
137+
assets: '$(PackagesRoot)/*'
138+
tagSource: 'userSpecifiedTag'
139+
tag: 'v$(ReleaseVersion)'
140+
title: 'v$(ReleaseVersion) Release of AIShell'
141+
isDraft: true
142+
addChangeLog: false
143+
action: 'create'
144+
releaseNotesFilePath: '$(ReleaseNotesFilePath)'
145+
isPrerelease: '$(IsPreRelease)'
146+
147+
- job: PushGitTag
148+
dependsOn: GithubReleaseDraft
149+
displayName: Push Git Tag
150+
pool:
151+
type: server
152+
timeoutInMinutes: 1440
93153

94-
- template: /.pipelines/templates/wait-for-approval.yml@self
95-
parameters:
154+
steps:
155+
- task: ManualValidation@0
96156
displayName: Push Git Tag
97-
jobName: PushGitTag
98-
dependsOnJob: GithubReleaseDraft
99-
instructions: |
100-
Push the git tag to upstream
157+
inputs:
158+
instructions: Push the git tag to upstream
159+
timeoutInMinutes: 1440
160+
161+
- job: DraftPublic
162+
dependsOn: PushGitTag
163+
displayName: Make Draft Public
164+
pool:
165+
type: server
166+
timeoutInMinutes: 1440
101167

102-
- template: /.pipelines/templates/wait-for-approval.yml@self
103-
parameters:
168+
steps:
169+
- task: ManualValidation@0
104170
displayName: Make Draft Public
105-
jobName: DraftPublic
106-
dependsOnJob: PushGitTag
107-
instructions: |
108-
Make the GitHub Release Draft Public
171+
inputs:
172+
instructions: Make the GitHub Release Draft Public
173+
timeoutInMinutes: 1440

.pipelines/templates/windows-package.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- group: DotNetPrivateBuildAccess
2121
- group: certificate_logical_to_actual
2222
- name: ob_sdl_sbom_enabled
23-
value: false
23+
value: true
2424
- name: ob_sdl_codeql_compiled_enabled
2525
value: false
2626
- name: ob_outputDirectory

shell/AIShell.Integration/AIShell.psm1

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@ if ($null -eq $module -or $module.Version -lt [version]"2.4.2") {
77
throw "The PSReadLine v2.4.2-beta2 or higher is required for the AIShell module to work properly."
88
}
99

10+
$runspace = $Host.Runspace
11+
if ($null -eq $runspace) {
12+
throw "Failed to import the module because '`$Host.Runspace' unexpectedly returns null.`nThe host details:`n$($Host | Out-String -Width 120)"
13+
}
14+
1015
## Create the channel singleton when loading the module.
11-
$null = [AIShell.Integration.Channel]::CreateSingleton($host.Runspace, [Microsoft.PowerShell.PSConsoleReadLine])
16+
$null = [AIShell.Integration.Channel]::CreateSingleton($runspace, [Microsoft.PowerShell.PSConsoleReadLine])

shell/AIShell.Integration/Channel.cs

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public class Channel : IDisposable
3131

3232
private Channel(Runspace runspace, Type psConsoleReadLineType)
3333
{
34+
ArgumentNullException.ThrowIfNull(runspace);
35+
ArgumentNullException.ThrowIfNull(psConsoleReadLineType);
36+
3437
_runspace = runspace;
3538
_psrlType = psConsoleReadLineType;
3639
_connSetupWaitHandler = new ManualResetEvent(false);

shell/shell.common.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<TargetFramework>net8.0</TargetFramework>
99
<ImplicitUsings>enable</ImplicitUsings>
1010
<LangVersion>12.0</LangVersion>
11-
<Version>1.0.0-preview.3</Version>
11+
<Version>1.0.0-preview.4</Version>
1212

1313
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
1414
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

0 commit comments

Comments
 (0)