├── .gitignore ├── .publishignore ├── ChangeLog.md ├── Docs ├── Get-GitModule.md ├── Install-GitModule.md ├── InstallModuleFromGit-help.xml ├── InstallModuleFromGit.md └── Update-GitModule.md ├── InstallModuleFromGit.psd1 ├── InstallModuleFromGit.psm1 ├── LICENSE ├── Private ├── ConvertTo-Uri.ps1 ├── Get-InstallPath.ps1 ├── Install-ModuleInfo.ps1 ├── Test-PathWritable.ps1 └── Test-Prerequisites.ps1 ├── Public ├── Get-GitModule.ps1 ├── Install-GitModule.ps1 └── Update-GitModule.ps1 ├── README.md ├── Tests ├── functions │ ├── Get-GitModule.Tests.ps1 │ ├── Install-GitModule.Tests.ps1 │ └── Update-GitModule.Tests.ps1 └── module │ └── InstallModuleFromGit.Tests.ps1 ├── cab ├── InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_HelpInfo.xml ├── InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_en-US_HelpContent.cab └── InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_en-US_HelpContent.zip ├── img ├── InstallModuleFromGit.logo.png └── TestResults-AzureDevops.png └── tools ├── InvokeTests.ps1 ├── PublishModule-VSTS.ps1 ├── PublishModule.ps1 └── UpdateHelp.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | PesterTestResults.xml 2 | en-US/InstallModuleFromGit-help.xml -------------------------------------------------------------------------------- /.publishignore: -------------------------------------------------------------------------------- 1 | # specifies files which will NOT be published to PS Gallery 2 | .* 3 | PesterTestResults.xml 4 | tools/* 5 | Tests/* 6 | img/* 7 | Docs/* 8 | cab/* 9 | en-US/InstallModuleFromGit-help.xml 10 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # v.1.2.0 2 | 3 | Date: TBA 4 | 5 | # v.1.1.0 6 | 7 | Date: June 25, 2019 8 | 9 | ## 🆕 new features in 1.1.0 10 | - new command Update-GitModule which installs module only if local version exists and if older than remote 11 | - both Get-GitModule and Update-GitModule support parameter -Name which extracts url from already installed module 12 | 13 | ## 🛠️ bug fixes in 1.1.0 14 | - n/a 15 | 16 | For a full feature list, check [GitHub milestone link](https://github.com/iricigor/InstallModuleFromGit/milestone/4?closed=1). 17 | 18 | - - - 19 | 20 | # v.1.0.1 21 | 22 | Date: April 10, 2019 23 | 24 | For a full feature list, check [GitHub milestone link](https://github.com/iricigor/InstallModuleFromGit/milestone/2?closed=1). 25 | 26 | ## new features in 1.0.1 27 | - reduced number of files in published module 28 | - added extra links to published module 29 | - documentation updated 30 | - updatable help system _(Windows only)_ 31 | 32 | ## bug fixes in 1.0.1 33 | - returned module name is evaluated against manifest name and repository name 34 | 35 | - - - 36 | 37 | # v.1.0.0 38 | 39 | Date: April 7, 2019 40 | 41 | Initial release. 42 | 43 | For a full feature list, check [GitHub milestone link](https://github.com/iricigor/InstallModuleFromGit/milestone/1?closed=1). 44 | -------------------------------------------------------------------------------- /Docs/Get-GitModule.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: InstallModuleFromGit-help.xml 3 | Module Name: InstallModuleFromGit 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-GitModule 9 | 10 | ## SYNOPSIS 11 | This cmdlet will check for existence of PowerShell module in given repository and return its version. 12 | 13 | ## SYNTAX 14 | 15 | ### ByUri 16 | ``` 17 | Get-GitModule [-ProjectUri] [-Branch ] [-KeepTempCopy] [] 18 | ``` 19 | 20 | ### ByName 21 | ``` 22 | Get-GitModule -Name [-Branch ] [-KeepTempCopy] [] 23 | ``` 24 | 25 | ## DESCRIPTION 26 | This cmdlet will check for existence of PowerShell module in given repository and return its version. 27 | You can also specify desired git branch. 28 | 29 | Cmdlet requires \`git\` client tool to work. 30 | It will download (\`git clone\`) specified repository to temporary directory and analyze it. 31 | By default, it will delete this temporary copy, but if needed, it can be kept. 32 | 33 | Cmdlet searches for module manifest ( .psd1) file. If that is not found, then it searches for module (.psm1) file itself. 34 | 35 | ## EXAMPLES 36 | 37 | ### Example 1 38 | ``` 39 | PS C:\> Get-GitModule 'https://github.com/iricigor/FIFA2018' -Verbose 40 | 41 | Name : FIFA2018 42 | Version : 0.3.46 43 | Path : 44 | Root : True 45 | Git : https://github.com/iricigor/FIFA2018 46 | ``` 47 | 48 | This cmdlet will check for existence of PowerShell module in given repository (https://github.com/iricigor/FIFA2018') and return its version (currently 0.3.46). 49 | 50 | ### Example 2 51 | ``` 52 | PS C:\> $M = Find-Module FIFA2018; $M.Version; ($M | Get-GitModule).Version 53 | 54 | 0.2.45 55 | 0.3.46 56 | ``` 57 | 58 | This illustrates how you can check latest versions of the module both in PSGallery and in its repository. 59 | Notice that cmdlet \`Get-GitModule\` accepts value for \`-ProjectURI\` via pipeline. 60 | 61 | ## PARAMETERS 62 | 63 | ### -Branch 64 | Optional parameter that specifies which branch should be cloned. 65 | If omitted, \`master\` branch will be used. 66 | 67 | ```yaml 68 | Type: String 69 | Parameter Sets: (All) 70 | Aliases: 71 | 72 | Required: False 73 | Position: Named 74 | Default value: None 75 | Accept pipeline input: False 76 | Accept wildcard characters: False 77 | ``` 78 | 79 | ### -KeepTempCopy 80 | Cmdlet will download (\`git clone\`) specified repository to temporary directory and analyze it. 81 | By default, it will delete this temporary copy. 82 | If needed use this switch parameter to keep this temporary copy. 83 | You can check \`Path\` attribute of return value to see exact path where temporary copy is located. 84 | 85 | This is used for example in \`Install-GitModule\` to directly install module from this temporary copy. 86 | 87 | ```yaml 88 | Type: SwitchParameter 89 | Parameter Sets: (All) 90 | Aliases: 91 | 92 | Required: False 93 | Position: Named 94 | Default value: False 95 | Accept pipeline input: False 96 | Accept wildcard characters: False 97 | ``` 98 | 99 | ### -Name 100 | You can query already installed modules for their online version if ProjectUri is specified in the module info. 101 | To do this, just specify module name(s) with parameter -Name. 102 | 103 | ```yaml 104 | Type: String[] 105 | Parameter Sets: ByName 106 | Aliases: 107 | 108 | Required: True 109 | Position: Named 110 | Default value: None 111 | Accept pipeline input: False 112 | Accept wildcard characters: False 113 | ``` 114 | 115 | ### -ProjectUri 116 | Mandatory parameter specifying URL or the repository. 117 | Multiple values are supported. 118 | Parameter is passed to \`git\` client, so whatever works there is good value. 119 | For example, in GitHub URLs you can specify parameter both with or without \`.git\` at the end of URL. 120 | 121 | You can pass this parameter also via pipeline, for example via \`Find-Module\` built-in cmdlet. 122 | 123 | ```yaml 124 | Type: String[] 125 | Parameter Sets: ByUri 126 | Aliases: 127 | 128 | Required: True 129 | Position: 0 130 | Default value: None 131 | Accept pipeline input: True (ByPropertyName) 132 | Accept wildcard characters: False 133 | ``` 134 | 135 | ### CommonParameters 136 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 137 | 138 | ## INPUTS 139 | 140 | ### System.String[] 141 | ## OUTPUTS 142 | 143 | ### System.Object 144 | ## NOTES 145 | 146 | ## RELATED LINKS 147 | -------------------------------------------------------------------------------- /Docs/Install-GitModule.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: InstallModuleFromGit-help.xml 3 | Module Name: InstallModuleFromGit 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Install-GitModule 9 | 10 | ## SYNOPSIS 11 | This cmdlet installs PowerShell module specified by its git repository URL to user's default install directory. 12 | 13 | ## SYNTAX 14 | 15 | ``` 16 | Install-GitModule [-ProjectUri] [[-Branch] ] [[-DestinationPath] ] [-Force] 17 | [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | This cmdlet installs PowerShell module specified by its git repository URL to user's default install folder. 22 | 23 | You can also specify desired git branch. 24 | 25 | Cmdlet internally uses \`Get-GitModule\` cmdlet, so it requires \`git\` client tool to work. 26 | Cmdlet will actually download specified repository to user's default install directory for PowerShell modules. 27 | 28 | It does not support functionality \`-Scope AllUsers\`, but it is possible to specify \`-DestinationPath\` argument which will provide the same result. 29 | 30 | Cmdlet searches for module manifest ( .psd1) file or if that is not found for module (.psm1) file itself. 31 | 32 | Note that this will not import module, only install it (the same as built-in cmdlet \`Install-Module\`). 33 | You can rely on PowerShell's automatic import of modules into user session when needed. 34 | 35 | ## EXAMPLES 36 | 37 | ### Example 1 38 | ``` 39 | PS C:\> Install-GitModule 'https://github.com/iricigor/psaptgetupdate' -Verbose 40 | ``` 41 | 42 | This cmdlet will install PowerShell module from given repository (https://github.com/iricigor/psaptgetupdate'). 43 | 44 | ## PARAMETERS 45 | 46 | ### -Branch 47 | Optional parameter that specifies which branch should be cloned. 48 | If omitted, \`master\` branch will be used. 49 | 50 | ```yaml 51 | Type: String 52 | Parameter Sets: (All) 53 | Aliases: 54 | 55 | Required: False 56 | Position: 1 57 | Default value: None 58 | Accept pipeline input: False 59 | Accept wildcard characters: False 60 | ``` 61 | 62 | ### -DestinationPath 63 | If you have a specific setup, you can override default install location with this parameter. 64 | As cmdlet always installs to user specific location, this can be useful to perform system wide installation (requires also elevated prompt). 65 | 66 | ```yaml 67 | Type: String 68 | Parameter Sets: (All) 69 | Aliases: 70 | 71 | Required: False 72 | Position: 2 73 | Default value: None 74 | Accept pipeline input: False 75 | Accept wildcard characters: False 76 | ``` 77 | 78 | ### -Force 79 | If the module with specified name and the version exists, installation will fail. 80 | You can override this behaviour with \`-Force\` switch. 81 | 82 | ```yaml 83 | Type: SwitchParameter 84 | Parameter Sets: (All) 85 | Aliases: 86 | 87 | Required: False 88 | Position: Named 89 | Default value: False 90 | Accept pipeline input: False 91 | Accept wildcard characters: False 92 | ``` 93 | 94 | ### -ProjectUri 95 | Mandatory parameter specifying URL or the repository. 96 | Multiple values are supported. 97 | Parameter is passed to \`git\` client, so whatever works there is good value. 98 | For example, in GitHub URLs you can specify parameter both with or without \`.git\` at the end of URL. 99 | 100 | You can pass this parameter also via pipeline, for example via \`Find-Module\` built-in cmdlet. 101 | 102 | ```yaml 103 | Type: String[] 104 | Parameter Sets: (All) 105 | Aliases: 106 | 107 | Required: True 108 | Position: 0 109 | Default value: None 110 | Accept pipeline input: True (ByPropertyName) 111 | Accept wildcard characters: False 112 | ``` 113 | 114 | ### CommonParameters 115 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 116 | 117 | ## INPUTS 118 | 119 | ### System.String[] 120 | ## OUTPUTS 121 | 122 | ### System.Object 123 | ## NOTES 124 | 125 | ## RELATED LINKS 126 | -------------------------------------------------------------------------------- /Docs/InstallModuleFromGit-help.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Get-GitModule 6 | Get 7 | GitModule 8 | 9 | This cmdlet will check for existence of PowerShell module in given repository and return its version. 10 | 11 | 12 | 13 | This cmdlet will check for existence of PowerShell module in given repository and return its version. You can also specify desired git branch. 14 | Cmdlet requires `git` client tool to work. It will download (`git clone`) specified repository to temporary directory and analyze it. By default, it will delete this temporary copy, but if needed, it can be kept. 15 | Cmdlet searches for module manifest ( .psd1) file or if that is not found for module (.psm1) file itself. 16 | 17 | 18 | 19 | Get-GitModule 20 | 21 | ProjectUri 22 | 23 | Mandatory parameter specifying URL or the repository. Multiple values are supported. Parameter is passed to `git` client, so whatever works there is good value. For example, in GitHub URLs you can specify parameter both with or without `.git` at the end of URL. 24 | You can pass this parameter also via pipeline, for example via `Find-Module` built-in cmdlet. 25 | 26 | String[] 27 | 28 | String[] 29 | 30 | 31 | None 32 | 33 | 34 | Branch 35 | 36 | Optional parameter that specifies which branch should be cloned. If omitted, `master` branch will be used. 37 | 38 | String 39 | 40 | String 41 | 42 | 43 | None 44 | 45 | 46 | KeepTempCopy 47 | 48 | Cmdlet will download (`git clone`) specified repository to temporary directory and analyze it. By default, it will delete this temporary copy. If needed use this switch parameter to keep this temporary copy. You can check `Path` attribute of return value to see exact path where temporary copy is located. 49 | This is used for example in `Install-GitModule` to directly install module from this temporary copy. 50 | 51 | 52 | SwitchParameter 53 | 54 | 55 | False 56 | 57 | 58 | 59 | 60 | 61 | Branch 62 | 63 | Optional parameter that specifies which branch should be cloned. If omitted, `master` branch will be used. 64 | 65 | String 66 | 67 | String 68 | 69 | 70 | None 71 | 72 | 73 | KeepTempCopy 74 | 75 | Cmdlet will download (`git clone`) specified repository to temporary directory and analyze it. By default, it will delete this temporary copy. If needed use this switch parameter to keep this temporary copy. You can check `Path` attribute of return value to see exact path where temporary copy is located. 76 | This is used for example in `Install-GitModule` to directly install module from this temporary copy. 77 | 78 | SwitchParameter 79 | 80 | SwitchParameter 81 | 82 | 83 | False 84 | 85 | 86 | ProjectUri 87 | 88 | Mandatory parameter specifying URL or the repository. Multiple values are supported. Parameter is passed to `git` client, so whatever works there is good value. For example, in GitHub URLs you can specify parameter both with or without `.git` at the end of URL. 89 | You can pass this parameter also via pipeline, for example via `Find-Module` built-in cmdlet. 90 | 91 | String[] 92 | 93 | String[] 94 | 95 | 96 | None 97 | 98 | 99 | 100 | 101 | 102 | System.String[] 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | System.Object 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------- Example 1 -------------------------- 127 | PS C:\> Get-GitModule 'https://github.com/iricigor/FIFA2018' -Verbose 128 | 129 | Name : FIFA2018 130 | Version : 0.3.46 131 | Path : 132 | Root : True 133 | Git : https://github.com/iricigor/FIFA2018 134 | 135 | This cmdlet will check for existence of PowerShell module in given repository (https://github.com/iricigor/FIFA2018') and return its version (currently 0.3.46) . 136 | 137 | 138 | 139 | -------------------------- Example 2 -------------------------- 140 | PS C:\> $M = Find-Module FIFA2018; $M.Version; ($M | Get-GitModule).Version 141 | 142 | 0.2.45 143 | 0.3.46 144 | 145 | This illustrates how you can check latest versions of the module both in PSGallery and in its repository. Notice that cmdlet `Get-GitModule` accepts value for `-ProjectURI` via pipeline. 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Install-GitModule 154 | Install 155 | GitModule 156 | 157 | This cmdlet installs PowerShell module specified by its git repository URL to user's default install directory. 158 | 159 | 160 | 161 | This cmdlet installs PowerShell module specified by its git repository URL to user's default install folder. 162 | You can also specify desired git branch. 163 | Cmdlet internally uses `Get-GitModule` cmdlet, so it requires `git` client tool to work. Cmdlet will actually download specified repository to user's default install directory for PowerShell modules. 164 | It does not support functionality `-Scope AllUsers`, but it is possible to specify `-DestinationPath` argument which will provide the same result. 165 | Cmdlet searches for module manifest ( .psd1) file or if that is not found for module (.psm1) file itself. 166 | Note that this will not import module, only install it (the same as built-in cmdlet `Install-Module`). You can rely on PowerShell's automatic import of modules into user session when needed. 167 | 168 | 169 | 170 | Install-GitModule 171 | 172 | ProjectUri 173 | 174 | Mandatory parameter specifying URL or the repository. Multiple values are supported. Parameter is passed to `git` client, so whatever works there is good value. For example, in GitHub URLs you can specify parameter both with or without `.git` at the end of URL. 175 | You can pass this parameter also via pipeline, for example via `Find-Module` built-in cmdlet. 176 | 177 | String[] 178 | 179 | String[] 180 | 181 | 182 | None 183 | 184 | 185 | Branch 186 | 187 | Optional parameter that specifies which branch should be cloned. If omitted, `master` branch will be used. 188 | 189 | String 190 | 191 | String 192 | 193 | 194 | None 195 | 196 | 197 | DestinationPath 198 | 199 | If you have a specific setup, you can override default install location with this parameter. As cmdlet always installs to user specific location, this can be useful to perform system wide installation (requires also elevated prompt). 200 | 201 | String 202 | 203 | String 204 | 205 | 206 | None 207 | 208 | 209 | Force 210 | 211 | If the module with specified name and the version exists, installation will fail. You can override this behaviour with `-Force` switch. 212 | 213 | 214 | SwitchParameter 215 | 216 | 217 | False 218 | 219 | 220 | 221 | 222 | 223 | Branch 224 | 225 | Optional parameter that specifies which branch should be cloned. If omitted, `master` branch will be used. 226 | 227 | String 228 | 229 | String 230 | 231 | 232 | None 233 | 234 | 235 | DestinationPath 236 | 237 | If you have a specific setup, you can override default install location with this parameter. As cmdlet always installs to user specific location, this can be useful to perform system wide installation (requires also elevated prompt). 238 | 239 | String 240 | 241 | String 242 | 243 | 244 | None 245 | 246 | 247 | Force 248 | 249 | If the module with specified name and the version exists, installation will fail. You can override this behaviour with `-Force` switch. 250 | 251 | SwitchParameter 252 | 253 | SwitchParameter 254 | 255 | 256 | False 257 | 258 | 259 | ProjectUri 260 | 261 | Mandatory parameter specifying URL or the repository. Multiple values are supported. Parameter is passed to `git` client, so whatever works there is good value. For example, in GitHub URLs you can specify parameter both with or without `.git` at the end of URL. 262 | You can pass this parameter also via pipeline, for example via `Find-Module` built-in cmdlet. 263 | 264 | String[] 265 | 266 | String[] 267 | 268 | 269 | None 270 | 271 | 272 | 273 | 274 | 275 | System.String[] 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | System.Object 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | -------------------------- Example 1 -------------------------- 300 | PS C:\> Install-GitModule 'https://github.com/iricigor/psaptgetupdate' -Verbose 301 | 302 | This cmdlet will install PowerShell module from given repository (https://github.com/iricigor/psaptgetupdate'). 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | Update-GitModule 311 | Update 312 | GitModule 313 | 314 | This cmdlet updates previously installed PowerShell module specified by its git repository URL if repository contains newer version than installed one. 315 | 316 | 317 | 318 | This cmdlet updates previously installed PowerShell module specified by its git repository URL if repository contains newer version than installed one. 319 | You can also specify desired git branch. 320 | Cmdlet internally uses `Get-GitModule` cmdlet, so it requires `git` client tool to work. Cmdlet will actually download specified repository to user's default install directory for PowerShell modules. 321 | Cmdlet searches for module manifest ( .psd1) file or if that is not found for module (.psm1) file itself. 322 | If you do not have the same module already installed, commandlet will throw an error. 323 | Note that this will not import module, only install it (the same as built-in cmdlet `Update-Module`). You can rely on PowerShell's automatic import of modules into user session when needed. 324 | 325 | 326 | 327 | Update-GitModule 328 | 329 | ProjectUri 330 | 331 | Mandatory parameter specifying URL or the repository. Multiple values are supported. Parameter is passed to `git` client, so whatever works there is good value. For example, in GitHub URLs you can specify parameter both with or without `.git` at the end of URL. 332 | You can pass this parameter also via pipeline, for example via `Find-Module` built-in cmdlet. 333 | 334 | String[] 335 | 336 | String[] 337 | 338 | 339 | None 340 | 341 | 342 | Branch 343 | 344 | Optional parameter that specifies which branch should be cloned. If omitted, `master` branch will be used. 345 | 346 | String 347 | 348 | String 349 | 350 | 351 | None 352 | 353 | 354 | DestinationPath 355 | 356 | If you have a specific setup, you can override default install location with this parameter. As cmdlet always installs to user specific location, this can be useful to perform system wide installation (requires also elevated prompt). 357 | 358 | String 359 | 360 | String 361 | 362 | 363 | None 364 | 365 | 366 | Force 367 | 368 | If DestinationPath location is not empty, commandlet will not install newer version there. This behavior can be overridden with -Force switch. 369 | 370 | 371 | SwitchParameter 372 | 373 | 374 | False 375 | 376 | 377 | 378 | 379 | 380 | Branch 381 | 382 | Optional parameter that specifies which branch should be cloned. If omitted, `master` branch will be used. 383 | 384 | String 385 | 386 | String 387 | 388 | 389 | None 390 | 391 | 392 | DestinationPath 393 | 394 | If you have a specific setup, you can override default install location with this parameter. As cmdlet always installs to user specific location, this can be useful to perform system wide installation (requires also elevated prompt). 395 | 396 | String 397 | 398 | String 399 | 400 | 401 | None 402 | 403 | 404 | Force 405 | 406 | If DestinationPath location is not empty, commandlet will not install newer version there. This behavior can be overridden with -Force switch. 407 | 408 | SwitchParameter 409 | 410 | SwitchParameter 411 | 412 | 413 | False 414 | 415 | 416 | ProjectUri 417 | 418 | Mandatory parameter specifying URL or the repository. Multiple values are supported. Parameter is passed to `git` client, so whatever works there is good value. For example, in GitHub URLs you can specify parameter both with or without `.git` at the end of URL. 419 | You can pass this parameter also via pipeline, for example via `Find-Module` built-in cmdlet. 420 | 421 | String[] 422 | 423 | String[] 424 | 425 | 426 | None 427 | 428 | 429 | 430 | 431 | 432 | System.String[] 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | System.Object 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | -------------------------- Example 1 -------------------------- 457 | PS C:\> Update-GitModule https://github.com/microsoft/SpeculationControl 458 | 459 | Updates the most downloadable PowerShell module directly from GitHub. If you do not have it installed, it will throw an error. 460 | 461 | 462 | 463 | 464 | 465 | https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Update-GitModule.md 466 | https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Update-GitModule.md 467 | 468 | 469 | 470 | -------------------------------------------------------------------------------- /Docs/InstallModuleFromGit.md: -------------------------------------------------------------------------------- 1 | --- 2 | Module Name: InstallModuleFromGit 3 | Module Guid: d6a1577c-e3b5-48f2-a698-f08ab4865a58 4 | Download Help Link: https://github.com/iricigor/InstallModuleFromGit/raw/master/cab/ 5 | Help Version: 1.0.0.0 6 | Locale: en-US 7 | --- 8 | 9 | # InstallModuleFromGit Module 10 | ## Description 11 | This PowerShell module will be help you to easily instal PowerShell modules directly from [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/repos/) (_aka VSTS_) or [GitHub](https://github.com/). 12 | All you need to know is a URL of the git repository and the module will take care of everything else. 13 | 14 | ## InstallModuleFromGit Cmdlets 15 | ### [Get-GitModule](Get-GitModule.md) 16 | This cmdlet will check for existence of PowerShell module in given repository and return its version. 17 | 18 | ### [Install-GitModule](Install-GitModule.md) 19 | This cmdlet installs PowerShell module specified by its git repository URL to user's default install directory. 20 | 21 | -------------------------------------------------------------------------------- /Docs/Update-GitModule.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: InstallModuleFromGit-help.xml 3 | Module Name: InstallModuleFromGit 4 | online version: https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Update-GitModule.md 5 | schema: 2.0.0 6 | --- 7 | 8 | # Update-GitModule 9 | 10 | ## SYNOPSIS 11 | This cmdlet updates previously installed PowerShell module specified by its git repository URL if repository contains newer version than installed one. 12 | 13 | ## SYNTAX 14 | 15 | ### ByUri 16 | ``` 17 | Update-GitModule [-ProjectUri] [-Branch ] [-DestinationPath ] [-Force] 18 | [] 19 | ``` 20 | 21 | ### ByName 22 | ``` 23 | Update-GitModule -Name [-Branch ] [-DestinationPath ] [-Force] [] 24 | ``` 25 | 26 | ## DESCRIPTION 27 | 28 | This cmdlet updates previously installed PowerShell module specified by its git repository URL if repository contains newer version than installed one. 29 | 30 | You can also specify desired git branch. 31 | 32 | Cmdlet internally uses \`Get-GitModule\` cmdlet, so it requires \`git\` client tool to work. 33 | Cmdlet will actually download specified repository to user's default install directory for PowerShell modules. 34 | 35 | Cmdlet searches for module manifest ( .psd1) file or if that is not found for module (.psm1) file itself. 36 | 37 | If you do not have the same module already installed, commandlet will throw an error. 38 | 39 | Note that this will not import module, only install it (the same as built-in cmdlet \`Update-Module\`). 40 | You can rely on PowerShell's automatic import of modules into user session when needed. 41 | 42 | ## EXAMPLES 43 | 44 | ### Example 1 45 | ```powershell 46 | PS C:\> Update-GitModule https://github.com/microsoft/SpeculationControl 47 | ``` 48 | 49 | Updates the most downloadable PowerShell module directly from GitHub. If you do not have it installed, it will throw an error. 50 | 51 | ## PARAMETERS 52 | 53 | ### -Branch 54 | Optional parameter that specifies which branch should be cloned. 55 | If omitted, \`master\` branch will be used. 56 | 57 | ```yaml 58 | Type: String 59 | Parameter Sets: (All) 60 | Aliases: 61 | 62 | Required: False 63 | Position: Named 64 | Default value: None 65 | Accept pipeline input: False 66 | Accept wildcard characters: False 67 | ``` 68 | 69 | ### -DestinationPath 70 | If you have a specific setup, you can override default install location with this parameter. 71 | As cmdlet always installs to user specific location, this can be useful to perform system wide installation (requires also elevated prompt). 72 | 73 | ```yaml 74 | Type: String 75 | Parameter Sets: (All) 76 | Aliases: 77 | 78 | Required: False 79 | Position: Named 80 | Default value: None 81 | Accept pipeline input: False 82 | Accept wildcard characters: False 83 | ``` 84 | 85 | ### -Force 86 | If DestinationPath location is not empty, commandlet will not install newer version there. 87 | This behavior can be overridden with -Force switch. 88 | 89 | ```yaml 90 | Type: SwitchParameter 91 | Parameter Sets: (All) 92 | Aliases: 93 | 94 | Required: False 95 | Position: Named 96 | Default value: None 97 | Accept pipeline input: False 98 | Accept wildcard characters: False 99 | ``` 100 | 101 | ### -Name 102 | You can update already installed modules with their git online version if ProjectUri is specified in the module info. 103 | To do this, just specify module name(s) with parameter -Name. 104 | 105 | ```yaml 106 | Type: String[] 107 | Parameter Sets: ByName 108 | Aliases: 109 | 110 | Required: True 111 | Position: Named 112 | Default value: None 113 | Accept pipeline input: False 114 | Accept wildcard characters: False 115 | ``` 116 | 117 | ### -ProjectUri 118 | Mandatory parameter specifying URL or the repository. 119 | Multiple values are supported. 120 | Parameter is passed to \`git\` client, so whatever works there is good value. 121 | For example, in GitHub URLs you can specify parameter both with or without \`.git\` at the end of URL. 122 | 123 | You can pass this parameter also via pipeline, for example via \`Find-Module\` built-in cmdlet. 124 | 125 | ```yaml 126 | Type: String[] 127 | Parameter Sets: ByUri 128 | Aliases: 129 | 130 | Required: True 131 | Position: 0 132 | Default value: None 133 | Accept pipeline input: True (ByPropertyName) 134 | Accept wildcard characters: False 135 | ``` 136 | 137 | ### CommonParameters 138 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 139 | 140 | ## INPUTS 141 | 142 | ### System.String[] 143 | 144 | ## OUTPUTS 145 | 146 | ### System.Object 147 | ## NOTES 148 | 149 | ## RELATED LINKS 150 | 151 | [https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Update-GitModule.md](https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Update-GitModule.md) 152 | 153 | -------------------------------------------------------------------------------- /InstallModuleFromGit.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'InstallModuleFromGit' 3 | # 4 | # Generated by: Igor 5 | # 6 | # Generated on: 29-Mar-19 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'InstallModuleFromGit.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '1.2.0' 16 | 17 | # Supported PSEditions 18 | # CompatiblePSEditions = @() 19 | 20 | # ID used to uniquely identify this module 21 | GUID = 'd6a1577c-e3b5-48f2-a698-f08ab4865a58' 22 | 23 | # Author of this module 24 | Author = 'iricigor@outlook.com' 25 | 26 | # Company or vendor of this module 27 | # CompanyName = 'Unknown' 28 | 29 | # Copyright statement for this module 30 | # Copyright = '(c) 2019 Igor. All rights reserved.' 31 | 32 | # Description of the functionality provided by this module 33 | Description = 'Installs module from Git repository (i.e. GitHub or Azure DevOps aka VSTS)' 34 | 35 | # Minimum version of the Windows PowerShell engine required by this module 36 | # PowerShellVersion = '' 37 | 38 | # Name of the Windows PowerShell host required by this module 39 | # PowerShellHostName = '' 40 | 41 | # Minimum version of the Windows PowerShell host required by this module 42 | # PowerShellHostVersion = '' 43 | 44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 45 | # DotNetFrameworkVersion = '' 46 | 47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 48 | # CLRVersion = '' 49 | 50 | # Processor architecture (None, X86, Amd64) required by this module 51 | # ProcessorArchitecture = '' 52 | 53 | # Modules that must be imported into the global environment prior to importing this module 54 | # RequiredModules = @() 55 | 56 | # Assemblies that must be loaded prior to importing this module 57 | # RequiredAssemblies = @() 58 | 59 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 60 | # ScriptsToProcess = @() 61 | 62 | # Type files (.ps1xml) to be loaded when importing this module 63 | # TypesToProcess = @() 64 | 65 | # Format files (.ps1xml) to be loaded when importing this module 66 | # FormatsToProcess = @() 67 | 68 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 69 | # NestedModules = @() 70 | 71 | # 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. 72 | FunctionsToExport = @('Get-GitModule','Install-GitModule','Update-GitModule') 73 | 74 | # Cmdlets 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 cmdlets to export. 75 | CmdletsToExport = @() 76 | 77 | # Variables to export from this module 78 | VariablesToExport = '' 79 | 80 | # Aliases 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 aliases to export. 81 | AliasesToExport = @() 82 | 83 | # DSC resources to export from this module 84 | # DscResourcesToExport = @() 85 | 86 | # List of all modules packaged with this module 87 | # ModuleList = @() 88 | 89 | # List of all files packaged with this module 90 | # FileList = @() 91 | 92 | # 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. 93 | PrivateData = @{ 94 | 95 | PSData = @{ 96 | 97 | # Tags applied to this module. These help with module discovery in online galleries. 98 | Tags = @('Azure','DevOps','ADO','VSTS','GitHub','Install-Module','git-clone','git','git-client','PowerShellGet', 'Windows', 'Linux') 99 | 100 | # A URL to the license for this module. 101 | LicenseUri = 'https://github.com/iricigor/InstallModuleFromGit/blob/master/LICENSE' 102 | 103 | # A URL to the main website for this project. 104 | ProjectUri = 'https://github.com/iricigor/InstallModuleFromGit' 105 | 106 | # A URL to an icon representing this module. 107 | IconUri = 'https://github.com/iricigor/InstallModuleFromGit/raw/master/img/InstallModuleFromGit.logo.png' 108 | 109 | # ReleaseNotes of this module 110 | ReleaseNotes = 'https://github.com/iricigor/InstallModuleFromGit/blob/master/ChangeLog.md' 111 | 112 | } # End of PSData hashtable 113 | 114 | } # End of PrivateData hashtable 115 | 116 | # HelpInfo URI of this module 117 | HelpInfoURI = 'https://github.com/iricigor/InstallModuleFromGit/raw/master/cab/' 118 | 119 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 120 | # DefaultCommandPrefix = '' 121 | 122 | } 123 | 124 | -------------------------------------------------------------------------------- /InstallModuleFromGit.psm1: -------------------------------------------------------------------------------- 1 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost','')] 2 | param() 3 | 4 | $ModName = 'InstallModuleFromGit' 5 | Get-Module $ModName | Remove-Module -Force 6 | 7 | Write-Host "`n`n$ModName module import starting`n" -ForegroundColor Cyan 8 | 9 | # 10 | # Module definitions 11 | # 12 | 13 | 14 | 15 | # 16 | # Import main functions 17 | # 18 | 19 | $Public = @(Get-ChildItem (Join-Path $PSScriptRoot 'Public') -Filter *.ps1) 20 | $Private = @(Get-ChildItem (Join-Path $PSScriptRoot 'Private') -Filter *.ps1 -ErrorAction SilentlyContinue) 21 | 22 | foreach ($F in ($Private+$Public) ) { 23 | 24 | Write-Host ("Importing $($F.Name)... ") -NoNewline 25 | 26 | try { 27 | . ($F.FullName) 28 | Write-Host ' OK ' -ForegroundColor Green 29 | } catch { 30 | Write-Host 'FAILED' -ForegroundColor Red 31 | } 32 | } 33 | 34 | Export-ModuleMember -Function $Public.BaseName 35 | Write-Host "Exported $($Public.Count) member(s)" 36 | Export-ModuleMember -Alias * 37 | 38 | 39 | Write-Host "`nType 'Get-Command -Module $ModName' for list of commands, 'Get-Help ' for help, or" 40 | Write-Host "'Get-Command -Module $ModName | Get-Help | Select Name, Synopsis' for explanation on all commands`n" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Igor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Private/ConvertTo-Uri.ps1: -------------------------------------------------------------------------------- 1 | function ConvertTo-Uri { 2 | # converts array of module names to uris based on projectUri field 3 | 4 | param ( 5 | [Parameter(Mandatory)] 6 | [string[]]$Name 7 | ) 8 | 9 | Write-Verbose -Message "$(Get-Date -f T) searching module URIs from their names" 10 | foreach ($N1 in $Name) { 11 | $Module = Get-InstalledModule $N1 -ea 0 12 | if (!$Module) {$Module = Get-Module $N1 -ListAvailable -ea 0} 13 | 14 | if (!$Module) { 15 | Write-Error "$FunctionName found no module $N1" 16 | continue 17 | } 18 | 19 | if (!($Module | ? ProjectUri)) { 20 | Write-Warning "$FunctionName found module $N1, but it has no ProjectUri information" 21 | continue 22 | } 23 | 24 | # return information to $ProjectUri variable 25 | $Module | Sort-Object Version | Select-Object -Last 1 -ExpandProperty ProjectUri 26 | } 27 | } -------------------------------------------------------------------------------- /Private/Get-InstallPath.ps1: -------------------------------------------------------------------------------- 1 | function Get-InstallPath { 2 | 3 | # returns OS specific path for module installation, it support only -Scope CurrentUser 4 | 5 | $defaultPath = if ($IsLinux -or $IsOSX) { 6 | #"$HOME/.local/share/powershell/Modules" 7 | # https://github.com/PowerShell/PowerShellGet/blob/d4dfebbbec4dfbe73392719a8a331541ed75d508/src/PowerShellGet/private/modulefile/PartOne.ps1#L71 8 | Join-Path (Split-Path -Path ([System.Management.Automation.Platform]::SelectProductNameForDirectory('USER_MODULES')) -Parent) 'Modules' 9 | } else { 10 | # https://github.com/PowerShell/PowerShellGet/blob/8004c304a2fa8ad32b92c6c2ba7efe116df3c862/src/PowerShellGet/private/modulefile/PartOne.ps1#L46 11 | try { 12 | if ($PSVersionTable.PSEdition -eq 'Core') { 13 | [Environment]::GetFolderPath("MyDocuments") + '\PowerShell\Modules' 14 | } else { 15 | [Environment]::GetFolderPath("MyDocuments") + '\WindowsPowerShell\Modules' 16 | } 17 | } catch { 18 | "$home\Documents\PowerShell\Modules" 19 | } 20 | } 21 | 22 | $ModulePaths = $Env:PSModulePath -split (';:'[[int]($IsLinux -or $IsMacOS)]) 23 | if ($defaultPath -in $ModulePaths) { 24 | $defaultPath 25 | } else { 26 | # default path is not in findable by get-module, try to avoid it 27 | $writablePath = '' 28 | foreach ($P1 in $ModulePaths) { 29 | if (([string]::IsNullOrEmpty($writablePath)) -and (Test-PathWritable $P1)) { 30 | $writablePath = $P1 31 | } 32 | } 33 | if ([string]::IsNullOrEmpty($writablePath)) { 34 | # we found no writable paths, return default one 35 | $defaultPath 36 | } else { 37 | $writablePath 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Private/Install-ModuleInfo.ps1: -------------------------------------------------------------------------------- 1 | function Install-ModuleInfo { 2 | 3 | param( 4 | [PSObject]$ModuleInfo, 5 | [string]$DestinationPath, 6 | [switch]$Force 7 | ) 8 | 9 | # verify properties 10 | if (!$ModuleInfo.Root) { 11 | Write-Warning -Message "$FunctionName installing module with manifest not located in module root directory" 12 | } 13 | if (!$ModuleInfo.SameName) { 14 | Write-Warning -Message "$FunctionName installing module with module name not the same as its directory name" 15 | } 16 | 17 | # check target directory 18 | $TargetDir = Join-Path (Join-Path $DestinationPath $ModuleInfo.Name) $ModuleInfo.Version 19 | if (!(Test-Path $TargetDir)) { 20 | New-Item $TargetDir -ItemType Directory -Force | Out-Null 21 | } elseif ((Get-ChildItem $TargetDir) -and (!$Force)) { 22 | Write-Error "$FunctionName cannot install into non-empty directory $TargetDir, use different -Destination or -Force to override it" 23 | continue 24 | } 25 | 26 | # copy module 27 | Write-Verbose -Message "$(Get-Date -f T) installing module to $TargetDir" 28 | Copy-Item "$($ModuleInfo.LocalPath)/*" $TargetDir -Force -Recurse | Out-Null 29 | 30 | # clean up 31 | $gitDir = Join-Path $TargetDir '.git' 32 | if (Test-Path $gitDir) {Remove-Item $gitDir -Recurse -Force} 33 | Remove-Item $ModuleInfo.LocalPath -Recurse -Force | Out-Null 34 | Write-Verbose -Message "$(Get-Date -f T) module $ModuleName installation completed" 35 | 36 | # return value 37 | $ModuleInfo.LocalPath = $TargetDir 38 | $ModuleInfo 39 | } -------------------------------------------------------------------------------- /Private/Test-PathWritable.ps1: -------------------------------------------------------------------------------- 1 | function Test-PathWritable { 2 | param ( 3 | [string]$Path 4 | ) 5 | # returns true if given directory is writable, false otherwise 6 | if (!(Test-Path $Path -PathType Container)) { 7 | #throw "Path $Path is not a directory" 8 | $false 9 | } 10 | 11 | $FileName = Join-Path $Path ([io.path]::GetRandomFileName()) 12 | 13 | try { 14 | [io.file]::OpenWrite($FileName).close() 15 | [io.file]::Delete($FileName) 16 | $true 17 | } catch { 18 | $false 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /Private/Test-Prerequisites.ps1: -------------------------------------------------------------------------------- 1 | function Test-Prerequisites { 2 | # check if git command is available, can be extended as needed 3 | if (Get-Command 'git') {$true} else {$false} 4 | } -------------------------------------------------------------------------------- /Public/Get-GitModule.ps1: -------------------------------------------------------------------------------- 1 | function Get-GitModule { 2 | 3 | [CmdletBinding(HelpUri='https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Get-GitModule.md')] 4 | 5 | param ( 6 | 7 | 8 | [Parameter(Mandatory,ValueFromPipelineByPropertyName,Position=0,ParameterSetName='ByUri')] 9 | [string[]]$ProjectUri, 10 | # https://github.com/dfinke/InstallModuleFromGitHub 11 | # https://github.com/iricigor/FIFA2018 12 | 13 | [Parameter(Mandatory,ParameterSetName='ByName')] 14 | [string[]]$Name, 15 | 16 | [string]$Branch = "master", 17 | [switch]$KeepTempCopy 18 | 19 | ) 20 | 21 | BEGIN { 22 | $FunctionName = $MyInvocation.MyCommand.Name 23 | Write-Verbose -Message "$(Get-Date -f G) $FunctionName starting" 24 | 25 | if (!(Test-Prerequisites)) { 26 | throw "$FunctionName prerequisites not met" 27 | # TODO: Add more details 28 | } 29 | 30 | if ($env:AGENT_TEMPDIRECTORY) { 31 | $tmpRoot = $env:AGENT_TEMPDIRECTORY 32 | } else { 33 | $tmpRoot = [System.IO.Path]::GetTempPath() 34 | } 35 | 36 | if ($Name) {$ProjectUri = ConvertTo-Uri -Name $Name} 37 | 38 | } 39 | 40 | PROCESS { 41 | 42 | foreach ($P1 in $ProjectUri) { 43 | 44 | Write-Verbose -Message "$(Get-Date -f T) processing $P1" 45 | 46 | $ModuleName = ($P1 -split '/')[-1] 47 | $tempDir = Join-Path $tmpRoot $ModuleName 48 | if (!(Test-Path $tempDir)) { 49 | Write-Verbose -Message "$(Get-Date -f T) creating directory $tempDir" 50 | New-Item $tempDir -ItemType Directory -Force | Out-Null 51 | } elseif (Get-ChildItem $tempDir -Force) { 52 | Write-Verbose -Message "$(Get-Date -f T) deleting content of temp directory $tempDir" 53 | Remove-Item (Join-Path $tempDir '*') -Recurse -Force 54 | } 55 | Write-Verbose -Message "$(Get-Date -f T) cloning repository to $tempDir" 56 | git clone $P1 --branch $Branch --single-branch $tempDir --quiet 57 | $psd1 = Get-ChildItem $tempDir -Include *.psd1 -Recurse 58 | if (!$psd1) { 59 | # try to make manifest from psm1 file 60 | Write-Verbose -Message "$(Get-Date -f T) manifest not found, searching for root module" 61 | $psm1 = Get-ChildItem $tempDir -Include *.psm1 -Recurse 62 | if ($psm1.FullName -is [string]) { 63 | Write-Verbose -Message "$(Get-Date -f T) root module $($psm1.Name) found" 64 | $psd1File = $psm1.FullName -replace 'psm1$','psd1' 65 | New-ModuleManifest -Path $psd1File -RootModule $psm1.Name -ModuleVersion ([version]::new()) | Out-Null 66 | $psd1 = Get-ChildItem $tempDir -Include *.psd1 -Recurse 67 | } 68 | } 69 | 70 | $psd0 = $psd1 | ? BaseName -eq $ModuleName 71 | if (($psd1 -is [array]) -and (@($psd0).Count -ne 1)) { 72 | $errorText = "$FunctionName found multiple module manifests for $ModuleName" 73 | } elseif (($psd1 -is [array]) -and (@($psd0).Count -eq 1)) { 74 | $ModuleVersion = (Get-Content -Raw $psd0.FullName | Invoke-Expression).ModuleVersion 75 | $errorText = $null 76 | $psd1 = $psd0 77 | } elseif (!($psd1.FullName -is [string])) { 78 | $errorText = "$FunctionName found no module manifest for $ModuleName" 79 | } else { 80 | $ModuleVersion = (Get-Content -Raw $psd1.FullName | Invoke-Expression).ModuleVersion 81 | $errorText = $null 82 | } 83 | 84 | if ($KeepTempCopy) { 85 | Write-Verbose -Message "$(Get-Date -f T) not deleting temp copy" 86 | } else { 87 | Write-Verbose -Message "$(Get-Date -f T) deleting temp copy" 88 | Remove-Item $tempDir -Force -Recurse -ea 0 | Out-Null 89 | } 90 | 91 | if ($errorText) { 92 | # we need to throw the error after deleting temp directory 93 | Write-Error $errorText 94 | continue 95 | } 96 | 97 | # return value 98 | Write-Verbose -Message "$(Get-Date -f T) preparing return value" 99 | [PSCustomObject]@{ 100 | Name = $ModuleName 101 | Version = $ModuleVersion 102 | LocalPath = if ($KeepTempCopy) {$tempDir} else {$null} 103 | Root = ((Split-Path $psd1.FullName -Parent) -eq $tempDir) 104 | SameName = ($psd1.BaseName -eq $ModuleName) 105 | ManifestName = $psd1.BaseName 106 | GitPath = $P1 107 | } 108 | } 109 | } 110 | 111 | END { 112 | Write-Verbose -Message "$(Get-Date -f G) $FunctionName completed" 113 | } 114 | 115 | } -------------------------------------------------------------------------------- /Public/Install-GitModule.ps1: -------------------------------------------------------------------------------- 1 | function Install-GitModule { 2 | 3 | [CmdletBinding(HelpUri='https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Install-GitModule.md')] 4 | 5 | param ( 6 | 7 | 8 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 9 | [string[]]$ProjectUri, 10 | # https://github.com/dfinke/InstallModuleFromGitHub 11 | # https://github.com/iricigor/FIFA2018 12 | 13 | [string]$Branch = "master", 14 | [string]$DestinationPath = (Get-InstallPath), 15 | [switch]$Force 16 | 17 | ) 18 | 19 | BEGIN { 20 | $FunctionName = $MyInvocation.MyCommand.Name 21 | Write-Verbose -Message "$(Get-Date -f G) $FunctionName starting" 22 | 23 | if (!(Test-Prerequisites)) { 24 | throw "$FunctionName prerequisites not met" 25 | # TODO: Add more details 26 | } 27 | 28 | $tmpRoot = [System.IO.Path]::GetTempPath() 29 | 30 | $PSModulePaths = $env:PSModulePath -split (';:'[[int]($IsLinux -or $IsMacOS)]) 31 | if ($DestinationPath -notin $PSModulePaths) { 32 | Write-Warning -Message "$FunctionName using path which is not in `$Env:PSModulePath ($DestinationPath)" 33 | } 34 | 35 | 36 | } 37 | 38 | PROCESS { 39 | 40 | foreach ($P1 in $ProjectUri) { 41 | 42 | Write-Verbose -Message "$(Get-Date -f T) processing $P1" 43 | 44 | $ModuleInfo = Get-GitModule -ProjectUri $P1 -KeepTempCopy 45 | if (!$ModuleInfo -or ($ModuleInfo.Count -gt 1)) {continue} # we have the error in get-gitmodule 46 | 47 | Install-ModuleInfo -ModuleInfo $ModuleInfo -DestinationPath $DestinationPath -Force:$Force 48 | } 49 | } 50 | 51 | END { 52 | Write-Verbose -Message "$(Get-Date -f G) $FunctionName completed" 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /Public/Update-GitModule.ps1: -------------------------------------------------------------------------------- 1 | function Update-GitModule { 2 | 3 | [CmdletBinding(HelpUri='https://github.com/iricigor/InstallModuleFromGit/blob/master/Docs/Update-GitModule.md')] 4 | 5 | param ( 6 | 7 | 8 | [Parameter(Mandatory,ValueFromPipelineByPropertyName,Position=0,ParameterSetName='ByUri')] 9 | [string[]]$ProjectUri, 10 | # https://github.com/dfinke/InstallModuleFromGitHub 11 | # https://github.com/iricigor/FIFA2018 12 | 13 | [Parameter(Mandatory,ParameterSetName='ByName')] 14 | [string[]]$Name, 15 | 16 | [string]$Branch = "master", 17 | [string]$DestinationPath = (Get-InstallPath), 18 | [switch]$Force 19 | 20 | ) 21 | 22 | BEGIN { 23 | $FunctionName = $MyInvocation.MyCommand.Name 24 | Write-Verbose -Message "$(Get-Date -f G) $FunctionName starting" 25 | 26 | if (!(Test-Prerequisites)) { 27 | throw "$FunctionName prerequisites not met" 28 | # TODO: Add more details 29 | } 30 | 31 | if ($env:AGENT_TEMPDIRECTORY) { 32 | $tmpRoot = $env:AGENT_TEMPDIRECTORY 33 | } else { 34 | $tmpRoot = [System.IO.Path]::GetTempPath() 35 | } 36 | 37 | if ($Name) {$ProjectUri = ConvertTo-Uri -Name $Name} 38 | 39 | } 40 | 41 | PROCESS { 42 | 43 | foreach ($P1 in $ProjectUri) { 44 | 45 | Write-Verbose -Message "$(Get-Date -f T) processing $P1" 46 | 47 | $RemoteModuleInfo = Get-GitModule -ProjectUri $P1 -KeepTempCopy 48 | if (!$RemoteModuleInfo -or ($RemoteModuleInfo.Count -gt 1)) {continue} # we have the error in get-gitmodule 49 | $ModuleName = $RemoteModuleInfo.Name 50 | 51 | # TODO: continue only after cleanup! 52 | 53 | # Check version, and if higher install it 54 | $AllModules = @( 55 | (Get-Module -Name $ModuleName -ListAvailable), 56 | (Get-InstalledModule -Name $ModuleName -ErrorAction SilentlyContinue) 57 | ) | Select Name, Version 58 | $LocalModuleInfo = $AllModules | Sort-Object Version -Descending | Select -First 1 59 | if (!$LocalModuleInfo) { 60 | Write-Error "$FunctionName cannot find local module '$ModuleName'" 61 | continue 62 | } 63 | if ($LocalModuleInfo.Version -ge $RemoteModuleInfo.Version) { 64 | Write-Verbose "$(Get-Date -f T) not updating module '$ModuleName', local version $($LocalModuleInfo.Version), remote version $($RemoteModuleInfo.Version)" 65 | } else { 66 | Install-ModuleInfo -ModuleInfo $RemoteModuleInfo -DestinationPath $DestinationPath -Force:$Force 67 | } 68 | } 69 | } 70 | 71 | END { 72 | Write-Verbose -Message "$(Get-Date -f G) $FunctionName completed" 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ![github/release](https://img.shields.io/github/release/iricigor/InstallModuleFromGit.svg) ![last-release-date](https://img.shields.io/github/release-date/iricigor/InstallModuleFromGit.svg) ![commits-since-latest](https://img.shields.io/github/commits-since/iricigor/InstallModuleFromGit/latest.svg) ![last-commit](https://img.shields.io/github/last-commit/iricigor/InstallModuleFromGit.svg) 4 | 5 | # Install Module from Git 6 | 7 | :bowtie: This PowerShell module will help you to easily instal PowerShell modules directly from [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/repos/) (_aka VSTS_) or [GitHub](https://github.com/) or any other git repository. 8 | All you need to know is a URL of the git repository and the module will take care of everything else. 9 | 10 | The module is compatible both with **Linux** and **Windows** versions of PowerShell _(Windows PowerShell 5 or PowerShell Core 6)_. 11 | 12 | ## Prerequisites 13 | 14 | :exclamation: **Git** client must be installed and available on path. 15 | If you don't have it, you can get it for example from [git-scm.com](https://git-scm.com/downloads). 16 | You can check if you have it by running `Get-Command git` in your PowerShell. 17 | 18 | ## Installation 19 | 20 | ### From PowerShell gallery 21 | 22 | This is recommended way how to install module. [![downloads](https://img.shields.io/powershellgallery/dt/InstallModuleFromGit.svg?label=downloads&logo=PowerShell)](https://www.powershellgallery.com/packages/InstallModuleFromGit) 23 | 24 | ```PowerShell 25 | Install-Module InstallModuleFromGit -Scope CurrentUser 26 | ``` 27 | 28 | ### Clone GitHub repository 29 | 30 | ```PowerShell 31 | git clone https://github.com/iricigor/InstallModuleFromGit 32 | Import-Module ./InstallModuleFromGit/InstallModuleFromGit.psd1 33 | ``` 34 | 35 | ### Using this module 36 | 37 | If you have this module already installed, you can install latest / not-yet-published version from this GitHUb repository using the module itself! 38 | As all commits are verified before and after they are merged to master branch, this should be pretty safe operation also. 39 | 40 | ```PowerShell 41 | Install-GitModule https://github.com/iricigor/InstallModuleFromGit 42 | ``` 43 | 44 | ## Examples 45 | 46 | ```PowerShell 47 | # Check for module existence and its version 48 | PS:\> Get-GitModule 'https://github.com/iricigor/FIFA2018' -Verbose 49 | 50 | # Download and import module in one line 51 | PS:\> (Install-GitModule 'https://github.com/iricigor/psaptgetupdate').Name | Import-Module 52 | ``` 53 | 54 | ## Commands 55 | 56 | ### Module 57 | 58 | The module Install Module From Git exposes two new commandlets. More info on module [here](/Docs/InstallModuleFromGit.md). 59 | 60 | ### Get-GitModule 61 | 62 | Checks for module existence and returns its version. More info [here](/Docs/Get-GitModule.md). 63 | 64 | ### Install-GitModule 65 | 66 | Installs PowerShell module to user's default install folder. More info [here](/Docs/Install-GitModule.md). 67 | 68 | ### Update-GitModule 69 | 70 | Updates previously installed PowerShell module if Git repository contains newer version. More info [here](/Docs/Update-GitModule.md). 71 | 72 | ### Commands Help System 73 | 74 | Module provides updatable help system, though it is working currently only on Windows PowerShell. Tracking issue is [here](https://github.com/iricigor/InstallModuleFromGit/issues/3). 75 | 76 | ```PowerShell 77 | Update-Help -Module InstallModuleFromGit -Force 78 | ``` 79 | 80 | ## Tests 81 | 82 | :smirk: Module has testing against two platforms - Linux and Windows. Code is verified before and after merging to master branch. Tests results are available on the Tests tab ([example here](/img/TestResults-AzureDevops.png)). 83 | 84 | ![supported-OS](https://img.shields.io/powershellgallery/p/InstallModuleFromGit.svg?style=popout&logo=PowerShell) [![test-details](https://img.shields.io/azure-devops/tests/iiric/PS1/16.svg?style=popout&logo=Windows&logoColor=blue)](https://dev.azure.com/iiric/PS1/_build/latest?definitionId=16&branchName=master) [![test-details](https://img.shields.io/azure-devops/tests/iiric/PS1/17.svg?style=popout&logo=Linux&logoColor=black)](https://dev.azure.com/iiric/PS1/_build/latest?definitionId=17&branchName=master) 85 | 86 | _Click on images to see details about the latest build runs._ 87 | 88 | ## Similar PowerShell modules 89 | 90 | - :mega: [dfinke](https://github.com/dfinke)/[InstallModuleFromGitHub](https://github.com/dfinke/InstallModuleFromGitHub), (pluses) does not require git client, (minuses) works only with GitHub 91 | 92 | ## Support 93 | 94 | You can chat about this commandlet via [Skype](https://www.skype.com) _(no Skype ID required)_, by clicking a link below. 95 | 96 | [![chat on Skype](https://img.shields.io/badge/chat-on%20Skype-blue.svg?style=popout&logo=Skype)](https://join.skype.com/hQMRyp7kwjd2) 97 | 98 | ## Contributing 99 | 100 | If you find any problems, feel free to open a new issue. 101 | 102 | [![open a new issue](https://img.shields.io/badge/open%20new-issue-success.svg?logo=GitHub&logoColor=black)](https://github.com/iricigor/InstallModuleFromGit/issues/new) 103 | ![GitHub open issues](https://img.shields.io/github/issues/iricigor/InstallModuleFromGit.svg?style=flat) 104 | ![GitHub closed issues](https://img.shields.io/github/issues-closed/iricigor/InstallModuleFromGit.svg?style=flat) 105 | 106 | If you want to contribute, please fork the code and make a new PR after! 107 | 108 | ![GitHub](https://img.shields.io/github/license/iricigor/InstallModuleFromGit.svg?style=flat) 109 | ![GitHub top language](https://img.shields.io/github/languages/top/iricigor/InstallModuleFromGit.svg?style=flat) 110 | ![repo-stars](https://img.shields.io/github/stars/iricigor/InstallModuleFromGit.svg) 111 | ![repo-watchers](https://img.shields.io/github/watchers/iricigor/InstallModuleFromGit.svg) 112 | -------------------------------------------------------------------------------- /Tests/functions/Get-GitModule.Tests.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # This is a PowerShell Unit Test file. 3 | # You need a unit test framework such as Pester to run PowerShell Unit tests. 4 | # You can download Pester from http://go.microsoft.com/fwlink/?LinkID=534084 5 | # 6 | 7 | $CommandName = 'Get-GitModule' 8 | 9 | Describe "$CommandName basic testing" -Tag 'Functionality' { 10 | 11 | $moduleName = 'FIFA2018' 12 | $moduleURL = 'https://github.com/iricigor/' + $moduleName 13 | 14 | It "$CommandName does not throw an exception" { 15 | {Get-GitModule $moduleURL} | Should -Not -Throw 16 | } 17 | 18 | It "$CommandName returns some value" { 19 | Get-GitModule $moduleURL | Should -Not -Be $null 20 | } 21 | 22 | It "$CommandName returns proper value" { 23 | (Get-GitModule $moduleURL).Name | Should -Be $moduleName 24 | } 25 | 26 | It "$CommandName properly parses retrieved module" { 27 | (Get-GitModule $moduleURL).SameName | Should -Be $true 28 | } 29 | 30 | $moduleName = 'HBOParser' 31 | $moduleURL = 'https://github.com/iricigor/' + $moduleName 32 | It "$CommandName reads repository without psd1" { 33 | (Get-GitModule $moduleURL).Name | Should -Be $moduleName 34 | } 35 | 36 | $moduleName = 'FIFA2018' 37 | Install-Module -Name $moduleName -Repository PSGallery -Scope CurrentUser -Force 38 | It "$CommandName finds module $moduleName by name" { 39 | (Get-GitModule -Name $moduleName).Name | Should -Be $moduleName 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Tests/functions/Install-GitModule.Tests.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # This is a PowerShell Unit Test file. 3 | # You need a unit test framework such as Pester to run PowerShell Unit tests. 4 | # You can download Pester from http://go.microsoft.com/fwlink/?LinkID=534084 5 | # 6 | 7 | $CommandName = 'Install-GitModule' 8 | 9 | Describe "$CommandName basic testing" -Tag 'Functionality' { 10 | 11 | $moduleName = 'psaptgetupdate' 12 | $moduleURL = 'https://github.com/iricigor/' + $moduleName 13 | 14 | It "$CommandName does not throw an exception" { 15 | {Install-GitModule $moduleURL -Force} | Should -Not -Throw 16 | } 17 | 18 | It "$CommandName returns some value" { 19 | Install-GitModule $moduleURL -Force | Should -Not -Be $null 20 | } 21 | 22 | It "$CommandName returns proper value" { 23 | (Install-GitModule $moduleURL -Force).Name | Should -Be $moduleName 24 | } 25 | 26 | It "$CommandName really installs module" { 27 | Get-Module $moduleName -ListAvailable | Should -Not -Be $null 28 | } 29 | } -------------------------------------------------------------------------------- /Tests/functions/Update-GitModule.Tests.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # This is a PowerShell Unit Test file. 3 | # You need a unit test framework such as Pester to run PowerShell Unit tests. 4 | # You can download Pester from http://go.microsoft.com/fwlink/?LinkID=534084 5 | # 6 | 7 | $CommandName = 'Update-GitModule' 8 | 9 | Describe "$CommandName basic testing" -Tag 'Functionality' { 10 | 11 | 12 | $moduleName = 'FIFA2018' 13 | $moduleURL = 'https://github.com/iricigor/' + $moduleName 14 | 15 | $ExistingModule = Get-InstalledModule $moduleName -ea 0 16 | It 'Should uninstall module if installed' -Skip:($ExistingModule -eq $null) { 17 | {Uninstall-Module $moduleName} | Should -Not -Throw 18 | } 19 | 20 | # its not so easy to remove PowerShell module 21 | $ExistingModule = Get-Module $moduleName -ListAvailable 22 | It 'Should delete module if still found' -Skip:($ExistingModule -eq $null) { 23 | {Split-Path ($ExistingModule.Path) -Parent | Remove-Item -Force -Recurse} | Should -Not -Throw 24 | } 25 | 26 | It 'Should install module from PSGallery' { 27 | $OldProgressPreference = $ProgressPreference 28 | $ProgressPreference = 'SilentlyContinue' 29 | {Install-Module $moduleName -Repository PSGallery -Scope CurrentUser -Force} | Should -Not -Throw 30 | $ProgressPreference = $OldProgressPreference 31 | } 32 | 33 | It 'Should update module to newer version' { 34 | Update-GitModule -ProjectUri $moduleURL -Force | Should -Not -Be $null 35 | } 36 | 37 | } 38 | 39 | Describe "$CommandName byName testing" -Tag 'Functionality' { 40 | 41 | 42 | $moduleName = 'FIFA2018' 43 | $moduleURL = 'https://github.com/iricigor/' + $moduleName 44 | 45 | $ExistingModule = Get-InstalledModule $moduleName -ea 0 46 | It 'Should uninstall again module if installed' -Skip:($ExistingModule -eq $null) { 47 | {Uninstall-Module $moduleName} | Should -Not -Throw 48 | } 49 | 50 | # its not so easy to remove PowerShell module 51 | $ExistingModule = Get-Module $moduleName -ListAvailable 52 | It 'Should delete again module if still found' -Skip:($ExistingModule -eq $null) { 53 | {Split-Path ($ExistingModule.Path) -Parent | Remove-Item -Force -Recurse} | Should -Not -Throw 54 | } 55 | 56 | It 'Should install again module from PSGallery' { 57 | $OldProgressPreference = $ProgressPreference 58 | $ProgressPreference = 'SilentlyContinue' 59 | {Install-Module $moduleName -Repository PSGallery -Scope CurrentUser -Force} | Should -Not -Throw 60 | $ProgressPreference = $OldProgressPreference 61 | } 62 | 63 | It 'Should update module byName to newer version' { 64 | Update-GitModule -Name $moduleName -Force | Should -Not -Be $null 65 | } 66 | 67 | } 68 | 69 | 70 | Describe "$CommandName error handling" -Tag 'Functionality' { 71 | 72 | $moduleName = 'dbatools' 73 | $moduleURL = 'https://github.com/sqlcollaborative/' + $moduleName 74 | 75 | It "Should not update non existing module" -Skip:((Get-Module $moduleName -ListAvailable) -ne $null) { 76 | {Update-GitModule -ProjectUri $moduleURL -ea Stop} | Should -Throw 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /Tests/module/InstallModuleFromGit.Tests.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # This is a PowerShell Unit Test file. 3 | # You need a unit test framework such as Pester to run PowerShell Unit tests. 4 | # You can download Pester from http://go.microsoft.com/fwlink/?LinkID=534084 5 | # 6 | 7 | # 8 | # Import module 9 | # 10 | 11 | $ModuleName = 'InstallModuleFromGit' 12 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path # Tests/Module folder 13 | $root = (get-item $here).Parent.Parent.FullName # module root folder 14 | Import-Module (Join-Path $root "$ModuleName.psd1") -Force 15 | 16 | 17 | # 18 | # Fake test 19 | # 20 | 21 | Describe "Fake-Test" -Tag 'Other' { 22 | It "Should be fixed by developer" { 23 | $true | Should -Be $true 24 | } 25 | } 26 | 27 | 28 | # 29 | # Module manifest should have proper format 30 | # 31 | 32 | Describe 'Proper Module Declaration' -Tag 'Documentation' { 33 | 34 | $ModuleManifestFile = "$root/$ModuleName.psd1" 35 | It 'Module manifest can be parsed' { 36 | {Test-ModuleManifest $ModuleManifestFile} | Should -Not -Throw 37 | } 38 | 39 | $ModuleManifest = Test-ModuleManifest $ModuleManifestFile 40 | $ModuleVersion = $ModuleManifest.Version 41 | It 'Module version must be x.y.z' { 42 | ($ModuleVersion.ToString() -split '\.').Count -ge 3 | Should -Be $true -Because "Module with version $ModuleVersion cannot exist online" 43 | } 44 | 45 | It "Checks online for module version $ModuleVersion" { 46 | Find-Module $ModuleName -Repository PSGallery -RequiredVersion $ModuleVersion -ea 0 | Should -Be $null 47 | } 48 | } 49 | 50 | 51 | # 52 | # Module should import three functions 53 | # 54 | 55 | 56 | Describe 'Proper Functions Declaration' -Tag 'Other' { 57 | 58 | It 'Checks for existence of functions' { 59 | @(Get-Command -Module $ModuleName -CommandType Function).Count | Should -Be 3 -Because 'We should have two functions defined' 60 | Get-Command NonExistingCommand -ea 0 | Should -Be $Null 61 | Get-Command Get-GitModule -ea 0 | Should -Not -Be $Null 62 | Get-Command Update-GitModule -ea 0 | Should -Not -Be $Null 63 | Get-Command Install-GitModule -ea 0 | Should -Not -Be $Null 64 | } 65 | } 66 | 67 | 68 | Describe 'Proper Documentation' -Tag 'Documentation' { 69 | 70 | Push-Location $root 71 | 72 | It 'Updates documentation and does git diff' { 73 | 74 | # install PlatyPS 75 | # Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force 76 | if (!(Get-Module platyPS -List -ea 0)) {Install-Module platyPS -Force -Scope CurrentUser} 77 | Import-Module platyPS 78 | 79 | # update documentation 80 | Push-Location -Path $root 81 | Update-MarkdownHelp -Path .\Docs -AlphabeticParamsOrder 82 | New-ExternalHelp -Path .\Docs -OutputPath .\en-US -Force 83 | 84 | # test it 85 | $diff = git diff --ignore-space-change .\Docs .\en-US 86 | Pop-Location 87 | $diff | Should -Be $null 88 | } 89 | 90 | $Blank = '{{ Fill .+}}' 91 | foreach ($File in (Get-ChildItem .\Docs)) { 92 | It "Documentation for $($File.Name) should not have blanks" { 93 | Get-Content $File.FullName | Select-String -Pattern $Blank | Should -Be $null 94 | } 95 | } 96 | 97 | Pop-Location 98 | } 99 | 100 | 101 | Describe 'ScriptAnalyzer Tests' -Tag 'Documentation' { 102 | it 'Checks cmdlets and finds no errors' { 103 | # Install PSScriptAnalyzer 104 | if (!(Get-Module PSScriptAnalyzer -List -ea 0)) {Install-Module PSScriptAnalyzer -Force -Scope CurrentUser} 105 | Import-Module PSScriptAnalyzer 106 | # Check code 107 | $SA = Invoke-ScriptAnalyzer -Path $root -Recurse 108 | $SA | where Severity -eq 'Error' | Should -Be $null 109 | } 110 | } -------------------------------------------------------------------------------- /cab/InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_HelpInfo.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | https://github.com/iricigor/InstallModuleFromGit/raw/master/cab/ 4 | 5 | 6 | en-US 7 | 1.0.0.0 8 | 9 | 10 | -------------------------------------------------------------------------------- /cab/InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_en-US_HelpContent.cab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iricigor/InstallModuleFromGit/5f7760e4717e73c3028273e78aebe2b967743376/cab/InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_en-US_HelpContent.cab -------------------------------------------------------------------------------- /cab/InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_en-US_HelpContent.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iricigor/InstallModuleFromGit/5f7760e4717e73c3028273e78aebe2b967743376/cab/InstallModuleFromGit_d6a1577c-e3b5-48f2-a698-f08ab4865a58_en-US_HelpContent.zip -------------------------------------------------------------------------------- /img/InstallModuleFromGit.logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iricigor/InstallModuleFromGit/5f7760e4717e73c3028273e78aebe2b967743376/img/InstallModuleFromGit.logo.png -------------------------------------------------------------------------------- /img/TestResults-AzureDevops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iricigor/InstallModuleFromGit/5f7760e4717e73c3028273e78aebe2b967743376/img/TestResults-AzureDevops.png -------------------------------------------------------------------------------- /tools/InvokeTests.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Script which invokes tests inside of Azure DevOps Pipelines 3 | # 4 | 5 | param ( 6 | # Describes what type of tests to run 7 | [ValidateSet('FunctionalityOnly','DocumentationOnly','All')] 8 | [string]$TestsToRun 9 | ) 10 | 11 | function InstallModule ([string]$Name,[version]$Version,[version]$MaxVersion=$null){ 12 | if ($MaxVersion) { 13 | if (!(Get-Module $Name -List | where Version -ge $Version | where Version -le $MaxVersion)) { 14 | Write-Host "Installing $Name with Max Version $MaxVersion" 15 | Install-Module -Name $Name -Force -SkipPublisherCheck -Scope CurrentUser -Repository PSGallery -MaximumVersion $MaxVersion 16 | } 17 | Import-Module $Name -MaximumVersion $MaxVersion 18 | } else { 19 | if (!(Get-Module $Name -List | where Version -ge $Version)) { 20 | Write-Host "Installing $Name" 21 | Install-Module -Name $Name -Force -SkipPublisherCheck -Scope CurrentUser -Repository PSGallery 22 | } 23 | Import-Module $Name 24 | } 25 | if ($env:TF_BUILD) {Get-Module $Name -List} 26 | } 27 | 28 | # 29 | # Display diagnostic information 30 | # 31 | 32 | if ($env:TF_BUILD) { 33 | $PSVersionTable 34 | Get-ChildItem Env:\ 35 | $Env:PSModulePath -split (';:'[[int]($IsLinux -or $IsMacOS)]) 36 | Get-Module -ListAvailable | Format-Table -Property ModuleType, Name, Version 37 | } 38 | 39 | # 40 | # Install Pester and Platy, if needed 41 | # 42 | 43 | InstallModule Pester '4.0.0' '4.99' 44 | InstallModule PlatyPS '0.14.0' 45 | InstallModule PSScriptAnalyzer '1.17.0' 46 | 47 | 48 | # 49 | # Run Pester Tests 50 | # 51 | 52 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path # tools folder 53 | $root = (get-item $here).Parent.FullName # module root folder 54 | $tests = Join-Path $root 'Tests' # tests folder 55 | 56 | switch ($TestsToRun) { 57 | 'FunctionalityOnly' { $Tags = @('Functionality','Other') } 58 | 'DocumentationOnly' { $Tags = @('Documentation','Other') } 59 | 'All' { $Tags = @('Documentation','Functionality','Other') } 60 | } 61 | 62 | Write-Host "Run Pester tests" 63 | $Result = Invoke-Pester -Path "$tests/module", "$tests/functions" -Tag $Tags -PassThru -OutputFile PesterTestResults.xml 64 | if ($Result.failedCount -ne 0) {Write-Error "Pester returned errors"} 65 | -------------------------------------------------------------------------------- /tools/PublishModule-VSTS.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Script should be executed inside of VSTS pipeline 3 | # 4 | 5 | $ModuleName = 'InstallModuleFromGit' 6 | 7 | if ($Env:TF_BUILD -ne 'True') { 8 | throw 'This script should be executed only from VSTS. Please use the other publishing script.' 9 | } 10 | 11 | 12 | # check running folder 13 | if (Test-Path "..\s\$ModuleName.psd1") { 14 | "Checking module $(Resolve-Path ".\$ModuleName.psd1")" 15 | } else { 16 | throw "We are not in correct folder, please run this tool as .\tools\PublishModule.ps1" 17 | } 18 | 19 | 20 | # test manifest 21 | try { 22 | $Module = Test-ModuleManifest "$ModuleName.psd1" -ea Stop 23 | "Module $ModuleName.psd1 is OK" 24 | } catch { 25 | throw 'Module manifest not in proper format' 26 | } 27 | 28 | 29 | # test version, must be x.y.z 30 | if (($Module.Version.ToString() -split '\.').Count -lt 3) { 31 | throw "Module version must have three segments at least, currently it is $($Module.Version.ToString())" 32 | } else { 33 | "Module version tag '$($Module.Version.ToString())' is OK" 34 | } 35 | 36 | 37 | # test if the module is not already published with same version number 38 | "Checking for module with version $($Module.Version) online..." 39 | if (Find-Module -Name $ModuleName -RequiredVersion ($Module.Version) -Repository PSGallery -ea 0) { 40 | throw 'Module with same version already exists' 41 | } else { 42 | "No module with version $($Module.Version) found online" 43 | } 44 | 45 | 46 | # get publishing key from pipeline or directly 47 | if ($Env:NugetKey) { 48 | "NugetKey found" 49 | } else { 50 | throw 'Please define NugetKey (secret) variable' 51 | } 52 | 53 | # copy entire folder to temp location 54 | if ($IsLinux -or $IsMacOS) {$Destination = '/tmp'} else {$Destination = $Env:TEMP} 55 | $Destination2 = Join-Path $Destination $ModuleName 56 | if (Test-Path $Destination2) {Remove-Item $Destination2 -Recurse -Force} 57 | 58 | "Copying to $Destination2" 59 | New-Item -Path $Destination2 -ItemType Directory | Out-Null 60 | Get-ChildItem -Force | Copy-Item -Destination $Destination2 -Container -Recurse 61 | "`nverifying content of $Destination2" 62 | Get-ChildItem $Destination2 -Force 63 | 64 | 65 | # remove not needed files (as per .publishignore) 66 | "Removing not needed files" 67 | $pwdLength = (Get-Item $Destination2).FullName.Length + 1 # expands 'C:\Users\VSSADM~1\AppData\Local\Temp' 68 | foreach ($line in (Get-Content '.publishignore'| where {$_ -notlike '#*'})) { 69 | "Checking files like $line" 70 | foreach ($file in (Get-ChildItem -Path $Destination2 -Recurse -Force -File)) { 71 | $relativeName = $file.FullName.Substring($pwdLength) -replace '\\','/' 72 | #"$relativeName" 73 | if ($relativeName -like $line) { 74 | "Removing $relativeName" 75 | Remove-Item $file.FullName -Recurse -Force 76 | } 77 | } 78 | } 79 | 80 | 81 | # publish 82 | "Publishing total of $((Get-ChildItem $Destination2 -Recurse -File).Count) files" 83 | Get-ChildItem $Destination2 -Recurse -File 84 | if ($Env:ModuleVersionToPublish -eq $Module.Version) { 85 | Publish-Module -Path $Destination2 -Repository PSGallery -NuGetApiKey $Env:NugetKey -Verbose 86 | "Module $ModuleName published to PowerShell Gallery" 87 | } else { 88 | throw "Mismatching module versions $($Env:ModuleVersionToPublish) and $($Module.Version), please update pipeline variable ModuleVersionToPublish" 89 | } 90 | -------------------------------------------------------------------------------- /tools/PublishModule.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Script should be executed manually by developer 3 | # 4 | 5 | $ModuleName = 'InstallModuleFromGit' 6 | 7 | if ($Env:TF_BUILD -eq 'True') { 8 | throw 'This script should not be executed from VSTS. Please use dedicated script for that.' 9 | } 10 | 11 | 12 | # check running folder 13 | if (Test-Path "..\$ModuleName\$ModuleName.psd1") { 14 | "Checking module $(Resolve-Path ".\$ModuleName.psd1")" 15 | } else { 16 | throw "We are not in correct folder, please run this tool as .\tools\PublishModule.ps1" 17 | } 18 | 19 | 20 | # test manifest 21 | try { 22 | $Module = Test-ModuleManifest "$ModuleName.psd1" -ea Stop 23 | "Module $ModuleName.psd1 is OK" 24 | } catch { 25 | throw 'Module manifest not in proper format' 26 | } 27 | 28 | 29 | # test version, must be x.y.z 30 | if (($Module.Version.ToString() -split '\.').Count -lt 3) { 31 | throw "Module version must have three segments at least, currently it is $($Module.Version.ToString())" 32 | } else { 33 | "Module version tag '$($Module.Version.ToString())' is OK" 34 | } 35 | 36 | 37 | # test if the module is not already published with same version number 38 | "Checking for module with version $($Module.Version) online..." 39 | if (Find-Module -Name $ModuleName -RequiredVersion ($Module.Version) -Repository PSGallery -ea 0) { 40 | throw 'Module with same version already exists' 41 | } else { 42 | "No module with version $($Module.Version) found online" 43 | } 44 | 45 | 46 | # get publishing key 47 | if ($NugetKey) { 48 | "NugetKey found" 49 | } else { 50 | throw 'Please define $NugetKey variable (run $NugetKey = Read-Host)' 51 | } 52 | 53 | 54 | # copy entire folder to temp location 55 | if ($IsLinux -or $IsMacOS) {$Destination = '/tmp'} else {$Destination = $Env:TEMP} 56 | $Destination2 = Join-Path $Destination $ModuleName 57 | if (Test-Path $Destination2) {Remove-Item $Destination2 -Recurse -Force} 58 | 59 | "Copying to $Destination2" 60 | Copy-Item -Path . -Destination $Destination -Recurse # it creates folder $ModuleName 61 | 62 | 63 | # remove not needed files (as per .publishignore) 64 | "Removing not needed files" 65 | $pwdLength = (Get-Item $Destination2).FullName.Length + 1 # expands 'C:\Users\VSSADM~1\AppData\Local\Temp' 66 | foreach ($line in (Get-Content '.publishignore'| where {$_ -notlike '#*'})) { 67 | "Checking files like $line" 68 | foreach ($file in (Get-ChildItem -Path $Destination2 -Recurse -Force -File)) { 69 | $relativeName = $file.FullName.Substring($pwdLength) -replace '\\','/' 70 | #"$relativeName" 71 | if ($relativeName -like $line) { 72 | "Removing $relativeName" 73 | Remove-Item $file.FullName -Recurse -Force 74 | } 75 | } 76 | } 77 | 78 | # publish 79 | "Publishing total of $((Get-ChildItem $Destination2 -Recurse -File).Count) files" 80 | Read-Host "All prerequisites check. Press Enter to Publish module or Ctrl+C to abort" 81 | Publish-Module -Path $Destination2 -Repository PSGallery -NuGetApiKey $NugetKey -Verbose 82 | "Module $ModuleName published to PowerShell Gallery" 83 | -------------------------------------------------------------------------------- /tools/UpdateHelp.ps1: -------------------------------------------------------------------------------- 1 | break # seat-belt 2 | $ModuleName='InstallModuleFromGit' 3 | 4 | if (!(Test-Path '.\Docs')) { 5 | throw 'Please run this as .\tools\UpdateHelps.ps1' 6 | } 7 | 8 | # just initial time, or with good backup, run next command 9 | # New-MarkdownHelp -Module InstallModuleFromGit -OutputFolder .\Docs -WithModulePage -Force 10 | 11 | New-ExternalHelp -Path .\Docs\ -OutputPath .\Docs\ -Force 12 | New-ExternalHelpCab -CabFilesFolder .\Docs\ -LandingPagePath ".\Docs\$ModuleName.md" -OutputFolder .\cab\ 13 | Update-Help -Module $ModuleName -Verbose --------------------------------------------------------------------------------