diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c2b3e7c..7fc653b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 \ No newline at end of file diff --git a/.gitignore b/.gitignore index d49aacd..bf999c6 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/build/.goreleaser.yml b/build/.goreleaser.yml index f3a3677..74de77b 100644 --- a/build/.goreleaser.yml +++ b/build/.goreleaser.yml @@ -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: @@ -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: diff --git a/build/build_package.sh b/build/build_package.sh new file mode 100755 index 0000000..74c56de --- /dev/null +++ b/build/build_package.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +############################################################################## +# Build a macOS installer package containing a weep universal binary +# Author: Patrick Sanders +############################################################################## +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" diff --git a/build/package/macos/application/uninstall.sh b/build/package/macos/application/uninstall.sh new file mode 100644 index 0000000..9723778 --- /dev/null +++ b/build/package/macos/application/uninstall.sh @@ -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 diff --git a/build/package/macos/darwin/Distribution.xml b/build/package/macos/darwin/Distribution.xml new file mode 100755 index 0000000..9b5b5f0 --- /dev/null +++ b/build/package/macos/darwin/Distribution.xml @@ -0,0 +1,29 @@ + + + Weep + + + + + + + + + + + + + + + weep.pkg + diff --git a/build/package/macos/darwin/Resources/LICENSE b/build/package/macos/darwin/Resources/LICENSE new file mode 120000 index 0000000..2a64f9d --- /dev/null +++ b/build/package/macos/darwin/Resources/LICENSE @@ -0,0 +1 @@ +../../../../../LICENSE \ No newline at end of file diff --git a/build/package/macos/darwin/Resources/Netflix-OSS-Logo.png b/build/package/macos/darwin/Resources/Netflix-OSS-Logo.png new file mode 100644 index 0000000..d0e8275 Binary files /dev/null and b/build/package/macos/darwin/Resources/Netflix-OSS-Logo.png differ diff --git a/build/package/macos/darwin/Resources/banner.png b/build/package/macos/darwin/Resources/banner.png new file mode 100644 index 0000000..a1ef5bc Binary files /dev/null and b/build/package/macos/darwin/Resources/banner.png differ diff --git a/build/package/macos/darwin/Resources/conclusion.html b/build/package/macos/darwin/Resources/conclusion.html new file mode 100644 index 0000000..ec159ba --- /dev/null +++ b/build/package/macos/darwin/Resources/conclusion.html @@ -0,0 +1,50 @@ + + + + + Install Weep + + + +
+

Thank you for installing Weep.

+

Run Weep

+

Open a new terminal and run the following command to get started with Weep:

+   $ weep --help +
+
+
+

Uninstall Weep

+

Run the following command to uninstall Weep:
+
  $ sudo /Library/weep/uninstall.sh
+

+
+ + + diff --git a/build/package/macos/darwin/Resources/welcome.html b/build/package/macos/darwin/Resources/welcome.html new file mode 100644 index 0000000..16866bd --- /dev/null +++ b/build/package/macos/darwin/Resources/welcome.html @@ -0,0 +1,25 @@ + + + + + Install Weep + + + +
+

Weep, the ConsoleMe CLI

+

This will install Weep __VERSION__ on your computer. You will be guided through the steps necessary to install this software.

+

Weep is open source software written and maintained with ❤️ and ☕️ by Netflix and our awesome ✨contributors✨. Interested in getting involved? Check out the project on GitHub!

+
+ + diff --git a/build/package/macos/darwin/scripts/postinstall b/build/package/macos/darwin/scripts/postinstall new file mode 100755 index 0000000..56fcdfa --- /dev/null +++ b/build/package/macos/darwin/scripts/postinstall @@ -0,0 +1,21 @@ +#!/bin/bash + +set -euo pipefail + +#Parameters +PRODUCT_HOME=/Library/weep +APPLICATION_FILE_PATH=bin/weep-universal + +echo "Post installation process started" + +#Change permissions in home directory +echo "Change permissions in product home" +pushd "$PRODUCT_HOME" +chmod -R 755 . +[ -d /usr/local/bin ] || mkdir /usr/local/bin + +#Add application shortcut to /usr/local/bin +rm -f /usr/local/bin/weep +ln -s ${PRODUCT_HOME}/${APPLICATION_FILE_PATH} /usr/local/bin/weep +echo "Post installation process finished" +popd