2pm Monday
Author slide
Speaker notes: Welcome everyone. Quick show of hands — who here manages Chocolatey packages? Who's done it by hand? Keep that hand up if you've ever said "just run this script and then run that one." Yeah. That's what we're fixing today.
Panning shot to a young and eager Gilbert ripsticking down the hallway.... Responsible for lots of things. Patching, vmware, etc.
Speaker notes: At Meta we had hundreds of apps running across 30,000 Windows machines. The "build process" for Chocolatey packages was: file a ticket, wait, hope. The person who built your package kept the knowledge in their head. Then they left. Or got pulled onto something else. And you were stuck. That doesn't scale. It barely works at 10 packages.
Speaker notes: This was a real pattern. Teams building cross-platform software would just skip Windows packaging because it felt hard and alien. The file locking bugs alone were a constant source of tickets. POSIX vs Windows file locking semantics bite you in ways you don't expect until a machine at 2am tells you about it. If the tooling makes it hard, people won't do it. Simple as that.
Speaker notes: This is the core insight I want you to leave with, even if you forget everything else. There's no magic. No proprietary format. No arcane knowledge required. A Chocolatey package is a nuspec file and a PowerShell script. That's it. We're going to prove it in about 10 minutes. Side note for consumers: choco install mypackage is all they ever see. Your packaging work is invisible to them — which is the goal.
Act 2: Chocolatey Crash Course
7m mark - 2:07p choco new scaffolds everything for you. The nuspec is your package manifest — name, version, dependencies. The install script is PowerShell that runs when someone does choco install. Two files that matter. That's the whole mental model.
The nuspec is just XML. The install script is just PowerShell.
Install-ChocolateyPackage handles downloads, checksums, and silent installs. If you know PowerShell, you already know how to write this. No Chocolatey-specific magic. Just PowerShell with convenience functions on top.
Speaker notes: <pre|post>-<install|beforemodify|uninstall>-<packageID>.ps1 Hooks fire around every single install without the package author doing anything. Install your hook package once, and it runs everywhere. We'll come back to this with a real example in a minute.
13-15m mark ~ 2:15pm Speaker notes: psake — pronounced "sake" like the Japanese rice wine, not "p-sake" — is a build automation tool written in PowerShell. Think Make or Rake, but for PowerShell people. You declare tasks, you declare what each task depends on, psake runs them in the right order and stops loudly if something fails. I maintain psake, which is either a great reason to trust me on this or a great reason to be suspicious. I'll let you decide. The reason I keep coming back to it for Chocolatey work is the same reason I fell for it in the first place: it's the language you're already writing. No context switch. No new mental model. Just PowerShell.
Show of hands — who has a README like this? The problem isn't the steps. The steps are fine. The problem is that the steps live in a document nobody reads until something breaks. That's not a people problem. That's an automation problem.
Every "don't forget" becomes a dependency. The precondition on Push means it simply won't run unless you're on main — no human judgement required. Notice the descriptions — that's what shows up in Invoke-psake -docs. Your build script is now self-documenting. Sarah doesn't need to read the README.
The dependency graph means you never think about order again. Want to just repack without re-running tests? Invoke-psake -taskList Pack. The exact same command you just ran at your desk is what GitHub Actions will run. No drift. If it passes locally, it passes in CI. Now — let me show you why this matters when your infrastructure is more complicated than a single package. The Brazil story.
Small office. Bad connection. 200mb Office Killed. CDN was in DC's.
We put all of that CDN routing logic into an extension. One module. One place to fix. One place to improve. Teams writing packages didn't need to know any of it existed. They called Get-PackageFromCDN and it did the right thing for their location. That's what extensions are for: your org's infrastructure knowledge in one module, not scattered across hundreds of install scripts.
Act 4: Live Demo
25-30m - 2:30 Here's what we're going to build in the next 20 minutes: A GitHub repo with a Chocolatey package, a psakefile that validates, tests, and packs it, and GitHub Actions workflows that run CI on PRs and auto-publish when we merge to main. If you want to follow along, the repo will be linked at the end. [SWITCH TO TERMINAL] Demo script: 1. gh repo create choco-psake-demo --public 2. choco new mypackage — show the generated structure 3. Write psakefile.ps1 with Test, Pack, Push tasks 4. Add nuspec XML schema validation task 5. Add Pester test for package metadata 6. Run Invoke-psake locally — watch it pass 7. Add .github/workflows/ci.yml — test on PR 8. Add .github/workflows/publish.yml — push on merge to main 9. Push, open a PR, watch CI go green 10. Merge, watch the package publish
Act 5: Payoff
Goal: 40m Speaker notes: Here's what we just wired together. The key insight is the bottom row — none of this required separate scripts for local vs CI. One psakefile. Everywhere.
Speaker notes: I want to kill a misconception before you leave. This is not enterprise-only tooling. The patterns we used today — declared tasks, validated XML, tested packages, auto-publishing — these pay off at 5 packages just as much as 500. You get your Saturday afternoons back. You stop being the person who has to manually push a release because nobody else knows how. That's worth it at any scale. - Auto-publish on merge — no manual push steps - Validated nuspec XML — catch errors before they ship - Pester tests — know it works before your users find out it doesn't - Extensions — your org's logic in one place, not copy-pasted everywhere - Hooks — compliance, logging, CDN routing — free for every package
Speaker notes: This is the Meta story, but it's also your story if you want it to be. The developer who doesn't "do Windows" can still contribute because the process is encoded, tested, and automated. The person who built the psakefile doesn't need to be in the loop for every release. That's what good tooling does — it transfers knowledge from people into systems.
Speaker notes: I want to leave you with this. The goal was never "cool automation." The goal was never to impress anyone with your psakefile. The goal is a build pipeline so reliable, so boring, that you stop thinking about it entirely — and just ship packages. That's what we built today. Demo repo is at the link. psake is open source and always looking for contributors. I'm around for questions — thank you.