Hide inputs from action logs

This commit was merged in pull request #180.
This commit is contained in:
Bryan
2026-01-12 17:31:05 -06:00
committed by GitHub
parent 1650994efa
commit 3c312dad7b
10 changed files with 802 additions and 557 deletions

View File

@@ -3,56 +3,16 @@ run-name: Custom Android Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
server: version:
description: 'Rendezvous Server' description: 'version to buld'
required: true required: true
default: '' default: ''
type: string type: string
key: zip_url:
description: 'Public Key' description: 'url to zip of json'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
@@ -71,7 +31,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ fromJson(inputs.extras).version }}" VERSION: "${{ inputs.version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -84,7 +44,7 @@ jobs:
generate-bridge-linux: generate-bridge-linux:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ fromJson(inputs.extras).version }} version: ${{ inputs.version }}
build-rustdesk-android: build-rustdesk-android:
needs: [generate-bridge-linux] needs: [generate-bridge-linux]
@@ -116,6 +76,46 @@ jobs:
suffix: "", suffix: "",
} }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}')
r.raise_for_status()
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Free Disk Space (Ubuntu) - name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main uses: jlumbroso/free-disk-space@main
with: with:
@@ -135,14 +135,14 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -151,7 +151,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}'
- name: Install dependencies - name: Install dependencies
run: | run: |
@@ -281,16 +281,16 @@ jobs:
prefix-key: rustdesk-lib-cache-android # TODO: drop '-android' part after caches are invalidated prefix-key: rustdesk-lib-cache-android # TODO: drop '-android' part after caches are invalidated
key: ${{ matrix.job.target }} key: ${{ matrix.job.target }}
###########################################################echo "${{ inputs.iconbase64 }}" | base64 -d > ./res/icon.png ###########################################################echo "${{ env.iconbase64 }}" | base64 -d > ./res/icon.png
- name: icon stuff - name: icon stuff
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
mv ./res/icon.ico ./res/icon.ico.bak mv ./res/icon.ico ./res/icon.ico.bak
mv ./res/icon.png ./res/icon.png.bak mv ./res/icon.png ./res/icon.png.bak
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
wget -O ./res/icon.png ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }} wget -O ./res/icon.png ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }}
mv ./res/32x32.png ./res/32x32.png.bak mv ./res/32x32.png ./res/32x32.png.bak
mv ./res/64x64.png ./res/64x64.png.bak mv ./res/64x64.png ./res/64x64.png.bak
mv ./res/128x128.png ./res/128x128.png.bak mv ./res/128x128.png ./res/128x128.png.bak
@@ -315,74 +315,74 @@ jobs:
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
# ./flutter/pubspec.yaml # ./flutter/pubspec.yaml
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml #sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
- name: change appname to custom - name: change appname to custom
if: inputs.appname != 'rustdesk' if: env.appname != 'rustdesk'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml
sed -i 's|name = "RustDesk"|name = "${{ inputs.appname }}"|' ./Cargo.toml sed -i 's|name = "RustDesk"|name = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
sed -i -e 's|"RustDesk Remote Desktop"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"RustDesk Remote Desktop"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ inputs.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ env.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"rustdesk.exe"|"${{ inputs.filename }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"rustdesk.exe"|"${{ env.filename }}"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
sed -i -e 's|RustDesk|${{ inputs.appname }}|' ./flutter/android/app/src/main/res/values/strings.xml sed -i -e 's|RustDesk|${{ env.appname }}|' ./flutter/android/app/src/main/res/values/strings.xml
sed -i -e "s|title: 'RustDesk'|title: '${{ inputs.appname }}'|" ./flutter/lib/main.dart sed -i -e "s|title: 'RustDesk'|title: '${{ env.appname }}'|" ./flutter/lib/main.dart
sed -i -e "s|return 'RustDesk';|return '${{ inputs.appname }}';|" ./flutter/lib/web/bridge.dart sed -i -e "s|return 'RustDesk';|return '${{ env.appname }}';|" ./flutter/lib/web/bridge.dart
sed -i 's|android:label="RustDesk"|android:label="${{ inputs.appname }}"|' ./flutter/android/app/src/main/AndroidManifest.xml sed -i 's|android:label="RustDesk"|android:label="${{ env.appname }}"|' ./flutter/android/app/src/main/AndroidManifest.xml
sed -i 's|android:label="RustDesk Input"|android:label="${{ inputs.appname }} Input"|' ./flutter/android/app/src/main/AndroidManifest.xml sed -i 's|android:label="RustDesk Input"|android:label="${{ env.appname }} Input"|' ./flutter/android/app/src/main/AndroidManifest.xml
sed -i 's|RustDesk is Open|${{ inputs.appname }} is Open|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt sed -i 's|RustDesk is Open|${{ env.appname }} is Open|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt
sed -i 's|Show Rustdesk|Show ${{ inputs.appname }}|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/FloatingWindowService.kt sed -i 's|Show Rustdesk|Show ${{ env.appname }}|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/FloatingWindowService.kt
sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
sed -i 's|"RustDesk Service|"${{ inputs.appname }} Service|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt sed -i 's|"RustDesk Service|"${{ env.appname }} Service|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
sed -i 's|RustDesk|${{ inputs.appname }}|' ./flutter/lib/main.dart sed -i 's|RustDesk|${{ env.appname }}|' ./flutter/lib/main.dart
sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/lib/desktop/widgets/tabbar_widget.dart sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/lib/desktop/widgets/tabbar_widget.dart
sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./libs/hbb_common/src/config.rs sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./libs/hbb_common/src/config.rs
- name: change url to custom - name: change url to custom
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com' if: env.urlLink != 'https://rustdesk.com'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|child: Text('rustdesk.com',|child: Text('${{ fromJson(inputs.extras).urlLink }}',|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|child: Text('rustdesk.com',|child: Text('${{ env.urlLink }}',|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change app id to custom - name: change app id to custom
if: fromJson(inputs.extras).androidappid != 'com.carriez.flutter_hbb' if: env.androidappid != 'com.carriez.flutter_hbb'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|com.carriez.flutter_hbb|${{ fromJson(inputs.extras).androidappid }}|' ./flutter/android/app/build.gradle sed -i -e 's|com.carriez.flutter_hbb|${{ env.androidappid }}|' ./flutter/android/app/build.gradle
- name: change download link to custom - name: change download link to custom
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download' if: env.downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
- name: allow custom.txt - name: allow custom.txt
continue-on-error: true continue-on-error: true
@@ -394,35 +394,35 @@ jobs:
- name: fix connection delay - name: fix connection delay
continue-on-error: true continue-on-error: true
if: ${{ fromJson(inputs.extras).delayFix == 'true' }} if: ${{ env.delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).cycleMonitor == 'true' if: env.cycleMonitor == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).xOffline == 'true' if: env.xOffline == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: hide-cm - name: hide-cm
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).hidecm == 'true' if: env.hidecm == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
git apply hidecm.diff git apply hidecm.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).removeNewVersionNotif == 'true' if: env.removeNewVersionNotif == 'true'
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
@@ -434,10 +434,10 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "35% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "35% complete"}'
- name: replace flutter icons - name: replace flutter icons
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
run: | run: |
pushd ./flutter pushd ./flutter
flutter pub get flutter pub get
@@ -489,10 +489,10 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "45% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "45% complete"}'
- name: icons - name: icons
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
run: | run: |
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
@@ -515,7 +515,7 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
@@ -526,7 +526,7 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
@@ -537,7 +537,7 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/x86_64 mkdir -p ./flutter/android/app/src/main/jniLibs/x86_64
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86_64/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86_64/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86_64/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86_64/librustdesk.so
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
@@ -548,7 +548,7 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/x86 mkdir -p ./flutter/android/app/src/main/jniLibs/x86
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86/librustdesk.so
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
@@ -558,7 +558,7 @@ jobs:
esac esac
popd popd
mkdir -p signed-apk; pushd signed-apk mkdir -p signed-apk; pushd signed-apk
mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.apk ./${{ inputs.filename }}-${{ matrix.job.arch }}.apk mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.apk ./${{ env.filename }}-${{ matrix.job.arch }}.apk
popd popd
- name: Report Status - name: Report Status
@@ -568,7 +568,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "75% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "75% complete"}'
- uses: r0adkll/sign-android-release@v1 - uses: r0adkll/sign-android-release@v1
name: Sign app APK name: Sign app APK
@@ -586,16 +586,16 @@ jobs:
BUILD_TOOLS_VERSION: "30.0.2" BUILD_TOOLS_VERSION: "30.0.2"
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./signed-apk/${{ inputs.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
- name: send file to api server - name: send file to api server
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./signed-apk/${{ inputs.filename }}-${{ matrix.job.arch }}.apk" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" ${{ env.apiServer }}/api/save_custom_client
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -604,7 +604,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}' data: '{"uuid": "${{ env.uuid }}", "status": "Success"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -613,7 +613,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -622,4 +622,4 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}'

View File

@@ -3,56 +3,16 @@ run-name: Custom Linux Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
server: version:
description: 'Rendezvous Server' description: 'version to buld'
required: true required: true
default: '' default: ''
type: string type: string
key: zip_url:
description: 'Public Key' description: 'url to zip of json'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
@@ -71,7 +31,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ fromJson(inputs.extras).version }}" VERSION: "${{ inputs.version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -84,7 +44,7 @@ jobs:
generate-bridge-linux: generate-bridge-linux:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ fromJson(inputs.extras).version }} version: ${{ inputs.version }}
build-rustdesk-linux: build-rustdesk-linux:
needs: [generate-bridge-linux] needs: [generate-bridge-linux]
@@ -112,6 +72,48 @@ jobs:
vcpkg-triplet: arm64-linux, vcpkg-triplet: arm64-linux,
} }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Export GitHub Actions cache environment variables - name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6 uses: actions/github-script@v6
with: with:
@@ -120,14 +122,14 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -136,7 +138,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}'
- name: Maximize build space - name: Maximize build space
run: | run: |
@@ -205,7 +207,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "15% complete"}'
- name: Restore bridge files - name: Restore bridge files
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true' if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
@@ -243,14 +245,14 @@ jobs:
shell: bash shell: bash
- name: icon stuff - name: icon stuff
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
mv ./res/icon.ico ./res/icon.ico.bak mv ./res/icon.ico ./res/icon.ico.bak
mv ./res/icon.png ./res/icon.png.bak mv ./res/icon.png ./res/icon.png.bak
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
wget -O ./res/icon.png ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }} wget -O ./res/icon.png ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }}
mv ./res/32x32.png ./res/32x32.png.bak mv ./res/32x32.png ./res/32x32.png.bak
mv ./res/64x64.png ./res/64x64.png.bak mv ./res/64x64.png ./res/64x64.png.bak
mv ./res/128x128.png ./res/128x128.png.bak mv ./res/128x128.png ./res/128x128.png.bak
@@ -268,97 +270,97 @@ jobs:
b64="" b64=""
- name: change appname to custom - name: change appname to custom
if: inputs.appname != 'rustdesk' if: env.appname != 'rustdesk'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
sed -i -e '/-p tmpdeb\/usr\/lib\/rustdesk/d' ./build.py sed -i -e '/-p tmpdeb\/usr\/lib\/rustdesk/d' ./build.py
- name: change company name - name: change company name
if: fromJson(inputs.extras).compname != 'Purslane Ltd' if: env.compname != 'Purslane Ltd'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./Cargo.toml sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./libs/portable/Cargo.toml sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml
- name: allow custom.txt - name: allow custom.txt
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff
git apply allowCustom.diff git apply allowCustom.diff
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
git apply removeSetupServerTip.diff git apply removeSetupServerTip.diff
echo -n "${{ inputs.custom }}" | cat > ./custom_.txt echo -n "${{ env.custom }}" | cat > ./custom_.txt
# sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml # sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
- name: change url to custom - name: change url to custom
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com' if: env.urlLink != 'https://rustdesk.com'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change download link to custom - name: change download link to custom
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download' if: env.downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
- name: fix connection delay - name: fix connection delay
continue-on-error: true continue-on-error: true
if: ${{ fromJson(inputs.extras).delayFix == 'true' }} if: ${{ env.delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).cycleMonitor == 'true' if: env.cycleMonitor == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).xOffline == 'true' if: env.xOffline == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: hide-cm - name: hide-cm
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).hidecm == 'true' if: env.hidecm == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
git apply hidecm.diff git apply hidecm.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).removeNewVersionNotif == 'true' if: env.removeNewVersionNotif == 'true'
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
@@ -377,7 +379,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "65% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "65% complete"}'
- uses: rustdesk-org/run-on-arch-action@amd64-support - uses: rustdesk-org/run-on-arch-action@amd64-support
name: Build rustdesk name: Build rustdesk
@@ -523,10 +525,10 @@ jobs:
export DEB_ARCH=${{ matrix.job.deb_arch }} export DEB_ARCH=${{ matrix.job.deb_arch }}
mkdir -p flutter/tmpdeb/usr/share/rustdesk mkdir -p flutter/tmpdeb/usr/share/rustdesk
cp ./custom_.txt ./flutter/tmpdeb/usr/share/rustdesk/custom_.txt cp ./custom_.txt ./flutter/tmpdeb/usr/share/rustdesk/custom_.txt
if [[ "${{ inputs.logolink }}" != "false" ]]; then if [[ "${{ env.logolink_url }}" != "false" ]]; then
wget -O ./flutter/assets/logo.png ${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}"&"uuid=${{ fromJson(inputs.logolink).uuid }} wget -O ./flutter/assets/logo.png ${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}"&"uuid=${{ env.logolink_uuid }}
fi fi
if [[ "${{ inputs.iconlink }}" != "false" ]]; then if [[ "${{ env.iconlink_url }}" != "false" ]]; then
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
convert ./res/icon.png ./flutter/assets/icon.svg convert ./res/icon.png ./flutter/assets/icon.svg
convert ./res/128x128.png -resize 200% ./flutter/assets/128x128@2x.png || true convert ./res/128x128.png -resize 200% ./flutter/assets/128x128@2x.png || true
@@ -541,7 +543,7 @@ jobs:
fi fi
python3 ./build.py --flutter --skip-cargo python3 ./build.py --flutter --skip-cargo
for name in rustdesk*??.deb; do for name in rustdesk*??.deb; do
mv "$name" /workspace/output/"${{ inputs.filename }}-${{ matrix.job.arch }}.deb" mv "$name" /workspace/output/"${{ env.filename }}-${{ matrix.job.arch }}.deb"
done done
# rpm package # rpm package
@@ -555,7 +557,7 @@ jobs:
HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }} pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
for name in rustdesk*??.rpm; do for name in rustdesk*??.rpm; do
mv "$name" /workspace/output/"${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" mv "$name" /workspace/output/"${{ env.filename }}-${{ matrix.job.arch }}.rpm"
done done
# rpm suse package # rpm suse package
@@ -569,7 +571,7 @@ jobs:
HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }} pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
for name in rustdesk*??.rpm; do for name in rustdesk*??.rpm; do
mv "$name" /workspace/output/"${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" mv "$name" /workspace/output/"${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm"
done done
# only x86_64 for arch since we can not find newest arm64 docker image to build # only x86_64 for arch since we can not find newest arm64 docker image to build
@@ -597,32 +599,32 @@ jobs:
continue-on-error: true continue-on-error: true
if: matrix.job.arch == 'x86_64' && env.UPLOAD_ARTIFACT == 'true' && env.VERSION != 'master' if: matrix.job.arch == 'x86_64' && env.UPLOAD_ARTIFACT == 'true' && env.VERSION != 'master'
run: | run: |
cp ./res/rustdesk-${{ env.VERSION }}-0-x86_64.pkg.tar.zst ./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst cp ./res/rustdesk-${{ env.VERSION }}-0-x86_64.pkg.tar.zst ./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
- name: send file to api server - name: send file to api server
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" ${{ env.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ inputs.apiServer }}/api/save_custom_client || true curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ env.apiServer }}/api/save_custom_client || true
- name: Upload deb - name: Upload deb
uses: actions/upload-artifact@master uses: actions/upload-artifact@master
if: env.UPLOAD_ARTIFACT == 'true' if: env.UPLOAD_ARTIFACT == 'true'
with: with:
name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb name: ${{ env.filename }}-${{ matrix.job.arch }}.deb
path: ./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb path: ./output/${{ env.filename }}-${{ matrix.job.arch }}.deb
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -631,7 +633,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Finished ${{ matrix.job.arch }}"}' data: '{"uuid": "${{ env.uuid }}", "status": "Finished ${{ matrix.job.arch }}"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -640,7 +642,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -649,7 +651,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}'
build-appimage: build-appimage:
name: Build appimage ${{ matrix.job.target }} name: Build appimage ${{ matrix.job.target }}
@@ -662,6 +664,48 @@ jobs:
- { target: x86_64-unknown-linux-gnu, arch: x86_64 } - { target: x86_64-unknown-linux-gnu, arch: x86_64 }
- { target: aarch64-unknown-linux-gnu, arch: aarch64 } - { target: aarch64-unknown-linux-gnu, arch: aarch64 }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -680,12 +724,12 @@ jobs:
- name: Download Binary - name: Download Binary
uses: actions/download-artifact@master uses: actions/download-artifact@master
with: with:
name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb name: ${{ env.filename }}-${{ matrix.job.arch }}.deb
path: . path: .
- name: Rename Binary - name: Rename Binary
run: | run: |
mv ${{ inputs.filename }}-${{ matrix.job.arch }}.deb appimage/rustdesk.deb mv ${{ env.filename }}-${{ matrix.job.arch }}.deb appimage/rustdesk.deb
- name: Build appimage package - name: Build appimage package
shell: bash shell: bash
@@ -698,19 +742,19 @@ jobs:
# run appimage-builder # run appimage-builder
pushd appimage pushd appimage
sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml
sudo mv ./rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.AppImage ./${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage sudo mv ./rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.AppImage ./${{ env.filename }}-${{ matrix.job.arch }}.AppImage
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./appimage/${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
- name: send file to api server - name: send file to api server
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./appimage/${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" ${{ env.apiServer }}/api/save_custom_client
build-flatpak: build-flatpak:
name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }} name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }}
@@ -737,6 +781,48 @@ jobs:
suffix: "", suffix: "",
} }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -755,12 +841,12 @@ jobs:
- name: Download Binary - name: Download Binary
uses: actions/download-artifact@master uses: actions/download-artifact@master
with: with:
name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb name: ${{ env.filename }}-${{ matrix.job.arch }}.deb
path: . path: .
- name: Rename Binary - name: Rename Binary
run: | run: |
mv ${{ inputs.filename }}-${{ matrix.job.arch }}.deb flatpak/rustdesk.deb mv ${{ env.filename }}-${{ matrix.job.arch }}.deb flatpak/rustdesk.deb
- uses: rustdesk-org/run-on-arch-action@amd64-support - uses: rustdesk-org/run-on-arch-action@amd64-support
name: Build rustdesk flatpak package for ${{ matrix.job.arch }} name: Build rustdesk flatpak package for ${{ matrix.job.arch }}
@@ -789,21 +875,21 @@ jobs:
pushd flatpak pushd flatpak
git clone https://github.com/flathub/shared-modules.git --depth=1 git clone https://github.com/flathub/shared-modules.git --depth=1
flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json
flatpak build-bundle ./repo ${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak com.rustdesk.RustDesk flatpak build-bundle ./repo ${{ env.filename }}-${{ matrix.job.arch }}.flatpak com.rustdesk.RustDesk
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./flatpak/${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
- name: send file to api server - name: send file to api server
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./flatpak/${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" ${{ env.apiServer }}/api/save_custom_client
@@ -811,16 +897,66 @@ jobs:
needs: [build-rustdesk-linux,build-flatpak,build-appimage] needs: [build-rustdesk-linux,build-flatpak,build-appimage]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -828,9 +964,9 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}' data: '{"uuid": "${{ env.uuid }}", "status": "Success"}'
- uses: geekyeggo/delete-artifact@v5 - uses: geekyeggo/delete-artifact@v5
continue-on-error: true continue-on-error: true
with: with:
name: ${{ inputs.filename }}-*.deb name: ${{ env.filename }}-*.deb

View File

@@ -3,56 +3,16 @@ run-name: Custom macOS Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
server: version:
description: 'Rendezvous Server' description: 'version to buld'
required: true required: true
default: '' default: ''
type: string type: string
key: zip_url:
description: 'Public Key' description: 'url to zip of json'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
@@ -71,7 +31,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ fromJson(inputs.extras).version }}" VERSION: "${{ inputs.version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -83,7 +43,7 @@ jobs:
generate-bridge: generate-bridge:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ fromJson(inputs.extras).version }} version: ${{ inputs.version }}
build-for-macos: build-for-macos:
name: ${{ matrix.job.target }} name: ${{ matrix.job.target }}
@@ -95,7 +55,7 @@ jobs:
job: job:
- { - {
target: x86_64-apple-darwin, target: x86_64-apple-darwin,
os: macos-13, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel os: macos-15-intel, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel
extra-build-args: "", extra-build-args: "",
arch: x86_64, arch: x86_64,
vcpkg-triplet: x64-osx, vcpkg-triplet: x64-osx,
@@ -109,9 +69,59 @@ jobs:
vcpkg-triplet: arm64-osx, vcpkg-triplet: arm64-osx,
} }
env: env:
STATUS_URL: ${{ fromJson(inputs.extras).rdgen == 'true' && format('{0}/updategh', secrets.GENURL) || format('{0}/api/updategh', inputs.apiServer) }} STATUS_URL: "${{ secrets.GENURL }}/updategh"
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}')
r.raise_for_status()
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
api_server = secrets.get('apiServer', '').strip()
api_server = api_server.rstrip('/')
rdgen_value = str(secrets.get('rdgen', 'false')).lower()
if rdgen_value == "true":
status_url = "${{ secrets.GENURL }}/updategh"
else:
status_url = f"{api_server}/api/updategh"
env_file.write(f"STATUS_URL={status_url}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Export GitHub Actions cache environment variables - name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6 uses: actions/github-script@v6
with: with:
@@ -125,7 +135,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}'
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
@@ -158,73 +168,73 @@ jobs:
cp ./flutter/macos/Runner/Configs/AppInfo.xcconfig ./flutter/macos/Runner/Configs/AppInfo.xcconfig.bak cp ./flutter/macos/Runner/Configs/AppInfo.xcconfig ./flutter/macos/Runner/Configs/AppInfo.xcconfig.bak
# MACSTUFF Update Info.plist # MACSTUFF Update Info.plist
sed -i '' -e 's|<key>CFBundleName</key>.*<string>.*</string>|<key>CFBundleName</key>\n\t<string>${{ inputs.appname }}</string>|' ./flutter/macos/Runner/Info.plist sed -i '' -e 's|<key>CFBundleName</key>.*<string>.*</string>|<key>CFBundleName</key>\n\t<string>${{ env.appname }}</string>|' ./flutter/macos/Runner/Info.plist
sed -i '' -e 's|<key>CFBundleDisplayName</key>.*<string>.*</string>|<key>CFBundleDisplayName</key>\n\t<string>${{ inputs.appname }}</string>|' ./flutter/macos/Runner/Info.plist sed -i '' -e 's|<key>CFBundleDisplayName</key>.*<string>.*</string>|<key>CFBundleDisplayName</key>\n\t<string>${{ env.appname }}</string>|' ./flutter/macos/Runner/Info.plist
sed -i '' -e 's|<key>CFBundleIdentifier</key>.*<string>.*</string>|<key>CFBundleIdentifier</key>\n\t<string>com.${{ inputs.appname }}.app</string>|' ./flutter/macos/Runner/Info.plist sed -i '' -e 's|<key>CFBundleIdentifier</key>.*<string>.*</string>|<key>CFBundleIdentifier</key>\n\t<string>com.${{ env.appname }}.app</string>|' ./flutter/macos/Runner/Info.plist
# sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ inputs.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist # sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ env.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
# MACSTUFF Update AppInfo.xcconfig # MACSTUFF Update AppInfo.xcconfig
sed -i '' -e 's|PRODUCT_NAME = .*|PRODUCT_NAME = ${{ inputs.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig sed -i '' -e 's|PRODUCT_NAME = .*|PRODUCT_NAME = ${{ env.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
sed -i '' -e 's|PRODUCT_BUNDLE_IDENTIFIER = .*|PRODUCT_BUNDLE_IDENTIFIER = com.${{ inputs.appname }}.app|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig sed -i '' -e 's|PRODUCT_BUNDLE_IDENTIFIER = .*|PRODUCT_BUNDLE_IDENTIFIER = com.${{ env.appname }}.app|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
sed -i '' -e 's|Purslane Ltd.|${{ inputs.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig sed -i '' -e 's|Purslane Ltd.|${{ env.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
# Keep DEVELOPMENT_TEAM if it exists, don't blank it out # Keep DEVELOPMENT_TEAM if it exists, don't blank it out
sed -i -e 's|Purslane Ltd.|${{ inputs.appname }}|' ./Cargo.toml sed -i -e 's|Purslane Ltd.|${{ env.appname }}|' ./Cargo.toml
sed -i -e 's|Purslane Ltd|${{ inputs.appname }}|' ./libs/portable/Cargo.toml sed -i -e 's|Purslane Ltd|${{ env.appname }}|' ./libs/portable/Cargo.toml
# Update Xcode project settings # Update Xcode project settings
sed -i '' -e 's/PRODUCT_NAME = "RustDesk"/PRODUCT_NAME = "${{ inputs.appname }}"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj sed -i '' -e 's/PRODUCT_NAME = "RustDesk"/PRODUCT_NAME = "${{ env.appname }}"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
sed -i '' -e 's/PRODUCT_BUNDLE_IDENTIFIER = ".*"/PRODUCT_BUNDLE_IDENTIFIER = "com.${{ inputs.appname }}.app"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj sed -i '' -e 's/PRODUCT_BUNDLE_IDENTIFIER = ".*"/PRODUCT_BUNDLE_IDENTIFIER = "com.${{ env.appname }}.app"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
# Don't modify DEVELOPMENT_TEAM in project.pbxproj # Don't modify DEVELOPMENT_TEAM in project.pbxproj
# Update CMake settings # Update CMake settings
if [ -f "./flutter/macos/CMakeLists.txt" ]; then if [ -f "./flutter/macos/CMakeLists.txt" ]; then
sed -i '' -e 's/set(BINARY_NAME ".*")/set(BINARY_NAME "${{ inputs.appname }}")/' ./flutter/macos/CMakeLists.txt sed -i '' -e 's/set(BINARY_NAME ".*")/set(BINARY_NAME "${{ env.appname }}")/' ./flutter/macos/CMakeLists.txt
fi fi
# Update Podfile - keep the target as 'Runner' # Update Podfile - keep the target as 'Runner'
# sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'${{ inputs.appname }}'"'"' do/' ./flutter/macos/Podfile # sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'${{ env.appname }}'"'"' do/' ./flutter/macos/Podfile
sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'Runner'"'"' do/' ./flutter/macos/Podfile sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'Runner'"'"' do/' ./flutter/macos/Podfile
cp ./src/lang/en.rs ./src/lang/en.rs.bak cp ./src/lang/en.rs ./src/lang/en.rs.bak
cp ./src/lang/nl.rs ./src/lang/nl.rs.bak cp ./src/lang/nl.rs ./src/lang/nl.rs.bak
find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ env.appname }}|' {} \;
sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' ./src/lang/nl.rs sed -i '' -e 's|RustDesk|${{ env.appname }}|' ./src/lang/nl.rs
sed -i '' -e 's|https://rustdesk.com|${{ fromJson(inputs.extras).urlLink }}|' ./build.py sed -i '' -e 's|https://rustdesk.com|${{ env.urlLink }}|' ./build.py
sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i '' -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i '' -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i '' -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i '' -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change download link to custom - name: change download link to custom
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download' if: env.downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
# Update slogan # Update slogan
#sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ inputs.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist #sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ env.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
# Update slogan - About in en.rs # Update slogan - About in en.rs
sed -i '' -e 's/("Slogan_tip", "Made with heart in this chaotic world!")/("Slogan_tip", "Powered by ${{ inputs.appname }}")/' ./src/lang/en.rs sed -i '' -e 's/("Slogan_tip", "Made with heart in this chaotic world!")/("Slogan_tip", "Powered by ${{ env.appname }}")/' ./src/lang/en.rs
sed -i '' -e 's/("About RustDesk", "")/("About RustDesk", "About ${{ inputs.appname }}")/' ./src/lang/en.rs sed -i '' -e 's/("About RustDesk", "")/("About RustDesk", "About ${{ env.appname }}")/' ./src/lang/en.rs
# Update slogan - About in nl.rs # Update slogan - About in nl.rs
sed -i '' -e 's/("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!")/("Slogan_tip", "Powered by ${{ inputs.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!")/("Slogan_tip", "Powered by ${{ env.appname }}")/' ./src/lang/nl.rs
sed -i '' -e 's/("Your Desktop", "Uw Bureaublad")/("Your Desktop", "Uw ${{ inputs.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("Your Desktop", "Uw Bureaublad")/("Your Desktop", "Uw ${{ env.appname }}")/' ./src/lang/nl.rs
sed -i '' -e 's/("About RustDesk", "Over RustDesk")/("About RustDesk", "Over ${{ inputs.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("About RustDesk", "Over RustDesk")/("About RustDesk", "Over ${{ env.appname }}")/' ./src/lang/nl.rs
sed -i '' -e 's/("About", "Over")/("About", "Over ${{ inputs.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("About", "Over")/("About", "Over ${{ env.appname }}")/' ./src/lang/nl.rs
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff
git apply allowCustom.diff git apply allowCustom.diff
@@ -244,11 +254,11 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "10% complete"}'
- name: Install build runtime - name: Install build runtime
run: | run: |
brew install llvm create-dmg nasm brew install llvm create-dmg
# pkg-config is handled in a separate step, because it may be already installed by `macos-latest`(14.7.1) runner # pkg-config is handled in a separate step, because it may be already installed by `macos-latest`(14.7.1) runner
if command -v pkg-config &>/dev/null; then if command -v pkg-config &>/dev/null; then
echo "pkg-config is already installed" echo "pkg-config is already installed"
@@ -256,6 +266,17 @@ jobs:
brew install pkg-config brew install pkg-config
fi fi
- name: Install NASM
run: |
# Install NASM 2.16.x from official release.
# Do NOT use `brew install nasm` which installs NASM 3.x.
# NASM 3.x is a complete rewrite with incompatible CLI options and removed features.
# aom and other multimedia libraries require NASM 2.x for x86/x86_64 assembly.
wget https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/macosx/nasm-2.16.03-macosx.zip
unzip nasm-2.16.03-macosx.zip
sudo cp nasm-2.16.03/nasm /usr/local/bin/nasm
nasm --version
- name: Install flutter - name: Install flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
@@ -288,7 +309,7 @@ jobs:
prefix-key: ${{ matrix.job.os }} prefix-key: ${{ matrix.job.os }}
- name: Magick stuff for macOS - name: Magick stuff for macOS
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -302,8 +323,8 @@ jobs:
# Download icon using curl with additional SSL options # Download icon using curl with additional SSL options
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \ curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
-H "User-Agent: Mozilla/5.0" \ -H "User-Agent: Mozilla/5.0" \
"${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}&uuid=${{ fromJson(inputs.iconlink).uuid }}" \ "${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}&uuid=${{ env.iconlink_uuid }}" \
-o ./res/icon.png || wget --no-check-certificate -O ./res/icon.png "${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}&uuid=${{ fromJson(inputs.iconlink).uuid }}" -o ./res/icon.png || wget --no-check-certificate -O ./res/icon.png "${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}&uuid=${{ env.iconlink_uuid }}"
# Backup existing files (if they exist) # Backup existing files (if they exist)
[ -f "./res/32x32.png" ] && mv ./res/32x32.png ./res/32x32.png.bak [ -f "./res/32x32.png" ] && mv ./res/32x32.png ./res/32x32.png.bak
@@ -398,7 +419,7 @@ jobs:
ls -lh rustdesk/data/flutter_assets/assets/ ls -lh rustdesk/data/flutter_assets/assets/
- name: replace flutter icons - name: replace flutter icons
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -406,8 +427,8 @@ jobs:
# Create required directories and files # Create required directories and files
mkdir -p web mkdir -p web
mkdir -p assets mkdir -p assets
echo '{"name":"${{ inputs.appname }}","short_name":"${{ inputs.appname }}","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#ffffff","description":"A remote desktop software."}' > web/manifest.json echo '{"name":"${{ env.appname }}","short_name":"${{ env.appname }}","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#ffffff","description":"A remote desktop software."}' > web/manifest.json
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${{ inputs.appname }}</title></head><body></body></html>' > web/index.html echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${{ env.appname }}</title></head><body></body></html>' > web/index.html
# Ensure the AppIcon.appiconset directory exists # Ensure the AppIcon.appiconset directory exists
mkdir -p macos/Runner/Assets.xcassets/AppIcon.appiconset mkdir -p macos/Runner/Assets.xcassets/AppIcon.appiconset
@@ -422,7 +443,7 @@ jobs:
cd .. cd ..
- name: ui.rs - name: ui.rs
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
@@ -435,35 +456,35 @@ jobs:
- name: fix connection delay - name: fix connection delay
continue-on-error: false continue-on-error: false
if: ${{ fromJson(inputs.extras).delayFix == 'true' }} if: ${{ env.delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).cycleMonitor == 'true' if: env.cycleMonitor == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).xOffline == 'true' if: env.xOffline == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: hide-cm - name: hide-cm
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).hidecm == 'true' if: env.hidecm == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
git apply hidecm.diff git apply hidecm.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).removeNewVersionNotif == 'true' if: env.removeNewVersionNotif == 'true'
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
@@ -474,7 +495,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "20% complete"}'
- name: Restore bridge files - name: Restore bridge files
uses: actions/download-artifact@master uses: actions/download-artifact@master
@@ -510,7 +531,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "25% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "25% complete"}'
- name: Create MacOS directory structure - name: Create MacOS directory structure
run: | run: |
@@ -525,7 +546,7 @@ jobs:
sed -i -e "s/osx_minimum_system_version = \"[0-9]*.[0-9]*\"/osx_minimum_system_version = \"${MIN_MACOS_VERSION}\"/" Cargo.toml sed -i -e "s/osx_minimum_system_version = \"[0-9]*.[0-9]*\"/osx_minimum_system_version = \"${MIN_MACOS_VERSION}\"/" Cargo.toml
sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj
fi fi
sed -i -e "s/RustDesk.app/\"${{ inputs.appname }}.app\"/" build.py sed -i -e "s/RustDesk.app/\"${{ env.appname }}.app\"/" build.py
./build.py --flutter --hwcodec --unix-file-copy-paste ${{ matrix.job.extra-build-args }} ./build.py --flutter --hwcodec --unix-file-copy-paste ${{ matrix.job.extra-build-args }}
# - name: Copy service file # - name: Copy service file
@@ -538,7 +559,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}' data: '{"uuid": "${{ env.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
- name: Install rcodesign tool - name: Install rcodesign tool
if: env.MACOS_P12_BASE64 != null if: env.MACOS_P12_BASE64 != null
@@ -566,7 +587,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}' data: '{"uuid": "${{ env.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}'
- name: Show version information (Rust, cargo, Clang) - name: Show version information (Rust, cargo, Clang)
shell: bash shell: bash
@@ -579,7 +600,7 @@ jobs:
rustc -V rustc -V
- name: icon svg handling - name: icon svg handling
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -595,7 +616,7 @@ jobs:
rm ./temp_icon.pbm rm ./temp_icon.pbm
- name: logo handling - name: logo handling
if: ${{ inputs.logolink != 'false' }} if: ${{ env.logolink_url != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -603,11 +624,11 @@ jobs:
mkdir -p "$ASSETS_DIR" mkdir -p "$ASSETS_DIR"
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \ curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
-H "User-Agent: Mozilla/5.0" \ -H "User-Agent: Mozilla/5.0" \
"${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}&uuid=${{ fromJson(inputs.logolink).uuid }}" \ "${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}" \
-o "$ASSETS_DIR/logo.png" || \ -o "$ASSETS_DIR/logo.png" || \
wget --no-check-certificate \ wget --no-check-certificate \
-O "$ASSETS_DIR/logo.png" \ -O "$ASSETS_DIR/logo.png" \
"${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}&uuid=${{ fromJson(inputs.logolink).uuid }}" "${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}"
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -615,7 +636,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "85% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "85% complete"}'
- name: Sign macOS app bundle - name: Sign macOS app bundle
if: env.MACOS_P12_BASE64 != '' if: env.MACOS_P12_BASE64 != ''
@@ -628,21 +649,21 @@ jobs:
# Rename RustDesk.app to the custom app name first # Rename RustDesk.app to the custom app name first
if [ -d "RustDesk.app" ]; then if [ -d "RustDesk.app" ]; then
# First rename the app if it's still called RustDesk.app # First rename the app if it's still called RustDesk.app
mv "RustDesk.app" "${{ inputs.appname }}.app" mv "RustDesk.app" "${{ env.appname }}.app"
echo "Renamed RustDesk.app to ${{ inputs.appname }}.app" echo "Renamed RustDesk.app to ${{ env.appname }}.app"
fi fi
echo "App bundle contents after rename:" echo "App bundle contents after rename:"
ls -la "${{ inputs.appname }}.app" || echo "App not found" ls -la "${{ env.appname }}.app" || echo "App not found"
ls -la "${{ inputs.appname }}.app/Contents" || echo "Contents not found" ls -la "${{ env.appname }}.app/Contents" || echo "Contents not found"
# Decode the certificate # Decode the certificate
echo "${{ secrets.MACOS_P12_BASE64 }}" | base64 --decode > certificate.p12 echo "${{ secrets.MACOS_P12_BASE64 }}" | base64 --decode > certificate.p12
# Sign the app bundle and its contents # Sign the app bundle and its contents
if [ -d "${{ inputs.appname }}.app/Contents/MacOS" ]; then if [ -d "${{ env.appname }}.app/Contents/MacOS" ]; then
echo "Signing main executable..." echo "Signing main executable..."
MAIN_EXECUTABLE="${{ inputs.appname }}.app/Contents/MacOS/${{ inputs.appname }}" MAIN_EXECUTABLE="${{ env.appname }}.app/Contents/MacOS/${{ env.appname }}"
if [ -f "$MAIN_EXECUTABLE" ]; then if [ -f "$MAIN_EXECUTABLE" ]; then
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime "$MAIN_EXECUTABLE" --code-signature-flags runtime "$MAIN_EXECUTABLE"
@@ -650,23 +671,23 @@ jobs:
echo "Main executable not found at expected path: $MAIN_EXECUTABLE" echo "Main executable not found at expected path: $MAIN_EXECUTABLE"
# Try to find the actual executable # Try to find the actual executable
echo "Available executables in MacOS directory:" echo "Available executables in MacOS directory:"
ls -la "${{ inputs.appname }}.app/Contents/MacOS/" ls -la "${{ env.appname }}.app/Contents/MacOS/"
ACTUAL_EXECUTABLE=$(ls "${{ inputs.appname }}.app/Contents/MacOS/" | head -n 1) ACTUAL_EXECUTABLE=$(ls "${{ env.appname }}.app/Contents/MacOS/" | head -n 1)
if [ -n "$ACTUAL_EXECUTABLE" ]; then if [ -n "$ACTUAL_EXECUTABLE" ]; then
echo "Found executable: $ACTUAL_EXECUTABLE" echo "Found executable: $ACTUAL_EXECUTABLE"
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime "${{ inputs.appname }}.app/Contents/MacOS/$ACTUAL_EXECUTABLE" --code-signature-flags runtime "${{ env.appname }}.app/Contents/MacOS/$ACTUAL_EXECUTABLE"
fi fi
fi fi
echo "Signing frameworks..." echo "Signing frameworks..."
find "${{ inputs.appname }}.app/Contents/Frameworks" -type f -not -name ".*" -exec \ find "${{ env.appname }}.app/Contents/Frameworks" -type f -not -name ".*" -exec \
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime {} \; --code-signature-flags runtime {} \;
echo "Signing main bundle..." echo "Signing main bundle..."
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime "${{ inputs.appname }}.app" --code-signature-flags runtime "${{ env.appname }}.app"
else else
echo "Error: Invalid app bundle structure" echo "Error: Invalid app bundle structure"
exit 1 exit 1
@@ -684,24 +705,24 @@ jobs:
# Find the actual .app bundle # Find the actual .app bundle
if [ -d "RustDesk.app" ]; then if [ -d "RustDesk.app" ]; then
# First rename the app if it's still called RustDesk.app # First rename the app if it's still called RustDesk.app
mv "RustDesk.app" "${{ inputs.appname }}.app" mv "RustDesk.app" "${{ env.appname }}.app"
fi fi
if [ ! -d "${{ inputs.appname }}.app" ]; then if [ ! -d "${{ env.appname }}.app" ]; then
echo "Could not find .app bundle!" echo "Could not find .app bundle!"
exit 1 exit 1
fi fi
echo "Creating DMG for ${{ inputs.appname }}.app" echo "Creating DMG for ${{ env.appname }}.app"
create-dmg \ create-dmg \
--volname "${{ inputs.appname }}" \ --volname "${{ env.appname }}" \
--window-pos 200 120 \ --window-pos 200 120 \
--window-size 800 400 \ --window-size 800 400 \
--icon-size 100 \ --icon-size 100 \
--icon "${{ inputs.appname }}.app" 200 190 \ --icon "${{ env.appname }}.app" 200 190 \
--hide-extension "${{ inputs.appname }}.app" \ --hide-extension "${{ env.appname }}.app" \
--app-drop-link 600 185 \ --app-drop-link 600 185 \
"${{ inputs.appname }}-${{ matrix.job.arch }}.dmg" \ "${{ env.appname }}-${{ matrix.job.arch }}.dmg" \
"${{ inputs.appname }}.app" "${{ env.appname }}.app"
mv "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg" $GITHUB_WORKSPACE/ mv "${{ env.appname }}-${{ matrix.job.arch }}.dmg" $GITHUB_WORKSPACE/
- name: Rename rustdesk - name: Rename rustdesk
if: env.UPLOAD_ARTIFACT == 'true' if: env.UPLOAD_ARTIFACT == 'true'
@@ -711,38 +732,38 @@ jobs:
ls -la ls -la
# Find the DMG file dynamically # Find the DMG file dynamically
DMG_FILE=$(find . -name "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg") DMG_FILE=$(find . -name "${{ env.appname }}-${{ matrix.job.arch }}.dmg")
if [ -n "$DMG_FILE" ]; then if [ -n "$DMG_FILE" ]; then
echo "Found DMG file: $DMG_FILE" echo "Found DMG file: $DMG_FILE"
mv "$DMG_FILE" "${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" mv "$DMG_FILE" "${{ env.filename }}-${{ matrix.job.arch }}.dmg"
echo "Renamed to ${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" echo "Renamed to ${{ env.filename }}-${{ matrix.job.arch }}.dmg"
else else
echo "No DMG file found matching the pattern" echo "No DMG file found matching the pattern"
exit 1 exit 1
fi fi
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST \ curl -i -X POST \
-H "Content-Type: multipart/form-data" \ -H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" \ -H "Authorization: Bearer ${{ env.token }}" \
-F "file=@$GITHUB_WORKSPACE/${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" \ -F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \
-F "uuid=${{ inputs.uuid }}" \ -F "uuid=${{ env.uuid }}" \
"${{ secrets.GENURL }}/save_custom_client" "${{ secrets.GENURL }}/save_custom_client"
- name: send file to api server - name: send file to api server
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST \ curl -i -X POST \
-H "Content-Type: multipart/form-data" \ -H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" \ -H "Authorization: Bearer ${{ env.token }}" \
-F "file=@$GITHUB_WORKSPACE/${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" \ -F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \
"${{ inputs.apiServer }}/api/save_custom_client" "${{ env.apiServer }}/api/save_custom_client"
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -750,7 +771,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}' data: '{"uuid": "${{ env.uuid }}", "status": "Success"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -759,7 +780,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -768,4 +789,4 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}'

View File

@@ -3,56 +3,16 @@ run-name: Custom Windows Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
server: version:
description: 'Rendezvous Server' description: 'version to buld'
required: true required: true
default: '' default: ''
type: string type: string
key: zip_url:
description: 'Public Key' description: 'url to zip of json'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
@@ -71,7 +31,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ fromJson(inputs.extras).version }}" VERSION: "${{ inputs.version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -85,7 +45,7 @@ jobs:
generate-bridge: generate-bridge:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ fromJson(inputs.extras).version }} version: ${{ inputs.version }}
build-RustDeskTempTopMostWindow: build-RustDeskTempTopMostWindow:
uses: ./.github/workflows/third-party-RustDeskTempTopMostWindow.yml uses: ./.github/workflows/third-party-RustDeskTempTopMostWindow.yml
@@ -116,6 +76,46 @@ jobs:
} }
# - { target: aarch64-pc-windows-msvc, os: windows-2022, arch: aarch64 } # - { target: aarch64-pc-windows-msvc, os: windows-2022, arch: aarch64 }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}')
r.raise_for_status()
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Export GitHub Actions cache environment variables - name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6 uses: actions/github-script@v6
with: with:
@@ -124,14 +124,14 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $env:GITHUB_ENV echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $env:GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -140,7 +140,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}'
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
@@ -175,34 +175,34 @@ jobs:
sed -i -e 's|2ded7f146437a761ffe6981e2f742038f85ca68d|08a471bb8ceccdd50483c81cdfa8b81b07b14b87|' ./flutter/pubspec.yaml sed -i -e 's|2ded7f146437a761ffe6981e2f742038f85ca68d|08a471bb8ceccdd50483c81cdfa8b81b07b14b87|' ./flutter/pubspec.yaml
- name: change appname to custom - name: change appname to custom
if: inputs.appname != 'rustdesk' if: env.appname != 'rustdesk'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
# ./Cargo.toml # ./Cargo.toml
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml
# ./libs/portable/Cargo.toml # ./libs/portable/Cargo.toml
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
# ./flutter/windows/runner/Runner.rc # ./flutter/windows/runner/Runner.rc
sed -i -e 's|"RustDesk Remote Desktop"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"RustDesk Remote Desktop"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ inputs.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ env.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"rustdesk.exe"|"${{ inputs.filename }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"rustdesk.exe"|"${{ env.filename }}"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc
# ./src/lang/en.rs # ./src/lang/en.rs
# change powered by rustdek to powered by compname # change powered by rustdek to powered by compname
if [ ! -z "${{ fromJson(inputs.extras).compname }}" ]; then if [ ! -z "${{ env.compname }}" ]; then
find ./src/lang -name "*.rs" -exec sed -i '/powered_by_me/s|RustDesk|${{ fromJson(inputs.extras).compname }}|g' {} \; find ./src/lang -name "*.rs" -exec sed -i '/powered_by_me/s|RustDesk|${{ env.compname }}|g' {} \;
fi fi
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
- name: fix registry if appname has a space - name: fix registry if appname has a space
if: contains(inputs.appname, ' ') if: contains(env.appname, ' ')
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
@@ -222,47 +222,47 @@ jobs:
sed -i -e 's|reg delete HKEY_CLASSES_ROOT\\\\{ext} /f|reg delete \\\"HKEY_CLASSES_ROOT\\\\{ext}\\\" /f|' ./src/platform/windows.rs sed -i -e 's|reg delete HKEY_CLASSES_ROOT\\\\{ext} /f|reg delete \\\"HKEY_CLASSES_ROOT\\\\{ext}\\\" /f|' ./src/platform/windows.rs
- name: change company name - name: change company name
if: fromJson(inputs.extras).compname != 'Purslane Ltd' if: env.compname != 'Purslane Ltd'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e 's|PURSLANE|${{ fromJson(inputs.extras).compname }}|' ./res/msi/preprocess.py sed -i -e 's|PURSLANE|${{ env.compname }}|' ./res/msi/preprocess.py
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./res/msi/preprocess.py sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./res/msi/preprocess.py
sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025 ${{ fromJson(inputs.extras).compname }}. All rights reserved."|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025 ${{ env.compname }}. All rights reserved."|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./flutter/windows/runner/Runner.rc sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./Cargo.toml sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./libs/portable/Cargo.toml sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml
- name: change url to custom - name: change url to custom
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com' if: env.urlLink != 'https://rustdesk.com'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change download link to custom - name: change download link to custom
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download' if: env.downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
- name: set server, key, and apiserver - name: set server, key, and apiserver
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
# ./flutter/pubspec.yaml # ./flutter/pubspec.yaml
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml #sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
@@ -287,7 +287,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "10% complete"}'
- name: Install flutter - name: Install flutter
uses: subosito/flutter-action@v2.12.0 #https://github.com/subosito/flutter-action/issues/277 uses: subosito/flutter-action@v2.12.0 #https://github.com/subosito/flutter-action/issues/277
@@ -325,7 +325,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "15% complete"}'
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
with: with:
@@ -338,7 +338,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "20% complete"}'
- name: Setup vcpkg with Github Actions binary cache - name: Setup vcpkg with Github Actions binary cache
uses: lukka/run-vcpkg@v11 uses: lukka/run-vcpkg@v11
@@ -368,10 +368,10 @@ jobs:
shell: bash shell: bash
- name: magick stuff - name: magick stuff
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
run: | run: |
Invoke-WebRequest -Uri ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }} -OutFile ./res/iconx.png Invoke-WebRequest -Uri ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }} -OutFile ./res/iconx.png
mv ./res/icon.ico ./res/icon.ico.bak mv ./res/icon.ico ./res/icon.ico.bak
mv ./res/icon.png ./res/icon.png.bak mv ./res/icon.png ./res/icon.png.bak
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
@@ -389,7 +389,7 @@ jobs:
- name: ui.rs icon - name: ui.rs icon
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
@@ -400,28 +400,28 @@ jobs:
- name: fix connection delay - name: fix connection delay
continue-on-error: true continue-on-error: true
if: ${{ fromJson(inputs.extras).delayFix == 'true' }} if: ${{ env.delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).cycleMonitor == 'true' if: env.cycleMonitor == 'true'
run: | run: |
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff -OutFile cycle_monitor.diff Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff -OutFile cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).xOffline == 'true' if: env.xOffline == 'true'
run: | run: |
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff -OutFile xoffline.diff Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff -OutFile xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: fromJson(inputs.extras).removeNewVersionNotif == 'true' if: env.removeNewVersionNotif == 'true'
shell: bash shell: bash
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
@@ -429,7 +429,7 @@ jobs:
# - name: run as admin # - name: run as admin
# continue-on-error: true # continue-on-error: true
# if: ${{ fromJson(inputs.extras).runasadmin == 'true' }} # if: ${{ env.runasadmin == 'true' }}
# shell: bash # shell: bash
# run: | # run: |
# sed -i '/<\/compatibility>/a \ # sed -i '/<\/compatibility>/a \
@@ -444,10 +444,10 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "25% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "25% complete"}'
- name: replace flutter icons - name: replace flutter icons
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
run: | run: |
cd ./flutter cd ./flutter
@@ -463,7 +463,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}' data: '{"uuid": "${{ env.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
- name: Build rustdesk - name: Build rustdesk
run: | run: |
@@ -506,17 +506,17 @@ jobs:
} }
- name: icon stuff - name: icon stuff
if: ${{ inputs.iconlink != 'false' }} if: ${{ env.iconlink_url != 'false' }}
continue-on-error: true continue-on-error: true
run: | run: |
mv ./rustdesk/data/flutter_assets/assets/icon.svg ./rustdesk/data/flutter_assets/assets/icon.svg.bak mv ./rustdesk/data/flutter_assets/assets/icon.svg ./rustdesk/data/flutter_assets/assets/icon.svg.bak
magick ./res/icon.png ./rustdesk/data/flutter_assets/assets/icon.svg magick ./res/icon.png ./rustdesk/data/flutter_assets/assets/icon.svg
- name: logo stuff - name: logo stuff
if: ${{ inputs.logolink != 'false' }} if: ${{ env.logolink_url != 'false' }}
continue-on-error: true continue-on-error: true
run: | run: |
Invoke-WebRequest -Uri ${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}"&"uuid=${{ fromJson(inputs.logolink).uuid }} -OutFile ./rustdesk/data/flutter_assets/assets/logo.png Invoke-WebRequest -Uri ${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}"&"uuid=${{ env.logolink_uuid }} -OutFile ./rustdesk/data/flutter_assets/assets/logo.png
- name: find Runner.res - name: find Runner.res
# Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res # Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res
@@ -548,7 +548,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}' data: '{"uuid": "${{ env.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}'
- name: zip dlls - name: zip dlls
continue-on-error: true continue-on-error: true
@@ -581,17 +581,17 @@ jobs:
- name: Create custom.txt file - name: Create custom.txt file
shell: bash shell: bash
run: | run: |
echo -n "${{ inputs.custom }}" | cat > ./rustdesk/custom_.txt echo -n "${{ env.custom }}" | cat > ./rustdesk/custom_.txt
- name: Build self-extracted executable - name: Build self-extracted executable
shell: bash shell: bash
if: env.UPLOAD_ARTIFACT == 'true' if: env.UPLOAD_ARTIFACT == 'true'
run: | run: |
mv "./rustdesk/rustdesk.exe" "./rustdesk/${{ inputs.appname }}.exe" || echo "rustdesk.exe" mv "./rustdesk/rustdesk.exe" "./rustdesk/${{ env.appname }}.exe" || echo "rustdesk.exe"
sed -i '/dpiAware/d' res/manifest.xml sed -i '/dpiAware/d' res/manifest.xml
pushd ./libs/portable pushd ./libs/portable
pip3 install -r requirements.txt pip3 install -r requirements.txt
python3 ./generate.py -f ../../rustdesk/ -o . -e "../../rustdesk/${{ inputs.appname }}.exe" python3 ./generate.py -f ../../rustdesk/ -o . -e "../../rustdesk/${{ env.appname }}.exe"
popd popd
mkdir -p ./SignOutput mkdir -p ./SignOutput
mv ./target/release/rustdesk-portable-packer.exe "./SignOutput/rustdesk.exe" mv ./target/release/rustdesk-portable-packer.exe "./SignOutput/rustdesk.exe"
@@ -603,8 +603,8 @@ jobs:
continue-on-error: true continue-on-error: true
if: env.UPLOAD_ARTIFACT == 'true' if: env.UPLOAD_ARTIFACT == 'true'
run: | run: |
$myappname = "${{ inputs.appname }}" -replace '\s','_' $myappname = "${{ env.appname }}" -replace '\s','_'
cp "rustdesk/${{ inputs.appname }}.exe" "rustdesk/${myappname}.exe" -ErrorAction SilentlyContinue cp "rustdesk/${{ env.appname }}.exe" "rustdesk/${myappname}.exe" -ErrorAction SilentlyContinue
pushd ./res/msi pushd ./res/msi
python preprocess.py --app-name "$myappname" --arp -d ../../rustdesk python preprocess.py --app-name "$myappname" --arp -d ../../rustdesk
nuget restore msi.sln nuget restore msi.sln
@@ -620,7 +620,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "85% complete"}' data: '{"uuid": "${{ env.uuid }}", "status": "85% complete"}'
- name: zip exe and msi - name: zip exe and msi
continue-on-error: true continue-on-error: true
@@ -652,26 +652,26 @@ jobs:
- name: rename rustdesk.exe to filename.exe - name: rename rustdesk.exe to filename.exe
run: | run: |
mv ./SignOutput/rustdesk.exe "./SignOutput/${{ inputs.filename }}.exe" || echo "rustdesk" mv ./SignOutput/rustdesk.exe "./SignOutput/${{ env.filename }}.exe" || echo "rustdesk"
- name: rename rustdesk.msi to filename.msi - name: rename rustdesk.msi to filename.msi
continue-on-error: true continue-on-error: true
run: | run: |
mv ./SignOutput/rustdesk.msi "./SignOutput/${{ inputs.filename }}.msi" || echo "rustdesk" mv ./SignOutput/rustdesk.msi "./SignOutput/${{ env.filename }}.msi" || echo "rustdesk"
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ fromJson(inputs.extras).rdgen == 'true' }} if: ${{ env.rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./SignOutput/${{ inputs.filename }}.exe" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./SignOutput/${{ inputs.filename }}.msi" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
- name: send file to api server - name: send file to api server
if: ${{ fromJson(inputs.extras).rdgen == 'false' }} if: ${{ env.rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./SignOutput/${{ inputs.filename }}.exe" ${{ inputs.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.exe" ${{ env.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./SignOutput/${{ inputs.filename }}.msi" ${{ inputs.apiServer }}/api/save_custom_client || true curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" ${{ env.apiServer }}/api/save_custom_client || true
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -679,7 +679,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}' data: '{"uuid": "${{ env.uuid }}", "status": "Success"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -688,7 +688,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -697,4 +697,4 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}'

View File

@@ -1,6 +1,7 @@
services: services:
rdgen: rdgen:
# use bryangerlach/rdgen:latest for the latest build # use bryangerlach/rdgen:latest for the latest build
#build: .
image: bryangerlach/rdgen:latest image: bryangerlach/rdgen:latest
restart: unless-stopped restart: unless-stopped
environment: environment:
@@ -8,6 +9,8 @@ services:
GHUSER: "github_username" GHUSER: "github_username"
GHBEARER: "github_access_token" GHBEARER: "github_access_token"
GENURL: "accessible_url_of_server" GENURL: "accessible_url_of_server"
ZIP_PASSWORD: ""
GHBRANCH: "master"
PROTOCOL: "https" PROTOCOL: "https"
REPONAME: "rdgen" REPONAME: "rdgen"
ports: ports:

View File

@@ -24,6 +24,8 @@ SECRET_KEY = os.environ.get('SECRET_KEY','django-insecure-!(t-!f#6g#sr%yfded9(xh
GHUSER = os.environ.get("GHUSER", '') GHUSER = os.environ.get("GHUSER", '')
GHBEARER = os.environ.get("GHBEARER", '') GHBEARER = os.environ.get("GHBEARER", '')
GENURL = os.environ.get("GENURL", '') GENURL = os.environ.get("GENURL", '')
GHBRANCH = os.environ.get("GHBRANCH",'master')
ZIP_PASSWORD = os.environ.get("ZIP_PASSWORD",'insecure')
PROTOCOL = os.environ.get("PROTOCOL", 'https') PROTOCOL = os.environ.get("PROTOCOL", 'https')
REPONAME = os.environ.get("REPONAME", 'rdgen') REPONAME = os.environ.get("REPONAME", 'rdgen')

View File

@@ -32,4 +32,5 @@ urlpatterns = [
url(r'^startgh',views.startgh), url(r'^startgh',views.startgh),
url(r'^get_png',views.get_png), url(r'^get_png',views.get_png),
url(r'^save_custom_client',views.save_custom_client), url(r'^save_custom_client',views.save_custom_client),
url(r'^get_zip',views.get_zip),
] ]

View File

@@ -9,14 +9,13 @@ import requests
import base64 import base64
import json import json
import uuid import uuid
import pyzipper
from django.conf import settings as _settings from django.conf import settings as _settings
from django.db.models import Q from django.db.models import Q
from .forms import GenerateForm from .forms import GenerateForm
from .models import GithubRun from .models import GithubRun
from PIL import Image from PIL import Image
from urllib.parse import quote from urllib.parse import quote
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
def generator_view(request): def generator_view(request):
if request.method == 'POST': if request.method == 'POST':
@@ -48,6 +47,8 @@ def generator_view(request):
installation = form.cleaned_data['installation'] installation = form.cleaned_data['installation']
settings = form.cleaned_data['settings'] settings = form.cleaned_data['settings']
appname = form.cleaned_data['appname'] appname = form.cleaned_data['appname']
if not appname:
appname = "rustdesk"
filename = form.cleaned_data['exename'] filename = form.cleaned_data['exename']
compname = form.cleaned_data['compname'] compname = form.cleaned_data['compname']
if not compname: if not compname:
@@ -98,18 +99,22 @@ def generator_view(request):
iconfile = form.cleaned_data.get('iconfile') iconfile = form.cleaned_data.get('iconfile')
if not iconfile: if not iconfile:
iconfile = form.cleaned_data.get('iconbase64') iconfile = form.cleaned_data.get('iconbase64')
iconlink = save_png(iconfile,myuuid,full_url,"icon.png") iconlink_url, iconlink_uuid, iconlink_file = save_png(iconfile,myuuid,full_url,"icon.png")
except: except:
print("failed to get icon, using default") print("failed to get icon, using default")
iconlink = "false" iconlink_url = "false"
iconlink_uuid = "false"
iconlink_file = "false"
try: try:
logofile = form.cleaned_data.get('logofile') logofile = form.cleaned_data.get('logofile')
if not logofile: if not logofile:
logofile = form.cleaned_data.get('logobase64') logofile = form.cleaned_data.get('logobase64')
logolink = save_png(logofile,myuuid,full_url,"logo.png") logolink_url, logolink_uuid, logolink_file = save_png(logofile,myuuid,full_url,"logo.png")
except: except:
print("failed to get logo") print("failed to get logo")
logolink = "false" logolink_url = "false"
logolink_uuid = "false"
logolink_file = "false"
###create the custom.txt json here and send in as inputs below ###create the custom.txt json here and send in as inputs below
decodedCustom = {} decodedCustom = {}
@@ -192,21 +197,20 @@ def generator_view(request):
base64_bytes = base64.b64encode(string_bytes) base64_bytes = base64.b64encode(string_bytes)
encodedCustom = base64_bytes.decode("ascii") encodedCustom = base64_bytes.decode("ascii")
#github limits inputs to 10, so lump extras into one with json # #github limits inputs to 10, so lump extras into one with json
extras = {} # extras = {}
extras['genurl'] = _settings.GENURL # extras['genurl'] = _settings.GENURL
#extras['runasadmin'] = runasadmin # #extras['runasadmin'] = runasadmin
extras['urlLink'] = urlLink # extras['urlLink'] = urlLink
extras['downloadLink'] = downloadLink # extras['downloadLink'] = downloadLink
extras['delayFix'] = 'true' if delayFix else 'false' # extras['delayFix'] = 'true' if delayFix else 'false'
extras['version'] = version # extras['rdgen'] = 'true'
extras['rdgen'] = 'true' # extras['cycleMonitor'] = 'true' if cycleMonitor else 'false'
extras['cycleMonitor'] = 'true' if cycleMonitor else 'false' # extras['xOffline'] = 'true' if xOffline else 'false'
extras['xOffline'] = 'true' if xOffline else 'false' # extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false'
extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false' # extras['compname'] = compname
extras['compname'] = compname # extras['androidappid'] = androidappid
extras['androidappid'] = androidappid # extra_input = json.dumps(extras)
extra_input = json.dumps(extras)
####from here run the github action, we need user, repo, access token. ####from here run the github action, we need user, repo, access token.
if platform == 'windows': if platform == 'windows':
@@ -223,19 +227,59 @@ def generator_view(request):
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches' url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
#url = 'https://api.github.com/repos/'+_settings.GHUSER+'/rustdesk/actions/workflows/test.yml/dispatches' #url = 'https://api.github.com/repos/'+_settings.GHUSER+'/rustdesk/actions/workflows/test.yml/dispatches'
inputs_raw = {
"server":server,
"key":key,
"apiServer":apiServer,
"custom":encodedCustom,
"uuid":myuuid,
"iconlink_url":iconlink_url,
"iconlink_uuid":iconlink_uuid,
"iconlink_file":iconlink_file,
"logolink_url":logolink_url,
"logolink_uuid":logolink_uuid,
"logolink_file":logolink_file,
"appname":appname,
"genurl":_settings.GENURL,
"urlLink":urlLink,
"downloadLink":downloadLink,
"delayFix": 'true' if delayFix else 'false',
"rdgen":'true',
"cycleMonitor": 'true' if cycleMonitor else 'false',
"xOffline": 'true' if xOffline else 'false',
"removeNewVersionNotif": 'true' if removeNewVersionNotif else 'false',
"compname": compname,
"androidappid":androidappid,
"filename":filename
}
temp_json_path = f"data_{uuid.uuid4()}.json"
zip_filename = f"secrets_{uuid.uuid4()}.zip"
zip_path = "temp_zips/%s" % (zip_filename)
Path("temp_zips").mkdir(parents=True, exist_ok=True)
with open(temp_json_path, "w") as f:
json.dump(inputs_raw, f)
with pyzipper.AESZipFile(zip_path, 'w', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) as zf:
zf.setpassword(_settings.ZIP_PASSWORD.encode())
zf.write(temp_json_path, arcname="secrets.json")
# 4. Cleanup the plain JSON file immediately
if os.path.exists(temp_json_path):
os.remove(temp_json_path)
zipJson = {}
zipJson['url'] = full_url
zipJson['file'] = zip_filename
zip_url = json.dumps(zipJson)
data = { data = {
"ref":"master", "ref":_settings.GHBRANCH,
"inputs":{ "inputs":{
"server":server, "version":version,
"key":key, "zip_url":zip_url
"apiServer":apiServer,
"custom":encodedCustom,
"uuid":myuuid,
"iconlink":iconlink,
"logolink":logolink,
"appname":appname,
"extras":extra_input,
"filename":filename
} }
} }
#print(data) #print(data)
@@ -357,7 +401,7 @@ def startgh(request):
####from here run the github action, we need user, repo, access token. ####from here run the github action, we need user, repo, access token.
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-'+data_.get('platform')+'.yml/dispatches' url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-'+data_.get('platform')+'.yml/dispatches'
data = { data = {
"ref":"master", "ref": _settings.GHBRANCH,
"inputs":{ "inputs":{
"server":data_.get('server'), "server":data_.get('server'),
"key":data_.get('key'), "key":data_.get('key'),
@@ -400,12 +444,12 @@ def save_png(file, uuid, domain, name):
with open(file_save_path, "wb+") as f: with open(file_save_path, "wb+") as f:
for chunk in file.chunks(): for chunk in file.chunks():
f.write(chunk) f.write(chunk)
imageJson = {} # imageJson = {}
imageJson['url'] = domain # imageJson['url'] = domain
imageJson['uuid'] = uuid # imageJson['uuid'] = uuid
imageJson['file'] = name # imageJson['file'] = name
#return "%s/%s" % (domain, file_save_path) #return "%s/%s" % (domain, file_save_path)
return json.dumps(imageJson) return domain, uuid, name
def save_custom_client(request): def save_custom_client(request):
file = request.FILES['file'] file = request.FILES['file']
@@ -417,3 +461,37 @@ def save_custom_client(request):
f.write(chunk) f.write(chunk)
return HttpResponse("File saved successfully!") return HttpResponse("File saved successfully!")
def cleanup_secrets(request):
# Pass the UUID as a query param or in JSON body
my_uuid = request.GET.get('uuid')
if not my_uuid:
return HttpResponse("Missing UUID", status=400)
# 1. Find the files in your temp directory matching the UUID
temp_dir = os.path.join('temp_zips')
# We look for any file starting with 'secrets_' and containing the uuid
for filename in os.listdir(temp_dir):
if my_uuid in filename and filename.endswith('.zip'):
file_path = os.path.join(temp_dir, filename)
try:
os.remove(file_path)
print(f"Successfully deleted {file_path}")
except OSError as e:
print(f"Error deleting file: {e}")
return HttpResponse("Cleanup successful", status=200)
def get_zip(request):
filename = request.GET['filename']
#filename = filename+".exe"
file_path = os.path.join('temp_zips',filename)
with open(file_path, 'rb') as file:
response = HttpResponse(file, headers={
'Content-Type': 'application/vnd.microsoft.portable-executable',
'Content-Disposition': f'attachment; filename="{filename}"'
})
return response

View File

@@ -2,4 +2,4 @@ django
requests requests
pillow pillow
gunicorn gunicorn
cryptography>=42.0.0 pyzipper

View File

@@ -20,10 +20,14 @@
* Now click New repository secret * Now click New repository secret
* Set the Name to GENURL * Set the Name to GENURL
* Set the Secret to https://rdgen.hostname.com (or whatever your server will be accessed from) * Set the Secret to https://rdgen.hostname.com (or whatever your server will be accessed from)
* Now click New repository secret again
* Set the Name to ZIP_PASSWORD
* Set the Secret to any password you want (use this in the next step as well) - generate a password by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
4. Now download the docker-compose.yml file and fill in the environment variables: 4. Now download the docker-compose.yml file and fill in the environment variables:
* SECRET_KEY="your secret key" - generate a secret key by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'``` * SECRET_KEY="your secret key" - generate a secret key by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
* GHUSER="your github username" * GHUSER="your github username"
* GHBEARER="your fine-grained access token" * GHBEARER="your fine-grained access token"
* ZIP_PASSWORD="the same password that you entered as a github secret"
* PROTOCOL="https" *optional - defaults to "https", change to "http" if you need to * PROTOCOL="https" *optional - defaults to "https", change to "http" if you need to
* REPONAME="rdgen" *optional - defaults to "rdgen", change this if you renamed the repo when you forked it * REPONAME="rdgen" *optional - defaults to "rdgen", change this if you renamed the repo when you forked it
5. Now just run ```docker compose up -d``` 5. Now just run ```docker compose up -d```