I have always been fascinated about productivity and how we as developer can make things less manual.
Today I will show my currently most used custom productivity scripts.
Create Branch and PR in draft mode (github)
This script automates the creation of a new branch and a draft pull request, saving a min that would otherwise be spent creating the PR manually.
It takes three parameters:
- TicketNumber (often required to link the branch to a specific ticket)
- Description (combined with the ticket number to form the branch name and used in the PR description)
- BaseBranch (optional, could be enhanced to automatically detect the main branch)
- It uses a PR template if the repository contains one.
- It relies on the GitHub CLI (gh), which uses its own authentication token instead of a personal access token.
- It adds an empty commit because GitHub requires at least one commit to create a pull request.
function Create-BranchAndPR {
param (
[Parameter(Mandatory = $true)]
[string]$TicketNumber,
[Parameter(Mandatory = $true)]
[string]$Description,
[string]$BaseBranch = "master"
)
try {
# Sanitize the description to create a valid branch name
$sanitizedDescription = $Description -replace '[^a-zA-Z0-9\- ]', '-' -replace '[- ]+', '-'
# Construct the branch name
$branchName = "$TicketNumber-$sanitizedDescription"
# Ensure the base branch is up to date
git checkout $BaseBranch
git pull origin $BaseBranch
# Create and switch to the new branch
git checkout -b $branchName
# Create an initial empty commit
git commit --allow-empty -m "Initial empty commit for $branchName"
# Push the new branch to the remote repository
git push -u origin $branchName
# Prepare the PR title
$TicketNumber = $TicketNumber.ToUpper()
$prTitle = "[$TicketNumber] $Description"
# Define the default PR body
$defaultPrBody = @"
# ${prTitle}
ANY ADDITIONAL DESCRIPTION
"@
# Check if a custom PR template exists
$prTemplatePath = ".github/PULL_REQUEST_TEMPLATE.md"
$customPrBody = if (Test-Path $prTemplatePath) {
Get-Content $prTemplatePath -Raw
}
else {
""
}
# Use the custom PR template if it exists and is not empty; otherwise, use the default
$prBody = if (![string]::IsNullOrWhiteSpace($customPrBody)) {
$customPrBody
}
else {
$defaultPrBody
}
# Create the draft pull request using the specified PR body
$prCreateResult = gh pr create `
--title "${prTitle}" `
--body "$prBody" `
--draft `
--head $branchName `
--base $BaseBranch `
2>&1 # Capture error output
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to create pull request: $prCreateResult"
return
}
Write-Host "Draft pull request created successfully!"
}
catch {
Write-Error "An error occurred: $_"
}
}
Show pull request
A simple script that constructs a URL using the current Git branch and then opens that URL in Chrome (or any other browser).
function Show-PullRequests {
# --------------------------------------------------
# Configurable Variables
# --------------------------------------------------
$organization = "[Enter Organization]" # Used if needed for other org references
$githubOrg = "[Enter github org]" # The GitHub organization or user namespace
$chromePath = "[Enter browser exe]" # For example C:\Program Files\Google\Chrome\Application\chrome.exe
# Use the current directory to determine the project (not strictly required in this script)
$currentDirectory = Get-Location
$directoryName = Split-Path -Leaf $currentDirectory
# Validate the Chrome path
if (-Not (Test-Path $chromePath)) {
Write-Error "Chrome executable not found at path: $chromePath"
exit
}
try {
# Determine the Git root directory
$gitRoot = (& git rev-parse --show-toplevel).Trim()
$repository = Split-Path -Leaf $gitRoot
$project = $repository -split '-' | Select-Object -First 1
# Get the git remote URL
$gitRemote = (& git config --get remote.origin.url).Trim()
if (-Not $gitRemote) {
Write-Error "Could not retrieve git remote URL. Ensure it is configured correctly."
exit
}
# Get the current branch name
$branchName = (git rev-parse --abbrev-ref HEAD).Trim()
if (-Not $branchName -or $branchName -eq "HEAD") {
Write-Error "Could not determine the current branch name. Ensure you are on a branch."
exit
}
# Construct the URL based on the remote type
if ($gitRemote -match "github.com") {
# Handle GitHub URL
$url = "https://github.com/$githubOrg/$repository/compare/$branchName?expand=1"
}
else {
Write-Error "Unsupported git remote URL format: $gitRemote"
exit
}
# Open the URL in Chrome
& $chromePath $url
}
catch {
Write-Error "An error occurred: $_"
exit
}
}
Open solution
This script searches for a solution (.sln) file in the current directory and its subdirectories. It’s handy when you don’t remember the exact name of the solution file and just need to open the single solution in your repository. Although it’s limited if there are multiple .sln files in the folder, in most cases you’ll only have one and won’t need to know its exact name.
function Open-Solution {
[Alias("os")]
Param ([string] $Pattern, [int] $Depth = 2)
if (Test-Path -Path $Pattern -PathType Leaf) {
$ExactMatch = Get-ChildItem $Pattern
Write-Host "Opening $($ExactMatch.Name)..."
Invoke-Expression "& ($ExactMatch.FullName)" | Out-Null
return;
}
$SingleMatch = Get-ChildItem -Recurse -Filter "$Pattern.sln" -Depth $Depth
if ($SingleMatch) {
Write-Host "Opening $($SingleMatch.Name)..."
Invoke-Expression "& ($SingleMatch.FullName)" | Out-Null
return;
}
$MatchingSlnFiles = Get-ChildItem -Recurse -Filter "*$Pattern*.sln" -Depth $Depth
if ($MatchingSlnFiles.Count -eq 0) {
Write-Host "No matching solution found"
return;
}
if ($MatchingSlnFiles.Count -gt 1) {
Write-Host "Multiple matching solutions found:"
$MatchingSlnFiles | ForEach-Object { $_.Name }
return;
}
$matchingSlnFile = $MatchingSlnFiles[0]
Write-Host "Opening $($matchingSlnFile.Name)..."
Invoke-Expression "& $($matchingSlnFile.FullName)" | Out-Null
}
Measure Time
A very simple script which I have use to perform time-measurements when running scripts.
function Measure-Time {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[ScriptBlock]$ScriptBlock
)
# Start the stopwatch
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
try {
# Execute the script block without capturing the output
& $ScriptBlock
}
finally {
# Stop the stopwatch
$stopwatch.Stop()
# Display the execution time
Write-Host "Execution Time: $($stopwatch.Elapsed.TotalSeconds) seconds"
}
}
Usage:
Measure-Time {
# Put the code you want to measure here
Start-Sleep -Seconds 5
}
# Outputs something like: "Execution Time: 5.003 seconds"
Thats pretty much it, happy coding!