Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add script to build a macOS installer #83

Merged
merged 1 commit into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
build, sign, notarize, and upload macos installer pkg
  • Loading branch information
patricksanders committed Aug 6, 2021
commit 91199ef59cd09cc790ffab00aa37574ab69afd91
61 changes: 61 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,64 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
-
name: Store Binaries
uses: actions/upload-artifact@v2
with:
name: binaries
path: dist/bin/
retention-days: 5
package:
needs: goreleaser
runs-on: macos-latest
environment: Signing
steps:
-
name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
-
name: Retrieve Binaries
uses: actions/download-artifact@v2
with:
name: binaries
path: dist/bin/
-
name: Import Signing Certificates
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
-
name: Build, Sign, & Notarize Package
env:
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
VERSION: ${{ env.GITHUB_REF }}
run: |
./build/build_package.sh
-
name: Store Package
uses: actions/upload-artifact@v2
with:
name: package
path: dist/macos/*.pkg
upload:
needs: package
runs-on: ubuntu-latest
steps:
-
name: Retrieve Package
uses: actions/download-artifact@v2
with:
name: package
path: dist/macos/
-
name: Upload package to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/macos/*.pkg
file_glob: true
tag: ${{ github.ref }}
overwrite: true
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ dist/
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Generated source files
pkged.go

# Dependency directories (remove the comment below to include it)
# vendor/

# IDE configs
.idea/

# Build files
build/package/macos/tmp/
build/package/macos/application/bin/
4 changes: 4 additions & 0 deletions build/.goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ builds:
-X github.com/netflix/weep/internal/metadata.Commit={{.CommitDate}}
-X github.com/netflix/weep/internal/metadata.Date={{.Date}}
mod_timestamp: '{{ .CommitTimestamp }}'
no_unique_dist_dir: true
binary: 'bin/{{ .Target }}/weep'
-
id: demo
env:
Expand All @@ -35,6 +37,8 @@ builds:
-X github.com/netflix/weep/metadata.Commit={{.CommitDate}}
-X github.com/netflix/weep/metadata.Date={{.Date}}
mod_timestamp: '{{ .CommitTimestamp }}'
no_unique_dist_dir: true
binary: 'bin/demo/{{ .Target }}/weep'
archives:
-
builds:
Expand Down
149 changes: 149 additions & 0 deletions build/build_package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env bash
##############################################################################
# Build a macOS installer package containing a weep universal binary
# Author: Patrick Sanders <psanders@netflix.com>
##############################################################################
set -euo pipefail

BASE_DIR="build/package/macos"
APP_DIR="$BASE_DIR/application"
BIN_DIR="$APP_DIR/bin"
BUILD_DIR="$BASE_DIR/tmp"
PKG_DIR="$BUILD_DIR/darwinpkg"
OUT_DIR="dist/macos"
VERSION=${VERSION:=dev}
FINAL_PACKAGE="$OUT_DIR/weep-installer-macos-$VERSION.pkg"

rm -rf "$BIN_DIR"
rm -rf "$BUILD_DIR"
mkdir -p "$BIN_DIR"
mkdir -p "$OUT_DIR"
mkdir -p "$PKG_DIR"

cp -r "$BASE_DIR/darwin" "$BUILD_DIR/"
chmod -R 755 "$BUILD_DIR/darwin/scripts"
chmod 755 "$BUILD_DIR/darwin/Distribution.xml"

printf "🟢 starting build for %s\n" "$FINAL_PACKAGE"

function prep_package() {
# Prepare package structure
mkdir -p "$BUILD_DIR/darwinpkg/Library/weep"
cp -a "$APP_DIR/." "$BUILD_DIR/darwinpkg/Library/weep"
chmod -R 755 "$BUILD_DIR/darwinpkg/Library/weep"

# Replace tokens in package files
sed -i '' -e "s/__VERSION__/$VERSION/g" ${BUILD_DIR}/darwin/Resources/*.html
}

function combine_binaries() {
printf "🦾 creating universal binary..."
output=$1
bin1=$2
bin2=$3
lipo -create -output "$output" "$bin1" "$bin2"
printf " done ✅ \n"
}

function sign_binary() {
printf "🔏 signing binary..."
binary=$1
codesign \
--options runtime \
--sign "Developer ID Application: Netflix, Inc." \
--force \
--timestamp=http://timestamp.apple.com/ts01 \
"$binary" > /dev/null 2>&1
printf " done ✅ \n"
}

function build_package() {
printf "📦 building package..."
pkgbuild --identifier "com.netflix.weep" \
--version "$VERSION" \
--scripts "$BUILD_DIR/darwin/scripts" \
--root "$BUILD_DIR/darwinpkg" \
weep.pkg > /dev/null 2>&1

productbuild --distribution "$BUILD_DIR/darwin/Distribution.xml" \
--resources "$BUILD_DIR/darwin/Resources" \
--package-path "$BUILD_DIR/package" \
"$OUT_DIR/weep-$VERSION-unsigned.pkg" > /dev/null 2>&1
printf " done ✅ \n"
}

function sign_package() {
printf "🔏 signing package..."
productsign --sign "Developer ID Installer: Netflix, Inc." \
"$OUT_DIR/weep-$VERSION-unsigned.pkg" \
"$FINAL_PACKAGE" > /dev/null 2>&1

pkgutil --check-signature "$FINAL_PACKAGE" > /dev/null 2>&1
printf " done ✅ \n"
}

function notarize() {
printf "🔐 notarizing package..."
output=$(xcrun altool \
--notarize-app \
--primary-bundle-id "com.netflix.weep" \
--username "psanders@netflix.com" \
--password "$AC_PASSWORD" \
--file "$FINAL_PACKAGE")
printf " done ✅ \n"
request_id=$(echo "$output" | grep RequestUUID | awk '{ print $3 }')
printf "💡 notarize request id is %s\n" "$request_id"
# give the server side a few seconds to sort things out
sleep 3
while true; do
status=$(check_notarize_status "$request_id")
printf "👀 current status \"%s\"" "$status"
case "$status" in
"success")
printf ", done ✅ \n"
break
;;
"failure")
printf ", exiting! 🔴\n"
exit 1
;;
*)
printf ", not ready yet 😴\n"
sleep 5
;;
esac
done
}

function check_notarize_status() {
request_id=$1
output=$(xcrun altool \
--notarization-info "$request_id" \
--username "psanders@netflix.com" \
--password "$AC_PASSWORD")
status=$(echo "$output" | grep "Status:" | awk '{ for (i=2; i<=NF; i++) printf("%s ", $i) }' | awk '{$1=$1;print}')
echo "$status"
}

function staple() {
printf "📎 stapling..."
xcrun stapler staple "$FINAL_PACKAGE" > /dev/null 2>&1
printf " done ✅ \n"
}

function cleanup() {
rm dist/macos/*-unsigned.pkg
}

combine_binaries "$BIN_DIR/weep-universal" \
dist/bin/darwin_amd64/weep \
dist/bin/darwin_arm64/weep
sign_binary "$BIN_DIR/weep-universal"
prep_package
build_package
sign_package
notarize
staple
cleanup

printf "🙌 successfully built and notarized %s 🎉 \n" "$FINAL_PACKAGE"
46 changes: 46 additions & 0 deletions build/package/macos/application/uninstall.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

#Check running user
if (( $EUID != 0 )); then
echo "Please run as root."
exit
fi

echo "Welcome to the Weep Uninstaller"
echo "The following packages will be REMOVED:"
echo " weep"
while true; do
read -p "Do you wish to continue [Y/n]?" answer
[[ $answer == "y" || $answer == "Y" || $answer == "" ]] && break
[[ $answer == "n" || $answer == "N" ]] && exit 0
echo "Please answer with 'y' or 'n'"
done


echo "Uninstalling Weep"
# remove binary symlink
if rm -rf "/usr/local/bin/weep"
then
echo "[1/3] [DONE] Successfully deleted shortcut links"
else
echo "[1/3] [ERROR] Could not delete shortcut links" >&2
fi

#forget from pkgutil
if pkgutil --forget "com.netflix.weep" > /dev/null 2>&1
then
echo "[2/3] [DONE] Successfully deleted application information"
else
echo "[2/3] [ERROR] Could not delete application information" >&2
fi

#remove application source distribution
if rm -rf "/Library/weep"
then
echo "[3/3] [DONE] Successfully deleted application"
else
echo "[3/3] [ERROR] Could not delete application" >&2
fi

echo "Application uninstall process finished"
exit 0
29 changes: 29 additions & 0 deletions build/package/macos/darwin/Distribution.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-script minSpecVersion="1.000000">
<title>Weep</title>
<background mime-type="image/png" alignment="bottomleft" file="banner.png" scaling="proportional"/>
<welcome file="welcome.html" mime-type="text/html" />
<conclusion file="conclusion.html" mime-type="text/html" />
<license file="LICENSE"/>
<options customize="never" allow-external-scripts="no"/>
<domains enable_localSystem="true" />
<installation-check script="installCheck();"/>
<script>
function installCheck() {
if(system.files.fileExistsAtPath('/Library/weep/')) {
my.result.title = 'Previous Installation Detected';
my.result.message = 'A previous installation of Weep exists at /Library/weep. This installer will remove the previous installation prior to installing.';
my.result.type = 'Warning';
return false;
}
return true;
}
</script>
<choices-outline>
<line choice="Weep"/>
</choices-outline>
<choice id="Weep" title="Weep">
<pkg-ref id="weep.pkg"/>
</choice>
<pkg-ref id="weep.pkg" auth="Root">weep.pkg</pkg-ref>
</installer-script>
1 change: 1 addition & 0 deletions build/package/macos/darwin/Resources/LICENSE
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 50 additions & 0 deletions build/package/macos/darwin/Resources/conclusion.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Install Weep</title>
<style>
body {
font-family: Helvetica, sans-serif;
}
p {
color: #020202;
}
code {
color: #c6a72b;
font-size: 11px;
font-family: Menlo, monospace;
}
div {
padding-left: 10px;
}
.footer {
font-size: 10px;
position: absolute;
bottom: 25px;
left: 10px;
width: 100%;
height: 10px;
}
</style>
</head>
<body>
<div>
<p>Thank you for installing Weep.</p>
<h4>Run Weep</h4>
<p>Open a new terminal and run the following command to get started with Weep:</p>
<code>&nbsp; $ <span style="color: #abb0b0">weep --help</span></code>
</div>
<div>
<br/>
<h4>Uninstall Weep</h4>
<p>Run the following command to uninstall Weep: <br />
<code><br />&nbsp; $ <span style="color: #abb0b0">sudo /Library/weep/uninstall.sh</span></code>
</p>
</div>
<div class="footer">
<p>Copyright © 2021 Netflix, Inc. All rights reserved.</p>
<p>Take care. Stay rad.</p>
</div>
</body>
</html>
Loading