Deploying to Netlify With Powershell

For a while I’ve had on my todo list to migrate this site to something that doesn’t require a database backend - mostly for administrative simplicity, but also for security, ease of hosting, and performance. To this end I’ve migrated to Hugo, a static site generator. This has allowed me to move to Netlify for hosting, which is both free and packed with great features like form processing. Netlify also have a great API which allows me to script uploading new versions of the site once Hugo has regenerated the static HTML files.

Eventually I’d like to create a build process hooked into my source control, but that’s a project for another time. For the time being I’ve chosen to go down the batch file route, and call powershell from inside that because it allows me to double click on the file to deploy instead of having to run a PowerShell script from the CLI.

The batch file is very simple and does a few things

  1. Deletes the current public/ folder which stores the generated Hugo site
  2. Generates a fresh build of the site
  3. Compresses the site using PowerShell (v5 required, but there are ways on older versions)
  4. Uploads the zipped file to Netlify via their API

Long story short here is the batch file

rmdir /s /q public
hugo

powershell -Command Compress-Archive public "public.zip" -force
powershell -Command "&{Invoke-WebRequest -Method POST -Headers @{'Content-Type' = 'application/zip'; 'Authorization' = 'Bearer <YOUR_API_TOKEN>'} -InFile public.zip https://api.netlify.com/api/v1/sites/<NETLIFY_SITE_FQDN>/deploys}"

pause

If all goes well the API will return some status codes along with a bunch of other data

StatusCode        : 200
StatusDescription : OK
< truncated.. >

But it doesn’t work…

Everything will look like it uploaded without issue, but then you’ll go to check your site and find everything returning a 404.

This was one of those unnecessary rabbit holes that makes one consider a change of profession.

Some time ago ago Microsoft decided to ignore the .Zip File Format Specification which states that files in folders must use forward slashes (/) as separators, and not blackslashes (\). I.e., blog/post.html instead of blog\post.html.

This can be confirmed with a Hex editor, here is a PowerShell / .NET (System.IO.Compression.ZipArchive) archive file.

.NET Archive Hex

And here is one created with 7Zip

7Zip Archive Hex

This makes the .NET Archive expand without subdirectories on Linux systems (which I would guess Netlify use) and results in 404s.

There is a fix

Turns out I’m not the only one that had this issue, and the Microsoft PowerShell team have released an update to the Archive module, but it requires a manual download (at least at the time of writing).

The following needs to be ran under an Administrative PowerShell prompt, at which point the module will be updated, and the above script will work.

Install-Module Microsoft.PowerShell.Archive -MinimumVersion 1.2.3.0 -Repository PSGallery -Force

Now everything should work - and if you’re reading this instead of a 404, I guess we’re all good :)