<# | |
.SYNOPSIS | |
Convert Git tags to the format required by the DSC Resource module | |
CI Process. | |
.PARAMETER Remote | |
The name of the Git remote repository for your fork. | |
.PARAMETER Upstream | |
The name of the Git remote repository for the upstream fork. | |
.PARAMETER ModuleName | |
The name of the module that will be used in the tag comment. | |
.PARAMETER DeleteOldTags | |
Delete the old tags after they have been converted. | |
#> | |
[CmdletBinding(SupportsShouldProcess=$True)] | |
param ( | |
[Parameter()] | |
[System.String] | |
$Remote = 'origin', | |
[Parameter()] | |
[System.String] | |
$Upstream = 'upstream', | |
[Parameter()] | |
[System.String] | |
$ModuleName = (Get-Location | Split-Path -Leaf), | |
[Parameter()] | |
[Switch] | |
$DeleteOldTags | |
) | |
function Test-GitTag { | |
[CmdletBinding()] | |
[OutputType([System.Boolean])] | |
param ( | |
[Parameter()] | |
[System.String] | |
$Tag | |
) | |
$result = & git @('tag','-l',$Tag) | |
return -not ([System.String]::IsNullOrWhiteSpace($result)) | |
} | |
Write-Verbose -Message "Checking out master branch." | |
& git @('checkout','master') | |
Write-Verbose -Message "Pulling latest tags from '$Upstream'." | |
& git @('pull',$Upstream,'master','--tags') | |
if ($PSCmdlet.ShouldProcess($Remote, "Push tags to '$Remote' master")) | |
{ | |
Write-Verbose -Message "Pushing latest tags to '$Remote'." | |
& git @('push',$Remote,'master','--tags') | |
} | |
$tagRefs = & git @('show-ref','--tags') | |
$backupDatetime = Get-Date -Format FileDateTime | |
$backupGuid = [Guid]::NewGuid().Guid | |
$repoName = Split-Path -Path (Get-Location) -Leaf | |
$backupFile = Join-Path -Path $ENV:Temp -ChildPath "Convert-GitTagForDsc_$($repoName)_$($backupDatetime)_$($backupGuid).txt" | |
$tagRefs | Out-File -FilePath $backupFile | |
Write-Host -Object "A backup of the current tags has been written to '$backupFile'. Use this with the Restore-GitTagForDsc function to restore tags if something goes wrong." -ForegroundColor Yellow | |
foreach ($tagRef in $tagRefs) | |
{ | |
$hash, $ref = $tagRef -split ' ' | |
$tag = ($ref -split '/')[2] | |
Write-Verbose -Message "Begin processing tag '$tag'." | |
if ($tag -match '^v([0-9]+)\.([0-9]+)\.([0-9]+)(\.([0-9]+))?') | |
{ | |
Write-Warning -Message "Tag '$tag' already appears to be in the desired format. Tag will be skipped." | |
break | |
} | |
try { | |
$version = [Version] ($tag -split '-')[0] | |
} | |
catch | |
{ | |
Write-Warning -Message "Error converting tag '$tag' to version string. Tag will be skipped." | |
break | |
} | |
$newTag = 'v' + $version.Major + '.' + $version.Minor + '.' + $version.Build | |
if (Test-GitTag -Tag $newTag) | |
{ | |
Write-Verbose -Message "Tag '$newTag' already exists so skipping create." | |
} | |
else | |
{ | |
$message = "Release of version $version of $ModuleName" | |
if ($PSCmdlet.ShouldProcess($newTag, "Creating tag '$newTag' against '$hash' with message '$message'")) | |
{ | |
Write-Verbose -Message "Creating tag '$newTag' against '$hash' with message '$message'." | |
& git @('tag','-a',$newTag,$hash,'-m',$message) | |
} | |
} | |
if ($DeleteOldTags.IsPresent) | |
{ | |
if (Test-GitTag -Tag $tag) | |
{ | |
if ($PSCmdlet.ShouldProcess($tag, "Deleting tag '$tag' from local")) | |
{ | |
Write-Verbose -Message "Deleting tag '$tag' from local." | |
& git @('tag','-d',$tag) | |
} | |
if ($PSCmdlet.ShouldProcess($tag, "Deleting tag '$tag' from '$Remote'")) | |
{ | |
Write-Verbose -Message "Deleting tag '$tag' from '$Remote'." | |
& git @('push',$Remote,":$tag") | |
} | |
if ($PSCmdlet.ShouldProcess($tag, "Deleting tag '$tag' from '$Upstream'")) | |
{ | |
Write-Verbose -Message "Deleting tag '$tag' from '$Upstream'." | |
& git @('push',$Upstream,":$tag") | |
} | |
} | |
else | |
{ | |
Write-Verbose -Message "Tag '$tag' does not exist so skipping delete." | |
} | |
} | |
} | |
if ($PSCmdlet.ShouldProcess($Remote, "Pushing '$Remote' tags")) | |
{ | |
Write-Verbose -Message "Pushing '$Remote' tags." | |
& git @('push',$Remote,'--tag') | |
} | |
if ($PSCmdlet.ShouldProcess($Upstream, "Pushing '$Upstream' tags")) | |
{ | |
Write-Verbose -Message "Pushing '$Upstream' tags." | |
& git @('push',$Upstream,'--tag') | |
} |
I think it should checkout master so that it does not tag a commit in some other branch, if the commit would happen to exist in another branch? 🤔
Suggest removing the last line since it assumes to have the remotes according to the defaults, and there are no check to see if they exist.
I have added example to run the script to the "Steps" instead.
Ignore the above, there are more things to be done than just checkout master, like getting latest changes of master (rebase) and pulling existing tags.
@johlju - I've updated the script with some of your improvements. I'm about to try it out on NetworkingDsc.
Looks good. I will update the Steps if you see it working.
I added a WhatIf as well. Have successfully run it against NetworkingDsc.
@PlagueHO I have cloned the repos to several computers. If I push a new version tag from another computer I will also push any old tags that I already removed in origin resulting I get back all *PSGallery tags. Unless I remember to push just the one new tag. I suggest this script also supports a new parameter to only clear/remove tags locally that does not exist in upstream. 😄
Ah right! I'll have a think about how I might be able to detect if a tag only exists in the upstream. The git tag -l
command doesn't look like it supports specifying an upstream - it only works on local. Any ideas?
In my case you just need to delete any tags not having the correct format, no need to check if they exist in upstream.
git show
doesn’t seems to take a remote either.
Maybe this works? I haven’t tested, on the phone now https://stackoverflow.com/questions/6294224/check-if-pushed-tag-is-on-the-git-remote/6295385
@PlagueHO Missing closing parenthesis on line 81.