Consolidate separate platform CI build workflows and improve !build c… #3
This file contains hidden or 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: "Build" | |
| on: | |
| push: | |
| branches: | |
| - master | |
| workflow_dispatch: | |
| inputs: | |
| web: | |
| description: "Web" | |
| type: boolean | |
| windows: | |
| description: "Windows" | |
| type: boolean | |
| mac: | |
| description: "Mac" | |
| type: boolean | |
| linux: | |
| description: "Linux" | |
| type: boolean | |
| push_to_nix_cache: | |
| description: "Linux: push to Nix cache" | |
| type: boolean | |
| debug: | |
| description: "Debug build" | |
| type: boolean | |
| workflow_call: | |
| inputs: | |
| web: | |
| type: boolean | |
| windows: | |
| type: boolean | |
| mac: | |
| type: boolean | |
| linux: | |
| type: boolean | |
| push_to_nix_cache: | |
| type: boolean | |
| debug: | |
| type: boolean | |
| checkout_repo: | |
| type: string | |
| checkout_ref: | |
| type: string | |
| pr_number: | |
| type: string | |
| jobs: | |
| web: | |
| if: github.event_name == 'push' || inputs.web | |
| runs-on: [self-hosted, target/wasm] | |
| permissions: | |
| contents: write | |
| deployments: write | |
| pull-requests: write | |
| actions: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUSTC_WRAPPER: /usr/bin/sccache | |
| CARGO_INCREMENTAL: 0 | |
| SCCACHE_DIR: /var/lib/github-actions/.cache | |
| INDEX_HTML_HEAD_REPLACEMENT: <script defer data-domain="dev.graphite.art" data-api="https://graphite.art/visit/event" src="https://graphite.art/visit/script.hash.js"></script> | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ inputs.checkout_repo || github.repository }} | |
| ref: ${{ inputs.checkout_ref || '' }} | |
| - name: 🗑 Clear wasm-bindgen cache | |
| run: rm -r ~/.cache/.wasm-pack || true | |
| - name: 🟢 Install Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version-file: .nvmrc | |
| - name: 🚧 Install build dependencies | |
| run: | | |
| cd frontend | |
| npm run setup | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| override: true | |
| rustflags: "" | |
| target: wasm32-unknown-unknown | |
| - name: ✂ Replace template in <head> of index.html | |
| if: github.event_name == 'push' | |
| run: | | |
| sed -i "s|<!-- INDEX_HTML_HEAD_REPLACEMENT -->|$INDEX_HTML_HEAD_REPLACEMENT|" frontend/index.html | |
| - name: 🌐 Build Graphite web code | |
| env: | |
| NODE_ENV: production | |
| run: mold -run cargo run build web${{ inputs.debug && ' debug' || '' }} | |
| - name: 📤 Publish to Cloudflare Pages | |
| id: cloudflare | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| run: | | |
| MAX_ATTEMPTS=5 | |
| DELAY=30 | |
| for ATTEMPT in $(seq 1 $MAX_ATTEMPTS); do | |
| echo "Attempt $ATTEMPT of $MAX_ATTEMPTS..." | |
| if OUTPUT=$(npx wrangler@3 pages deploy "frontend/dist" --project-name="graphite-dev" --commit-dirty=true 2>&1); then | |
| URL=$(echo "$OUTPUT" | grep -oP 'https://[^\s]+\.pages\.dev' | head -1) | |
| echo "url=$URL" >> "$GITHUB_OUTPUT" | |
| echo "Published successfully: $URL" | |
| exit 0 | |
| fi | |
| echo "Attempt $ATTEMPT failed:" | |
| echo "$OUTPUT" | |
| if [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; then | |
| echo "Retrying in ${DELAY}s..." | |
| sleep $DELAY | |
| DELAY=$((DELAY * 3)) | |
| fi | |
| done | |
| echo "All $MAX_ATTEMPTS Cloudflare Pages publish attempts failed." | |
| exit 1 | |
| - name: 💬 Comment with the build link | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CF_URL: ${{ steps.cloudflare.outputs.url }} | |
| run: | | |
| if [ -z "$CF_URL" ]; then | |
| echo "No Cloudflare URL available, skipping comment." | |
| exit 0 | |
| fi | |
| COMMENT_BODY="| 📦 **Web Build Complete for** $(git rev-parse HEAD) | | |
| |-| | |
| | $CF_URL |" | |
| if [ "${{ github.event_name }}" = "push" ]; then | |
| # Comment on the commit hash page | |
| gh api \ | |
| -X POST \ | |
| -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/commits/$(git rev-parse HEAD)/comments \ | |
| -f body="$COMMENT_BODY" | |
| else | |
| # Comment on the PR (use provided PR number from !build, or look it up by branch name) | |
| PR_NUMBER="${{ inputs.pr_number }}" | |
| if [ -z "$PR_NUMBER" ]; then | |
| BRANCH=$(git rev-parse --abbrev-ref HEAD) | |
| PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true) | |
| fi | |
| if [ -n "$PR_NUMBER" ]; then | |
| gh pr comment "$PR_NUMBER" --repo ${{ github.repository }} --body "$COMMENT_BODY" | |
| else | |
| echo "No open PR found, skipping comment." | |
| fi | |
| fi | |
| - name: ✂ Strip analytics script from built output for clean artifact | |
| if: github.event_name == 'push' | |
| run: | | |
| sed -i "s|$INDEX_HTML_HEAD_REPLACEMENT||" frontend/dist/index.html | |
| - name: 📦 Upload web bundle artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-web-bundle | |
| path: frontend/dist | |
| - name: 📃 Generate code documentation info for website | |
| if: github.event_name == 'push' | |
| run: | | |
| cd tools/editor-message-tree | |
| cargo run | |
| cd ../.. | |
| mkdir -p artifacts-generated | |
| mv website/generated/hierarchical_message_system_tree.txt artifacts-generated/hierarchical_message_system_tree.txt | |
| - name: 💿 Obtain cache of auto-generated code docs artifacts, to check if they've changed | |
| if: github.event_name == 'push' | |
| id: cache-website-code-docs | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: artifacts | |
| key: website-code-docs | |
| - name: 🔍 Check if auto-generated code docs artifacts changed | |
| if: github.event_name == 'push' | |
| id: website-code-docs-changed | |
| run: | | |
| if ! diff --brief --recursive artifacts-generated artifacts; then | |
| echo "Auto-generated code docs artifacts have changed." | |
| rm -rf artifacts | |
| mv artifacts-generated artifacts | |
| echo "changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Auto-generated code docs artifacts have not changed." | |
| rm -rf artifacts | |
| rm -rf artifacts-generated | |
| fi | |
| - name: 💾 Save cache of auto-generated code docs artifacts | |
| if: github.event_name == 'push' && steps.website-code-docs-changed.outputs.changed == 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: artifacts | |
| key: ${{ steps.cache-website-code-docs.outputs.cache-primary-key }} | |
| - name: ♻️ Trigger website rebuild if the auto-generated code docs artifacts have changed | |
| if: github.event_name == 'push' && steps.website-code-docs-changed.outputs.changed == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| rm -rf artifacts | |
| gh workflow run website.yml --ref master | |
| windows: | |
| if: github.event_name == 'push' || inputs.windows | |
| runs-on: windows-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| pull-requests: write | |
| env: | |
| WASM_BINDGEN_CLI_VERSION: "0.2.100" | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ inputs.checkout_repo || github.repository }} | |
| ref: ${{ inputs.checkout_ref || '' }} | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| override: true | |
| rustflags: "" | |
| target: wasm32-unknown-unknown | |
| - name: 💾 Set up Cargo cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ${{ env.USERPROFILE }}\.cargo\registry | |
| ${{ env.USERPROFILE }}\.cargo\git | |
| target | |
| key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }} | |
| - name: 🟢 Install Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version-file: .nvmrc | |
| cache: npm | |
| cache-dependency-path: | | |
| package-lock.json | |
| frontend/package-lock.json | |
| - name: 📦 Install 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 | |
| shell: bash # `cargo-about` refuses to run in powershell | |
| env: | |
| CARGO_TERM_COLOR: always | |
| run: cargo run build desktop${{ inputs.debug && ' debug' || '' }} | |
| - name: 📁 Stage artifacts | |
| shell: bash | |
| run: | | |
| PROFILE=${{ inputs.debug && 'debug' || 'release' }} | |
| rm -rf target/artifacts | |
| mkdir -p target/artifacts | |
| cp -R target/$PROFILE/Graphite target/artifacts/Graphite | |
| - name: 📦 Upload Windows bundle | |
| if: github.event_name != 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-windows-bundle | |
| path: target/artifacts | |
| - name: 💬 Comment artifact link on PR | |
| if: github.event_name != 'push' | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| ARTIFACT_URL=$(gh api /repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --jq '.artifacts[] | select(.name == "graphite-windows-bundle") | .archive_download_url') | |
| PR_NUMBER="${{ inputs.pr_number }}" | |
| if [ -z "$PR_NUMBER" ]; then | |
| BRANCH=$(git rev-parse --abbrev-ref HEAD) | |
| PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true) | |
| fi | |
| if [ -n "$PR_NUMBER" ] && [ -n "$ARTIFACT_URL" ]; then | |
| gh pr comment "$PR_NUMBER" --repo ${{ github.repository }} --body "| 📦 **Windows Build Complete for** $(git rev-parse HEAD) | | |
| |-| | |
| | [Download artifact]($ARTIFACT_URL) |" | |
| fi | |
| - name: 🔑 Azure login | |
| if: github.event_name == 'push' | |
| 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 | |
| if: github.event_name == 'push' | |
| 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 | |
| if: github.event_name == 'push' | |
| 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 signed Windows bundle | |
| if: github.event_name == 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-windows-bundle-signed | |
| path: target/artifacts | |
| mac: | |
| if: github.event_name == 'push' || inputs.mac | |
| runs-on: macos-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| env: | |
| WASM_BINDGEN_CLI_VERSION: "0.2.100" | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ inputs.checkout_repo || github.repository }} | |
| ref: ${{ inputs.checkout_ref || '' }} | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| override: true | |
| rustflags: "" | |
| target: wasm32-unknown-unknown | |
| - name: 💾 Set up Cargo cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }} | |
| - name: 🟢 Install Node.js | |
| 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: cargo run build desktop${{ inputs.debug && ' debug' || '' }} | |
| - name: 📁 Stage artifacts | |
| shell: bash | |
| run: | | |
| PROFILE=${{ inputs.debug && 'debug' || 'release' }} | |
| rm -rf target/artifacts | |
| mkdir -p target/artifacts | |
| cp -R target/$PROFILE/Graphite.app target/artifacts/Graphite.app | |
| - name: 📦 Upload Mac bundle | |
| if: github.event_name != 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-mac-bundle | |
| path: target/artifacts | |
| - name: 💬 Comment artifact link on PR | |
| if: github.event_name != 'push' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| ARTIFACT_URL=$(gh api /repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --jq '.artifacts[] | select(.name == "graphite-mac-bundle") | .archive_download_url') | |
| PR_NUMBER="${{ inputs.pr_number }}" | |
| if [ -z "$PR_NUMBER" ]; then | |
| BRANCH=$(git rev-parse --abbrev-ref HEAD) | |
| PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true) | |
| fi | |
| if [ -n "$PR_NUMBER" ] && [ -n "$ARTIFACT_URL" ]; then | |
| gh pr comment "$PR_NUMBER" --repo ${{ github.repository }} --body "| 📦 **Mac Build Complete for** $(git rev-parse HEAD) | | |
| |-| | |
| | [Download artifact]($ARTIFACT_URL) |" | |
| fi | |
| - name: 🔏 Sign and notarize (preparation) | |
| if: github.event_name == 'push' | |
| 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 | |
| if: github.event_name == 'push' | |
| 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 signed Mac bundle | |
| if: github.event_name == 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-mac-bundle-signed | |
| path: target/artifacts | |
| linux: | |
| if: github.event_name == 'push' || inputs.linux | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ inputs.checkout_repo || github.repository }} | |
| ref: ${{ inputs.checkout_ref || '' }} | |
| - name: ❄ Install Nix | |
| uses: DeterminateSystems/nix-installer-action@main | |
| - name: 🗑 Free disk space | |
| run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache | |
| - name: 📦 Build Nix package | |
| run: nix build .#graphite${{ inputs.debug && '-dev' || '' }} --no-link --print-out-paths | |
| - name: 📤 Push to Nix cache | |
| if: (github.event_name == 'push' || inputs.push_to_nix_cache) && !inputs.debug | |
| env: | |
| NIX_CACHE_AUTH_TOKEN: ${{ secrets.NIX_CACHE_AUTH_TOKEN }} | |
| run: | | |
| nix run nixpkgs#cachix -- authtoken $NIX_CACHE_AUTH_TOKEN | |
| nix build --no-link --print-out-paths | nix run nixpkgs#cachix -- push graphite | |
| - name: 🏗 Build Linux bundle | |
| run: nix build .#graphite${{ inputs.debug && '-dev' || '' }}-bundle.tar.xz && cp ./result ./graphite-linux-bundle.tar.xz | |
| - name: 📦 Upload Linux bundle | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-linux-bundle | |
| path: graphite-linux-bundle.tar.xz | |
| compression-level: 0 | |
| - name: 💬 Comment artifact link on PR | |
| if: github.event_name != 'push' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| ARTIFACT_URL=$(gh api /repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts --jq '.artifacts[] | select(.name == "graphite-linux-bundle") | .archive_download_url') | |
| PR_NUMBER="${{ inputs.pr_number }}" | |
| if [ -z "$PR_NUMBER" ]; then | |
| BRANCH=$(git rev-parse --abbrev-ref HEAD) | |
| PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true) | |
| fi | |
| if [ -n "$PR_NUMBER" ] && [ -n "$ARTIFACT_URL" ]; then | |
| gh pr comment "$PR_NUMBER" --repo ${{ github.repository }} --body "| 📦 **Linux Build Complete for** $(git rev-parse HEAD) | | |
| |-| | |
| | [Download artifact]($ARTIFACT_URL) |" | |
| fi | |
| - name: 🔧 Install Flatpak tooling | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y flatpak flatpak-builder | |
| flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| - name: 🏗 Build Flatpak | |
| run: | | |
| nix build .#graphite-flatpak-manifest | |
| rm -rf .flatpak | |
| mkdir -p .flatpak | |
| cp ./result .flatpak/manifest.json | |
| cd .flatpak | |
| mkdir -p repo | |
| flatpak-builder --user --force-clean --install-deps-from=flathub --repo=repo build ./manifest.json | |
| flatpak build-bundle repo Graphite.flatpak art.graphite.Graphite --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo | |
| - name: 📦 Upload Flatpak package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: graphite-flatpak | |
| path: .flatpak/Graphite.flatpak | |
| compression-level: 0 |