Skip to content

Commit 0011dfa

Browse files
committed
(#86) Improves Offline Download Process
Adds dependency packages explicitly to manifest and downloads each ignoring chains. This should hopefully allow folk to internalize everything a little more reliably. Some packages were slipping through the cracks and not being downloaded. This could be problematic, so I ~overengineered the solution~ added some pre-existing functions in.
1 parent fb0ac69 commit 0011dfa

File tree

6 files changed

+204
-31
lines changed

6 files changed

+204
-31
lines changed

OfflineInstallPreparation.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ if (-not (Test-Path $ChocoInstallScript)) {
5151
$Signature = Get-AuthenticodeSignature -FilePath $ChocoInstallScript
5252

5353
if ($Signature.Status -eq 'Valid' -and $Signature.SignerCertificate.Subject -eq 'CN="Chocolatey Software, Inc.", O="Chocolatey Software, Inc.", L=Topeka, S=Kansas, C=US') {
54-
if (-not (Get-Command choco.exe)) {
54+
if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) {
5555
if (Test-Path $PSScriptRoot\files\chocolatey.*.nupkg) {
5656
$env:ChocolateyDownloadUrl = (Convert-Path $PSScriptRoot\files\chocolatey.*.nupkg)[0]
5757
}
@@ -88,6 +88,7 @@ foreach ($Package in (Get-Content $PSScriptRoot\files\chocolatey.json | ConvertF
8888
$ChocoArgs = @(
8989
"download", "$($Package.Name)"
9090
"--output-directory", $PackageWorkingDirectory
91+
"--ignore-dependencies"
9192
)
9293
$ChocoArgs += switch ($Package.psobject.properties.name) {
9394
"Version" { "--version=$($Package.Version)" }
@@ -98,10 +99,10 @@ foreach ($Package in (Get-Content $PSScriptRoot\files\chocolatey.json | ConvertF
9899
}
99100

100101
try {
101-
if (-not (Test-Path "$($PackageWorkingDirectory)\$($Package.Name)*.nupkg") -and -not (Test-Path "$PSScriptRoot\files\$($Package.Name)*.nupkg")) {
102+
if (-not (Get-ChocolateyPackageMetadata -Path $PackageWorkingDirectory -Id $Package.Name) -and -not (Get-ChocolateyPackageMetadata -Path "$PSScriptRoot\files\" -Id $Package.Name)) {
102103
Write-Host "Downloading '$($Package.Name)'"
103104

104-
while ((Get-ChildItem $PackageWorkingDirectory -Filter *.nupkg).Where{$_.CreationTime -gt (Get-Date).AddMinutes(-2)}.Count -gt 5) {
105+
while ((Get-ChildItem $PackageWorkingDirectory -Filter *.nupkg).Where{$_.CreationTime -gt (Get-Date).AddMinutes(-1)}.Count -gt 5) {
105106
Write-Verbose "Slowing down for a minute, in order to not trigger rate-limiting..."
106107
Start-Sleep -Seconds 5
107108
}

Set-SslSecurity.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ process {
211211
$chocoArgs = @('apikey', "--source='$RepositoryUrl'", "--api-key='$NuGetApiKey'")
212212
& choco @chocoArgs
213213

214+
# Reset the NuGet v3 cache, such that it doesn't capture localhost as the FQDN
215+
Remove-NexusRepositoryFolder -RepositoryName ChocolateyInternal -Name v3
216+
214217
Update-JsonFile -Path "$env:SystemDrive\choco-setup\logs\nexus.json" -Properties @{
215218
NexusUri = "https://$($SubjectWithoutCn):8443"
216219
NexusRepo = $RepositoryUrl

Start-C4bSetup.ps1

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,13 @@ param(
6767
$Thumbprint,
6868

6969
# If provided, shows all Chocolatey output. Otherwise, blissful quiet.
70-
[switch]$ShowChocoOutput
70+
[switch]$ShowChocoOutput,
71+
72+
# The branch or Pull Request to download the C4B setup scripts from.
73+
# Defaults to main.
74+
[string]
75+
[Alias('PR')]
76+
$Branch = $env:CHOCO_QSG_BRANCH
7177
)
7278

7379
if ($host.name -ne 'ConsoleHost') {
@@ -80,11 +86,16 @@ if ($ShowChocoOutput) {
8086
$global:PSDefaultParameterValues["Invoke-Choco:InformationAction"] = "Continue"
8187
}
8288

83-
if ($env:CHOCO_QSG_DEVELOP){
84-
$QsRepo = "https://github.com/chocolatey/choco-quickstart-scripts/archive/refs/heads/develop.zip"
85-
}
86-
else {
87-
$QsRepo = "https://github.com/chocolatey/choco-quickstart-scripts/archive/main.zip"
89+
$QsRepo = if ($Branch) {
90+
if ((Invoke-RestMethod -Uri "https://api.github.com/repos/chocolatey/choco-quickstart-scripts/branches").name -contains $Branch) {
91+
"https://api.github.com/repos/chocolatey/choco-quickstart-scripts/zipball/$Branch"
92+
} elseif ($PullRequest = Invoke-RestMethod -Uri "https://api.github.com/repos/chocolatey/choco-quickstart-scripts/pulls/$Branch" -ErrorAction SilentlyContinue) {
93+
$PullRequest.head.repo.archive_url -replace '{archive_format}', 'zipball' -replace '{/ref}', "/$($PullRequest.head.ref)"
94+
} else {
95+
Write-Error "'$($Branch)' is not a valid branch or pull request number. Please provide a valid branch or pull request number."
96+
}
97+
} else {
98+
"https://api.github.com/repos/chocolatey/choco-quickstart-scripts/zipball/main"
8899
}
89100

90101
$DefaultEap, $ErrorActionPreference = $ErrorActionPreference, 'Stop'
@@ -104,10 +115,13 @@ try {
104115

105116
if (-not $PSScriptRoot -or $PSScriptRoot -ne $FilesDir) {
106117
# Download and extract C4B setup files from repo
107-
Invoke-WebRequest -Uri $QsRepo -UseBasicParsing -OutFile "$TempDir\main.zip"
108-
Expand-Archive "$TempDir\main.zip" $TempDir
109-
Copy-Item "$TempDir\choco-quickstart-scripts-main\*" $FilesDir -Recurse
110-
Remove-Item "$TempDir" -Recurse -Force
118+
try {
119+
Invoke-WebRequest -Uri $QsRepo -UseBasicParsing -OutFile "$TempDir\choco-quickstart-scripts.zip"
120+
Expand-Archive "$TempDir\choco-quickstart-scripts.zip" $TempDir
121+
Copy-Item "$TempDir\*\*" $FilesDir -Recurse -Force
122+
} finally {
123+
Remove-Item "$TempDir" -Recurse -Force
124+
}
111125
}
112126

113127
# Import Helper Functions
@@ -117,10 +131,10 @@ try {
117131
Write-Host "Downloading missing nupkg files to $($PkgsDir)." -ForegroundColor Green
118132
Write-Host "This will take some time. Feel free to get a tea or coffee." -ForegroundColor Green
119133

120-
& $PSScriptRoot\OfflineInstallPreparation.ps1 -LicensePath $LicenseFile
134+
& $FilesDir\OfflineInstallPreparation.ps1 -LicensePath $LicenseFile
121135

122-
if (Test-Path $PSScriptRoot\files\*.nupkg) {
123-
choco source add --name ChocolateySetup --source $PSScriptRoot\files\ --Priority 1
136+
if (Test-Path $FilesDir\files\*.nupkg) {
137+
choco source add --name LocalChocolateySetup --source $FilesDir\files\ --Priority 1
124138
}
125139

126140
# Set Choco Server Chocolatey Configuration

files/chocolatey.json

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
{
22
"packages": [
3-
{ "name": "KB2919442", "version": "1.0.20160915", "internalize": false },
4-
{ "name": "KB2919355", "version": "1.0.20160915", "internalize": false },
5-
{ "name": "chocolatey" },
63
{ "name": "chocolatey-agent" },
7-
{ "name": "chocolatey.extension" },
8-
{ "name": "chocolateygui" },
9-
{ "name": "chocolateygui.extension" },
10-
{ "name": "dotnet-aspnetcoremodule-v2", "version": "16.0.24081" },
11-
{ "name": "dotnet-6.0-runtime", "version": "6.0.29" },
12-
{ "name": "dotnet-6.0-aspnetruntime", "version": "6.0.29" },
4+
{ "name": "chocolatey-compatibility.extension" },
5+
{ "name": "chocolatey-core.extension" },
6+
{ "name": "chocolatey-dotnetfx.extension" },
137
{ "name": "chocolatey-management-database", "internalize": false },
148
{ "name": "chocolatey-management-service", "internalize": false },
159
{ "name": "chocolatey-management-web", "internalize": false },
16-
{ "name": "chocolatey-licensed-jenkins-scripts" },
17-
{ "name": "nexus-repository" },
10+
{ "name": "chocolatey-windowsupdate.extension" },
11+
{ "name": "chocolatey.extension" },
12+
{ "name": "chocolatey" },
13+
{ "name": "chocolateygui.extension" },
14+
{ "name": "chocolateygui" },
15+
{ "name": "dotnet-6.0-aspnetruntime", "version": "6.0.29" },
16+
{ "name": "dotnet-6.0-runtime", "version": "6.0.29" },
17+
{ "name": "dotnet-aspnetcoremodule-v2", "version": "16.0.24081" },
18+
{ "name": "dotnetfx" },
1819
{ "name": "jenkins" },
19-
{ "name": "temurin21jre" },
20-
{ "name": "nexushell" },
20+
{ "name": "KB2919355", "internalize": false },
21+
{ "name": "KB2919442", "internalize": false },
22+
{ "name": "KB2999226", "internalize": false },
23+
{ "name": "KB3033929", "internalize": false },
24+
{ "name": "KB3035131", "internalize": false },
25+
{ "name": "KB3063858", "internalize": false },
26+
{ "name": "microsoft-edge" },
27+
{ "name": "nexus-repository" },
2128
{ "name": "sql-server-express" },
22-
{ "name": "microsoft-edge" }
29+
{ "name": "temurin21jre" },
30+
{ "name": "vcredist140" }
2331
]
2432
}

scripts/Create-ChocoLicensePkg.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ param(
1313
# Local path used to build the license package.
1414
[Parameter()]
1515
[string]
16-
$PackagesPath = "$env:SystemDrive\choco-setup\packages",
16+
$PackagesPath = "$env:SystemDrive\choco-setup\files\files",
1717

1818
# Path to the license file.
1919
[Parameter()]

scripts/Get-Helpers.ps1

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,153 @@ function Invoke-Choco {
2929
}
3030
}
3131

32+
#region Package functions (OfflineInstallPreparation.ps1)
33+
if (-not ("System.IO.Compression.ZipArchive" -as [type])) {
34+
Add-Type -Assembly 'System.IO.Compression'
35+
}
36+
37+
function Find-FileInArchive {
38+
<#
39+
.Synopsis
40+
Finds files with a name matching a pattern in an archive.
41+
.Example
42+
Find-FileInArchive -Path "C:\Archive.zip" -like "tools/files/*-x86.exe"
43+
.Example
44+
Find-FileInArchive -Path $Nupkg -match "tools/files/dotnetcore-sdk-(?<Version>\d+\.\d+\.\d+)-win-x86\.exe(\.ignore)?"
45+
.Notes
46+
Please be aware that this matches against the full name of the file, not just the file name.
47+
Though given that, you can easily write something to match the file name.
48+
#>
49+
[CmdletBinding(DefaultParameterSetName = "match")]
50+
param(
51+
# Path to the archive
52+
[Parameter(Mandatory)]
53+
[string]$Path,
54+
55+
# Pattern to match with regex
56+
[Parameter(Mandatory, ValueFromPipeline, ParameterSetName = "match")]
57+
[string]$match,
58+
59+
# Pattern to match with basic globbing
60+
[Parameter(Mandatory, ParameterSetName = "like")]
61+
[string]$like
62+
)
63+
begin {
64+
while (-not $Zip -and $AccessRetries++ -lt 3) {
65+
try {
66+
$Stream = [IO.FileStream]::new($Path, [IO.FileMode]::Open)
67+
$Zip = [IO.Compression.ZipArchive]::new($Stream, [IO.Compression.ZipArchiveMode]::Read)
68+
} catch [System.IO.IOException] {
69+
if ($AccessRetries -ge 3) {
70+
Write-Error -Message "Accessing '$Path' failed after $AccessRetries attempts." -TargetObject $Path
71+
} else {
72+
Write-Information "Could not access '$Path', retrying..."
73+
Start-Sleep -Milliseconds 500
74+
}
75+
}
76+
}
77+
}
78+
process {
79+
if ($Zip) {
80+
# Improve "security"?
81+
$WhereBlock = [ScriptBlock]::Create("`$_.FullName -$($PSCmdlet.ParameterSetName) '$(Get-Variable -Name $PSCmdlet.ParameterSetName -ValueOnly)'")
82+
$Zip.Entries | Where-Object -FilterScript $WhereBlock
83+
}
84+
}
85+
end {
86+
if ($Zip) {
87+
$Zip.Dispose()
88+
}
89+
if ($Stream) {
90+
$Stream.Close()
91+
$Stream.Dispose()
92+
}
93+
}
94+
}
95+
96+
function Get-FileContentInArchive {
97+
<#
98+
.Synopsis
99+
Returns the content of a file from within an archive
100+
.Example
101+
Get-FileContentInArchive -Path $ZipPath -Name "chocolateyInstall.ps1"
102+
.Example
103+
Get-FileContentInArchive -Zip $Zip -FullName "tools\chocolateyInstall.ps1"
104+
.Example
105+
Find-FileInArchive -Path $ZipPath -Like *.nuspec | Get-FileContentInArchive
106+
#>
107+
[CmdletBinding(DefaultParameterSetName = "PathFullName")]
108+
[OutputType([string])]
109+
param(
110+
# Path to the archive
111+
[Parameter(Mandatory, ParameterSetName = "PathFullName")]
112+
[Parameter(Mandatory, ParameterSetName = "PathName")]
113+
[string]$Path,
114+
115+
# Zip object for the archive
116+
[Parameter(Mandatory, ParameterSetName = "ZipFullName", ValueFromPipelineByPropertyName)]
117+
[Parameter(Mandatory, ParameterSetName = "ZipName", ValueFromPipelineByPropertyName)]
118+
[Alias("Archive")]
119+
[IO.Compression.ZipArchive]$Zip,
120+
121+
# Name of the file(s) to remove from the archive
122+
[Parameter(Mandatory, ParameterSetName = "PathFullName", ValueFromPipelineByPropertyName)]
123+
[Parameter(Mandatory, ParameterSetName = "ZipFullName", ValueFromPipelineByPropertyName)]
124+
[string]$FullName,
125+
126+
# Name of the file(s) to remove from the archive
127+
[Parameter(Mandatory, ParameterSetName = "PathName")]
128+
[Parameter(Mandatory, ParameterSetName = "ZipName")]
129+
[string]$Name
130+
)
131+
begin {
132+
if (-not $PSCmdlet.ParameterSetName.StartsWith("Zip")) {
133+
$Stream = [IO.FileStream]::new($Path, [IO.FileMode]::Open)
134+
$Zip = [IO.Compression.ZipArchive]::new($Stream, [IO.Compression.ZipArchiveMode]::Read)
135+
}
136+
}
137+
process {
138+
if (-not $FullName) {
139+
$MatchingEntries = $Zip.Entries | Where-Object {$_.Name -eq $Name}
140+
if ($MatchingEntries.Count -ne 1) {
141+
Write-Error "File '$Name' not found in archive" -ErrorAction Stop
142+
}
143+
$FullName = $MatchingEntries[0].FullName
144+
}
145+
[System.IO.StreamReader]::new(
146+
$Zip.GetEntry($FullName).Open()
147+
).ReadToEnd()
148+
}
149+
end {
150+
if (-not $PSCmdlet.ParameterSetName.StartsWith("Zip")) {
151+
$Zip.Dispose()
152+
$Stream.Close()
153+
$Stream.Dispose()
154+
}
155+
}
156+
}
157+
158+
function Get-ChocolateyPackageMetadata {
159+
[CmdletBinding(DefaultParameterSetName='All')]
160+
param(
161+
# The folder or nupkg to check
162+
[Parameter(Mandatory, Position=0, ValueFromPipelineByPropertyName)]
163+
[string]$Path,
164+
165+
# If provided, filters found packages by ID
166+
[Parameter(Mandatory, Position=1, ParameterSetName='Id')]
167+
[SupportsWildcards()]
168+
[Alias('Name')]
169+
[string]$Id = '*'
170+
)
171+
process {
172+
Get-ChildItem $Path -Filter $Id*.nupkg | ForEach-Object {
173+
([xml](Find-FileInArchive -Path $_.FullName -Like *.nuspec | Get-FileContentInArchive)).package.metadata | Where-Object Id -like $Id
174+
}
175+
}
176+
}
177+
#endregion
178+
32179
#region Nexus functions (Start-C4BNexusSetup.ps1)
33180
function Wait-Nexus {
34181
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::tls12

0 commit comments

Comments
 (0)