1
+ <#
2
+ . SYNOPSIS
3
+ A publishing script used to bullk-publish modules.
4
+
5
+ . DESCRIPTION
6
+ A publishing script used to bullk-publish modules.
7
+ This assumes a source control system such as Azure DevOps or any other viable tool with direct git access.
8
+ It also expects an installed git client and makes no provisions for authentication.
9
+
10
+ All modules must be provided via the same "DevOpsPath" - meaning they must be in the same collection if on Azure DevOps.
11
+ Each module requires its own repository (or ideally project).
12
+
13
+ While this script _assumes_ the use of Azure DevOps, it should be compatible with other services.
14
+
15
+ There are also no provisions for powershell repository authentication.
16
+ Either come pre-authenticated, use windows authentication or use PSResourceGet and have authentication configured for the repository.
17
+
18
+ . PARAMETER Repository
19
+ Name of the PowerShell repository to publish the finished modules to.
20
+
21
+ . PARAMETER DevOpsPath
22
+ The full path used for "git clone".
23
+ Insert a "{0}" placeholder for the name of the module.
24
+
25
+ . PARAMETER UseGetV3
26
+ By default, this script will use "Find-Module" and "Publish-MModule"
27
+ Use this switch to instead use "Find-PSResource" and "Publish-PSResource"
28
+
29
+ . PARAMETER Modules
30
+ The modules to publish.
31
+ Must be provided in the correct order of dependency.
32
+ Will possibly fail if not all dependencies are specified, even if the target repository contains said dependencies.
33
+ Defaults to include all modules needed for the ADMF project.
34
+
35
+ . EXAMPLE
36
+ PS C:\> .\Publish-Admf.ps1 -Repository internal -DevOpsPath "<insertgoodexample>" -UseGetV3
37
+
38
+ Uses PSResourceGet to clone all ADMF repositories from the source control system, and publish as needed to the internal repository using PSResourceGet.
39
+ #>
40
+ [CmdletBinding ()]
41
+ param (
42
+ [Parameter (Mandatory = $true )]
43
+ [string ]
44
+ $Repository ,
45
+
46
+ [Parameter (Mandatory = $true )]
47
+ [string ]
48
+ $DevOpsPath ,
49
+
50
+ [switch ]
51
+ $UseGetV3 ,
52
+
53
+ [string []]
54
+ $Modules = @ (
55
+ ' string'
56
+ ' PSFramework'
57
+ ' ResolveString'
58
+ ' Principal'
59
+ ' ADSec'
60
+ ' ADMF.Core'
61
+ ' DCManagement'
62
+ ' DomainManagement'
63
+ ' ForestManagement'
64
+ ' ADMF'
65
+ )
66
+ )
67
+
68
+ $ErrorActionPreference = ' Stop'
69
+ trap {
70
+ Remove-Item - Path $tempRoot - Force - Recurse - ErrorAction SilentlyContinue
71
+ Write-Warning " Script failed: $_ "
72
+ throw $_
73
+ }
74
+
75
+ # region Functions
76
+ function New-TempDirectory {
77
+ [CmdletBinding ()]
78
+ param (
79
+
80
+ )
81
+
82
+ $directory = New-Item - Path $env: TEMP - Name " PSModule-$ ( Get-Random ) " - ItemType Directory
83
+ $directory.FullName
84
+ }
85
+
86
+ function Build-Module {
87
+ [CmdletBinding ()]
88
+ param (
89
+ [string ]
90
+ $WorkingDirectory ,
91
+
92
+ [string ]
93
+ $Repository ,
94
+
95
+ [string ]
96
+ $Name ,
97
+
98
+ [string ]
99
+ $DevOpsPath ,
100
+
101
+ [switch ]
102
+ $UseGetV3
103
+ )
104
+
105
+ Assert-ModulePath - Root $WorkingDirectory
106
+
107
+ Install-ModuleProject - Path $WorkingDirectory - DevOpsPath $DevOpsPath - Name $Name
108
+ Publish-FakeModule - Path $WorkingDirectory - Name $Name
109
+ if (-not (Test-ModuleUpdatePending - Path $WorkingDirectory - Name $Name - Repository $Repository - UseGetV3:$UseGetV3 )) {
110
+ Write-Host " Skipping Module $Name - no update needed."
111
+ return
112
+ }
113
+
114
+ Write-Host " Updating Module $Name "
115
+ switch ($Name ) {
116
+ ' string' {
117
+ if ($UseGetV3 ) { Publish-PSResource - Path " $WorkingDirectory \$Name \$Name " - Repository $Repository }
118
+ else { Publish-Module - Path " $WorkingDirectory \$Name \$Name " - Repository $Repository }
119
+ }
120
+ default {
121
+ & " $WorkingDirectory \$Name \build\vsts-build.ps1" - Repository $Repository - ApiKey DevOps
122
+ }
123
+ }
124
+ }
125
+
126
+ function Assert-ModulePath {
127
+ [CmdletBinding ()]
128
+ param (
129
+ [Parameter (Mandatory = $true )]
130
+ [string ]
131
+ $Root
132
+ )
133
+
134
+ $modulePath = Join-Path - Path $Root - ChildPath ' _modules'
135
+ if (Test-Path - Path $modulePath ) { return }
136
+
137
+ $null = New-Item - Path $modulePath - ItemType Directory - Force
138
+ $env: PSModulePath = $modulePath , $env: PSModulePath -join ' ;'
139
+ }
140
+
141
+ function Install-ModuleProject {
142
+ [CmdletBinding ()]
143
+ param (
144
+ [Parameter (Mandatory = $true )]
145
+ [string ]
146
+ $Path ,
147
+
148
+ [Parameter (Mandatory = $true )]
149
+ [string ]
150
+ $DevOpsPath ,
151
+
152
+ [Parameter (Mandatory = $true )]
153
+ [string ]
154
+ $Name
155
+ )
156
+
157
+ Push-Location - Path $Path
158
+ git clone " $ ( $DevOpsPath -f $Name ) "
159
+ Pop-Location
160
+ }
161
+
162
+ function Publish-FakeModule {
163
+ <#
164
+ . SYNOPSIS
165
+ Copies the module code of the selected repository into the modules folders.
166
+
167
+ . DESCRIPTION
168
+ Copies the module code of the selected repository into the modules folders.
169
+ The folder being the "_modules" subfolder.
170
+
171
+ Publish-Module requires all dependencies to be present not only in the repository, but also on the machine doing the publishing.
172
+ This command - together with "Assert-ModulePath" - will ensure a copy is in a local location PowerShell knows to look for.
173
+
174
+ . PARAMETER Path
175
+ The root path where the module repositories to be published are cloned to.
176
+ Also the parent folder under which this function expects a "_modules" folder.
177
+
178
+ . PARAMETER Name
179
+ Name of the module to fake-pulish.
180
+ #>
181
+ [CmdletBinding ()]
182
+ param (
183
+ [Parameter (Mandatory = $true )]
184
+ [string ]
185
+ $Path ,
186
+
187
+ [Parameter (Mandatory = $true )]
188
+ [string ]
189
+ $Name
190
+ )
191
+
192
+ Copy-Item - Path " $Path \$Name \$Name " - Destination " $Path \_modules" - Recurse - Force
193
+ }
194
+
195
+ function Test-ModuleUpdatePending {
196
+ [CmdletBinding ()]
197
+ param (
198
+ [Parameter (Mandatory = $true )]
199
+ [string ]
200
+ $Path ,
201
+
202
+ [Parameter (Mandatory = $true )]
203
+ [string ]
204
+ $Name ,
205
+
206
+ [Parameter (Mandatory = $true )]
207
+ [string ]
208
+ $Repository ,
209
+
210
+ [switch ]
211
+ $UseGetV3
212
+ )
213
+
214
+ # Would prefer to use "Import-PowerShellDataFile", but some manifests cannot be read that way
215
+ $localVersion = (Get-Content - Path " $Path \$Name \$Name \$Name .psd1" | Where-Object { $_ -match ' ModuleVersion' }) -replace " ^.+?['`" ]" -replace " ['`" ]+$" -as [version ]
216
+
217
+ if ($UseGetV3 ) { $remoteVersion = (Find-PSResource - Name $Name - Repository $Repository ).Version -as [Version ] }
218
+ else { $remoteVersion = (Find-Module - Name $Name - Repository $Repository ).Version -as [Version ] }
219
+
220
+ if (-not $remoteVersion ) { return $true }
221
+ if ($remoteVersion -lt $localVersion ) { return $true }
222
+ $false
223
+ }
224
+ # endregion Functions
225
+
226
+ if ($UseGetV3 ) {
227
+ Set-Alias - Scope Global - Name Publish-Module - Value Publish-PSResource
228
+ }
229
+ $tempRoot = New-TempDirectory
230
+
231
+ foreach ($moduleName in $Modules ) {
232
+ Build-Module - WorkingDirectory $tempRoot - Repository $Repository - Name $moduleName - DevOpsPath $DevOpsPath - UseGetV3:$UseGetV3
233
+ }
234
+
235
+ Remove-Item - Path $tempRoot - Force - Recurse
0 commit comments