Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
Notarize and staple before creating Squirrel release
Browse files Browse the repository at this point in the history
  • Loading branch information
caesay committed Jun 20, 2022
1 parent 581915f commit 9826a40
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 38 deletions.
55 changes: 38 additions & 17 deletions src/Squirrel.CommandLine/OSX/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,37 @@ private static void Pack(PackOptions options)
options.packId, options.packTitle, options.packAuthors, options.packVersion, options.releaseNotes, options.includePdb, "osx");

var nuspecPath = Path.Combine(contentsDir, Utility.SpecVersionFileName);

// nuspec and UpdateMac need to be in contents dir or this package can't update
File.WriteAllText(nuspecPath, nuspecText);
File.Copy(HelperExe.UpdateMacPath, Path.Combine(contentsDir, "UpdateMac"));

// code signing
var machoFiles = Directory.EnumerateFiles(appBundlePath, "*", SearchOption.AllDirectories)
.Where(f => PlatformUtil.IsMachOImage(f))
.ToArray();

HelperExe.CodeSign(options.signAppIdentity, options.signEntitlements, machoFiles);

Log.Info("Creating Squirrel Release");
var zipPath = Path.Combine(releaseDir.FullName, options.packId + ".zip");
if (File.Exists(zipPath)) File.Delete(zipPath);

// code signing all mach-o binaries
if (SquirrelRuntimeInfo.IsOSX && !String.IsNullOrEmpty(options.signAppIdentity) && !String.IsNullOrEmpty(options.notaryProfile)) {
var machoFiles = Directory.EnumerateFiles(appBundlePath, "*", SearchOption.AllDirectories)
.Where(f => PlatformUtil.IsMachOImage(f))
.ToArray();

HelperExe.CodeSign(options.signAppIdentity, options.signEntitlements, machoFiles);

// notarize and staple the .app before creating a Squirrel release
HelperExe.CreateDittoZip(appBundlePath, zipPath);
HelperExe.Notarize(zipPath, options.notaryProfile);
HelperExe.Staple(appBundlePath);

// re-create the zip from the app with the stapled notarization
File.Delete(zipPath);
HelperExe.CreateDittoZip(appBundlePath, zipPath);
} else {
Log.Warn("Package will not be signed or notarized. Only supported on OSX with the --signAppIdentity and --notaryProfile options.");
EasyZip.CreateZipFromDirectory(zipPath, appBundlePath, nestDirectory: true);
}

// create release / delta from notarized .app
Log.Info("Creating Squirrel Release");
using var _ = Utility.GetTempDirectory(out var tmp);
var nupkgPath = NugetConsole.CreatePackageFromNuspecPath(tmp, appBundlePath, nuspecPath);

Expand All @@ -150,18 +167,22 @@ private static void Pack(PackOptions options)
var dp = deltaBuilder.CreateDeltaPackage(prev, rp, deltaFile);
releases.Add(ReleaseEntry.GenerateFromFile(deltaFile));
}

releases.Add(ReleaseEntry.GenerateFromFile(newPkgPath));
ReleaseEntry.WriteReleaseFile(releases, releaseFilePath);

// need to pack as zip using ditto for notarization to succeed
// var zipPath = Path.Combine(releaseDir.FullName, options.packId + ".zip");

var pkgPath = Path.Combine(releaseDir.FullName, options.packId + ".pkg");
HelperExe.CreateInstallerPkg(appBundlePath, pkgPath, options.signInstallIdentity);
// create installer package and notarize
if (SquirrelRuntimeInfo.IsOSX && !String.IsNullOrEmpty(options.signInstallIdentity) && !String.IsNullOrEmpty(options.notaryProfile)) {
var pkgPath = Path.Combine(releaseDir.FullName, options.packId + ".pkg");
if (File.Exists(pkgPath)) File.Delete(pkgPath);
HelperExe.CreateInstallerPkg(appBundlePath, pkgPath, options.signInstallIdentity);
HelperExe.Notarize(pkgPath, options.notaryProfile);
HelperExe.Staple(pkgPath);
} else {
Log.Warn("Package installer (.pkg) will not be created. Only supported on OSX with the --signInstallIdentity and --notaryProfile options.");
}

HelperExe.NotarizePkg(pkgPath, options.notaryProfile);
HelperExe.StapleNotarization(pkgPath);
Log.Info("Done.");
}

private static void CopyFiles(DirectoryInfo source, DirectoryInfo target)
Expand Down
39 changes: 18 additions & 21 deletions src/Squirrel.CommandLine/OSX/HelperExe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,55 +72,50 @@ public static void CreateInstallerPkg(string appBundlePath, string pkgOutputPath
}

[SupportedOSPlatform("osx")]
public static void StapleNotarization(string filePath)
public static void Staple(string filePath)
{
Log.Info($"Stapling Notarization to '{filePath}'");
var args = new List<string> {
"stapler", "staple", filePath,
};
InvokeAndThrowIfNonZero("xcrun", args, null);
Console.WriteLine(InvokeAndThrowIfNonZero("xcrun", args, null));
}

[SupportedOSPlatform("osx")]
public static void NotarizePkg(string pkgPath, string profileName)
public static void Notarize(string filePath, string keychainProfileName)
{
Log.Info($"Preparing to Notarize '{pkgPath}'. This will upload to Apple and usually takes minutes, but could take hours.");
Log.Info($"Preparing to Notarize '{filePath}'. This will upload to Apple and usually takes minutes, but could take hours.");

var args = new List<string> {
"notarytool",
"submit",
"-f", "json",
// "--apple-id", appleId,
// "--password", appPwd,
// "--team-id", teamId,
"--keychain-profile", profileName,
"--keychain-profile", keychainProfileName,
"--wait",
pkgPath
filePath
};

var ntresultjson = PlatformUtil.InvokeProcess("xcrun", args, null, CancellationToken.None);
Log.Info(ntresultjson);
if (ntresultjson.ExitCode != 0) {
try {
var ntresult = JsonConvert.DeserializeObject<NotaryToolResult>(ntresultjson.StdOutput);
// find and report notarization errors if possible
Log.Info(ntresultjson.StdOutput);

// try to catch any notarization errors. if we have a submission id, retrieve notary logs.
try {
var ntresult = JsonConvert.DeserializeObject<NotaryToolResult>(ntresultjson.StdOutput);
if (ntresult?.status != "Accepted" || ntresultjson.ExitCode != 0) {
if (ntresult?.id != null) {
var logargs = new List<string> {
"notarytool",
"log",
ntresult?.id,
"--keychain-profile", profileName,
// "--apple-id", appleId,
// "--password", appPwd,
// "--team-id", teamId,
"--keychain-profile", keychainProfileName,
};

var result = PlatformUtil.InvokeProcess("xcrun", logargs, null, CancellationToken.None);
Log.Warn(result.StdOutput);
}
} catch { ;}

throw new Exception("Notarization failed: " + ntresultjson.StdOutput);
}
} catch (JsonReaderException) {
throw new Exception("Notarization failed: " + ntresultjson.StdOutput);
}

Expand All @@ -141,10 +136,12 @@ public static void CreateDittoZip(string folder, string outputZip)
"-c",
"-k",
"--keepParent",
"--sequesterRsrc",
folder,
outputZip
};

Log.Info($"Creating ditto bundle '{outputZip}'");
InvokeAndThrowIfNonZero("ditto", args, null);
}
}
Expand Down

0 comments on commit 9826a40

Please sign in to comment.