chore: add support for macos universal binary (#95) #149
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Publish | |
on: | |
workflow_dispatch: | |
push: | |
tags: | |
- "v*.*.*" | |
env: | |
# Necessary for most environments as build failure can occur due to OOM issues | |
NODE_OPTIONS: "--max-old-space-size=4096" | |
ARTIFACT_NAME_PREFIX: "SCANOSS Code Compare" | |
GOLANG_VERSION: "1.21" | |
NODE_VERSION: "16.x" | |
jobs: | |
build_mac: | |
name: Build for MacOS | |
runs-on: macos-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
# Setup and configure GoLang | |
- name: Setup GoLang | |
uses: actions/setup-go@v5 | |
with: | |
check-latest: true | |
go-version: ${{ env.GOLANG_VERSION }} | |
- run: go version | |
shell: bash | |
# Setup and configure NodeJS | |
- name: Setup NodeJS | |
uses: actions/setup-node@v4 | |
with: | |
node-version: ${{ env.NODE_VERSION }} | |
# Install Wails | |
- name: Install Wails | |
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest | |
shell: bash | |
# Build | |
- name: Build App | |
run: | | |
mkdir -p build | |
cp -r assets build/assets | |
cp assets/appicon.png build | |
# Build for ARM64 | |
wails build -ldflags "-X github.com/scanoss/scanoss.cc/backend/entities.AppVersion=$(git tag --sort=-version:refname | head -n 1)" --platform "darwin/arm64" -o "${{ env.ARTIFACT_NAME_PREFIX }}-arm64" | |
# Build for AMD64 | |
wails build -ldflags "-X github.com/scanoss/scanoss.cc/backend/entities.AppVersion=$(git tag --sort=-version:refname | head -n 1)" --platform "darwin/amd64" -o "${{ env.ARTIFACT_NAME_PREFIX }}-amd64" | |
# Create universal binary | |
lipo -create -output "build/bin/${{ env.ARTIFACT_NAME_PREFIX }}" "build/bin/${{ env.ARTIFACT_NAME_PREFIX }}-arm64" "build/bin/${{ env.ARTIFACT_NAME_PREFIX }}-amd64" | |
shell: bash | |
# Make sure the .app exists | |
- name: Check .app | |
run: ls -l "build/bin/${{ env.ARTIFACT_NAME_PREFIX }}.app" || (echo ".app not found!" && exit 1) | |
- name: Import Code-Signing Certificates for macOS | |
uses: Apple-Actions/import-codesign-certs@v3 | |
with: | |
keychain: signing_app | |
keychain-password: ${{ secrets.APPLE_PASSWORD }} | |
p12-file-base64: ${{ secrets.MACOS_DEVELOPER_CERT }} | |
p12-password: ${{ secrets.MACOS_DEVELOPER_CERT_PASSWORD }} | |
- name: Sign .app Bundle | |
env: | |
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
APPLE_ID: [email protected] | |
APP_CERTIFICATE: ${{ secrets.MACOS_DEVELOPER_CERT_FULL_ID }} | |
APPLE_DEVELOPER_ID: ${{ secrets.MACOS_DEVELOPER_CERT_ID }} | |
run: | | |
security default-keychain -s signing_app.keychain | |
APP_PATH="build/bin/${{ env.ARTIFACT_NAME_PREFIX }}.app" | |
codesign --remove-signature "$APP_PATH" | |
codesign --remove-signature "$APP_PATH/Contents/MacOS/${{ env.ARTIFACT_NAME_PREFIX }}" | |
echo "Signing .app with App Certificate: $APP_CERTIFICATE" | |
# Sign the main executable | |
codesign --timestamp --options runtime -s "$APP_CERTIFICATE" --verbose "$APP_PATH/Contents/MacOS/${{ env.ARTIFACT_NAME_PREFIX }}" | |
# Sign the .app bundle | |
codesign --timestamp --deep --options runtime -s "$APP_CERTIFICATE" --force --verbose "$APP_PATH" | |
echo "Verifying Code Signature" | |
codesign --verify --verbose=4 "$APP_PATH" | |
- name: Install create-dmg | |
run: brew install create-dmg | |
- name: Create .dmg package | |
run: | | |
mkdir -p dist dmg_contents | |
cp -R "build/bin/${{ env.ARTIFACT_NAME_PREFIX }}.app" dmg_contents/ | |
cp INSTALL_MACOS.md "dmg_contents/Installation Guide.md" | |
create-dmg \ | |
--volname "${{ env.ARTIFACT_NAME_PREFIX }} Installer" \ | |
--window-size 600 400 \ | |
--app-drop-link 450 200 \ | |
--icon "${{ env.ARTIFACT_NAME_PREFIX }}.app" 150 200 \ | |
--icon "Installation Guide.md" 300 200 \ | |
"dist/${{ env.ARTIFACT_NAME_PREFIX }}-$(git tag --sort=-version:refname | head -n 1).dmg" \ | |
dmg_contents/ | |
rm -rf dmg_contents | |
- name: Sign and Notarize DMG | |
env: | |
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
APPLE_ID: [email protected] | |
APP_CERTIFICATE: ${{ secrets.MACOS_DEVELOPER_CERT_FULL_ID }} | |
APPLE_DEVELOPER_ID: ${{ secrets.MACOS_DEVELOPER_CERT_ID }} | |
run: | | |
DMG_PATH="dist/${{ env.ARTIFACT_NAME_PREFIX }}-$(git tag --sort=-version:refname | head -n 1).dmg" | |
echo "Signing .dmg with Certificate" | |
codesign --timestamp --deep --options runtime -s "$APP_CERTIFICATE" --force --verbose "$DMG_PATH" | |
echo "Submitting DMG for notarization" | |
xcrun notarytool submit "$DMG_PATH" \ | |
--apple-id "$APPLE_ID" \ | |
--password "$APPLE_PASSWORD" \ | |
--team-id "$APPLE_DEVELOPER_ID" \ | |
--wait | |
echo "Stapling notarization ticket" | |
xcrun stapler staple "$DMG_PATH" | |
echo "Verifying staple" | |
stapler validate "$DMG_PATH" | |
- name: Build Mac zip file | |
shell: bash | |
run: | | |
cd dist && zip "${{env.ARTIFACT_NAME_PREFIX}}-mac.zip" *.dmg | |
- name: Calculate ZIP SHA256 | |
run: | | |
APP_VERSION=$(git tag --sort=-version:refname | head -n 1) | |
ZIP_PATH="dist/${{ env.ARTIFACT_NAME_PREFIX }}-mac.zip" | |
SHA256=$(shasum -a 256 "$ZIP_PATH" | awk '{print $1}') | |
echo "ZIP_SHA256=$SHA256" >> $GITHUB_ENV | |
echo "ZIP SHA256: $SHA256" | |
- name: Checkout Homebrew Tap | |
uses: actions/checkout@v4 | |
with: | |
repository: scanoss/homebrew-dist | |
path: homebrew-dist | |
token: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
- name: Update Cask Formula | |
run: | | |
APP_VERSION=$(git tag --sort=-version:refname | head -n 1) | |
APP_VERSION=${APP_VERSION#v} # Remove 'v' prefix if present | |
sed -i '' \ | |
-e "s/version \".*\"/version \"${APP_VERSION}\"/" \ | |
-e "s/sha256 \".*\"/sha256 \"${ZIP_SHA256}\"/" \ | |
homebrew-dist/Casks/scanoss-code-compare.rb | |
- name: Commit and Push Formula Update | |
run: | | |
cd homebrew-dist | |
git config user.name "SCANOSS Bot" | |
git config user.email "[email protected]" | |
git add Casks/scanoss-code-compare.rb | |
git commit -m "Update scanoss-code-compare to ${APP_VERSION}" | |
git push | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: artifact_m | |
path: | | |
dist/*.zip | |
build_linux: | |
name: Build for Linux | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
# Setup and configure GoLang | |
- name: Setup GoLang | |
uses: actions/setup-go@v5 | |
with: | |
check-latest: true | |
go-version: ${{ env.GOLANG_VERSION }} | |
- run: go version | |
shell: bash | |
# Setup and configure NodeJS | |
- name: Setup NodeJS | |
uses: actions/setup-node@v4 | |
with: | |
node-version: ${{ env.NODE_VERSION }} | |
# Install Wails | |
- name: Install Wails | |
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest | |
shell: bash | |
# Install Linux Wails deps | |
- name: Install Linux Wails deps | |
run: sudo apt-get update && sudo apt-get install libgtk-3-0 libwebkit2gtk-4.0-dev gcc-aarch64-linux-gnu | |
shell: bash | |
# Build | |
- name: Build App | |
run: | | |
mkdir -p build/bin | |
cp -r assets build/assets | |
cp assets/appicon.png build | |
wails build -ldflags "-X github.com/scanoss/scanoss.cc/backend/entities.AppVersion=$(git tag --sort=-version:refname | head -n 1)" --platform linux/amd64 -o "${{ env.ARTIFACT_NAME_PREFIX }}-linux" | |
shell: bash | |
- name: Make binary executable | |
run: chmod +x "./build/bin/${{ env.ARTIFACT_NAME_PREFIX }}-linux" | |
shell: bash | |
- name: Create AppImage | |
run: | | |
mkdir -p AppDir/usr/bin | |
cp "./build/bin/${{ env.ARTIFACT_NAME_PREFIX }}-linux" "AppDir/usr/bin/${{ env.ARTIFACT_NAME_PREFIX }}" | |
cp build/appicon.png AppDir/ | |
cp -r build/assets AppDir/ | |
- name: Create ZIP file | |
run: | | |
cd ./build/bin | |
zip -r "${{ env.ARTIFACT_NAME_PREFIX }}-linux.zip" "${{ env.ARTIFACT_NAME_PREFIX }}-linux" | |
shell: bash | |
- name: Upload build assets | |
uses: actions/upload-artifact@v4 | |
with: | |
name: artifact_l | |
path: ./build/bin/${{ env.ARTIFACT_NAME_PREFIX }}-linux.zip | |
build_w: | |
name: Build for Windows | |
runs-on: windows-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
# Setup and configure GoLang | |
- name: Setup GoLang | |
uses: actions/setup-go@v5 | |
with: | |
check-latest: true | |
go-version: ${{ env.GOLANG_VERSION }} | |
- run: go version | |
shell: bash | |
# Setup and configure Node JS | |
- name: Setup NodeJS | |
uses: actions/setup-node@v4 | |
with: | |
node-version: ${{ env.NODE_VERSION }} | |
# Install Wails | |
- name: Install Wails | |
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest | |
shell: bash | |
# Build | |
- name: Build App | |
run: | | |
mkdir -p build/bin | |
cp -r assets build/assets | |
cp assets/appicon.png build | |
wails build -ldflags "-X github.com/scanoss/scanoss.cc/backend/entities.AppVersion=$(git tag --sort=-version:refname | head -n 1)" --platform "windows/amd64" -webview2 download -o "${{ env.ARTIFACT_NAME_PREFIX }}-windows.exe" | |
shell: bash | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: artifact_w_unsigned | |
path: | | |
build/bin/${{ env.ARTIFACT_NAME_PREFIX }}*.exe | |
build_w_sign: | |
name: "Sign with CodeSignTool" | |
needs: [build_w] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Download artifact W unsigned | |
uses: actions/download-artifact@v4 | |
with: | |
name: artifact_w_unsigned | |
#This stage locates the unsigned .exe binary and move to win_unsigned folder. | |
#CodeSignTool does not support reading and writting into the same filepath | |
- name: Find Windows Artifact Path | |
id: win-path-artifact | |
run: | | |
# Use find to locate the exe file | |
WIN_BINARY_FILEPATH=$(find . -name "${{ env.ARTIFACT_NAME_PREFIX }}-windows.exe") | |
mkdir -p win_unsigned | |
mv "$WIN_BINARY_FILEPATH" win_unsigned/ | |
echo "ARTIFACT_WIN_PATH=win_unsigned/$(basename "$WIN_BINARY_FILEPATH")" >> "$GITHUB_OUTPUT" | |
shell: bash | |
- name: Sign Windows Artifact with CodeSignTool | |
uses: sslcom/esigner-codesign@develop | |
env: | |
ARTIFACT_WIN_PATH: ${{ steps.win-path-artifact.outputs.ARTIFACT_WIN_PATH }} | |
with: | |
command: sign | |
username: ${{secrets.WINDOWS_CODE_SIGNING_TOOL_ES_USERNAME}} | |
password: ${{secrets.WINDOWS_CODE_SIGNING_TOOL_ES_PASSWORD}} | |
credential_id: ${{secrets.WINDOWS_CODE_SIGNING_TOOL_CREDENTIAL_ID}} | |
totp_secret: ${{secrets.WINDOWS_CODE_SIGNING_TOOL_ES_TOTP_SECRET}} | |
file_path: ${GITHUB_WORKSPACE}/${{ env.ARTIFACT_WIN_PATH }} | |
output_path: ${GITHUB_WORKSPACE} | |
- name: zip file | |
shell: bash | |
run: | | |
mkdir -p build/bin | |
cd win_unsigned | |
# Create zip from the current directory | |
zip -j "../build/bin/${{ env.ARTIFACT_NAME_PREFIX }}-win.zip" "${{ env.ARTIFACT_NAME_PREFIX }}-windows.exe" | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: artifact_w | |
path: | | |
build/bin/*.zip | |
create_release: | |
needs: [build_w_sign, build_mac, build_linux] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Download artifact W | |
uses: actions/download-artifact@v4 | |
with: | |
name: artifact_w | |
- name: Download artifact M | |
uses: actions/download-artifact@v4 | |
with: | |
name: artifact_m | |
- name: Download artifact L | |
uses: actions/download-artifact@v4 | |
with: | |
name: artifact_l | |
- name: Create Release | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
# Create an array of zip files | |
zip_files=() | |
while IFS= read -r -d '' file; do | |
zip_files+=("$file") | |
done < <(find . -name "*.zip" -print0) | |
# Create the release with all zip files | |
gh release create "${{ github.ref_name }}" \ | |
--repo "${{ github.repository }}" \ | |
--generate-notes \ | |
--draft \ | |
"${zip_files[@]}" | |
shell: bash | |