Skip to content
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
153 changes: 153 additions & 0 deletions .github/workflows/build-mac-bundle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: Build Mac Bundle

on:
push:
branches:
- master

jobs:
build:
runs-on: macos-latest

env:
WASM_BINDGEN_CLI_VERSION: "0.2.100"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
override: true
rustflags: ""
target: wasm32-unknown-unknown

- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
cache-dependency-path: |
package-lock.json
frontend/package-lock.json

- name: Install Native Dependencies
env:
GITHUB_TOKEN: ${{ github.token }}
BINSTALL_DISABLE_TELEMETRY: "true"
run: |
brew update
brew install \
pkg-config \
openssl@3 \
binaryen \
llvm \
cargo-binstall

echo "OPENSSL_DIR=$(brew --prefix openssl@3)" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=$(brew --prefix openssl@3)/lib/pkgconfig" >> $GITHUB_ENV
echo "$(brew --prefix llvm)/bin" >> $GITHUB_PATH

cargo binstall --no-confirm --force wasm-pack
cargo binstall --no-confirm --force cargo-about
cargo binstall --no-confirm --force "wasm-bindgen-cli@${WASM_BINDGEN_CLI_VERSION}"

- name: Build Mac Bundle
env:
CARGO_TERM_COLOR: always
run: npm run build-desktop

- name: Stage Artifacts
shell: bash
run: |
rm -rf target/artifacts
mkdir -p target/artifacts
cp -R target/release/Graphite.app target/artifacts/Graphite.app

- name: Upload Mac Bundle
uses: actions/upload-artifact@v4
with:
name: graphite-mac-bundle
path: target/artifacts

- name: Sign and Notarize Mac Bundle Preparation
env:
APPLE_CERT_BASE64: ${{ secrets.APPLE_CERT_BASE64 }}
APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }}
run: |
mkdir -p .sign
echo "$APPLE_CERT_BASE64" | base64 --decode > .sign/certificate.p12

security create-keychain -p "" .sign/main.keychain
security default-keychain -s .sign/main.keychain
security unlock-keychain -p "" .sign/main.keychain
security set-keychain-settings -t 3600 -u .sign/main.keychain

security import .sign/certificate.p12 -k .sign/main.keychain -P "$APPLE_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
security set-key-partition-list -S apple-tool:,apple: -s -k "" .sign/main.keychain

cat > .sign/entitlements.plist <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
EOF

