-
-
Notifications
You must be signed in to change notification settings - Fork 410
[Feat] Desktop app (Electron + bundled PHP runtime) #1201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 4.x
Are you sure you want to change the base?
Changes from all commits
a2de481
c9f8b24
64be7ae
bcb39d6
a93d92c
53f95c5
ce27544
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| APP_NAME=Vito | ||
| APP_ENV=production | ||
| APP_KEY= | ||
| APP_DEBUG=false | ||
| APP_URL=http://127.0.0.1 | ||
|
|
||
| VITO_DESKTOP=true | ||
| VITO_DATA_PATH= | ||
| VITO_ENV_PATH= | ||
| VITO_STORAGE_PATH= | ||
|
|
||
| APP_SERVICES_CACHE= | ||
| APP_PACKAGES_CACHE= | ||
| APP_CONFIG_CACHE= | ||
| APP_ROUTES_CACHE= | ||
| APP_EVENTS_CACHE= | ||
| VIEW_COMPILED_PATH= | ||
|
|
||
| DB_CONNECTION=sqlite | ||
| DB_DATABASE=database.sqlite | ||
|
|
||
| QUEUE_CONNECTION=database | ||
| DB_QUEUE=default | ||
| QUEUE_FAILED_DRIVER=database-uuids | ||
|
|
||
| CACHE_DRIVER=file | ||
| SESSION_DRIVER=file | ||
| FILESYSTEM_DISK=local | ||
| INERTIA_ENSURE_PAGES_EXIST=false | ||
|
|
||
| MAIL_MAILER=log | ||
|
|
||
| WS_HOST=127.0.0.1 | ||
| WS_PORT=8085 | ||
| WS_ALLOWED_ORIGINS= | ||
| WS_BROADCAST_SECRET= | ||
|
|
||
| SCRIBE_AUTH_KEY="YOUR-API-KEY" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| name: desktop-ci | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - 'desktop/**' | ||
| - 'scripts/desktop/**' | ||
| - '.github/workflows/desktop-ci.yml' | ||
| - '.github/workflows/desktop-release.yml' | ||
| - 'vite.config.ts' | ||
| - 'bootstrap/app.php' | ||
| - 'config/desktop.php' | ||
| - 'app/Support/DesktopRuntime.php' | ||
|
|
||
| jobs: | ||
| typecheck: | ||
| runs-on: ubuntu-24.04 | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Pin workflow actions to immutable commit SHAs. The new packaging workflows depend on mutable action tags, allowing an upstream tag change to execute different code in privileged build and release jobs.
🧰 Tools🪛 zizmor (1.26.1)[warning] 20-20: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 20-20: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 📍 Affects 2 files
🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22.x' | ||
|
|
||
| - name: Install desktop shell dependencies | ||
| run: npm ci | ||
| working-directory: desktop | ||
|
|
||
| - name: Build desktop shell | ||
| run: npm run build | ||
| working-directory: desktop | ||
|
|
||
| package-smoke: | ||
| runs-on: ubuntu-24.04 | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup PHP | ||
| uses: shivammathur/setup-php@v2 | ||
| with: | ||
| php-version: '8.4' | ||
| extensions: ctype, curl, dom, fileinfo, filter, ftp, iconv, intl, mbstring, openssl, pdo_sqlite, sqlite3, zip | ||
|
|
||
| - name: Install Composer dependencies | ||
| run: composer install --prefer-dist --no-progress --no-dev --optimize-autoloader | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22.x' | ||
|
|
||
| - name: Install NPM dependencies | ||
| run: npm install --force | ||
|
|
||
| - name: Build desktop frontend assets | ||
| run: npm run build:desktop | ||
|
|
||
| - name: Assemble desktop app distribution | ||
| run: bash scripts/desktop/build-app.sh | ||
|
|
||
| - name: Cache PHP runtime | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: desktop/resources/bin | ||
| key: desktop-php-linux-x64-${{ hashFiles('scripts/desktop/fetch-php.sh') }} | ||
|
|
||
| - name: Fetch PHP runtime | ||
| run: bash scripts/desktop/fetch-php.sh linux x64 | ||
|
|
||
| - name: Smoke test desktop app distribution | ||
| run: bash scripts/desktop/smoke-test.sh "$PWD/desktop/resources/bin/linux/x64/php" | ||
|
|
||
| - name: Install desktop shell dependencies | ||
| run: npm ci | ||
| working-directory: desktop | ||
|
|
||
| - name: Build desktop shell | ||
| run: npm run build | ||
| working-directory: desktop | ||
|
|
||
| - name: Package desktop app (unpacked) | ||
| run: npx electron-builder --config electron-builder.yml --linux --x64 --dir --publish never | ||
| working-directory: desktop | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| name: desktop-release | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: 'Existing release tag to build and attach desktop apps to (e.g. 4.1.0)' | ||
| required: true | ||
| workflow_call: | ||
| inputs: | ||
| version: | ||
| description: 'Existing release tag to build and attach desktop apps to' | ||
| required: true | ||
| type: string | ||
| secrets: | ||
| DESKTOP_MAC_CSC_LINK: | ||
| required: false | ||
| DESKTOP_MAC_CSC_KEY_PASSWORD: | ||
| required: false | ||
| DESKTOP_WIN_CSC_LINK: | ||
| required: false | ||
| DESKTOP_WIN_CSC_KEY_PASSWORD: | ||
| required: false | ||
| DESKTOP_APPLE_ID: | ||
| required: false | ||
| DESKTOP_APPLE_APP_SPECIFIC_PASSWORD: | ||
| required: false | ||
| DESKTOP_APPLE_TEAM_ID: | ||
| required: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| build: | ||
| name: Build ${{ matrix.name }} | ||
| runs-on: ${{ matrix.os }} | ||
|
|
||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - name: macos-arm64 | ||
| os: macos-15 | ||
| platform: darwin | ||
| arch: arm64 | ||
| build-args: --mac --arm64 | ||
| - name: macos-x64 | ||
| os: macos-15-intel | ||
| platform: darwin | ||
| arch: x64 | ||
| build-args: --mac --x64 | ||
| - name: windows-x64 | ||
| os: windows-latest | ||
| platform: win32 | ||
| arch: x64 | ||
| build-args: --win --x64 | ||
| - name: linux-x64 | ||
| os: ubuntu-24.04 | ||
| platform: linux | ||
| arch: x64 | ||
| build-args: --linux --x64 | ||
|
|
||
| steps: | ||
| - name: Remove optional "v" prefix | ||
| id: version | ||
| shell: bash | ||
| run: echo "version=${VERSION#v}" >> "$GITHUB_OUTPUT" | ||
| env: | ||
| VERSION: ${{ inputs.version }} | ||
|
|
||
| - name: Checkout release tag | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ steps.version.outputs.version }} | ||
|
|
||
| - name: Setup PHP | ||
| uses: shivammathur/setup-php@v2 | ||
| with: | ||
| php-version: '8.4' | ||
| extensions: ctype, curl, dom, fileinfo, filter, ftp, iconv, intl, mbstring, openssl, pdo_sqlite, sqlite3, zip | ||
|
|
||
| - name: Install Composer dependencies | ||
| run: composer install --prefer-dist --no-progress --no-dev --optimize-autoloader | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22.x' | ||
|
|
||
| - name: Install NPM dependencies | ||
| run: npm install --force | ||
|
|
||
| - name: Build desktop frontend assets | ||
| run: npm run build:desktop | ||
|
|
||
| - name: Assemble desktop app distribution | ||
| shell: bash | ||
| run: bash scripts/desktop/build-app.sh | ||
|
|
||
| - name: Cache PHP runtime | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: desktop/resources/bin | ||
| key: desktop-php-${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('scripts/desktop/fetch-php.sh') }} | ||
|
|
||
| - name: Fetch PHP runtime | ||
| shell: bash | ||
| run: bash scripts/desktop/fetch-php.sh "${{ matrix.platform }}" "${{ matrix.arch }}" | ||
|
|
||
| - name: Smoke test desktop app distribution | ||
| shell: bash | ||
| run: | | ||
| PHP_BIN="desktop/resources/bin/${{ matrix.platform }}/${{ matrix.arch }}/php" | ||
| if [ "${{ matrix.platform }}" = "win32" ]; then | ||
| PHP_BIN="$PHP_BIN.exe" | ||
| fi | ||
| bash scripts/desktop/smoke-test.sh "$PWD/$PHP_BIN" | ||
|
|
||
| - name: Install desktop shell dependencies | ||
| shell: bash | ||
| run: npm ci | ||
| working-directory: desktop | ||
|
|
||
| - name: Build desktop shell | ||
| shell: bash | ||
| run: npm run build | ||
| working-directory: desktop | ||
|
|
||
| - name: Set desktop app version | ||
| shell: bash | ||
| run: npm version "${{ steps.version.outputs.version }}" --no-git-tag-version --allow-same-version | ||
| working-directory: desktop | ||
|
|
||
| - name: Package desktop app | ||
| shell: bash | ||
| run: npx electron-builder --config electron-builder.yml ${{ matrix.build-args }} --publish never | ||
| working-directory: desktop | ||
| env: | ||
| CSC_LINK: ${{ secrets.DESKTOP_MAC_CSC_LINK }} | ||
| CSC_KEY_PASSWORD: ${{ secrets.DESKTOP_MAC_CSC_KEY_PASSWORD }} | ||
| WIN_CSC_LINK: ${{ secrets.DESKTOP_WIN_CSC_LINK }} | ||
| WIN_CSC_KEY_PASSWORD: ${{ secrets.DESKTOP_WIN_CSC_KEY_PASSWORD }} | ||
| APPLE_ID: ${{ secrets.DESKTOP_APPLE_ID }} | ||
| APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.DESKTOP_APPLE_APP_SPECIFIC_PASSWORD }} | ||
| APPLE_TEAM_ID: ${{ secrets.DESKTOP_APPLE_TEAM_ID }} | ||
| CSC_IDENTITY_AUTO_DISCOVERY: ${{ secrets.DESKTOP_MAC_CSC_LINK != '' }} | ||
|
Comment on lines
+135
to
+147
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Expose signing credentials only to their target platform. Every matrix job currently receives the macOS, Windows, and Apple notarisation credentials. A compromised Linux or Windows packaging dependency could therefore exfiltrate unrelated signing identities. Export macOS secrets only for 🧰 Tools🪛 zizmor (1.26.1)[warning] 137-137: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI Agents |
||
|
|
||
| - name: Upload desktop apps to release | ||
| shell: bash | ||
| run: | | ||
| shopt -s nullglob | ||
| FILES=(desktop/release/*.dmg desktop/release/*-mac-*.zip desktop/release/*.exe desktop/release/*.AppImage) | ||
| if [ ${#FILES[@]} -eq 0 ]; then | ||
| echo "No desktop artifacts found to upload" >&2 | ||
| exit 1 | ||
| fi | ||
| gh release upload "$VERSION" "${FILES[@]}" --clobber | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| <?php | ||
|
|
||
| namespace App\Actions\Desktop; | ||
|
|
||
| use App\Actions\User\CreateUser; | ||
| use App\Enums\UserRole; | ||
| use App\Models\User; | ||
| use Illuminate\Support\Facades\DB; | ||
| use Illuminate\Support\Facades\Validator; | ||
|
|
||
| class SetupDesktopAdmin | ||
| { | ||
| /** | ||
| * @param array<string, mixed> $input | ||
| */ | ||
| public function create(array $input): User | ||
| { | ||
| Validator::make($input, [ | ||
| 'password' => ['required', 'string', 'confirmed'], | ||
| ])->validate(); | ||
|
|
||
| return DB::transaction(function () use ($input): User { | ||
| $user = app(CreateUser::class)->create([ | ||
| 'name' => $input['name'] ?? null, | ||
| 'email' => $input['email'] ?? null, | ||
| 'password' => $input['password'] ?? null, | ||
| 'role' => UserRole::ADMIN->value, | ||
| ]); | ||
|
|
||
| $user->ensureHasDefaultProject(); | ||
|
|
||
| return $user; | ||
| }); | ||
|
Comment on lines
+22
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift First-run administrator eligibility is not enforced atomically. Concurrent unauthenticated requests can both observe an empty user table before creating separate administrators.
🧰 Tools🪛 PHPMD (2.15.0)[error] 22-33: Avoid using static access to class '\Illuminate\Support\Facades\DB' in method 'create'. (undefined) (StaticAccess) 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Run desktop CI for every desktop integration surface.
These filters omit supplied stack dependencies such as
app/Actions/Desktop/**, desktop controllers and middleware, desktop authentication pages, and frontend types. Changes there can break the packaged application without running this workflow. Add the complete desktop integration paths, or use broaderapp/**,config/**, andresources/**filters.🧰 Tools
🪛 zizmor (1.26.1)
[warning] 3-13: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 Prompt for AI Agents