PowerShell script to build and pacakge Go application for release
$begingroup$
Background
I decided to write this PowerShell build script as a gentle introduction to PS. It builds this Go application, which is an internal tool I decided to open source, and not the focus of this review.
This script is used primarily for packaging artifacts for release.
My approach
The script below gets, vets and builds a small Go application and then invokes a separate command-line tool to add Windows rsrc metadata such as version strings and icons.
Since the version number is mandatory for the packaging process, I validated it using param()
rules rather than if
statements. It validates against a regex for semver.
I then execute every packing step, check for its return status, and present a graceful message in addition to the error output by the build step.
The packager relies on having rcedit-x64.exe
available in the PATH. I originally allowed specifying a path to the executable as a command-line flag, but it seemed to make the code messier for nothing, so I just removed it. The tool is primarily for myself.
Example
Invocation
powershell.exe -ExecutionPolicy Unrestricted .build.ps1 -version 1.1.0
Output
Packing bittray version 1.1.0
Cleaning old build products.
go get...
go vet...
go build...
Validating artifact...
Applying rsrc metadata...
Compressing archive (bittray-1.1.0.zip)...
SHA1 hash of bittray-1.1.0.zip:
cd283afd10f613919bb4dc694bce3c1f9bd23483
CertUtil: -hashfile command completed successfully.
Done!
Concerns
- Does the code follow PS idioms?
- Is there a more elegant way to check for the success of commands and bail than repeating
if (!$?)
all the time? - To wit, is the single
trap
appropriate? - Is the code adequately defensive? Overly defensive?
- I cannot sign my script as I don't have a code signing certificate. Is my invocation correct and safe?
- Is there a shorter invocation available without altering the system-side Execution Policy?
- Because of the validator on
-version
, you need to provide a valid version to be able to run just-clean
. Any way around that (like providing some order of precedence ofparam()
s, or short-cutting)? I really like those top-level validators, and would prefer to keep them in favor of if statements, if possible.
Code
param(
[string]
[Parameter(Mandatory = $True)]
[ValidateNotNullorEmpty()]
[ValidatePattern('^([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:.[0-9A-Za-z-]+)*))?(?:+[0-9A-Za-z-]+)?$')]
$version,
[switch]
$clean
)
function Clean-Artifacts
{
Write-Host "Cleaning old build products."
Remove-Item * -Include bittray.exe, bittray-*.zip
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to remove existing artifacts; see above."
exit 1
}
}
if ($clean -eq $True)
{
Clean-Artifacts
exit 0
}
if ((Get-Command "rcedit-x64.exe" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host -ForegroundColor red "Unable to find rcedit-x64.exe in your PATH."
exit 1
}
Write-Host "Packing bittray version $version" -ForegroundColor green
Clean-Artifacts
Write-Host "go get..."
go get
Write-Host "go vet..."
go vet ./...
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go vet' failed; see above."
exit 1
}
Write-Host "go build..."
go build -ldflags -H=windowsgui bittray.go
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' failed; see above."
exit 1
}
Write-Host "Validating artifact..."
if ( [System.IO.File]::Exists("bittray.exe"))
{
Write-Host "Applying rsrc metadata..."
trap
{
"Error adding resource metadata: $_"
}
rcedit-x64.exe --set-icon .bitbucket.ico "bittray.exe"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductName" "Bittray"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductVersion" "$version"
}
else
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' claims to have succeeded, but there is no artifact?"
exit 1
}
$package = "bittray-$version.zip"
Write-Host "Compressing archive ($package)..."
Compress-Archive -Path .bittray.exe -CompressionLevel Optimal -DestinationPath $package
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to create zip package."
exit 1
}
certUtil -hashfile "$package" sha1
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to generate SHA1 integrity checksum."
exit 1
}
else
{
Write-Host -BackgroundColor green -ForegroundColor white "Done!"
}
windows powershell
$endgroup$
add a comment |
$begingroup$
Background
I decided to write this PowerShell build script as a gentle introduction to PS. It builds this Go application, which is an internal tool I decided to open source, and not the focus of this review.
This script is used primarily for packaging artifacts for release.
My approach
The script below gets, vets and builds a small Go application and then invokes a separate command-line tool to add Windows rsrc metadata such as version strings and icons.
Since the version number is mandatory for the packaging process, I validated it using param()
rules rather than if
statements. It validates against a regex for semver.
I then execute every packing step, check for its return status, and present a graceful message in addition to the error output by the build step.
The packager relies on having rcedit-x64.exe
available in the PATH. I originally allowed specifying a path to the executable as a command-line flag, but it seemed to make the code messier for nothing, so I just removed it. The tool is primarily for myself.
Example
Invocation
powershell.exe -ExecutionPolicy Unrestricted .build.ps1 -version 1.1.0
Output
Packing bittray version 1.1.0
Cleaning old build products.
go get...
go vet...
go build...
Validating artifact...
Applying rsrc metadata...
Compressing archive (bittray-1.1.0.zip)...
SHA1 hash of bittray-1.1.0.zip:
cd283afd10f613919bb4dc694bce3c1f9bd23483
CertUtil: -hashfile command completed successfully.
Done!
Concerns
- Does the code follow PS idioms?
- Is there a more elegant way to check for the success of commands and bail than repeating
if (!$?)
all the time? - To wit, is the single
trap
appropriate? - Is the code adequately defensive? Overly defensive?
- I cannot sign my script as I don't have a code signing certificate. Is my invocation correct and safe?
- Is there a shorter invocation available without altering the system-side Execution Policy?
- Because of the validator on
-version
, you need to provide a valid version to be able to run just-clean
. Any way around that (like providing some order of precedence ofparam()
s, or short-cutting)? I really like those top-level validators, and would prefer to keep them in favor of if statements, if possible.
Code
param(
[string]
[Parameter(Mandatory = $True)]
[ValidateNotNullorEmpty()]
[ValidatePattern('^([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:.[0-9A-Za-z-]+)*))?(?:+[0-9A-Za-z-]+)?$')]
$version,
[switch]
$clean
)
function Clean-Artifacts
{
Write-Host "Cleaning old build products."
Remove-Item * -Include bittray.exe, bittray-*.zip
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to remove existing artifacts; see above."
exit 1
}
}
if ($clean -eq $True)
{
Clean-Artifacts
exit 0
}
if ((Get-Command "rcedit-x64.exe" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host -ForegroundColor red "Unable to find rcedit-x64.exe in your PATH."
exit 1
}
Write-Host "Packing bittray version $version" -ForegroundColor green
Clean-Artifacts
Write-Host "go get..."
go get
Write-Host "go vet..."
go vet ./...
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go vet' failed; see above."
exit 1
}
Write-Host "go build..."
go build -ldflags -H=windowsgui bittray.go
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' failed; see above."
exit 1
}
Write-Host "Validating artifact..."
if ( [System.IO.File]::Exists("bittray.exe"))
{
Write-Host "Applying rsrc metadata..."
trap
{
"Error adding resource metadata: $_"
}
rcedit-x64.exe --set-icon .bitbucket.ico "bittray.exe"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductName" "Bittray"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductVersion" "$version"
}
else
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' claims to have succeeded, but there is no artifact?"
exit 1
}
$package = "bittray-$version.zip"
Write-Host "Compressing archive ($package)..."
Compress-Archive -Path .bittray.exe -CompressionLevel Optimal -DestinationPath $package
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to create zip package."
exit 1
}
certUtil -hashfile "$package" sha1
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to generate SHA1 integrity checksum."
exit 1
}
else
{
Write-Host -BackgroundColor green -ForegroundColor white "Done!"
}
windows powershell
$endgroup$
add a comment |
$begingroup$
Background
I decided to write this PowerShell build script as a gentle introduction to PS. It builds this Go application, which is an internal tool I decided to open source, and not the focus of this review.
This script is used primarily for packaging artifacts for release.
My approach
The script below gets, vets and builds a small Go application and then invokes a separate command-line tool to add Windows rsrc metadata such as version strings and icons.
Since the version number is mandatory for the packaging process, I validated it using param()
rules rather than if
statements. It validates against a regex for semver.
I then execute every packing step, check for its return status, and present a graceful message in addition to the error output by the build step.
The packager relies on having rcedit-x64.exe
available in the PATH. I originally allowed specifying a path to the executable as a command-line flag, but it seemed to make the code messier for nothing, so I just removed it. The tool is primarily for myself.
Example
Invocation
powershell.exe -ExecutionPolicy Unrestricted .build.ps1 -version 1.1.0
Output
Packing bittray version 1.1.0
Cleaning old build products.
go get...
go vet...
go build...
Validating artifact...
Applying rsrc metadata...
Compressing archive (bittray-1.1.0.zip)...
SHA1 hash of bittray-1.1.0.zip:
cd283afd10f613919bb4dc694bce3c1f9bd23483
CertUtil: -hashfile command completed successfully.
Done!
Concerns
- Does the code follow PS idioms?
- Is there a more elegant way to check for the success of commands and bail than repeating
if (!$?)
all the time? - To wit, is the single
trap
appropriate? - Is the code adequately defensive? Overly defensive?
- I cannot sign my script as I don't have a code signing certificate. Is my invocation correct and safe?
- Is there a shorter invocation available without altering the system-side Execution Policy?
- Because of the validator on
-version
, you need to provide a valid version to be able to run just-clean
. Any way around that (like providing some order of precedence ofparam()
s, or short-cutting)? I really like those top-level validators, and would prefer to keep them in favor of if statements, if possible.
Code
param(
[string]
[Parameter(Mandatory = $True)]
[ValidateNotNullorEmpty()]
[ValidatePattern('^([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:.[0-9A-Za-z-]+)*))?(?:+[0-9A-Za-z-]+)?$')]
$version,
[switch]
$clean
)
function Clean-Artifacts
{
Write-Host "Cleaning old build products."
Remove-Item * -Include bittray.exe, bittray-*.zip
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to remove existing artifacts; see above."
exit 1
}
}
if ($clean -eq $True)
{
Clean-Artifacts
exit 0
}
if ((Get-Command "rcedit-x64.exe" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host -ForegroundColor red "Unable to find rcedit-x64.exe in your PATH."
exit 1
}
Write-Host "Packing bittray version $version" -ForegroundColor green
Clean-Artifacts
Write-Host "go get..."
go get
Write-Host "go vet..."
go vet ./...
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go vet' failed; see above."
exit 1
}
Write-Host "go build..."
go build -ldflags -H=windowsgui bittray.go
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' failed; see above."
exit 1
}
Write-Host "Validating artifact..."
if ( [System.IO.File]::Exists("bittray.exe"))
{
Write-Host "Applying rsrc metadata..."
trap
{
"Error adding resource metadata: $_"
}
rcedit-x64.exe --set-icon .bitbucket.ico "bittray.exe"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductName" "Bittray"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductVersion" "$version"
}
else
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' claims to have succeeded, but there is no artifact?"
exit 1
}
$package = "bittray-$version.zip"
Write-Host "Compressing archive ($package)..."
Compress-Archive -Path .bittray.exe -CompressionLevel Optimal -DestinationPath $package
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to create zip package."
exit 1
}
certUtil -hashfile "$package" sha1
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to generate SHA1 integrity checksum."
exit 1
}
else
{
Write-Host -BackgroundColor green -ForegroundColor white "Done!"
}
windows powershell
$endgroup$
Background
I decided to write this PowerShell build script as a gentle introduction to PS. It builds this Go application, which is an internal tool I decided to open source, and not the focus of this review.
This script is used primarily for packaging artifacts for release.
My approach
The script below gets, vets and builds a small Go application and then invokes a separate command-line tool to add Windows rsrc metadata such as version strings and icons.
Since the version number is mandatory for the packaging process, I validated it using param()
rules rather than if
statements. It validates against a regex for semver.
I then execute every packing step, check for its return status, and present a graceful message in addition to the error output by the build step.
The packager relies on having rcedit-x64.exe
available in the PATH. I originally allowed specifying a path to the executable as a command-line flag, but it seemed to make the code messier for nothing, so I just removed it. The tool is primarily for myself.
Example
Invocation
powershell.exe -ExecutionPolicy Unrestricted .build.ps1 -version 1.1.0
Output
Packing bittray version 1.1.0
Cleaning old build products.
go get...
go vet...
go build...
Validating artifact...
Applying rsrc metadata...
Compressing archive (bittray-1.1.0.zip)...
SHA1 hash of bittray-1.1.0.zip:
cd283afd10f613919bb4dc694bce3c1f9bd23483
CertUtil: -hashfile command completed successfully.
Done!
Concerns
- Does the code follow PS idioms?
- Is there a more elegant way to check for the success of commands and bail than repeating
if (!$?)
all the time? - To wit, is the single
trap
appropriate? - Is the code adequately defensive? Overly defensive?
- I cannot sign my script as I don't have a code signing certificate. Is my invocation correct and safe?
- Is there a shorter invocation available without altering the system-side Execution Policy?
- Because of the validator on
-version
, you need to provide a valid version to be able to run just-clean
. Any way around that (like providing some order of precedence ofparam()
s, or short-cutting)? I really like those top-level validators, and would prefer to keep them in favor of if statements, if possible.
Code
param(
[string]
[Parameter(Mandatory = $True)]
[ValidateNotNullorEmpty()]
[ValidatePattern('^([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*).([0-9]|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:.[0-9A-Za-z-]+)*))?(?:+[0-9A-Za-z-]+)?$')]
$version,
[switch]
$clean
)
function Clean-Artifacts
{
Write-Host "Cleaning old build products."
Remove-Item * -Include bittray.exe, bittray-*.zip
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to remove existing artifacts; see above."
exit 1
}
}
if ($clean -eq $True)
{
Clean-Artifacts
exit 0
}
if ((Get-Command "rcedit-x64.exe" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host -ForegroundColor red "Unable to find rcedit-x64.exe in your PATH."
exit 1
}
Write-Host "Packing bittray version $version" -ForegroundColor green
Clean-Artifacts
Write-Host "go get..."
go get
Write-Host "go vet..."
go vet ./...
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go vet' failed; see above."
exit 1
}
Write-Host "go build..."
go build -ldflags -H=windowsgui bittray.go
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' failed; see above."
exit 1
}
Write-Host "Validating artifact..."
if ( [System.IO.File]::Exists("bittray.exe"))
{
Write-Host "Applying rsrc metadata..."
trap
{
"Error adding resource metadata: $_"
}
rcedit-x64.exe --set-icon .bitbucket.ico "bittray.exe"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductName" "Bittray"
rcedit-x64.exe "bittray.exe" --set-version-string "ProductVersion" "$version"
}
else
{
Write-Host -BackgroundColor red -ForegroundColor white "'go build' claims to have succeeded, but there is no artifact?"
exit 1
}
$package = "bittray-$version.zip"
Write-Host "Compressing archive ($package)..."
Compress-Archive -Path .bittray.exe -CompressionLevel Optimal -DestinationPath $package
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to create zip package."
exit 1
}
certUtil -hashfile "$package" sha1
if (!$?)
{
Write-Host -BackgroundColor red -ForegroundColor white "Failed to generate SHA1 integrity checksum."
exit 1
}
else
{
Write-Host -BackgroundColor green -ForegroundColor white "Done!"
}
windows powershell
windows powershell
asked 14 mins ago
msanfordmsanford
2411316
2411316
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215590%2fpowershell-script-to-build-and-pacakge-go-application-for-release%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215590%2fpowershell-script-to-build-and-pacakge-go-application-for-release%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown