Stop Hand-Rolling Chocolate#
Automating Chocolatey with psake#
Gilbert Sanchez
@HeyItsGilbert
Thanks#
Hey! It’s Gilbert#
- Staff Software Development Engineer
- ADHD πΆοΈπ§
- Links.GilbertSanchez.com

Hands Up β#
“Back in my day…”#
The year is 2013#
The Build Process#
“The ticket queue was the build process.”#
- Teams needed a Windows packages built and deployed.
- They filed a ticket
- Someone (eventually) hand-crafted it
- That someone was the only one who knew how
“It Works on My Machine”#
Except your devs are on Macs#
- File locking differently
- Windows-specific paths, encodings, behaviors
- Packaging Windows software felt like a foreign language
Extra friction became an extra excuse.
Chocolatey is just PowerShell#
If you can write a script, you can ship a package.#
Scaffolding a Package#
choco new mypackage
mypackage/
βββ mypackage.nuspec β package metadata
βββ tools/
βββ chocolateyInstall.ps1 β runs on install
βββ chocolateyUninstall.ps1
βββ LICENSE.txtThat’s the whole package.
The Two Files That Matter: Metadata#
mypackage.nuspec β what the package is
<metadata>
<id>mypackage</id>
<version>1.0.0</version>
<description>Does a thing.</description>
</metadata>The Two Files That Matter: Installer#
tools/chocolateyInstall.ps1 β how it installs
$packageArgs = @{
packageName = 'mypackage'
url = 'https://example.com/installer.exe'
checksum = 'ABC123...'
}
Install-ChocolateyPackage @packageArgsExtensions#
Add new functions to any package
mycompany-chocolatey-extension/
βββ extensions/
βββ mycompany-helpers.psm1 β imported automaticallyHooks#
Run logic around every install
mycompany-hooks/
βββ hooks/
βββ pre-install-all.ps1 β before any package installs
βββ post-install-all.ps1 β after any package installspsake#
Tasks with dependencies#
That’s it. PowerShell Tasks.
Your Build Process is a README and Hope#
# HOW TO RELEASE (don't forget these steps)
1. Validate the nuspec manually
2. Run choco pack
3. Run the tests (yes, before you push JOHN!)
4. Push to the feed β but only on main!Every step is a chance for someone to skip it.
Manual Steps β Declared Tasks#
Task Default -depends Pack
Task Test -depends -description "Run Pester tests" {
Invoke-Pester .\Tests\
}
Task Pack -depends Test -description "Build the .nupkg" {
exec { choco pack }
}
Task Push -depends Pack -precondition { $env:GITHUB_REF -eq 'refs/heads/main' } {
exec { choco push mypackage.nupkg --source $env:CHOCO_FEED }
}The Task Graph#
Push (only on main)
βββ Pack
βββ TestRun everything: Invoke-psake
Run just tests: Invoke-psake -taskList Test
Same command. Local or CI. No surprises.
The Brazil Story#
The Brazil Story#
Extensions put your org’s knowledge in one place.
# mycompany-chocolatey-extension/extensions/mycompany-helpers.psm1
function Get-PackageFromCDN {
param($PackageName, $Version)
$node = Resolve-NearestCDNNode # β finds SΓ£o Paulo, not Virginia
$cached = Test-CDNCache -Node $node -Package $PackageName
if ($cached) { Get-FromCache -Node $node -Package $PackageName }
else { Get-FromOrigin -Package $PackageName -Version $Version }
}Every package calls Get-PackageFromCDN. Nobody hard-codes the CDN.
Let’s build it#
Blank repo β published, tested, CI-backed package.
What We Just Built#
| Step | What it does |
|---|---|
.\build.ps1 -Task Test | Runs Pester tests against the package |
.\build.ps1 -Task Pack | Builds the .nupkg |
.\build.ps1 -Task Push | Publishes β but only from main |
| CI workflow | Validates + tests every PR |
| Publish workflow | Auto-publishes on merge |
Same psakefile. Local and CI. No surprises.
“I Only Have 5 Packages”#
You still get:
- Auto-publish on merge
- Validated nuspec XML
- Pester tests
- Extensions & Hooks
Automation that reduces toil scales down just as well as it scales up.
Your Mac Dev Just Shipped a Windows Package#
They didn’t touch a Windows machine.
They didn’t learn Chocolatey internals.
They opened a PR. CI went green. They merged.
The packaging knowledge lives in the psakefile β not in someone’s head.
Boring is good#
Predictable. Auditable. Repeatable.#
The best build pipeline is the one you forget about.
THANK YOU#
Feedback is a gift#
Please review this session via the mobile app
Questions? Find me @heyitsgilbert


