Skip to content

Commit

Permalink
Added task Create_Release_Git_Tag (#380)
Browse files Browse the repository at this point in the history
  • Loading branch information
johlju authored May 28, 2022
1 parent 1430b37 commit 6e032d1
Show file tree
Hide file tree
Showing 6 changed files with 559 additions and 0 deletions.
183 changes: 183 additions & 0 deletions .build/tasks/Create_Release_Git_Tag.build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<#
.SYNOPSIS
This build task creates and pushes a preview release tag to the default
branch.
.DESCRIPTION
This build task creates and pushes a preview release tag to the default
branch.
This task is primarily meant to be used for SCM's that does not have
releases that connects to tags like GitHub does with GitHub Releases, but
this task can also be used as an alternative when using GitHub as SCM.
.PARAMETER ProjectPath
The root path to the project. Defaults to $BuildRoot.
.PARAMETER OutputDirectory
The base directory of all output. Defaults to folder 'output' relative to
the $BuildRoot.
.PARAMETER BuiltModuleSubdirectory
The parent path of the module to be built.
.PARAMETER VersionedOutputDirectory
If the module should be built using a version folder, e.g. ./MyModule/1.0.0.
Defaults to $true.
.PARAMETER ProjectName
The project name.
.PARAMETER SourcePath
The path to the source folder.
.PARAMETER SkipPublish
If publishing should be skipped. Defaults to $false.
.PARAMETER MainGitBranch
The name of the default branch. Defaults to 'main'.
.PARAMETER RepositoryPAT
The personal access token used for accessing hte Git repository.
.PARAMETER BuildInfo
The build info object from ModuleBuilder. Defaults to an empty hashtable.
.NOTES
This is a build task that is primarily meant to be run by Invoke-Build but
wrapped by the Sampler project's build.ps1 (https://github.com/gaelcolas/Sampler).
#>
param
(
[Parameter()]
[System.String]
$ProjectPath = (property ProjectPath $BuildRoot),

[Parameter()]
[System.String]
$OutputDirectory = (property OutputDirectory (Join-Path $BuildRoot 'output')),

[Parameter()]
[System.String]
$BuiltModuleSubdirectory = (property BuiltModuleSubdirectory ''),

[Parameter()]
[System.Management.Automation.SwitchParameter]
$VersionedOutputDirectory = (property VersionedOutputDirectory $true),

[Parameter()]
[System.String]
$ProjectName = (property ProjectName ''),

[Parameter()]
[System.String]
$SourcePath = (property SourcePath ''),

[Parameter()]
$SkipPublish = (property SkipPublish ''),

[Parameter()]
$MainGitBranch = (property MainGitBranch 'main'),

[Parameter()]
$RepositoryPAT = (property RepositoryPAT ''),

[Parameter()]
[string]
$GitConfigUserEmail = (property GitConfigUserEmail ''),

[Parameter()]
[string]
$GitConfigUserName = (property GitConfigUserName ''),

[Parameter()]
$BuildInfo = (property BuildInfo @{ })
)

# Synopsis: Creates a git tag for the release that is published to a Gallery
task Create_Release_Git_Tag {
if ($SkipPublish)
{
Write-Build Yellow ('Skipping the creating of a tag for module version ''{0}'' since ''$SkipPublish'' was set to ''$true''.' -f $ModuleVersion)

return
}

. Set-SamplerTaskVariable

<#
This will return the tag on the HEAD commit, or blank if it
fails (the error that is catched to $null).
This call should not use Invoke-SamplerGit since it should not throw
on error, but return $null if failing.
#>
$isCurrentTag = git describe --contains 2> $null

if ($isCurrentTag)
{
Write-Build Green ('Found a tag. Assuming a full release has been pushed for module version ''{0}''. Exiting.' -f $ModuleVersion)
}
else
{
Write-Build DarkGray ('About to create the tag ''{0}'' for module version ''{1}''.' -f $releaseTag, $ModuleVersion)

foreach ($gitConfigKey in @('UserName', 'UserEmail'))
{
$gitConfigVariableName = 'GitConfig{0}' -f $gitConfigKey

if (-not (Get-Variable -Name $gitConfigVariableName -ValueOnly -ErrorAction 'SilentlyContinue'))
{
# Variable is not set in context, use $BuildInfo.ChangelogConfig.<varName>
$configurationValue = $BuildInfo.GitConfig.($gitConfigKey)

Set-Variable -Name $gitConfigVariableName -Value $configurationValue

Write-Build DarkGray "`t...Set property $gitConfigVariableName to the value $configurationValue"
}
}

Write-Build DarkGray "`tSetting git configuration."

Sampler\Invoke-SamplerGit -Argument @('config', 'user.name', $GitConfigUserName)
Sampler\Invoke-SamplerGit -Argument @('config', 'user.email', $GitConfigUserEmail)

# Make empty line in output
""

$releaseTag = 'v{0}' -f $ModuleVersion

Write-Build DarkGray ("`tGetting HEAD commit for the default branch '{0}." -f $MainGitBranch)

$defaultBranchHeadCommit = Sampler\Invoke-SamplerGit -Argument @('rev-parse', "origin/$MainGitBranch")

Write-Build DarkGray ("`tCreating tag '{0}' on the commit '{1}'." -f $releaseTag, $defaultBranchHeadCommit)

Sampler\Invoke-SamplerGit -Argument @('tag', $releaseTag, $defaultBranchHeadCommit)

Write-Build DarkGray ("`tPushing created tag '{0}' to the default branch '{1}'." -f $releaseTag, $MainGitBranch)

$pushArguments = @()

if ($RepositoryPAT)
{
Write-Build DarkGray "`t`tUsing personal access token to push the tag."

$patBase64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(('{0}:{1}' -f 'PAT', $RepositoryPAT)))

$pushArguments += @('-c', ('http.extraheader="AUTHORIZATION: basic {0}"' -f $patBase64))
}

$pushArguments += @('-c', 'http.sslbackend="schannel"', 'push', 'origin', '--tags')

Sampler\Invoke-SamplerGit -Argument $pushArguments

<#
Wait for a few seconds so the tag have time to propegate.
This way next task have chance to find the tag.
#>
Start-Sleep -Seconds 5

Write-Build Green 'Tag created and pushed.'
}
}
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
no security.
- Now supports getting module version from `dotnet-gitversion` if it is available.
- Tests now run in Pester 5.
- Added task `Create_Release_Git_Tag` to create a Git tag for a preview release.
Fixes [#351](https://github.com/gaelcolas/Sampler/issues/351)

### Changed

Expand Down
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,31 @@ Add-Sample -Sample PublicFunction -PublicFunctionName Get-MyStuff
This example adds a public function to the module (in the current folder),
with a sample unit test that test the public function.

### `Invoke-SamplerGit`

This command executes git with the provided arguments and throws an error
if the call failed.

#### Syntax

<!-- markdownlint-disable MD013 - Line length -->
```plaintext
Invoke-SamplerGit [-Argument] <string[]> [<CommonParameters>]
```
<!-- markdownlint-enable MD013 - Line length -->

#### Outputs

[System.String]

#### Example

```powershell
Invoke-SamplerGit -Argument @('config', 'user.name', 'MyName')
```

Calls git to set user name in the git config.

### `New-SampleModule`

This command helps you scaffold your PowerShell module project by creating
Expand Down Expand Up @@ -1423,3 +1448,53 @@ THe path to the release notes markdown file. Defaults to the path for
The path to the source folder. Defaults to the same path where the module
manifest is found in either the folder 'source', 'src', or a folder with
the same name as the module.

## Tasks

### `Create_Release_Git_Tag`

This build task creates and pushes a preview release tag to the default branch.

>Note: This task is primarily meant to be used for SCM's that does not have
>releases that connects to tags like GitHub does with GitHub Releases, but
>this task can also be used as an alternative when using GitHub as SCM.
This is an example of how to use the task in the _build.yaml_ file:

```yaml
publish:
- Create_Release_Git_Tag
```
#### Task parameters
Some task parameters are vital for the resource to work. See comment based
help for the description for each available parameter. Below is the most
important.
#### Task configuration
The build configuration (_build.yaml_) can be used to control the behavior
of the build task.
```yaml
####################################################
# Git Configuration #
####################################################
GitConfig:
UserName: bot
UserEmail: [email protected]
```
#### Section GitConfig
This configures git. user name and e-mail address of the user before task pushes the
tag.
##### Property UserName
User name of the user that should push the tag.
##### Property UserEmail
E-mail address of the user that should push the tag.
56 changes: 56 additions & 0 deletions Sampler/Public/Invoke-SamplerGit.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<#
.SYNOPSIS
Executes git with the provided arguments.
.DESCRIPTION
This command executes git with the provided arguments and throws an error
if the call failed.
.PARAMETER Argument
Specifies the arguments to call git with. It is passes as an array of strings,
e.g. @('tag', 'v2.0.0').
.EXAMPLE
Invoke-SamplerGit -Argument @('config', 'user.name', 'MyName')
Calls git to set user name in the git config.
.NOTES
Git does not throw an error that can be caught by the pipeline. For example
this git command error but does not throw 'hello' as one would expect.
```
PS> try { git describe --contains } catch { throw 'hello' }
fatal: cannot describe '144e0422398e89cc8451ebba738c0a410b628302'
```
So we have to determine if git worked or not by checking the last exit code
and then throw an error to stop the pipeline.
#>
function Invoke-SamplerGit
{
param
(
[Parameter(Mandatory = $true)]
[System.String[]]
$Argument
)

# The catch is triggered only if 'git' can't be found.
try
{
& git $Argument
}
catch
{
throw $_
}

<#
This will trigger an error if git returned an error code from the above
execution. Git will also have outputted an error message to the console
so we just need to throw a generic error.
#>
if ($LASTEXITCODE)
{
throw "git returned exit code $LASTEXITCODE indicated failure."
}
}
Loading

0 comments on commit 6e032d1

Please sign in to comment.