- name: Sign and Notarize Mac Bundle
env:
APPLE_EMAIL: ${{ secrets.APPLE_EMAIL }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_CERT_NAME: ${{ secrets.APPLE_CERT_NAME }}
run: |
CERTIFICATE="$APPLE_CERT_NAME"
ENTITLEMENTS=".sign/entitlements.plist"
APP_PATH="target/artifacts/Graphite.app"
ZIP_PATH=".sign/Graphite.zip"

codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Graphite Helper.app"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Graphite Helper (GPU).app"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Graphite Helper (Renderer).app"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Chromium Embedded Framework.framework"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libcef_sandbox.dylib"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libEGL.dylib"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libGLESv2.dylib"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libvk_swiftshader.dylib"
codesign --force --options runtime --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE" "$APP_PATH" --deep

codesign --verify --deep --strict --verbose=4 "$APP_PATH"

ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"
xcrun notarytool submit "$ZIP_PATH" --wait --apple-id "$APPLE_EMAIL" --team-id "$APPLE_TEAM_ID" --password "$APPLE_PASSWORD"
rm "$ZIP_PATH"

xcrun stapler staple -v "$APP_PATH"

spctl -a -vv "$APP_PATH"

- name: Upload Mac Bundle Signed
uses: actions/upload-artifact@v4
with:
name: graphite-mac-bundle-signed
path: target/artifacts
167 changes: 167 additions & 0 deletions .github/workflows/build-win-bundle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
name: Build Windows Bundle

on:
push:
branches:
- master

permissions:
contents: read
id-token: write

jobs:
build:
runs-on: windows-latest

env:
WASM_BINDGEN_CLI_VERSION: "0.2.100"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
override: true
rustflags: ""
target: wasm32-unknown-unknown

- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
${{ env.USERPROFILE }}\.cargo\registry
${{ env.USERPROFILE }}\.cargo\git
target
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
cache-dependency-path: |
package-lock.json
frontend/package-lock.json

- name: Setup Cargo Binstall
uses: cargo-bins/cargo-binstall@main

- name: Install Native Dependencies
shell: pwsh
env:
GITHUB_TOKEN: ${{ github.token }}
BINSTALL_DISABLE_TELEMETRY: "true"
run: |
winget install --id LLVM.LLVM -e --accept-package-agreements --accept-source-agreements
winget install --id Kitware.CMake -e --accept-package-agreements --accept-source-agreements
winget install --id OpenSSL.OpenSSL -e --accept-package-agreements --accept-source-agreements
winget install --id WebAssembly.Binaryen -e --accept-package-agreements --accept-source-agreements
winget install --id GnuWin32.PkgConfig -e --accept-package-agreements --accept-source-agreements

"OPENSSL_DIR=C:\Program Files\OpenSSL-Win64" | Out-File -FilePath $env:GITHUB_ENV -Append
"PKG_CONFIG_PATH=C:\Program Files\OpenSSL-Win64\lib\pkgconfig" | Out-File -FilePath $env:GITHUB_ENV -Append

cargo binstall --no-confirm --force wasm-pack
cargo binstall --no-confirm --force cargo-about
cargo binstall --no-confirm --force "wasm-bindgen-cli@$env:WASM_BINDGEN_CLI_VERSION"

- name: Build Windows Bundle
env:
CARGO_TERM_COLOR: always
run: npm run build-desktop

- name: Stage Artifacts
shell: bash
run: |
rm -rf target/artifacts
mkdir -p target/artifacts
cp -R target/release/Graphite target/artifacts/Graphite

- name: Upload Windows Bundle
uses: actions/upload-artifact@v4
with:
name: graphite-windows-bundle
path: target/artifacts

- name: Azure login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true

- name: Sign
uses: azure/artifact-signing-action@v1
with:
endpoint: https://eus.codesigning.azure.net/
signing-account-name: Graphite
certificate-profile-name: Graphite
files: |
${{ github.workspace }}\target\artifacts\Graphite\Graphite.exe
${{ github.workspace }}\target\artifacts\Graphite\libcef.dll
${{ github.workspace }}\target\artifacts\Graphite\chrome_elf.dll
${{ github.workspace }}\target\artifacts\Graphite\vulkan-1.dll
${{ github.workspace }}\target\artifacts\Graphite\dxcompiler.dll
${{ github.workspace }}\target\artifacts\Graphite\libEGL.dll
${{ github.workspace }}\target\artifacts\Graphite\libGLESv2.dll
${{ github.workspace }}\target\artifacts\Graphite\vk_swiftshader.dll
file-digest: SHA256
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
correlation-id: ${{ github.sha }}

- name: Verify Signatures
shell: pwsh
run: |
$ErrorActionPreference = "Stop"

$TargetDir = "target\artifacts\Graphite"

if (-not (Test-Path $TargetDir)) {
throw "TargetDir not found: $TargetDir"
}

$UnsignedOrBad = @()

Get-ChildItem -Path $TargetDir -Recurse -File -Include *.exe,*.dll | ForEach-Object {
$sig = Get-AuthenticodeSignature -FilePath $_.FullName

if ($sig.Status -ne 'Valid') {
$UnsignedOrBad += "$($_.FullName) (Status=$($sig.Status))"
}
}

if ($UnsignedOrBad.Count -gt 0) {
Write-Host "Unsigned or invalid binaries detected:"
$UnsignedOrBad | ForEach-Object {
Write-Host "::error::$_"
}

if ($env:GITHUB_STEP_SUMMARY) {
"### ❌ Unsigned or invalid binaries detected" |
Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
"" | Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
$UnsignedOrBad | ForEach-Object {
"* `$_" | Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
}
}

exit 1
}

Write-Host "All binaries are signed and valid."

if ($env:GITHUB_STEP_SUMMARY) {
"### ✅ All binaries are signed and valid" |
Out-File $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
}

- name: Upload Windows Bundle Signed
uses: actions/upload-artifact@v4
with:
name: graphite-windows-bundle-signed
path: target/artifacts
25 changes: 25 additions & 0 deletions desktop/bundle/src/win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,33 @@ fn bundle(out_dir: &Path, app_bin: &Path) -> PathBuf {

copy_dir(&cef_path(), &app_dir);

if let Err(e) = remove_unnecessary_cef_files(&app_dir) {
eprintln!("Failed to remove unnecessary CEF files: {}", e);
}

let bin_path = app_dir.join(EXECUTABLE);
fs::copy(app_bin, &bin_path).unwrap();

bin_path
}

fn remove_unnecessary_cef_files(app_dir: &Path) -> Result<(), Box<dyn Error>> {
fs::remove_dir_all(app_dir.join("cmake"))?;
fs::remove_dir_all(app_dir.join("include"))?;
fs::remove_dir_all(app_dir.join("libcef_dll"))?;

for entry in fs::read_dir(app_dir.join("locales"))? {
let path = entry?.path();
if path.is_file() && path.file_name() != Some("en-US.pak".as_ref()) {
fs::remove_file(path)?;
}
}

fs::remove_file(app_dir.join("archive.json"))?;
fs::remove_file(app_dir.join("CMakeLists.txt"))?;
fs::remove_file(app_dir.join("bootstrapc.exe"))?;
fs::remove_file(app_dir.join("bootstrap.exe"))?;
fs::remove_file(app_dir.join("libcef.lib"))?;

Ok(())
}
2 changes: 1 addition & 1 deletion desktop/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ impl ApplicationHandler for App {
}
}

fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
fn new_events(&mut self, _event_loop: &dyn ActiveEventLoop, cause: winit::event::StartCause) {
if let StartCause::ResumeTimeReached { .. } = cause
&& let Some(window) = &self.window
{
Expand Down
Loading