Desktop: Build and Sign Mac and Windows Bundles in CI (#3728)
* Desktop: Build and Sign Mac and Windows Bundles in CI * Desktop: Remove unnecessary CEF files from Windows Bundle * Desktop: Use a temp file for license generation on Windows to avoid PowerShell modifying stdout
This commit is contained in:
parent
5efa81df85
commit
acab171bc5
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -27,8 +27,33 @@ fn bundle(out_dir: &Path, app_bin: &Path) -> PathBuf {
|
||||||
|
|
||||||
copy_dir(&cef_path(), &app_dir);
|
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);
|
let bin_path = app_dir.join(EXECUTABLE);
|
||||||
fs::copy(app_bin, &bin_path).unwrap();
|
fs::copy(app_bin, &bin_path).unwrap();
|
||||||
|
|
||||||
bin_path
|
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(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
if let StartCause::ResumeTimeReached { .. } = cause
|
||||||
&& let Some(window) = &self.window
|
&& let Some(window) = &self.window
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { spawnSync } from "child_process";
|
import { spawnSync } from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import os from "os";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
|
@ -298,12 +299,32 @@ function generateRustLicenses(): LicenseInfo[] {
|
||||||
try {
|
try {
|
||||||
// Call `cargo about` in the terminal to generate the license information for Rust crates.
|
// Call `cargo about` in the terminal to generate the license information for Rust crates.
|
||||||
// The `about.hbs` file is written so it generates a valid JavaScript array expression which we evaluate below.
|
// The `about.hbs` file is written so it generates a valid JavaScript array expression which we evaluate below.
|
||||||
const { stdout, stderr, status } = spawnSync("cargo", ["about", "generate", "about.hbs"], {
|
const { licenses, status, stderr } = (() => {
|
||||||
cwd: path.join(__dirname, ".."),
|
// On Windows, we have to write the output to a temporary file because of powershell's handling of stdout.
|
||||||
encoding: "utf8",
|
if (os.platform() === "win32") {
|
||||||
shell: true,
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "graphite-licenses-"));
|
||||||
windowsHide: true, // Hide the terminal on Windows
|
const licensesFile = path.join(tmpDir, "licenses.js");
|
||||||
});
|
|
||||||
|
const { status, stderr } = spawnSync("cargo", ["about", "generate", "about.hbs", "-o", licensesFile], {
|
||||||
|
cwd: path.join(__dirname, ".."),
|
||||||
|
encoding: "utf8",
|
||||||
|
shell: true,
|
||||||
|
windowsHide: true, // Hide the terminal on Windows
|
||||||
|
});
|
||||||
|
|
||||||
|
const licenses = fs.existsSync(licensesFile) ? fs.readFileSync(licensesFile, "utf8") : "";
|
||||||
|
|
||||||
|
return { licenses, status, stderr };
|
||||||
|
} else {
|
||||||
|
const { stdout, status, stderr } = spawnSync("cargo", ["about", "generate", "about.hbs"], {
|
||||||
|
cwd: path.join(__dirname, ".."),
|
||||||
|
encoding: "utf8",
|
||||||
|
shell: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { licenses: stdout, status, stderr };
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
// If the command failed, print the error message and exit early.
|
// If the command failed, print the error message and exit early.
|
||||||
if (status !== 0) {
|
if (status !== 0) {
|
||||||
|
|
@ -316,8 +337,8 @@ function generateRustLicenses(): LicenseInfo[] {
|
||||||
|
|
||||||
// Make sure the output starts with this expected label, which lets us know the file generated with expected output.
|
// Make sure the output starts with this expected label, which lets us know the file generated with expected output.
|
||||||
// We don't want to eval an error message or something else, so we fail early if that happens.
|
// We don't want to eval an error message or something else, so we fail early if that happens.
|
||||||
if (!stdout.trim().startsWith("GENERATED_BY_CARGO_ABOUT:")) {
|
if (!licenses.trim().startsWith("GENERATED_BY_CARGO_ABOUT:")) {
|
||||||
console.error("Unexpected output from cargo-about", stdout);
|
console.error("Unexpected output from cargo-about", licenses);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,7 +346,7 @@ function generateRustLicenses(): LicenseInfo[] {
|
||||||
// Security-wise, eval() isn't any worse than require(), but it's able to work without a temporary file.
|
// Security-wise, eval() isn't any worse than require(), but it's able to work without a temporary file.
|
||||||
// We call eval indirectly to avoid a warning as explained here: <https://esbuild.github.io/content-types/#direct-eval>.
|
// We call eval indirectly to avoid a warning as explained here: <https://esbuild.github.io/content-types/#direct-eval>.
|
||||||
const indirectEval = eval;
|
const indirectEval = eval;
|
||||||
const licensesArray = indirectEval(stdout) as LicenseInfo[];
|
const licensesArray = indirectEval(licenses) as LicenseInfo[];
|
||||||
|
|
||||||
// Remove the HTML character encoding caused by Handlebars.
|
// Remove the HTML character encoding caused by Handlebars.
|
||||||
const rustLicenses = (licensesArray || []).map(
|
const rustLicenses = (licensesArray || []).map(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue