feat(premiere-plugin): ZXP + Windows installer build pipeline
Replaces the manual robocopy / install-windows.ps1 flow with two real distributable artifacts: - dragonflight-premiere-panel-<version>.zxp (Mac + Win) - dragonflight-premiere-panel-<version>-windows-setup.exe (Win) The Windows installer copies the bundle to %APPDATA%\Adobe\CEP\extensions, sets PlayerDebugMode=1 for CSXS 8..13, registers an uninstaller, and offers to remove any legacy com.wilddragon.mam.panel folder so editors don't end up with duplicate panels. The .zxp is signed with a self-signed cert generated on first build and committed to build/cert/ so signature continuity is preserved across builds (Adobe rejects ZXP upgrades with a different cert fingerprint). Also migrates the CEP bundle ID from com.wilddragon.mam.panel to net.wilddragon.dragonflight.panel to match the wild-dragon -> dragonflight repo rename. Manifest, .debug, CSInterface.js, install docs, and the growing-files quickstart all updated. build/ is normally swept by the root .gitignore; added an explicit negation so the packaging pipeline stays tracked. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
674dccca4e
commit
f874009329
17 changed files with 565 additions and 98 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -14,6 +14,9 @@ yarn-error.log*
|
|||
# Build output
|
||||
dist/
|
||||
build/
|
||||
# ...but the Premiere panel's packaging pipeline lives at build/ — keep it tracked.
|
||||
!services/premiere-plugin/build/
|
||||
!services/premiere-plugin/build/**
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
|
|
|||
|
|
@ -29,15 +29,28 @@ and the panel relinks Premiere to the hi-res original.
|
|||
|
||||
## Premiere panel install
|
||||
|
||||
```
|
||||
# macOS
|
||||
rsync -a services/premiere-plugin/ ~/Library/Application\ Support/Adobe/CEP/extensions/com.wilddragon.mam.panel/
|
||||
Grab the latest release artifact and run it — the installer handles the file
|
||||
copy, registry/plist debug-mode flip, and removes any legacy
|
||||
`com.wilddragon.mam.panel` install:
|
||||
|
||||
# Windows
|
||||
robocopy services\premiere-plugin %APPDATA%\Adobe\CEP\extensions\com.wilddragon.mam.panel /MIR
|
||||
- **Windows:** `dragonflight-premiere-panel-<version>-windows-setup.exe`
|
||||
- **macOS / Win:** `dragonflight-premiere-panel-<version>.zxp` — install via
|
||||
[Anastasiy's ZXP Installer](https://install.anastasiy.com/) (free GUI)
|
||||
|
||||
Releases live at
|
||||
<https://forge.wilddragon.net/zgaetano/dragonflight/releases>.
|
||||
|
||||
Building locally (requires Windows for the `.exe`, any OS for the `.zxp`):
|
||||
|
||||
```
|
||||
cd services/premiere-plugin/build
|
||||
npm install
|
||||
pwsh -File build-all.ps1 # or: node build-zxp.mjs
|
||||
```
|
||||
|
||||
Enable CEP debug:
|
||||
The Windows installer takes care of `PlayerDebugMode`. If you installed the
|
||||
ZXP and the panel does not appear in **Window → Extensions**, enable debug
|
||||
mode manually:
|
||||
|
||||
```
|
||||
# macOS
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ExtensionList>
|
||||
<Extension Id="com.wilddragon.mam.panel">
|
||||
<Extension Id="net.wilddragon.dragonflight.panel">
|
||||
<HostList>
|
||||
<Host Name="PPRO" Port="7737"/>
|
||||
</HostList>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ns.adobe.com/CSXS/manifest http://ns.adobe.com/CSXS/manifest">
|
||||
<ExtensionBundleVersion>1.0.0</ExtensionBundleVersion>
|
||||
<ExtensionBundleId>com.wilddragon.mam.panel</ExtensionBundleId>
|
||||
<ExtensionBundleId>net.wilddragon.dragonflight.panel</ExtensionBundleId>
|
||||
<Author>Wild Dragon MAM</Author>
|
||||
|
||||
<License>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<AbstractionLayerRequest Name="PProPanel"/>
|
||||
</AbstractionLayers>
|
||||
|
||||
<Extension Id="com.wilddragon.mam.panel">
|
||||
<Extension Id="net.wilddragon.dragonflight.panel">
|
||||
<Type>Panel</Type>
|
||||
<HostList>
|
||||
<Host Name="PPRO" Version="[22.0,99.9]"/>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ FILE STRUCTURE AND PURPOSES
|
|||
CSXS/manifest.xml
|
||||
-----------------
|
||||
- CEP extension manifest file required by Adobe
|
||||
- Defines extension ID: com.wilddragon.mam.panel
|
||||
- Defines extension ID: net.wilddragon.dragonflight.panel
|
||||
- Specifies Premiere Pro (PPRO) version compatibility: 22.0 to 99.9
|
||||
- Sets panel dimensions: 400x700 (responsive 350-500px width)
|
||||
- Declares CEP version 11.0 requirement
|
||||
|
|
@ -173,20 +173,23 @@ PREMIERE PRO REQUIREMENTS
|
|||
DEPLOYMENT INSTRUCTIONS
|
||||
=======================
|
||||
|
||||
1. Copy entire com.wilddragon.mam.panel directory to CEP extensions folder:
|
||||
Windows: C:\Users\USERNAME\AppData\Roaming\Adobe\CEP\extensions\
|
||||
macOS: ~/Library/Application Support/Adobe/CEP/extensions/
|
||||
Use the installer artifacts from the latest release:
|
||||
https://forge.wilddragon.net/zgaetano/dragonflight/releases
|
||||
|
||||
2. Enable unsigned extension debugging (Windows Registry):
|
||||
HKEY_CURRENT_USER\Software\Adobe\CSXS.11
|
||||
Create DWORD: PlayerDebugMode = 1
|
||||
Windows: dragonflight-premiere-panel-<version>-windows-setup.exe
|
||||
Double-click. Installer copies bundle to
|
||||
%APPDATA%\Adobe\CEP\extensions\net.wilddragon.dragonflight.panel\,
|
||||
sets PlayerDebugMode=1 for CSXS 8..13, and removes any legacy
|
||||
com.wilddragon.mam.panel install.
|
||||
|
||||
3. Enable unsigned extension debugging (macOS):
|
||||
defaults write /Library/Preferences/com.adobe.CSXS.11 PlayerDebugMode 1
|
||||
macOS: dragonflight-premiere-panel-<version>.zxp
|
||||
Install with Anastasiy's ZXP Installer
|
||||
(https://install.anastasiy.com/), then run once in Terminal:
|
||||
defaults write com.adobe.CSXS.11 PlayerDebugMode 1
|
||||
|
||||
4. Restart Premiere Pro
|
||||
Restart Premiere Pro, then: Window > Extensions > Wild Dragon MAM
|
||||
|
||||
5. Access panel via Window > Extensions > Wild Dragon MAM
|
||||
To build the installers locally, see services/premiere-plugin/build/README.md.
|
||||
|
||||
DEVELOPMENT NOTES
|
||||
=================
|
||||
|
|
|
|||
|
|
@ -1,30 +1,40 @@
|
|||
# Wild Dragon MAM - Premiere Pro Panel Quick Start
|
||||
|
||||
## Installation (5 minutes)
|
||||
## Installation (1 minute)
|
||||
|
||||
Grab the installer from
|
||||
<https://forge.wilddragon.net/zgaetano/dragonflight/releases>.
|
||||
|
||||
### Windows
|
||||
```
|
||||
1. Copy folder to:
|
||||
C:\Users\<USERNAME>\AppData\Roaming\Adobe\CEP\extensions\com.wilddragon.mam.panel\
|
||||
|
||||
2. Open Registry Editor (regedit.exe)
|
||||
Navigate to: HKEY_CURRENT_USER\Software\Adobe\CSXS.11
|
||||
Create DWORD: PlayerDebugMode = 1
|
||||
|
||||
3. Restart Premiere Pro
|
||||
1. Download dragonflight-premiere-panel-<version>-windows-setup.exe
|
||||
2. Double-click it. Next -> Finish.
|
||||
3. Restart Premiere Pro.
|
||||
```
|
||||
|
||||
The installer copies the bundle to `%APPDATA%\Adobe\CEP\extensions\`,
|
||||
sets `PlayerDebugMode=1` for CSXS 8..13, and offers to remove any legacy
|
||||
`com.wilddragon.mam.panel` install.
|
||||
|
||||
### macOS
|
||||
```
|
||||
1. Copy folder to:
|
||||
~/Library/Application Support/Adobe/CEP/extensions/com.wilddragon.mam.panel/
|
||||
|
||||
2. Open Terminal and run:
|
||||
defaults write /Library/Preferences/com.adobe.CSXS.11 PlayerDebugMode 1
|
||||
|
||||
3. Restart Premiere Pro
|
||||
1. Download dragonflight-premiere-panel-<version>.zxp
|
||||
2. Open it with Anastasiy's ZXP Installer (https://install.anastasiy.com/)
|
||||
3. Run once in Terminal:
|
||||
defaults write com.adobe.CSXS.11 PlayerDebugMode 1
|
||||
4. Restart Premiere Pro.
|
||||
```
|
||||
|
||||
### Building from source
|
||||
|
||||
```
|
||||
cd services/premiere-plugin/build
|
||||
npm install
|
||||
pwsh -File build-all.ps1
|
||||
```
|
||||
|
||||
See [`build/README.md`](build/README.md).
|
||||
|
||||
## Access the Panel
|
||||
|
||||
Window > Extensions > Wild Dragon MAM
|
||||
|
|
@ -91,6 +101,7 @@ services/premiere-plugin/
|
|||
│ └── main.js Panel logic
|
||||
├── jsx/
|
||||
│ └── premiere.jsx Premiere integration
|
||||
├── build/ Installer build pipeline (.zxp + .exe)
|
||||
├── README.md Full docs
|
||||
└── QUICK_START.md This file
|
||||
```
|
||||
|
|
|
|||
|
|
@ -16,30 +16,41 @@ A professional media asset management (MAM) plugin for Adobe Premiere Pro that a
|
|||
|
||||
## Installation
|
||||
|
||||
### Windows
|
||||
Grab the installer for your platform from the
|
||||
[latest release](https://forge.wilddragon.net/zgaetano/dragonflight/releases):
|
||||
|
||||
1. Copy the entire `com.wilddragon.mam.panel` directory to:
|
||||
```
|
||||
C:\Users\<YourUsername>\AppData\Roaming\Adobe\CEP\extensions\com.wilddragon.mam.panel\
|
||||
```
|
||||
| File | Platform | How to install |
|
||||
|------|----------|----------------|
|
||||
| `dragonflight-premiere-panel-<version>-windows-setup.exe` | Windows | Double-click, Next → Finish. Copies the bundle, sets `PlayerDebugMode`, and removes any legacy `com.wilddragon.mam.panel` install. |
|
||||
| `dragonflight-premiere-panel-<version>.zxp` | macOS + Windows | Install with [Anastasiy's ZXP Installer](https://install.anastasiy.com/) (free GUI). |
|
||||
|
||||
2. For unsigned extensions, enable debug mode in the Windows Registry:
|
||||
- Open Registry Editor (`regedit.exe`)
|
||||
- Navigate to: `HKEY_CURRENT_USER\Software\Adobe\CSXS.11`
|
||||
- Create a new DWORD value named `PlayerDebugMode` and set it to `1`
|
||||
- Restart Premiere Pro
|
||||
### macOS ZXP — one extra step
|
||||
|
||||
### macOS
|
||||
The `.zxp` is self-signed, so macOS editors must enable CEP debug mode once
|
||||
before the panel will load:
|
||||
|
||||
1. Copy the entire `com.wilddragon.mam.panel` directory to:
|
||||
```
|
||||
~/Library/Application Support/Adobe/CEP/extensions/com.wilddragon.mam.panel/
|
||||
```
|
||||
```
|
||||
defaults write com.adobe.CSXS.11 PlayerDebugMode 1
|
||||
```
|
||||
|
||||
2. For unsigned extensions, enable debug mode in the plist:
|
||||
- Open Terminal
|
||||
- Run: `defaults write /Library/Preferences/com.adobe.CSXS.11 PlayerDebugMode 1`
|
||||
- Restart Premiere Pro
|
||||
Restart Premiere Pro afterward. The Windows `.exe` installer does this
|
||||
automatically for every CEP version Premiere might use (CSXS 8 through 13).
|
||||
|
||||
### Building from source
|
||||
|
||||
If you do not want to install the release artifact, you can run the panel
|
||||
straight from the source tree. See [`build/README.md`](build/README.md) for
|
||||
the build pipeline, or copy the directory yourself:
|
||||
|
||||
```
|
||||
# Windows (PowerShell, as the same user that runs Premiere)
|
||||
robocopy . "$env:APPDATA\Adobe\CEP\extensions\net.wilddragon.dragonflight.panel" /MIR /XD build
|
||||
|
||||
# macOS
|
||||
rsync -a --exclude=build/ ./ ~/Library/Application\ Support/Adobe/CEP/extensions/net.wilddragon.dragonflight.panel/
|
||||
```
|
||||
|
||||
Then enable `PlayerDebugMode` as above.
|
||||
|
||||
### Access the Panel
|
||||
|
||||
|
|
@ -47,6 +58,22 @@ A professional media asset management (MAM) plugin for Adobe Premiere Pro that a
|
|||
2. Go to **Window** > **Extensions** > **Wild Dragon MAM**
|
||||
3. The panel will open as a floating window on the right side
|
||||
|
||||
### Upgrading from `com.wilddragon.mam.panel`
|
||||
|
||||
The bundle ID changed to `net.wilddragon.dragonflight.panel` as part of the
|
||||
wild-dragon → dragonflight rename. The Windows installer offers to remove
|
||||
the old folder for you (checkbox on the install wizard, default on). For ZXP
|
||||
installs or manual copies, delete the legacy folder yourself or you will see
|
||||
two panels in **Window → Extensions**:
|
||||
|
||||
```
|
||||
# Windows
|
||||
Remove-Item -Recurse -Force "$env:APPDATA\Adobe\CEP\extensions\com.wilddragon.mam.panel"
|
||||
|
||||
# macOS
|
||||
rm -rf ~/Library/Application\ Support/Adobe/CEP/extensions/com.wilddragon.mam.panel
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Connect to MAM Server
|
||||
|
|
@ -102,7 +129,7 @@ To change the server URL:
|
|||
## File Structure
|
||||
|
||||
```
|
||||
com.wilddragon.mam.panel/
|
||||
net.wilddragon.dragonflight.panel/ # installed bundle
|
||||
├── CSXS/
|
||||
│ └── manifest.xml # CEP extension manifest
|
||||
├── css/
|
||||
|
|
@ -115,6 +142,13 @@ com.wilddragon.mam.panel/
|
|||
├── index.html # Main panel UI
|
||||
├── .debug # CEP debug configuration
|
||||
└── README.md # This file
|
||||
|
||||
build/ # not shipped — installer/.zxp build pipeline
|
||||
├── README.md # how to build .zxp + .exe locally
|
||||
├── build-all.ps1 # build both artifacts
|
||||
├── build-zxp.mjs # ZXP signer
|
||||
├── installer.iss # Inno Setup script
|
||||
└── ...
|
||||
```
|
||||
|
||||
## API Integration
|
||||
|
|
|
|||
4
services/premiere-plugin/build/.gitignore
vendored
Normal file
4
services/premiere-plugin/build/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
dist/
|
||||
stage/
|
||||
*.log
|
||||
86
services/premiere-plugin/build/README.md
Normal file
86
services/premiere-plugin/build/README.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Premiere panel installer — build pipeline
|
||||
|
||||
Produces two artifacts from `services/premiere-plugin/`:
|
||||
|
||||
| File | Platform | How an editor installs it |
|
||||
|------|----------|----------------------------|
|
||||
| `dist/dragonflight-premiere-panel-<version>.zxp` | macOS + Windows | Drag into [Anastasiy's ZXP Installer](https://install.anastasiy.com/) |
|
||||
| `dist/dragonflight-premiere-panel-<version>-windows-setup.exe` | Windows | Double-click, Next → Finish |
|
||||
|
||||
The version is read from `CSXS/manifest.xml`'s `<ExtensionBundleVersion>`. To
|
||||
cut a new release: bump that one number, rebuild, attach the two files to a
|
||||
Forgejo release tag.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| Building | Requires |
|
||||
|----------|----------|
|
||||
| `.zxp` only | Node 18+, runs on macOS / Linux / Windows |
|
||||
| `.exe` | Windows + [Inno Setup 6](https://jrsoftware.org/isinfo.php) on `PATH` (`ISCC.exe`) |
|
||||
| Both via `build-all.ps1` | Windows + Node 18+ + Inno Setup 6 |
|
||||
|
||||
Install Inno Setup with winget:
|
||||
|
||||
```
|
||||
winget install --id JRSoftware.InnoSetup
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
cd services/premiere-plugin/build
|
||||
npm install
|
||||
pwsh -File build-all.ps1
|
||||
```
|
||||
|
||||
Artifacts land in `services/premiere-plugin/build/dist/`.
|
||||
|
||||
To build just one:
|
||||
|
||||
```
|
||||
node build-zxp.mjs # cross-platform .zxp
|
||||
pwsh -File build-installer.ps1 # Windows .exe (needs ISCC.exe)
|
||||
```
|
||||
|
||||
## Signing cert (.zxp)
|
||||
|
||||
The first `node build-zxp.mjs` run generates a self-signed cert at
|
||||
`cert/dragonflight-selfsigned.p12` + passphrase at `cert/cert-passphrase.txt`.
|
||||
**Commit both files** — they need to be stable across builds so Adobe accepts
|
||||
ZXP upgrades in place. If you regenerate the cert, every editor who already
|
||||
installed an older `.zxp` has to uninstall + reinstall.
|
||||
|
||||
The cert is self-signed → editors still need `PlayerDebugMode=1`. The Windows
|
||||
`.exe` installer sets this automatically. ZXP installs on macOS need a manual
|
||||
`defaults write com.adobe.CSXS.11 PlayerDebugMode 1`.
|
||||
|
||||
See `cert/README.md` for cert details + how to regenerate.
|
||||
|
||||
## What the installers do
|
||||
|
||||
Both install the bundle as `net.wilddragon.dragonflight.panel`. The Windows
|
||||
`.exe` additionally:
|
||||
|
||||
1. Removes any legacy `com.wilddragon.mam.panel` folder (with a consent
|
||||
checkbox, default on) — avoids editors seeing two panels in
|
||||
**Window → Extensions**.
|
||||
2. Sets `HKCU\Software\Adobe\CSXS.{8..13}\PlayerDebugMode = "1"` so unsigned
|
||||
CEP extensions load.
|
||||
3. Registers itself in Add/Remove Programs so uninstall reverses both.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
build/
|
||||
├── README.md ← this file
|
||||
├── package.json ← devDep: zxp-sign-cmd
|
||||
├── .gitignore ← ignores dist/ + node_modules/
|
||||
├── build-all.ps1 ← runs both builders
|
||||
├── build-zxp.mjs ← Node: generates cert (first run), signs, packages
|
||||
├── build-installer.ps1 ← wraps ISCC.exe with version + bundle-id flags
|
||||
├── installer.iss ← Inno Setup script
|
||||
└── cert/
|
||||
├── README.md ← how to regenerate
|
||||
├── dragonflight-selfsigned.p12 ← generated on first build (commit it)
|
||||
└── cert-passphrase.txt ← generated on first build (commit it)
|
||||
```
|
||||
34
services/premiere-plugin/build/build-all.ps1
Normal file
34
services/premiere-plugin/build/build-all.ps1
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Dragonflight Premiere panel — build everything
|
||||
#
|
||||
# Produces both artifacts in dist/:
|
||||
# - dragonflight-premiere-panel-<version>.zxp (Mac + Win)
|
||||
# - dragonflight-premiere-panel-<version>-windows-setup.exe (Win)
|
||||
#
|
||||
# Requires: Node 18+, Inno Setup 6 (ISCC.exe on PATH).
|
||||
# Usage: pwsh -File build-all.ps1
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Set-Location $PSScriptRoot
|
||||
|
||||
if (-not (Test-Path 'node_modules')) {
|
||||
Write-Host 'Installing npm deps...'
|
||||
npm install --no-audit --no-fund
|
||||
if ($LASTEXITCODE -ne 0) { throw 'npm install failed' }
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '=== Building .zxp ==='
|
||||
node build-zxp.mjs
|
||||
if ($LASTEXITCODE -ne 0) { throw 'ZXP build failed' }
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '=== Building Windows .exe ==='
|
||||
& (Join-Path $PSScriptRoot 'build-installer.ps1')
|
||||
if ($LASTEXITCODE -ne 0) { throw 'Installer build failed' }
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'All artifacts:'
|
||||
Get-ChildItem -Path 'dist' | ForEach-Object {
|
||||
$size = [math]::Round($_.Length / 1KB, 1)
|
||||
Write-Host (' {0,8} KB {1}' -f $size, $_.Name)
|
||||
}
|
||||
46
services/premiere-plugin/build/build-installer.ps1
Normal file
46
services/premiere-plugin/build/build-installer.ps1
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Dragonflight Premiere panel — Windows installer build
|
||||
#
|
||||
# Parses the version from ../CSXS/manifest.xml and hands it to ISCC.exe.
|
||||
# Requires Inno Setup 6 on PATH (winget install JRSoftware.InnoSetup).
|
||||
#
|
||||
# Usage: pwsh -File build-installer.ps1
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Set-Location $PSScriptRoot
|
||||
|
||||
$manifestPath = Join-Path $PSScriptRoot '..\CSXS\manifest.xml'
|
||||
if (-not (Test-Path $manifestPath)) {
|
||||
throw "Manifest not found at $manifestPath"
|
||||
}
|
||||
$manifestXml = [xml](Get-Content -Raw -Path $manifestPath)
|
||||
$version = $manifestXml.ExtensionManifest.ExtensionBundleVersion
|
||||
if (-not $version) {
|
||||
throw 'Could not read <ExtensionBundleVersion> from manifest.xml'
|
||||
}
|
||||
Write-Host "Dragonflight Premiere panel - Windows installer build v$version"
|
||||
|
||||
$iscc = Get-Command 'ISCC.exe' -ErrorAction SilentlyContinue
|
||||
if (-not $iscc) {
|
||||
# Common install location if not on PATH.
|
||||
$fallback = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
|
||||
if (Test-Path $fallback) {
|
||||
$iscc = Get-Command $fallback
|
||||
} else {
|
||||
throw "ISCC.exe not found. Install Inno Setup 6: winget install JRSoftware.InnoSetup"
|
||||
}
|
||||
}
|
||||
|
||||
$distDir = Join-Path $PSScriptRoot 'dist'
|
||||
New-Item -ItemType Directory -Force -Path $distDir | Out-Null
|
||||
|
||||
& $iscc.Source "/DMyAppVersion=$version" "installer.iss"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "ISCC failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
$output = Join-Path $distDir "dragonflight-premiere-panel-$version-windows-setup.exe"
|
||||
if (-not (Test-Path $output)) {
|
||||
throw "Expected output not found: $output"
|
||||
}
|
||||
$size = [math]::Round((Get-Item $output).Length / 1KB, 1)
|
||||
Write-Host "Built $output ($size KB)"
|
||||
106
services/premiere-plugin/build/build-zxp.mjs
Normal file
106
services/premiere-plugin/build/build-zxp.mjs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env node
|
||||
// Build a signed .zxp for the Dragonflight Premiere panel.
|
||||
//
|
||||
// - Reads version from ../CSXS/manifest.xml (<ExtensionBundleVersion>)
|
||||
// - Generates a self-signed cert on first run (cert/dragonflight-selfsigned.p12)
|
||||
// - Stages the panel bundle into stage/ (excludes build/ + dev cruft)
|
||||
// - Calls zxp-sign-cmd to sign + package into dist/
|
||||
//
|
||||
// Usage: node build-zxp.mjs
|
||||
// Output: dist/dragonflight-premiere-panel-<version>.zxp
|
||||
|
||||
import { mkdirSync, existsSync, readFileSync, writeFileSync, rmSync, cpSync, readdirSync, statSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { randomBytes } from 'node:crypto';
|
||||
import zxp from 'zxp-sign-cmd';
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
const PANEL_DIR = resolve(HERE, '..');
|
||||
const MANIFEST = join(PANEL_DIR, 'CSXS', 'manifest.xml');
|
||||
const CERT_DIR = join(HERE, 'cert');
|
||||
const CERT_FILE = join(CERT_DIR, 'dragonflight-selfsigned.p12');
|
||||
const PASS_FILE = join(CERT_DIR, 'cert-passphrase.txt');
|
||||
const STAGE_DIR = join(HERE, 'stage');
|
||||
const DIST_DIR = join(HERE, 'dist');
|
||||
|
||||
// Files/dirs to exclude from the staged bundle.
|
||||
const EXCLUDE = new Set(['build', 'install-windows.ps1', '.git', '.gitignore', 'node_modules']);
|
||||
|
||||
function readVersion() {
|
||||
const xml = readFileSync(MANIFEST, 'utf8');
|
||||
const m = xml.match(/<ExtensionBundleVersion>([^<]+)<\/ExtensionBundleVersion>/);
|
||||
if (!m) throw new Error(`Could not find <ExtensionBundleVersion> in ${MANIFEST}`);
|
||||
return m[1].trim();
|
||||
}
|
||||
|
||||
function ensureCert() {
|
||||
mkdirSync(CERT_DIR, { recursive: true });
|
||||
if (existsSync(CERT_FILE) && existsSync(PASS_FILE)) {
|
||||
return readFileSync(PASS_FILE, 'utf8').trim();
|
||||
}
|
||||
console.log('No signing cert found — generating self-signed cert (one-time)…');
|
||||
const passphrase = randomBytes(24).toString('base64url');
|
||||
writeFileSync(PASS_FILE, passphrase + '\n', { mode: 0o600 });
|
||||
return new Promise((res, rej) => {
|
||||
zxp.selfSignedCert({
|
||||
country: 'US',
|
||||
province: 'WA',
|
||||
org: 'Wild Dragon LLC',
|
||||
name: 'Wild Dragon LLC',
|
||||
password: passphrase,
|
||||
output: CERT_FILE,
|
||||
validityDays: 365 * 25,
|
||||
}, (err) => {
|
||||
if (err) return rej(err);
|
||||
console.log(` wrote ${CERT_FILE}`);
|
||||
console.log(` wrote ${PASS_FILE}`);
|
||||
console.log(' >> COMMIT both files so future builds reuse them. <<');
|
||||
res(passphrase);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function stageBundle() {
|
||||
if (existsSync(STAGE_DIR)) rmSync(STAGE_DIR, { recursive: true, force: true });
|
||||
mkdirSync(STAGE_DIR, { recursive: true });
|
||||
for (const entry of readdirSync(PANEL_DIR)) {
|
||||
if (EXCLUDE.has(entry)) continue;
|
||||
const src = join(PANEL_DIR, entry);
|
||||
const dst = join(STAGE_DIR, entry);
|
||||
cpSync(src, dst, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
function signZxp(version, passphrase) {
|
||||
mkdirSync(DIST_DIR, { recursive: true });
|
||||
const output = join(DIST_DIR, `dragonflight-premiere-panel-${version}.zxp`);
|
||||
if (existsSync(output)) rmSync(output);
|
||||
return new Promise((res, rej) => {
|
||||
zxp.sign({
|
||||
input: STAGE_DIR,
|
||||
output,
|
||||
cert: CERT_FILE,
|
||||
password: passphrase,
|
||||
}, (err) => {
|
||||
if (err) return rej(err);
|
||||
const bytes = statSync(output).size;
|
||||
console.log(`Built ${output} (${(bytes / 1024).toFixed(1)} KB)`);
|
||||
res(output);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const version = readVersion();
|
||||
console.log(`Dragonflight Premiere panel — ZXP build v${version}`);
|
||||
const passphrase = await ensureCert();
|
||||
stageBundle();
|
||||
await signZxp(version, passphrase);
|
||||
rmSync(STAGE_DIR, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('ZXP build failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
53
services/premiere-plugin/build/cert/README.md
Normal file
53
services/premiere-plugin/build/cert/README.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Self-signed cert for ZXP signing
|
||||
|
||||
The `.zxp` package format requires a signature. We use a self-signed cert so
|
||||
there is no Certificate Authority cost; the trade-off is editors must enable
|
||||
`PlayerDebugMode` for the panel to load (the Windows `.exe` installer does
|
||||
this automatically).
|
||||
|
||||
## Files
|
||||
|
||||
| File | What it is | Commit to git? |
|
||||
|------|------------|----------------|
|
||||
| `dragonflight-selfsigned.p12` | PKCS#12 keystore containing the signing cert + private key | **yes** |
|
||||
| `cert-passphrase.txt` | Passphrase for the `.p12` | **yes** |
|
||||
|
||||
Both are auto-generated on the first `node build-zxp.mjs` run. They MUST be
|
||||
committed and reused across builds: Adobe's ZXP signature continuity rule
|
||||
means a re-signed package with a different cert fingerprint will not install
|
||||
over an existing version — editors would have to uninstall the panel first.
|
||||
|
||||
## Why is committing a private key OK here?
|
||||
|
||||
- The panel is proprietary internal tooling, not a public distribution.
|
||||
- The cert chains to nothing — a leak lets an attacker sign a fake
|
||||
`net.wilddragon.dragonflight.panel` bundle, which would still require
|
||||
`PlayerDebugMode=1` to load and physical access to the editor's machine to
|
||||
install. Threat model: low.
|
||||
- The alternative (rotating the cert on every build or keeping it in a
|
||||
secrets manager) would break upgrade-in-place for every editor on every
|
||||
build.
|
||||
|
||||
If you want a real codesigning cert later, drop a CA-issued `.p12` over the
|
||||
self-signed one with the same filename and update `cert-passphrase.txt`. The
|
||||
build script will reuse them.
|
||||
|
||||
## Regenerating
|
||||
|
||||
Delete both files. Next `node build-zxp.mjs` run will create a fresh
|
||||
self-signed cert (valid for 25 years). Commit the new pair. **Heads up:**
|
||||
every editor with the old `.zxp` installed must uninstall first before the
|
||||
new one will install.
|
||||
|
||||
Manual regeneration with the Adobe-published `ZXPSignCmd` (the
|
||||
`zxp-sign-cmd` npm package wraps this):
|
||||
|
||||
```
|
||||
npx zxp-sign-cmd selfSignedCert \
|
||||
--country US \
|
||||
--province WA \
|
||||
--org "Wild Dragon LLC" \
|
||||
--name "Wild Dragon LLC" \
|
||||
--password "$(cat cert-passphrase.txt)" \
|
||||
--output dragonflight-selfsigned.p12
|
||||
```
|
||||
95
services/premiere-plugin/build/installer.iss
Normal file
95
services/premiere-plugin/build/installer.iss
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
; Dragonflight Premiere Pro CEP panel — Windows installer
|
||||
; Build: iscc installer.iss /DMyAppVersion=1.0.0
|
||||
; (build-installer.ps1 parses CSXS/manifest.xml and passes the version)
|
||||
|
||||
#ifndef MyAppVersion
|
||||
#define MyAppVersion "0.0.0-dev"
|
||||
#endif
|
||||
|
||||
#define MyAppName "Dragonflight Premiere Panel"
|
||||
#define MyAppPublisher "Wild Dragon LLC"
|
||||
#define MyAppURL "https://forge.wilddragon.net/zgaetano/dragonflight"
|
||||
#define BundleId "net.wilddragon.dragonflight.panel"
|
||||
#define LegacyBundleId "com.wilddragon.mam.panel"
|
||||
#define PanelSrcDir "..\"
|
||||
#define OutDir "dist"
|
||||
|
||||
[Setup]
|
||||
AppId={{8E2C1F6D-1B9A-4D7E-9C3F-9F2E5A4C7B11}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppVerName={#MyAppName} {#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}/issues
|
||||
AppUpdatesURL={#MyAppURL}/releases
|
||||
DefaultDirName={userappdata}\Adobe\CEP\extensions\{#BundleId}
|
||||
DefaultGroupName={#MyAppName}
|
||||
DisableProgramGroupPage=yes
|
||||
DisableDirPage=yes
|
||||
PrivilegesRequired=lowest
|
||||
PrivilegesRequiredOverridesAllowed=
|
||||
OutputDir={#OutDir}
|
||||
OutputBaseFilename=dragonflight-premiere-panel-{#MyAppVersion}-windows-setup
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
UninstallDisplayName={#MyAppName} {#MyAppVersion}
|
||||
UninstallDisplayIcon={app}\index.html
|
||||
SetupLogging=yes
|
||||
|
||||
[Languages]
|
||||
Name: "en"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "removelegacy"; Description: "Remove legacy {#LegacyBundleId} install if present"; GroupDescription: "Migration:"; Check: LegacyPanelExists
|
||||
|
||||
[Files]
|
||||
; Copy the entire panel bundle, minus the build/ pipeline and the
|
||||
; deprecated install-windows.ps1 (this installer supersedes it).
|
||||
Source: "{#PanelSrcDir}*"; DestDir: "{app}"; Excludes: "build,install-windows.ps1,*.log"; \
|
||||
Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Registry]
|
||||
; Enable PlayerDebugMode for every CEP version Premiere Pro might use.
|
||||
; Adobe stores this as REG_SZ "1" (a STRING, not a DWORD). Intentionally
|
||||
; no uninsdeletevalue flag — other CEP panels need this key too.
|
||||
Root: HKCU; Subkey: "Software\Adobe\CSXS.8"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
|
||||
Root: HKCU; Subkey: "Software\Adobe\CSXS.9"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
|
||||
Root: HKCU; Subkey: "Software\Adobe\CSXS.10"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
|
||||
Root: HKCU; Subkey: "Software\Adobe\CSXS.11"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
|
||||
Root: HKCU; Subkey: "Software\Adobe\CSXS.12"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
|
||||
Root: HKCU; Subkey: "Software\Adobe\CSXS.13"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
|
||||
|
||||
[InstallDelete]
|
||||
; Wipe the legacy folder before installing the new one (only if user opted in).
|
||||
Type: filesandordirs; Name: "{userappdata}\Adobe\CEP\extensions\{#LegacyBundleId}"; Tasks: removelegacy
|
||||
|
||||
[UninstallDelete]
|
||||
; Strip the install dir clean on uninstall. App lives entirely in {app}.
|
||||
Type: filesandordirs; Name: "{app}"
|
||||
|
||||
[Code]
|
||||
function LegacyPanelExists: Boolean;
|
||||
begin
|
||||
Result := DirExists(ExpandConstant('{userappdata}\Adobe\CEP\extensions\{#LegacyBundleId}'));
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var
|
||||
PremiereRunning: Boolean;
|
||||
begin
|
||||
if CurStep = ssInstall then begin
|
||||
PremiereRunning := False;
|
||||
// Heuristic — Premiere's main exe is Adobe Premiere Pro.exe.
|
||||
// If it is running, files in {app} can still be replaced (CEP loads them
|
||||
// on panel open, not on Premiere launch), but the user needs a Premiere
|
||||
// restart before the new bundle is picked up. Just warn, don't block.
|
||||
if Exec('cmd.exe', '/C tasklist /FI "IMAGENAME eq Adobe Premiere Pro.exe" | find /I "Adobe Premiere Pro.exe" >nul', '', SW_HIDE, ewWaitUntilTerminated, PremiereRunning) and PremiereRunning then begin
|
||||
// exit code 0 from `find` means the process was found
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\README.md"; Description: "Open README"; Flags: shellexec postinstall skipifsilent unchecked
|
||||
18
services/premiere-plugin/build/package.json
Normal file
18
services/premiere-plugin/build/package.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "dragonflight-premiere-panel-build",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"description": "Build pipeline for the Dragonflight Premiere Pro CEP panel — produces a signed .zxp and a Windows .exe installer.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build:zxp": "node build-zxp.mjs",
|
||||
"build:exe": "pwsh -NoProfile -ExecutionPolicy Bypass -File build-installer.ps1",
|
||||
"build": "pwsh -NoProfile -ExecutionPolicy Bypass -File build-all.ps1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"zxp-sign-cmd": "^0.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# Wild Dragon MAM - Premiere Pro plugin installer (Windows)
|
||||
# Run from PowerShell as the same user that runs Premiere Pro (NOT as admin)
|
||||
#
|
||||
# Usage:
|
||||
# 1. Open this folder in PowerShell
|
||||
# 2. Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
# 3. .\install-windows.ps1
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$src = $PSScriptRoot
|
||||
$dest = Join-Path $env:APPDATA 'Adobe\CEP\extensions\com.wilddragon.mam.panel'
|
||||
|
||||
Write-Host "Source: $src"
|
||||
Write-Host "Target: $dest"
|
||||
|
||||
if (Test-Path $dest) {
|
||||
Write-Host "Removing existing extension at $dest"
|
||||
Remove-Item -Recurse -Force $dest
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path $dest | Out-Null
|
||||
Copy-Item -Recurse -Force "$src\*" $dest -Exclude 'install-windows.ps1'
|
||||
|
||||
Write-Host 'Files copied.'
|
||||
|
||||
# Enable CEP debug mode for the supported CEP versions (Premiere Pro uses CSXS.11+).
|
||||
foreach ($v in 8..13) {
|
||||
$regPath = "HKCU:\Software\Adobe\CSXS.$v"
|
||||
if (-not (Test-Path $regPath)) { New-Item -Path $regPath -Force | Out-Null }
|
||||
Set-ItemProperty -Path $regPath -Name 'PlayerDebugMode' -Value 1 -Type String
|
||||
Write-Host "Set PlayerDebugMode=1 on $regPath"
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Done. Restart Premiere Pro, then:'
|
||||
Write-Host ' Window -> Extensions -> Wild Dragon MAM'
|
||||
Write-Host ''
|
||||
Write-Host 'Server URL inside the panel should be the MAM web-UI, e.g.:'
|
||||
Write-Host ' http://10.0.0.25:47434'
|
||||
|
|
@ -32,7 +32,7 @@ class CSInterface {
|
|||
constructor() {
|
||||
this.requestIdCount = 1;
|
||||
this.requestMap = new Map();
|
||||
this.extensionId = "com.wilddragon.mam.panel";
|
||||
this.extensionId = "net.wilddragon.dragonflight.panel";
|
||||
|
||||
// Initialize event listener for messages from ExtendScript
|
||||
if (window.__adobe_cep__ !== undefined) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue