diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3dc8d6b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,74 @@ +name: Build Launcher +on: + pull_request: + push: + branches: + - "main" + +jobs: + build: + # both Windows and Linux builds run on Ubuntu + runs-on: ${{ matrix.build == 'macos' && 'macos' || 'ubuntu' }}-latest + strategy: + fail-fast: false + matrix: + build: [macos, windows, linux] + + steps: + - uses: actions/checkout@v3 + + - uses: chickensoft-games/setup-godot@v1 + with: + version: 4.2.1 + use-dotnet: false + + - name: Verify Setup + run: | + godot --version + + - name: Import certificate to Keychain + if: ${{ matrix.build == 'macos' }} + run: | + echo "${{ secrets.MACOS_CERTIFICATE }}" | base64 --decode > certificate.p12 + KEYCHAIN_PASSWORD=$(uuidgen) + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security import ./certificate.p12 -k ~/Library/Keychains/build.keychain -P ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" ~/Library/Keychains/build.keychain + env: + MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} + + - name: Setup notarization credentials + if: ${{ matrix.build == 'macos' }} + run: | + echo ${{ secrets.GODOT_MACOS_NOTARIZATION_API_KEY }} | base64 --decode > notarization_api_key.p8 + + - name: Export build + run: | + name="${{fromJSON('{"windows": "Windows Desktop", "macos": "macOS", "linux": "Linux/X11"}')[matrix.build] }}" + godot --headless --export-debug "$name" --verbose 2>&1 | tee build.log + + env: + GODOT_MACOS_NOTARIZATION_API_KEY_ID: + ${{ secrets.GODOT_MACOS_NOTARIZATION_API_KEY_ID }} + GODOT_MACOS_NOTARIZATION_API_KEY: ./notarization_api_key.p8 + GODOT_MACOS_NOTARIZATION_API_UUID: + ${{ secrets.GODOT_MACOS_NOTARIZATION_API_UUID }} + + - name: Upload build + uses: actions/upload-artifact@v4 + with: + name: drivechain_launcher_${{ matrix.build }} + if-no-files-found: error + path: build/drivechain_launcher-* + + - name: Wait for notarization to finish + if: ${{ matrix.build == 'macos' }} + run: | + request_id=$(grep 'Notarization request UUID' build.log | rev | cut -d ' ' -f 1 | rev | tr -d '"') + + xcrun notarytool wait $request_id \ + --issuer ${{ secrets.GODOT_MACOS_NOTARIZATION_API_UUID }} \ + --key-id ${{ secrets.GODOT_MACOS_NOTARIZATION_API_KEY_ID }} \ + --key ./notarization_api_key.p8 diff --git a/.gitignore b/.gitignore index 4709183..6be785a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ # Godot 4+ specific ignores .godot/ + +# Built artifacts go here +build diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ec8794d --- /dev/null +++ b/.prettierrc @@ -0,0 +1 @@ +{"proseWrap": "always"} \ No newline at end of file diff --git a/README.md b/README.md index 542a304..f1a9566 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,9 @@ This application is built using [Godot](https://github.com/godotengine/godot). -Godot may seem like an odd choice at first glance, but with its cross-platform abilities and an amazing set of GUI & IO features, it makes it very capable for this application. +Godot may seem like an odd choice at first glance, but with its cross-platform +abilities and an amazing set of GUI & IO features, it makes it very capable for +this application. We can currently run on Mac, Windows, and Linux. @@ -12,53 +14,145 @@ If you'd like to build from source, check below. ## Development Environment Prerequisites -- Godot 4.1.1 [Download Page](https://godotengine.org/download) +- Godot 4.2.1 [Download Page](https://godotengine.org/download) -Currently only scripted in GDScript, but we could use the .NET version of Godot which brings C# support. +```bash +# macOS +$ brew install godot -Once you've gotten your development environment set up: +# Ubuntu/Debian +$ snap install godot-4 # note: this gets installed as godot-4, not godot -- Clone repo -- Open the project and run +# Windows +$ choco install godot +``` -### Important +## Getting started -The app relies on external binaries to be downloaded from a specific GitHub release. This is a bit cumbersome, -but was the best we could come up with for now. +Ensure that `godot` is installed such that is in on your `$PATH`. -- chain_providers.cfg are where each of the sidechain configs starts. - The hash and file size for each platform binary is manually generated and added to the config - for the release if it has changed. -- version.cfg is where you would update the version and base GitHub release URL. - Sometimes you may need to create a pre-release, upload all the binaries there and point to that - as you are developing. -- Currently, each platform version is built on its respective platform. So build the launcher for Linux on Linux, - Mac on Mac, and Windows on Windows. -- Mac is a bit different as you need to have a developer ID certificate so that Godot can request a signature and - notarization. Whoever does this will need to create a signing certificate request and have Paul then create a - new developer ID certificate with that request. Then you would install that into your Mac keychain. - More info here: https://developer.apple.com/help/account/create-certificates/create-developer-id-certificates +For building releases, so-called "export templates" has to be downloaded. These +are available from the official +[website](https://github.com/godotengine/godot/releases/download/4.2.1-stable/Godot_v4.2.1-stable_export_templates.tpz). +Note that these are unique per version of Godot, but _not_ unique per platform +we're exporting for. + +From the GUI, these templates can be downloaded like this: + +1. "Project" menu in the toolbar +2. "Export" item within the "Project" menu +3. "Download and install" -### LICENSE +## Important + +The app relies on external binaries to be downloaded from a specific GitHub +release. This is a bit cumbersome, but was the best we could come up with for +now. + +- chain_providers.cfg are where each of the sidechain configs starts. The hash + and file size for each platform binary is manually generated and added to the + config for the release if it has changed. +- version.cfg is where you would update the version and base GitHub release URL. + Sometimes you may need to create a pre-release, upload all the binaries there + and point to that as you are developing. +- Currently, each platform version is built on its respective platform. So build + the launcher for Linux on Linux, Mac on Mac, and Windows on Windows. +- Mac is a bit different as you need to have a developer ID certificate so that + Godot can request a signature and notarization. Whoever does this will need to + create a signing certificate request and have Paul then create a new developer + ID certificate with that request. Then you would install that into your Mac + keychain. More info here: + https://developer.apple.com/help/account/create-certificates/create-developer-id-certificates + +## Export preset notes + +The file `export_presets.cfg` controls the export (i.e. build) process for the +Launcher. It is controlled through the Godot GUI. If you write comments in the +file, they will get **erased** once the file is saved. Furthermore, enums are +represented as numbers, not strings... + +`export_presets.cfg` is kept in Git. This file does not contain anything +sensitive. It is _merged_ with `.godot/export_credentials.cfg`, which _does_ +contain sensitive information. This file is also merged with certain environment +variables, such that this can be done on CI without fiddling around with files. + +### macOS + +Signing (and therefore also notarizing) the application requires having the +correct set of certificates + private keys on the machine doing the export. +Certificates can be viewed using `Keychain Access.app`. Seeing certificates +capable of signing (i.e. certificates with private keys): + +```bash +$ security find-identity -v -p codesigning | grep LayerTwo` +``` + +Notarizing the app requires an App Store Connect API key. Docs for generating +this can be found +[here](https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api). +There's three components to this key, which should go into +`.godot/export_credentials.cfg` before exporting: + +1. Issuer ID (`notarization/api_uuid`). This is an UUID indicating which + organization the key belongs to. This is available over the + [list of active keys](https://appstoreconnect.apple.com/access/integrations/api). +2. The key itself (`notarization/api_key`). This is a path to a `.p8` file, and + can only be obtained when creating the key. +3. Key ID (`notarization/api_key_id`). This is available in the + [list of active keys](https://appstoreconnect.apple.com/access/integrations/api). + +Explanation of export config file options: + +``` +export/distribution_type +0=testing ? +1=distribution +2=app store + +codesign/codesign +0=disabled +1=built-in ad-hoc +2=rcodesign ruby tool for exporting from Linux +3=Xcode codesign + +notarization/notarization +0=disabled +2=xcrun notarytool +``` + +Generate App Store Connect API keys: + +Download the key somewhere + +Docs on macOS: +https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_macos.html + +### Windows + +Signing (is that the correct Windows nomenclature?) of the build artifacts does +not happen in our pipeline. This leads to a scary pop-up warning the user when +they try and launch the app. This could probably be set up, somehow. Left as an +exercise to the reader! + +## LICENSE MIT License Copyright (c) 2023 Layer Two Labs -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build/.gitkeep b/build/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/export_presets.cfg b/export_presets.cfg index e95af85..ba794e6 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -8,7 +8,7 @@ custom_features="" export_filter="all_resources" include_filter="*.cfg" exclude_filter="" -export_path="../../../../../Desktop/drivechain_launcher-linux-1.2.0.x86_64" +export_path="build/drivechain_launcher-linux-1.2.0.x86_64" encryption_include_filters="" encryption_exclude_filters="" encrypt_pck=false @@ -48,7 +48,7 @@ custom_features="" export_filter="all_resources" include_filter="*.cfg" exclude_filter="" -export_path="../../../../../Desktop/windows-drivenet-launcher-1.2.0.exe" +export_path="./build/drivechain_launcher-windows-1.2.0.exe" encryption_include_filters="" encryption_exclude_filters="" encrypt_pck=false @@ -111,7 +111,7 @@ custom_features="" export_filter="all_resources" include_filter="*.cfg" exclude_filter="" -export_path="../../../Desktop/drivechain_launcher-osx64-1.2.0.dmg" +export_path="build/drivechain_launcher-osx64-1.2.0.dmg" encryption_include_filters="" encryption_exclude_filters="" encrypt_pck=false @@ -142,7 +142,7 @@ xcode/sdk_build="22C55" xcode/sdk_name="macosx13.1" xcode/xcode_version="1420" xcode/xcode_build="14C18" -codesign/codesign=2 +codesign/codesign=3 codesign/installer_identity="" codesign/apple_team_id="6AXPP357T2" codesign/identity="Developer ID Application: LayerTwo Labs, Inc. (6AXPP357T2)" @@ -171,7 +171,7 @@ codesign/entitlements/app_sandbox/files_movies=0 codesign/entitlements/app_sandbox/files_user_selected=0 codesign/entitlements/app_sandbox/helper_executables=[] codesign/custom_options=PackedStringArray() -notarization/notarization=1 +notarization/notarization=2 privacy/microphone_usage_description="" privacy/microphone_usage_description_localized={} privacy/camera_usage_description=""