A little zip trouble

For some strange reason AWS Elastic Beanstalk was handing me the error ” Failed to unzip source bundle, abort deployment (Executor::NonZeroExitStatus)” when I uploaded a new application version.

This was for a zip file put together using either Powershell’s Compress-Archive, or by using [IO.Compression.ZipFile]::CreateFromDirectory. The end result of either was an archive that Windows and 7zip were both perfectly happy to open, but AWS was not. And yet creating a zip-file with the same contents using 7zip and uploading it to AWS worked fine. Unfortunately I was trying to script this in Powershell and using 7zip wasn’t a useful option.

Figuring AWS was using Linux I opened a successful and unsuccessful zip in Ubuntu and there was an immediate difference: the good zip had a sub-folder called publish-output; while the bad one has lots of publish-output\xyz entries in the root. Despite that, both happily extracted in Ubuntu. This .NET/Linux incompatibility lead to some more Googling and finally an answer that .NET breaks the zip rules for path separators which turned into a wonderful workaround in Powershell:

$ZipEncoding=@"
using System;
using System.Text;

public class ZipEncoding : UTF8Encoding
{
    public ZipEncoding() : base(true) {}
    public override byte[] GetBytes(string s)
    {
        s = s.Replace("\\", "/");
        return base.GetBytes(s);
   }
}

"@
Add-Type -TypeDefinition $ZipEncoding
$encoder = New-Object -TypeName ZipEncoding

Add-Type -As System.IO.Compression.FileSystem 
[IO.Compression.ZipFile]::CreateFromDirectory((Resolve-Path $publishPath), $zipPath, "Optimal", $true, $encoder) # true creates a surrounding root folder