Skip to content

bundle

bundle #370

Workflow file for this run

name: Bundle
on:
push:
repository_dispatch:
types:
- bundle
defaults:
run:
shell: bash # necessary for windows
jobs:
bundle:
name: Bundle for ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
# NOTE: Should use the oldest available Ubuntu release, for maximum compatibility
os: [windows-latest, macOS-12, ubuntu-20.04]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ matrix.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install latest rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
if [[ $RUNNER_OS == "Windows" ]]; then
echo "${WIX}bin" >> $GITHUB_PATH
choco install yq
elif [[ $RUNNER_OS == "macOS" ]]; then
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
brew install create-dmg
elif [[ $RUNNER_OS == "Linux" ]]; then
sudo apt-get update
sudo apt-get -y install libatk1.0-dev libgtk-3-dev libsdl2-dev
fi
- name: Unpack bundle configuration
if: github.event.client_payload.configuration_url != ''
env:
CONFIGURATION_URL: ${{ github.event.client_payload.configuration_url }}
run: |
echo ::add-mask::$CONFIGURATION_URL
curl -OL $CONFIGURATION_URL
7z -y x *.zip -oconfig 2>&1 >/dev/null
- name: Set bundle name
run: echo "BUNDLE_NAME=$(yq '.name' config/config.yaml)" >> $GITHUB_ENV
- name: Set bundle version
run: echo "BUNDLE_VERSION=$(yq '.version // "${{ github.ref_name }}"' config/config.yaml)" >> $GITHUB_ENV
- name: Build
run: |
BINARIES_PATH="$RUNNER_TEMP/binaries"
mkdir -p $BINARIES_PATH
if [[ $RUNNER_OS == "Windows" ]]; then
cargo build --locked --release --features "netplay"
cp target/release/nes-bundler.exe $BINARIES_PATH/nes-bundler-netplay.exe
cargo build --locked --release
cp target/release/nes-bundler.exe $BINARIES_PATH/nes-bundler.exe
elif [[ $RUNNER_OS == "macOS" ]]; then
mkdir -p target/release/
# x86
cargo build --locked --release --target=x86_64-apple-darwin --features "netplay" &
# arch
cargo build --locked --release --target=aarch64-apple-darwin --features "netplay" &
wait
lipo target/x86_64-apple-darwin/release/nes-bundler \
target/aarch64-apple-darwin/release/nes-bundler \
-create -output $BINARIES_PATH/nes-bundler-netplay
# x86
cargo build --locked --release --target=x86_64-apple-darwin &
# arch
cargo build --locked --release --target=aarch64-apple-darwin &
wait
lipo target/x86_64-apple-darwin/release/nes-bundler \
target/aarch64-apple-darwin/release/nes-bundler \
-create -output $BINARIES_PATH/nes-bundler
elif [[ $RUNNER_OS == "Linux" ]]; then
cargo build --locked --release --features "netplay"
mv target/release/nes-bundler $BINARIES_PATH/nes-bundler-netplay
cargo build --locked --release
mv target/release/nes-bundler $BINARIES_PATH/nes-bundler
fi
- name: Import Certificates (macOS)
if: runner.os == 'macOS'
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
# create temporary keychain
KEYCHAIN_PASSWORD=`openssl rand -hex 12`
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security default-keychain -s $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Prepare Artifacts
env:
CODE_SIGN_IDENTITY: ${{ secrets.CODE_SIGN_IDENTITY }}
run: |
rm -rf artifacts || true
mkdir artifacts
ARTIFACTS=`readlink -f artifacts`
BUNDLE_CONFIG=`readlink -f config`
BINARIES_PATH="$RUNNER_TEMP/binaries"
if [[ $RUNNER_OS == "Windows" ]]; then
# Create and add installers
mkdir wix
cp $BINARIES_PATH/nes-bundler-netplay.exe wix/nes-bundler.exe
candle $BUNDLE_CONFIG/windows/wix/main.wxs -o wix/
light wix/*.wixobj -o "$BINARIES_PATH/nes-bundler-netplay.msi" -ext WixUIExtension
cp -f $BINARIES_PATH/nes-bundler.exe wix/
candle $BUNDLE_CONFIG/windows/wix/main.wxs -o wix/
light wix/*.wixobj -o "$BINARIES_PATH/nes-bundler.msi" -ext WixUIExtension
# Add artifacts
mv $BINARIES_PATH/nes-bundler-netplay.msi "$ARTIFACTS/$BUNDLE_NAME (Netplay).msi"
mv $BINARIES_PATH/nes-bundler.msi "$ARTIFACTS/$BUNDLE_NAME.msi"
mv $BINARIES_PATH/nes-bundler-netplay.exe "$ARTIFACTS/$BUNDLE_NAME (Netplay).exe"
mv $BINARIES_PATH/nes-bundler.exe "$ARTIFACTS/$BUNDLE_NAME.exe"
elif [[ $RUNNER_OS == "macOS" ]]; then
# Prepare the app structure
APP_BUNDLE="$RUNNER_TEMP/nes-bundler.app"
mkdir -p $APP_BUNDLE/Contents/MacOS || true
mkdir -p $APP_BUNDLE/Contents/Resources || true
cp $BUNDLE_CONFIG/macos/Info.plist $APP_BUNDLE/Contents/
iconutil $BUNDLE_CONFIG/macos/bundle.iconset -c icns --output $APP_BUNDLE/Contents/Resources/bundle.icns
NETPLAY_APP="$RUNNER_TEMP/netplay/$BUNDLE_NAME.app"
NON_NETPLAY_APP="$RUNNER_TEMP/no-netplay/$BUNDLE_NAME.app"
mkdir -p "$NETPLAY_APP"
mkdir -p "$NON_NETPLAY_APP"
rsync -a $APP_BUNDLE/ "$NETPLAY_APP"
rsync -a $APP_BUNDLE/ "$NON_NETPLAY_APP"
mv $BINARIES_PATH/nes-bundler-netplay "$NETPLAY_APP/Contents/MacOS/$BUNDLE_NAME"
mv $BINARIES_PATH/nes-bundler "$NON_NETPLAY_APP/Contents/MacOS/$BUNDLE_NAME"
codesign --force --options=runtime -s $CODE_SIGN_IDENTITY "$NETPLAY_APP/Contents/MacOS/$BUNDLE_NAME"
codesign --force --options=runtime -s $CODE_SIGN_IDENTITY "$NON_NETPLAY_APP/Contents/MacOS/$BUNDLE_NAME"
create-dmg \
--volname "$BUNDLE_NAME Installer" \
--volicon "$APP_BUNDLE/Contents/Resources/bundle.icns" \
--window-pos 200 120 \
--window-size 800 400 \
--icon-size 100 \
--icon "$BUNDLE_NAME.app" 200 170 \
--hide-extension "$BUNDLE_NAME.app" \
--app-drop-link 600 165 \
"$ARTIFACTS/$BUNDLE_NAME Installer (Netplay).dmg" \
"$NETPLAY_APP/../"
create-dmg \
--volname "$BUNDLE_NAME Installer" \
--volicon "$APP_BUNDLE/Contents/Resources/bundle.icns" \
--window-pos 200 120 \
--window-size 800 400 \
--icon-size 100 \
--icon "$BUNDLE_NAME.app" 200 170 \
--hide-extension "$BUNDLE_NAME.app" \
--app-drop-link 600 165 \
"$ARTIFACTS/$BUNDLE_NAME Installer.dmg" \
"$NON_NETPLAY_APP/../"
elif [[ $RUNNER_OS == "Linux" ]]; then
# archive artifact
strip $BINARIES_PATH/nes-bundler
tar czvf $ARTIFACTS/nes-bundler-linux-x86_64.tar.gz $BINARIES_PATH/nes-bundler
strip $BINARIES_PATH/nes-bundler-netplay
tar czvf $ARTIFACTS/nes-bundler-netplay-linux-x86_64.tar.gz $BINARIES_PATH/nes-bundler-netplay
# create appimage
curl -Lo linuxdeploy https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy
curl -Lo linuxdeploy-plugin-appimage https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/latest/download/linuxdeploy-plugin-appimage-x86_64.AppImage
chmod +x linuxdeploy-plugin-appimage
export LDAI_OUTPUT=nes-bundler.AppImage
export LDAI_UPDATE_INFORMATION="gh-releases-zsync|nes-bundler|nes-bundler|latest|nes-bundler.AppImage.zsync"
./linuxdeploy \
--executable=$BINARIES_PATH/nes-bundler \
--desktop-file=$BUNDLE_CONFIG/linux/bundle.desktop \
--appdir=AppDir \
--icon-file=$BUNDLE_CONFIG/linux/icon_256x256.png \
--output=appimage
mv nes-bundler.AppImage $ARTIFACTS/
mv nes-bundler.AppImage.zsync $ARTIFACTS/
mv $BINARIES_PATH/nes-bundler-netplay $BINARIES_PATH/nes-bundler
./linuxdeploy \
--executable=$BINARIES_PATH/nes-bundler \
--desktop-file=$BUNDLE_CONFIG/linux/bundle.desktop \
--appdir=AppDir \
--icon-file=$BUNDLE_CONFIG/linux/icon_256x256.png \
--output=appimage
mv nes-bundler.AppImage $ARTIFACTS/
mv nes-bundler.AppImage.zsync $ARTIFACTS/
fi
echo "RUNNER_OS=$RUNNER_OS" >> $GITHUB_ENV
- name: Sign and notarize final artifacts
# if: startsWith(github.event.ref, 'refs/tags/v')
env:
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
BUNDLE_APPLE_TEAM_ID: ${{ secrets.BUNDLE_APPLE_TEAM_ID }}
BUNDLE_APPLE_USER: ${{ secrets.BUNDLE_APPLE_USER }}
BUNDLE_APPLE_APP_PASSWORD: ${{ secrets.BUNDLE_APPLE_APP_PASSWORD }}
run: |
ARTIFACTS=`readlink -f artifacts`
if [[ $RUNNER_OS == "Windows" ]]; then
dotnet tool install --global AzureSignTool
for Item in "$BUNDLE_NAME (Netplay).exe" "$BUNDLE_NAME.exe" "$BUNDLE_NAME (Netplay).msi" "$BUNDLE_NAME.msi" ;
do
AzureSignTool sign -d "$BUNDLE_NAME" -kvu "${{ secrets.AZURE_KEY_VAULT_URI }}" -kvi "${{ secrets.AZURE_CLIENT_ID }}" -kvt "${{ secrets.AZURE_TENANT_ID }}" -kvs "${{ secrets.AZURE_CLIENT_SECRET }}" -kvc ${{ secrets.AZURE_CERT_NAME }} -tr http://timestamp.digicert.com -v "$ARTIFACTS/$Item" &
done
wait
elif [[ $RUNNER_OS == "macOS" ]]; then
# apply provisioning profile
PP_PATH=$RUNNER_TEMP/build_pp.provisionprofile
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
# Notarize
ARTIFACT1="$ARTIFACTS/$BUNDLE_NAME Installer (Netplay).dmg"
ARTIFACT2="$ARTIFACTS/$BUNDLE_NAME Installer.dmg"
xcrun notarytool submit \
--team-id $BUNDLE_APPLE_TEAM_ID \
--apple-id $BUNDLE_APPLE_USER \
--password $BUNDLE_APPLE_APP_PASSWORD \
--wait "$ARTIFACT1" &
xcrun notarytool submit \
--team-id $BUNDLE_APPLE_TEAM_ID \
--apple-id $BUNDLE_APPLE_USER \
--password $BUNDLE_APPLE_APP_PASSWORD \
--wait "$ARTIFACT2" &
wait
xcrun stapler staple "$ARTIFACT1"
xcrun stapler staple "$ARTIFACT2"
fi
- name: Password protect bundle
if: github.event.client_payload.configuration_url != ''
id: zip-bundle
run: |
BUNDLE_PASSWORD=$(openssl rand -hex 24)
echo ::add-mask::$BUNDLE_PASSWORD
7z a -p$BUNDLE_PASSWORD password_protected.zip artifacts/*
rm -rf artifacts/*
mv password_protected.zip artifacts/
echo "BUNDLE_PASSWORD=$BUNDLE_PASSWORD" >> $GITHUB_ENV
- uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: ${{ env.BUNDLE_NAME }} ${{ env.BUNDLE_VERSION }} ${{ env.RUNNER_OS }}
path: artifacts/*
- name: Get email address
if: always() && github.event.client_payload.recipient_email != ''
env:
RECIPIENT_EMAIL: ${{ github.event.client_payload.recipient_email }}
run: |
echo ::add-mask::$RECIPIENT_EMAIL
echo "RECIPIENT_EMAIL=$RECIPIENT_EMAIL" >> $GITHUB_ENV
- name: Create email
if: github.event.client_payload.recipient_email != ''
run: |
cat <<'EOF' >> email.html
<p>
<a href="${{ steps.artifact-upload-step.outputs.artifact-url }}">${{ env.BUNDLE_NAME }} ${{ env.BUNDLE_VERSION }} ${{ env.RUNNER_OS }}.zip</a><br />
Zip password: ${{ env.BUNDLE_PASSWORD }}
</p>
<p>The downloads will be available for 90 days and you have to be logged in to GitHub to access it.</p>
<p>Thanks for using NES Bundler!</p>
EOF
- name: Email bundle
if: github.event.client_payload.recipient_email != ''
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 465
username: ${{secrets.MAIL_USERNAME}}
password: ${{secrets.MAIL_PASSWORD}}
subject: ${{ env.BUNDLE_NAME }} for ${{ env.RUNNER_OS }} is bundled!
to: ${{ env.RECIPIENT_EMAIL }}
from: NES Bundler
html_body: file://email.html
- name: Email failure message
if: failure() && github.event.client_payload.recipient_email != ''
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 465
username: ${{secrets.MAIL_USERNAME}}
password: ${{secrets.MAIL_PASSWORD}}
subject: There was a problem serving your bundle request
to: ${{ env.RECIPIENT_EMAIL }}
from: NES Bundler
body: Go here ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} for details
release:
name: Release
needs: bundle
if: startsWith(github.event.ref, 'refs/tags/v') && github.event.client_payload.configuration_url == ''
runs-on: ubuntu-latest
steps:
- name: Get artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Zip artifact directories
working-directory: artifacts
run: |
for subdir in */; do
dirname=$(basename "$subdir")
zip -r "$dirname.zip" "$subdir"
done
- name: Create Release
uses: softprops/action-gh-release@v1
with:
name: ${{ github.ref_name }}
draft: false
prerelease: false
generate_release_notes: true
files: "artifacts/*.zip"