Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c904d0e02 | ||
|
|
6d9c13affa | ||
|
|
411622016b | ||
|
|
88fb3b7da0 | ||
|
|
e32ed80003 | ||
|
|
8adecbfc1d | ||
|
|
d186b7dd02 | ||
|
|
c24d4ab5a5 | ||
|
|
1dde44596d | ||
|
|
f45cd77923 | ||
|
|
e2389cc6f3 | ||
|
|
569fee8e52 | ||
|
|
3e8936998e | ||
|
|
5aa976dea4 | ||
|
|
94381d02df | ||
|
|
e8f54731bc | ||
|
|
f62cd9cf86 | ||
|
|
7d2f124eb6 | ||
|
|
f06610989a | ||
|
|
0c14df90eb | ||
|
|
910556d627 | ||
|
|
194cfb502b | ||
|
|
f1c386869f | ||
|
|
95bd0e0743 | ||
|
|
7cd47a99bd | ||
|
|
0947330a97 | ||
|
|
52d1f711ec | ||
|
|
85afc2fca4 | ||
|
|
f933b2ee84 | ||
|
|
2214d60adb | ||
|
|
35c7324669 | ||
|
|
cb464bdf37 | ||
|
|
9af16d5a32 | ||
|
|
2ab2b54f66 | ||
|
|
0853fdeed8 | ||
|
|
1728c51e93 | ||
|
|
971586decb | ||
|
|
7df38d7ffd | ||
|
|
7ca5a67d6c | ||
|
|
19bab19ab5 | ||
|
|
1d4edcfab5 | ||
|
|
7c5cf83628 | ||
|
|
4d2d956a68 | ||
|
|
f5773378d8 | ||
|
|
fce82c76e1 | ||
|
|
9c9e7ccb00 | ||
|
|
f2b3df06fd | ||
|
|
98128704a5 | ||
|
|
461a8a56ff | ||
|
|
60dc527cad | ||
|
|
bb43e468ac | ||
|
|
0cfe1ffb4c | ||
|
|
8ea114d36b | ||
|
|
6e7a5ba84a | ||
|
|
6dc19ccd05 | ||
|
|
28e48c8eb8 | ||
|
|
365af0fceb | ||
|
|
962c98f682 | ||
|
|
3a2ed3d23b | ||
|
|
1db75f1b33 | ||
|
|
533ee4f1bb | ||
|
|
f0943ddf1a | ||
|
|
55317863c0 | ||
|
|
b9fdac7d8c | ||
|
|
adc69d499a | ||
|
|
dd5291c9ba | ||
|
|
f9901f2f74 | ||
|
|
27b52d80e9 | ||
|
|
9c471075e3 | ||
|
|
e06ef09d75 | ||
|
|
cbe2b4e60f | ||
|
|
3c312dad7b |
37
.github/actions/decrypt-secrets/action.yml
vendored
Normal file
37
.github/actions/decrypt-secrets/action.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: 'Decrypt and Mask Secrets'
|
||||
description: 'Decrypts a zip and masks the JSON contents as env vars'
|
||||
inputs:
|
||||
zip_password:
|
||||
description: 'Password for the Zip'
|
||||
required: true
|
||||
zip_path:
|
||||
description: 'Path to the encrypted zip'
|
||||
required: false
|
||||
default: 'secrets.zip'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: install python deps
|
||||
shell: bash
|
||||
run: |
|
||||
pip install pyzipper
|
||||
- name: Decrypt and Mask
|
||||
shell: python
|
||||
run: |
|
||||
import pyzipper
|
||||
import json
|
||||
import os
|
||||
|
||||
with pyzipper.AESZipFile('${{ inputs.zip_path }}') as zf:
|
||||
zf.setpassword('${{ inputs.zip_password }}'.encode())
|
||||
with zf.open('secrets.json') as f:
|
||||
secrets = json.load(f)
|
||||
|
||||
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
|
||||
for key, value in secrets.items():
|
||||
if value:
|
||||
print(f"::add-mask::{value}")
|
||||
env_file.write(f"{key}={value}\n")
|
||||
|
||||
print(f"Successfully masked {len(secrets)} secrets.")
|
||||
32
.github/patches/privacyScreen.py
vendored
Normal file
32
.github/patches/privacyScreen.py
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import os
|
||||
|
||||
def convert_png_to_cpp(input_file, output_file, array_name="g_img"):
|
||||
if not os.path.exists(input_file):
|
||||
print(f"Error: {input_file} not found.")
|
||||
return
|
||||
|
||||
with open(input_file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
with open(output_file, "w") as f:
|
||||
f.write('#include "pch.h"\n')
|
||||
f.write('#include "./img.h"\n\n')
|
||||
f.write(f"const unsigned char {array_name}[] = {{\n")
|
||||
|
||||
for i in range(0, len(data), 20):
|
||||
chunk = data[i : i + 20]
|
||||
hex_chunk = [f"0x{b:02x}" for b in chunk]
|
||||
|
||||
line = ", ".join(hex_chunk)
|
||||
|
||||
if i + 20 < len(data):
|
||||
f.write(f"{line},\n")
|
||||
else:
|
||||
f.write(f"{line}\n")
|
||||
|
||||
f.write("};\n\n")
|
||||
f.write(f"const long long {array_name}Len = sizeof({array_name});\n")
|
||||
|
||||
#print(f"Successfully converted {input_file} to {output_file}")
|
||||
|
||||
convert_png_to_cpp("privacy.png", "img.cpp")
|
||||
46
.github/workflows/fetch-encrypted-secrets.yml
vendored
Normal file
46
.github/workflows/fetch-encrypted-secrets.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Fetch Encrypted Secrets
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
zip_url_json:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
download-zip:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download with Retry
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: python
|
||||
command: |
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
|
||||
input_data = json.loads('${{ inputs.zip_url_json }}')
|
||||
url = f"{input_data['url']}/get_zip?filename={input_data['file']}"
|
||||
|
||||
for attempt in range(5):
|
||||
try:
|
||||
print(f"Downloading (Attempt {attempt + 1})...")
|
||||
r = requests.get(url, timeout=20)
|
||||
r.raise_for_status()
|
||||
with open('secrets.zip', 'wb') as f:
|
||||
f.write(r.content)
|
||||
break
|
||||
except Exception as e:
|
||||
if attempt < 4:
|
||||
time.sleep(5 * (2 ** attempt))
|
||||
else: raise e
|
||||
|
||||
- name: Upload Encrypted Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
path: secrets.zip
|
||||
retention-days: 1
|
||||
267
.github/workflows/generator-android.yml
vendored
267
.github/workflows/generator-android.yml
vendored
File diff suppressed because one or more lines are too long
471
.github/workflows/generator-linux.yml
vendored
471
.github/workflows/generator-linux.yml
vendored
File diff suppressed because one or more lines are too long
154
.github/workflows/generator-macos.yml
vendored
154
.github/workflows/generator-macos.yml
vendored
@@ -40,6 +40,11 @@ env:
|
||||
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}"
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||
with:
|
||||
zip_url_json: ${{ inputs.zip_url }}
|
||||
|
||||
generate-bridge:
|
||||
uses: ./.github/workflows/bridge.yml
|
||||
with:
|
||||
@@ -48,7 +53,7 @@ jobs:
|
||||
build-for-macos:
|
||||
name: ${{ matrix.job.target }}
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
needs: [generate-bridge]
|
||||
needs: [generate-bridge, setup]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -72,52 +77,24 @@ jobs:
|
||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
||||
|
||||
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
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
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: Load Secrets
|
||||
uses: ./.github/actions/decrypt-secrets
|
||||
with:
|
||||
zip_password: ${{ secrets.ZIP_PASSWORD }}
|
||||
|
||||
- name: Finalize and Cleanup zip/json
|
||||
if: always() # Run even if previous steps fail
|
||||
continue-on-error: true
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
url: "${{ secrets.GENURL }}/cleanzip"
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}"}'
|
||||
@@ -129,14 +106,6 @@ jobs:
|
||||
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}'
|
||||
|
||||
- name: Checkout source code
|
||||
if: ${{ env.VERSION != 'master' }}
|
||||
uses: actions/checkout@v4
|
||||
@@ -236,8 +205,8 @@ jobs:
|
||||
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.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
|
||||
git apply allowCustom.diff
|
||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.py
|
||||
python allowCustom.py
|
||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
|
||||
git apply removeSetupServerTip.diff
|
||||
|
||||
@@ -246,15 +215,7 @@ jobs:
|
||||
echo " archive: ^3.6.1" > ./flutter/temp_dependency.txt
|
||||
awk '/intl:/{print;system("cat ./flutter/temp_dependency.txt");next}1' ./flutter/pubspec.yaml > ./flutter/pubspec.yaml.tmp
|
||||
mv ./flutter/pubspec.yaml.tmp ./flutter/pubspec.yaml
|
||||
rm ./flutter/temp_dependency.txt
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "10% complete"}'
|
||||
rm ./flutter/temp_dependency.txt
|
||||
|
||||
- name: Install build runtime
|
||||
run: |
|
||||
@@ -489,14 +450,6 @@ jobs:
|
||||
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
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "20% complete"}'
|
||||
|
||||
- name: Restore bridge files
|
||||
uses: actions/download-artifact@master
|
||||
with:
|
||||
@@ -525,14 +478,6 @@ jobs:
|
||||
fi
|
||||
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "25% complete"}'
|
||||
|
||||
- name: Create MacOS directory structure
|
||||
run: |
|
||||
mkdir -p ./build/macos/Build/Products/Release/RustDesk.app/Contents/MacOS
|
||||
@@ -552,14 +497,6 @@ jobs:
|
||||
# - name: Copy service file
|
||||
# run: |
|
||||
# cp -rf ../target/release/service ./build/macos/Build/Products/Release/RustDesk.app/Contents/MacOS/
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
|
||||
|
||||
- name: Install rcodesign tool
|
||||
if: env.MACOS_P12_BASE64 != null
|
||||
@@ -580,14 +517,6 @@ jobs:
|
||||
else
|
||||
brew install pkg-config
|
||||
fi
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}'
|
||||
|
||||
- name: Show version information (Rust, cargo, Clang)
|
||||
shell: bash
|
||||
@@ -630,14 +559,6 @@ jobs:
|
||||
-O "$ASSETS_DIR/logo.png" \
|
||||
"${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}"
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "85% complete"}'
|
||||
|
||||
- name: Sign macOS app bundle
|
||||
if: env.MACOS_P12_BASE64 != ''
|
||||
run: |
|
||||
@@ -765,28 +686,13 @@ jobs:
|
||||
-F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \
|
||||
"${{ env.apiServer }}/api/save_custom_client"
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
cleanup:
|
||||
needs: [build-for-macos]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
if: always()
|
||||
steps:
|
||||
- name: Delete secrets artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "Success"}'
|
||||
|
||||
- name: failed
|
||||
if: failure()
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}'
|
||||
|
||||
- name: failed
|
||||
if: cancelled()
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}'
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
298
.github/workflows/generator-windows-x86.yml
vendored
298
.github/workflows/generator-windows-x86.yml
vendored
@@ -3,56 +3,16 @@ run-name: Custom Windows x86 Client Generator
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
server:
|
||||
description: 'Rendezvous Server'
|
||||
version:
|
||||
description: 'version to buld'
|
||||
required: true
|
||||
default: ''
|
||||
type: string
|
||||
key:
|
||||
description: 'Public Key'
|
||||
zip_url:
|
||||
description: 'url to zip of json'
|
||||
required: true
|
||||
default: ''
|
||||
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:
|
||||
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
|
||||
@@ -76,7 +36,7 @@ env:
|
||||
# 2. Update the `VCPKG_COMMIT_ID` in `ci.yml` and `playground.yml`.
|
||||
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" # 2025.01.13, got "/opt/artifacts/vcpkg/vcpkg: No such file or directory" with latest version
|
||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
||||
VERSION: "${{ inputs.version }}"
|
||||
NDK_VERSION: "r27c"
|
||||
#signing keys env variable checks
|
||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||
@@ -86,8 +46,14 @@ env:
|
||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||
with:
|
||||
zip_url_json: ${{ inputs.zip_url }}
|
||||
|
||||
build-for-windows-sciter:
|
||||
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
|
||||
needs: setup
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
# Temporarily disable this action due to additional test is needed.
|
||||
# if: false
|
||||
@@ -105,6 +71,28 @@ jobs:
|
||||
}
|
||||
# - { target: aarch64-pc-windows-msvc, os: windows-2022 }
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
- name: Load Secrets
|
||||
uses: ./.github/actions/decrypt-secrets
|
||||
with:
|
||||
zip_password: ${{ secrets.ZIP_PASSWORD }}
|
||||
|
||||
- name: Finalize and Cleanup zip/json
|
||||
if: always() # Run even if previous steps fail
|
||||
continue-on-error: true
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: "${{ secrets.GENURL }}/cleanzip"
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}"}'
|
||||
|
||||
- name: Export GitHub Actions cache environment variables
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
@@ -113,23 +101,14 @@ jobs:
|
||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||
|
||||
- name: Set rdgen value
|
||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
||||
if: ${{ env.rdgen == 'true' }}
|
||||
run: |
|
||||
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Set rdgen value
|
||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
||||
if: ${{ env.rdgen == 'false' }}
|
||||
run: |
|
||||
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
|
||||
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Checkout source code
|
||||
if: ${{ env.VERSION != 'master' }}
|
||||
@@ -152,25 +131,27 @@ jobs:
|
||||
Get-ChildItem -Path "${env:ProgramFiles}" | % { $_.FullName } | Select-String -Pattern "[\/\\]ImageMagick[^\/\\]*$" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
|
||||
|
||||
- name: change appname to custom
|
||||
if: inputs.appname != 'rustdesk'
|
||||
if: env.appname != 'rustdesk'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
# ./Cargo.toml
|
||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml
|
||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./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|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./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 = "${{ env.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 = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
|
||||
# ./libs/portable/src/main.rs
|
||||
sed -i -e 's|const APP_PREFIX: \&str = "rustdesk";|const APP_PREFIX: \&str = "${{ env.appname }}";|' ./libs/portable/src/main.rs
|
||||
# ./src/lang/en.rs
|
||||
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
|
||||
if: contains(inputs.appname, ' ')
|
||||
if: contains(env.appname, ' ')
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -190,62 +171,58 @@ jobs:
|
||||
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
|
||||
if: fromJson(inputs.extras).compname != 'Purslane Ltd'
|
||||
if: env.compname != 'Purslane Ltd'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|PURSLANE|${{ fromJson(inputs.extras).compname }}|' ./res/msi/preprocess.py
|
||||
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./res/msi/preprocess.py
|
||||
sed -i -e 's|Copyright © 2025 Purslane Ltd.|Copyright \© 2025 ${{ fromJson(inputs.extras).compname }}|' ./src/ui/index.tis
|
||||
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./libs/portable/Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd.|${{ fromJson(inputs.extras).compname }}|' ./res/setup.nsi
|
||||
sed -i -e 's|PURSLANE|${{ env.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.|Copyright \© 2025 ${{ env.compname }}|' ./src/ui/index.tis
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd.|${{ env.compname }}|' ./res/setup.nsi
|
||||
|
||||
- name: change url to custom
|
||||
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com'
|
||||
if: env.urlLink != 'https://rustdesk.com'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
|
||||
sed -i -e "s|<div .link .custom-event url='https://rustdesk.com'>|<div .link .custom-event url='${{ fromJson(inputs.extras).urlLink }}'>|" ./src/ui/index.tis
|
||||
sed -i -e "s|<div .link .custom-event url='https://rustdesk.com/privacy.html'>|<div .link .custom-event url='${{ fromJson(inputs.extras).urlLink }}/privacy.html'>|" ./src/ui/index.tis
|
||||
sed -i -e "s|https://rustdesk.com/|${{fromJson(inputs.extras).urlLink }}|" ./res/setup.nsi
|
||||
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py
|
||||
sed -i -e "s|<div .link .custom-event url='https://rustdesk.com'>|<div .link .custom-event url='${{ env.urlLink }}'>|" ./src/ui/index.tis
|
||||
sed -i -e "s|<div .link .custom-event url='https://rustdesk.com/privacy.html'>|<div .link .custom-event url='${{ env.urlLink }}/privacy.html'>|" ./src/ui/index.tis
|
||||
sed -i -e "s|https://rustdesk.com/|${{env.urlLink }}|" ./res/setup.nsi
|
||||
|
||||
- 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
|
||||
shell: bash
|
||||
run: |
|
||||
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
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.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|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
|
||||
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./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|${{ env.apiServer }}|' ./src/common.rs
|
||||
sed -i -e 's|<span>{translate("Ready")}, <span .link #setup-server>{translate("setup_server_tip")}</span></span>|translate("Ready")|' ./src/ui/index.tis
|
||||
|
||||
- name: allow custom.txt
|
||||
continue-on-error: true
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff -OutFile allowCustom.diff
|
||||
git apply allowCustom.diff
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff -OutFile allowCustom.diff
|
||||
git apply allowCustom.diff
|
||||
|
||||
- name: Install LLVM and Clang
|
||||
uses: rustdesk-org/install-llvm-action-32bit@master
|
||||
with:
|
||||
version: ${{ env.LLVM_VERSION }}
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}'
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@v1
|
||||
@@ -258,15 +235,6 @@ jobs:
|
||||
with:
|
||||
prefix-key: ${{ matrix.job.os }}-sciter
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}'
|
||||
|
||||
- name: Setup vcpkg with Github Actions binary cache
|
||||
uses: lukka/run-vcpkg@v11
|
||||
with:
|
||||
@@ -295,7 +263,7 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: icon stuff
|
||||
if: ${{ inputs.iconlink != 'false' }}
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -304,24 +272,28 @@ jobs:
|
||||
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
||||
|
||||
- name: magick stuff
|
||||
if: ${{ inputs.iconlink != 'false' }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
Invoke-WebRequest -Uri ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }} -OutFile ./res/icon.png
|
||||
mv ./res/32x32.png ./res/32x32.png.bak
|
||||
mv ./res/64x64.png ./res/64x64.png.bak
|
||||
mv ./res/128x128.png ./res/128x128.png.bak
|
||||
mv ./res/128x128@2x.png ./res/128x128@2x.png.bak
|
||||
magick ./res/icon.png -define icon:auto-resize=256,64,48,32,16 ./res/icon.ico
|
||||
cp ./res/icon.ico ./res/tray-icon.ico
|
||||
magick ./res/icon.png -resize 32x32 ./res/32x32.png
|
||||
magick ./res/icon.png -resize 64x64 ./res/64x64.png
|
||||
magick ./res/icon.png -resize 128x128 ./res/128x128.png
|
||||
magick ./res/128x128.png -resize 200% ./res/128x128@2x.png
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
command: |
|
||||
Invoke-WebRequest -Uri ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }} -OutFile ./res/icon.png
|
||||
mv ./res/32x32.png ./res/32x32.png.bak
|
||||
mv ./res/64x64.png ./res/64x64.png.bak
|
||||
mv ./res/128x128.png ./res/128x128.png.bak
|
||||
mv ./res/128x128@2x.png ./res/128x128@2x.png.bak
|
||||
magick ./res/icon.png -define icon:auto-resize=256,64,48,32,16 ./res/icon.ico
|
||||
cp ./res/icon.ico ./res/tray-icon.ico
|
||||
magick ./res/icon.png -resize 32x32 ./res/32x32.png
|
||||
magick ./res/icon.png -resize 64x64 ./res/64x64.png
|
||||
magick ./res/icon.png -resize 128x128 ./res/128x128.png
|
||||
magick ./res/128x128.png -resize 200% ./res/128x128@2x.png
|
||||
|
||||
|
||||
- name: ui.rs icon
|
||||
if: ${{ inputs.iconlink != 'false' }}
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -332,28 +304,19 @@ jobs:
|
||||
|
||||
- name: fix connection delay
|
||||
continue-on-error: true
|
||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
||||
if: ${{ env.delayFix == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||
|
||||
- name: removeNewVersionNotif
|
||||
continue-on-error: true
|
||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
||||
if: env.removeNewVersionNotif == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|{software_update_url ? <UpdateMe /> : ""}||' ./src/ui/index.tis
|
||||
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
|
||||
|
||||
- name: Build rustdesk
|
||||
id: build
|
||||
shell: bash
|
||||
@@ -389,15 +352,6 @@ jobs:
|
||||
echo "list ./libs/portable/Runner.res";
|
||||
ls -l ./libs/portable/Runner.res;
|
||||
fi
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}'
|
||||
|
||||
- name: zip dlls
|
||||
continue-on-error: true
|
||||
@@ -430,29 +384,20 @@ jobs:
|
||||
- name: Create custom.txt file
|
||||
shell: bash
|
||||
run: |
|
||||
echo -n "${{ inputs.custom }}" | cat > ./Release/custom.txt
|
||||
echo -n "${{ env.custom }}" | cat > ./Release/custom.txt
|
||||
|
||||
- name: Build self-extracted executable
|
||||
shell: bash
|
||||
run: |
|
||||
mv "./Release/rustdesk.exe" "./Release/${{ inputs.appname }}.exe" || echo "rustdesk.exe"
|
||||
mv "./Release/rustdesk.exe" "./Release/${{ env.appname }}.exe" || echo "rustdesk.exe"
|
||||
sed -i '/dpiAware/d' res/manifest.xml
|
||||
pushd ./libs/portable
|
||||
pip3 install -r requirements.txt
|
||||
python3 ./generate.py -f ../../Release/ -o . -e "../../Release/${{ inputs.appname }}.exe"
|
||||
python3 ./generate.py -f ../../Release/ -o . -e "../../Release/${{ env.appname }}.exe"
|
||||
popd
|
||||
mkdir -p ./SignOutput
|
||||
mv ./target/release/rustdesk-portable-packer.exe "./SignOutput/rustdesk.exe"
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "85% complete"}'
|
||||
|
||||
- name: zip exe
|
||||
continue-on-error: true
|
||||
shell: pwsh
|
||||
@@ -483,42 +428,27 @@ jobs:
|
||||
|
||||
- name: rename rustdesk.exe to filename.exe
|
||||
run: |
|
||||
mv ./SignOutput/rustdesk.exe "./SignOutput/${{ inputs.filename }}.exe" || echo "rustdesk"
|
||||
mv ./SignOutput/rustdesk.exe "./SignOutput/${{ env.filename }}.exe" || echo "rustdesk"
|
||||
|
||||
- name: send file to rdgen server
|
||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
||||
if: ${{ env.rdgen == 'true' }}
|
||||
shell: bash
|
||||
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
|
||||
|
||||
- name: send file to api server
|
||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
||||
if: ${{ env.rdgen == 'false' }}
|
||||
shell: bash
|
||||
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
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
cleanup:
|
||||
needs: [build-for-windows-sciter]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
if: always()
|
||||
steps:
|
||||
- name: Delete secrets artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
|
||||
|
||||
- name: failed
|
||||
if: failure()
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}'
|
||||
|
||||
- name: failed
|
||||
if: cancelled()
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
276
.github/workflows/generator-windows.yml
vendored
276
.github/workflows/generator-windows.yml
vendored
@@ -42,12 +42,18 @@ env:
|
||||
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||
with:
|
||||
zip_url_json: ${{ inputs.zip_url }}
|
||||
|
||||
generate-bridge:
|
||||
uses: ./.github/workflows/bridge.yml
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
build-RustDeskTempTopMostWindow:
|
||||
needs: setup
|
||||
uses: ./.github/workflows/third-party-RustDeskTempTopMostWindow.yml
|
||||
with:
|
||||
upload-artifact: true
|
||||
@@ -55,12 +61,13 @@ jobs:
|
||||
configuration: Release
|
||||
platform: x64
|
||||
target_version: Windows10
|
||||
secrets: inherit
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
build-for-windows-flutter:
|
||||
name: Build Windows
|
||||
needs: [build-RustDeskTempTopMostWindow, generate-bridge]
|
||||
needs: [build-RustDeskTempTopMostWindow, generate-bridge, setup]
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -76,42 +83,24 @@ jobs:
|
||||
}
|
||||
# - { target: aarch64-pc-windows-msvc, os: windows-2022, arch: aarch64 }
|
||||
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
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
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: Load Secrets
|
||||
uses: ./.github/actions/decrypt-secrets
|
||||
with:
|
||||
zip_password: ${{ secrets.ZIP_PASSWORD }}
|
||||
|
||||
- name: Finalize and Cleanup zip/json
|
||||
if: always() # Run even if previous steps fail
|
||||
continue-on-error: true
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
url: "${{ secrets.GENURL }}/cleanzip"
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}"}'
|
||||
@@ -133,15 +122,6 @@ jobs:
|
||||
run: |
|
||||
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}'
|
||||
|
||||
- name: Checkout source code
|
||||
if: ${{ env.VERSION != 'master' }}
|
||||
uses: actions/checkout@v4
|
||||
@@ -189,6 +169,8 @@ jobs:
|
||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.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 = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
|
||||
# ./libs/portable/src/main.rs
|
||||
sed -i -e 's|const APP_PREFIX: \&str = "rustdesk";|const APP_PREFIX: \&str = "${{ env.appname }}";|' ./libs/portable/src/main.rs
|
||||
# ./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", "${{ env.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc
|
||||
@@ -200,6 +182,7 @@ jobs:
|
||||
find ./src/lang -name "*.rs" -exec sed -i '/powered_by_me/s|RustDesk|${{ env.compname }}|g' {} \;
|
||||
fi
|
||||
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
|
||||
sed -i -e 's|RustDesk|${{ env.appname }}|' ./res/msi/Package/License.rtf
|
||||
|
||||
- name: fix registry if appname has a space
|
||||
if: contains(env.appname, ' ')
|
||||
@@ -233,6 +216,7 @@ jobs:
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/windows/runner/Runner.rc
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./res/msi/Package/License.rtf
|
||||
|
||||
- name: change url to custom
|
||||
if: env.urlLink != 'https://rustdesk.com'
|
||||
@@ -246,6 +230,7 @@ jobs:
|
||||
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('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||
sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
||||
sed -i -e "s|rustdesk.com|${{ env.urlLink }}|" ./res/msi/Package/License.rtf
|
||||
|
||||
- name: change download link to custom
|
||||
if: env.downloadLink != 'https://rustdesk.com/download'
|
||||
@@ -267,28 +252,23 @@ jobs:
|
||||
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
|
||||
|
||||
- name: allow custom.txt
|
||||
continue-on-error: true
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.py -OutFile allowCustom.py
|
||||
python allowCustom.py
|
||||
# Remove Setup Server Tip
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff -OutFile removeSetupServerTip.diff
|
||||
git apply removeSetupServerTip.diff
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
command: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.py -OutFile allowCustom.py
|
||||
python allowCustom.py
|
||||
# Remove Setup Server Tip
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff -OutFile removeSetupServerTip.diff
|
||||
git apply removeSetupServerTip.diff
|
||||
|
||||
- name: Install LLVM and Clang
|
||||
uses: KyleMayes/install-llvm-action@v1
|
||||
with:
|
||||
version: ${{ env.LLVM_VERSION }}
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "10% complete"}'
|
||||
|
||||
- name: Install flutter
|
||||
uses: subosito/flutter-action@v2.12.0 #https://github.com/subosito/flutter-action/issues/277
|
||||
with:
|
||||
@@ -318,27 +298,9 @@ jobs:
|
||||
targets: ${{ matrix.job.target }}
|
||||
components: "rustfmt"
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "15% complete"}'
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
prefix-key: ${{ matrix.job.os }}
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "20% complete"}'
|
||||
|
||||
- name: Setup vcpkg with Github Actions binary cache
|
||||
uses: lukka/run-vcpkg@v11
|
||||
@@ -369,23 +331,27 @@ jobs:
|
||||
|
||||
- name: magick stuff
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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.png ./res/icon.png.bak
|
||||
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
||||
mv ./res/iconx.png ./res/icon.png
|
||||
mv ./res/32x32.png ./res/32x32.png.bak
|
||||
mv ./res/64x64.png ./res/64x64.png.bak
|
||||
mv ./res/128x128.png ./res/128x128.png.bak
|
||||
mv ./res/128x128@2x.png ./res/128x128@2x.png.bak
|
||||
magick ./res/icon.png -define icon:auto-resize=256,64,48,32,16 ./res/icon.ico
|
||||
cp ./res/icon.ico ./res/tray-icon.ico
|
||||
magick ./res/icon.png -resize 32x32 ./res/32x32.png
|
||||
magick ./res/icon.png -resize 64x64 ./res/64x64.png
|
||||
magick ./res/icon.png -resize 128x128 ./res/128x128.png
|
||||
magick ./res/128x128.png -resize 200% ./res/128x128@2x.png
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
command: |
|
||||
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.png ./res/icon.png.bak
|
||||
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
||||
mv ./res/iconx.png ./res/icon.png
|
||||
mv ./res/32x32.png ./res/32x32.png.bak
|
||||
mv ./res/64x64.png ./res/64x64.png.bak
|
||||
mv ./res/128x128.png ./res/128x128.png.bak
|
||||
mv ./res/128x128@2x.png ./res/128x128@2x.png.bak
|
||||
magick ./res/icon.png -define icon:auto-resize=256,64,48,32,16 ./res/icon.ico
|
||||
cp ./res/icon.ico ./res/tray-icon.ico
|
||||
magick ./res/icon.png -resize 32x32 ./res/32x32.png
|
||||
magick ./res/icon.png -resize 64x64 ./res/64x64.png
|
||||
magick ./res/icon.png -resize 128x128 ./res/128x128.png
|
||||
magick ./res/128x128.png -resize 200% ./res/128x128@2x.png
|
||||
|
||||
|
||||
- name: ui.rs icon
|
||||
@@ -406,18 +372,28 @@ jobs:
|
||||
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||
|
||||
- name: add cycle monitors to toolbar
|
||||
continue-on-error: true
|
||||
if: env.cycleMonitor == 'true'
|
||||
run: |
|
||||
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
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
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
|
||||
|
||||
- name: use X for offline display instead of orange circle
|
||||
continue-on-error: true
|
||||
if: env.xOffline == 'true'
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff -OutFile xoffline.diff
|
||||
git apply xoffline.diff
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff -OutFile xoffline.diff
|
||||
git apply xoffline.diff
|
||||
|
||||
- name: removeNewVersionNotif
|
||||
continue-on-error: true
|
||||
@@ -437,15 +413,6 @@ jobs:
|
||||
# <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> \
|
||||
# </security>' ./flutter/windows/runner/runner.exe.manifest
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "25% complete"}'
|
||||
|
||||
- name: replace flutter icons
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
@@ -456,15 +423,6 @@ jobs:
|
||||
flutter pub run flutter_launcher_icons
|
||||
cd ..
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
|
||||
|
||||
- name: Build rustdesk
|
||||
run: |
|
||||
# Windows: build RustDesk
|
||||
@@ -514,9 +472,14 @@ jobs:
|
||||
|
||||
- name: logo stuff
|
||||
if: ${{ env.logolink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
Invoke-WebRequest -Uri ${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}"&"uuid=${{ env.logolink_uuid }} -OutFile ./rustdesk/data/flutter_assets/assets/logo.png
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
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
|
||||
# Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res
|
||||
@@ -540,15 +503,6 @@ jobs:
|
||||
with:
|
||||
name: topmostwindow-artifacts
|
||||
path: "./rustdesk"
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}'
|
||||
|
||||
- name: zip dlls
|
||||
continue-on-error: true
|
||||
@@ -613,15 +567,6 @@ jobs:
|
||||
mv ./Package/bin/x64/Release/en-us/Package.msi ../../SignOutput/rustdesk.msi
|
||||
sha256sum ../../SignOutput/rustdesk.msi
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "85% complete"}'
|
||||
|
||||
- name: zip exe and msi
|
||||
continue-on-error: true
|
||||
shell: pwsh
|
||||
@@ -661,40 +606,33 @@ jobs:
|
||||
|
||||
- name: send file to rdgen server
|
||||
if: ${{ env.rdgen == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
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 ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: bash
|
||||
command: |
|
||||
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 ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
|
||||
|
||||
- name: send file to api server
|
||||
if: ${{ env.rdgen == 'false' }}
|
||||
shell: bash
|
||||
run: |
|
||||
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 ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" ${{ env.apiServer }}/api/save_custom_client || true
|
||||
|
||||
- name: Report Status
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "Success"}'
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: bash
|
||||
command: |
|
||||
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 ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" ${{ env.apiServer }}/api/save_custom_client || true
|
||||
|
||||
- name: failed
|
||||
if: failure()
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
cleanup:
|
||||
needs: [build-for-windows-flutter]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
if: always()
|
||||
steps:
|
||||
- name: Delete secrets artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}'
|
||||
|
||||
- name: failed
|
||||
if: cancelled()
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: ${{ env.STATUS_URL }}
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}'
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
562
.github/workflows/sh-generator-windows.yml
vendored
Normal file
562
.github/workflows/sh-generator-windows.yml
vendored
Normal file
@@ -0,0 +1,562 @@
|
||||
name: Custom Windows Client Generator
|
||||
run-name: Custom Windows Client Generator
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'version to buld'
|
||||
required: true
|
||||
default: ''
|
||||
type: string
|
||||
zip_url:
|
||||
description: 'url to zip of json'
|
||||
required: true
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
|
||||
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
|
||||
RUST_VERSION: "1.75" # sciter failed on m1 with 1.78 because of https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
|
||||
CARGO_NDK_VERSION: "3.1.2"
|
||||
SCITER_ARMV7_CMAKE_VERSION: "3.29.7"
|
||||
SCITER_NASM_DEBVERSION: "2.15.05-1"
|
||||
LLVM_VERSION: "15.0.6"
|
||||
FLUTTER_VERSION: "3.24.5"
|
||||
ANDROID_FLUTTER_VERSION: "3.24.5"
|
||||
# for arm64 linux because official Dart SDK does not work
|
||||
FLUTTER_ELINUX_VERSION: "3.16.9"
|
||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.07.12
|
||||
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||
VERSION: "${{ inputs.version }}"
|
||||
NDK_VERSION: "r27c"
|
||||
#signing keys env variable checks
|
||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
||||
UPLOAD_ARTIFACT: 'true'
|
||||
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}"
|
||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
||||
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||
with:
|
||||
zip_url_json: ${{ inputs.zip_url }}
|
||||
|
||||
generate-bridge:
|
||||
uses: ./.github/workflows/bridge.yml
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
build-RustDeskTempTopMostWindow:
|
||||
needs: setup
|
||||
uses: ./.github/workflows/third-party-RustDeskTempTopMostWindow.yml
|
||||
with:
|
||||
upload-artifact: true
|
||||
target: windows-2022
|
||||
configuration: Release
|
||||
platform: x64
|
||||
target_version: Windows10
|
||||
secrets: inherit
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
build-for-windows-flutter:
|
||||
name: Build Windows
|
||||
needs: [build-RustDeskTempTopMostWindow, generate-bridge, setup]
|
||||
runs-on: self-hosted
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
# - { target: i686-pc-windows-msvc , os: windows-2022 }
|
||||
# - { target: x86_64-pc-windows-gnu , os: windows-2022 }
|
||||
- {
|
||||
target: x86_64-pc-windows-msvc,
|
||||
os: windows-2022,
|
||||
arch: x86_64,
|
||||
vcpkg-triplet: x64-windows-static,
|
||||
}
|
||||
# - { target: aarch64-pc-windows-msvc, os: windows-2022, arch: aarch64 }
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
- name: Load Secrets
|
||||
uses: ./.github/actions/decrypt-secrets
|
||||
with:
|
||||
zip_password: ${{ secrets.ZIP_PASSWORD }}
|
||||
|
||||
- name: Finalize and Cleanup zip/json
|
||||
if: always() # Run even if previous steps fail
|
||||
continue-on-error: true
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: "${{ secrets.GENURL }}/cleanzip"
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}"}'
|
||||
|
||||
- name: Export GitHub Actions cache environment variables
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||
|
||||
- name: Set rdgen value
|
||||
if: ${{ env.rdgen == 'true' }}
|
||||
run: |
|
||||
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Set rdgen value
|
||||
if: ${{ env.rdgen == 'false' }}
|
||||
run: |
|
||||
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Checkout source code
|
||||
if: ${{ env.VERSION != 'master' }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: rustdesk/rustdesk
|
||||
ref: refs/tags/${{ env.VERSION }}
|
||||
submodules: recursive
|
||||
|
||||
- name: Checkout source code
|
||||
if: ${{ env.VERSION == 'master' }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: rustdesk/rustdesk
|
||||
submodules: recursive
|
||||
|
||||
- name: Restore bridge files
|
||||
uses: actions/download-artifact@master
|
||||
with:
|
||||
name: bridge-artifact
|
||||
path: ./
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Setup NuGet
|
||||
uses: NuGet/setup-nuget@v2
|
||||
with:
|
||||
nuget-version: 'latest'
|
||||
|
||||
- name: change appname to custom
|
||||
if: env.appname != 'rustdesk'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
# ./Cargo.toml
|
||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
|
||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml
|
||||
# ./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 = "${{ env.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 = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
|
||||
# ./libs/portable/src/main.rs
|
||||
sed -i -e 's|const APP_PREFIX: \&str = "rustdesk";|const APP_PREFIX: \&str = "${{ env.appname }}";|' ./libs/portable/src/main.rs
|
||||
# ./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", "${{ env.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc
|
||||
sed -i -e 's|"rustdesk.exe"|"${{ env.filename }}"|' ./flutter/windows/runner/Runner.rc
|
||||
sed -i -e 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc
|
||||
# ./src/lang/en.rs
|
||||
# change powered by rustdek to powered by compname
|
||||
if [ ! -z "${{ env.compname }}" ]; then
|
||||
find ./src/lang -name "*.rs" -exec sed -i '/powered_by_me/s|RustDesk|${{ env.compname }}|g' {} \;
|
||||
fi
|
||||
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
|
||||
sed -i -e 's|RustDesk|${{ env.appname }}|' ./res/msi/Package/License.rtf
|
||||
|
||||
- name: fix registry if appname has a space
|
||||
if: contains(env.appname, ' ')
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
#./src/platform/windows.rs
|
||||
sed -i -e 's|reg add {}|reg add \\\"{}\\\"|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\.{ext} /f|reg add \\\"HKEY_CLASSES_ROOT\\\\.{ext}\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\.{ext}\\\\DefaultIcon /f|reg add \\\"HKEY_CLASSES_ROOT\\\\.{ext}\\\\DefaultIcon\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\.{ext}\\\\shell /f|reg add \\\"HKEY_CLASSES_ROOT\\\\.{ext}\\\\shell\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\.{ext}\\\\shell\\\\open /f|reg add \\\"HKEY_CLASSES_ROOT\\\\.{ext}\\\\shell\\\\open\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\.{ext}\\\\shell\\\\open\\\\command|reg add \\\"HKEY_CLASSES_ROOT\\\\.{ext}\\\\shell\\\\open\\\\command\\\"|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\{ext} /f|reg add \\\"HKEY_CLASSES_ROOT\\\\{ext}\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\{ext}\\\\shell /f|reg add \\\"HKEY_CLASSES_ROOT\\\\{ext}\\\\shell\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\{ext}\\\\shell\\\\open /f|reg add \\\"HKEY_CLASSES_ROOT\\\\{ext}\\\\shell\\\\open\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|reg add HKEY_CLASSES_ROOT\\\\{ext}\\\\shell\\\\open\\\\command /f|reg add \\\"HKEY_CLASSES_ROOT\\\\{ext}\\\\shell\\\\open\\\\command\\\" /f|' ./src/platform/windows.rs
|
||||
sed -i -e 's|{subkey}|\\\"{subkey}\\\"|' ./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
|
||||
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
|
||||
if: env.compname != 'Purslane Ltd'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||
sed -i -e 's|PURSLANE|${{ env.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 ${{ env.compname }}. All rights reserved."|' ./flutter/windows/runner/Runner.rc
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/windows/runner/Runner.rc
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml
|
||||
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./res/msi/Package/License.rtf
|
||||
|
||||
- name: change url to custom
|
||||
if: env.urlLink != 'https://rustdesk.com'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
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('${{ env.urlLink }}'));|" ./flutter/lib/common.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('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_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('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||
sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
||||
sed -i -e "s|rustdesk.com|${{ env.urlLink }}|" ./res/msi/Package/License.rtf
|
||||
|
||||
- name: change download link to custom
|
||||
if: env.downloadLink != 'https://rustdesk.com/download'
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
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|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
||||
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
|
||||
|
||||
- name: set server, key, and apiserver
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./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|${{ env.apiServer }}|' ./src/common.rs
|
||||
# ./flutter/pubspec.yaml
|
||||
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
|
||||
|
||||
- name: allow custom.txt
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
command: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.py -OutFile allowCustom.py
|
||||
python allowCustom.py
|
||||
# Remove Setup Server Tip
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff -OutFile removeSetupServerTip.diff
|
||||
git apply removeSetupServerTip.diff
|
||||
|
||||
- name: magick stuff
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
command: |
|
||||
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.png ./res/icon.png.bak
|
||||
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
||||
mv ./res/iconx.png ./res/icon.png
|
||||
mv ./res/32x32.png ./res/32x32.png.bak
|
||||
mv ./res/64x64.png ./res/64x64.png.bak
|
||||
mv ./res/128x128.png ./res/128x128.png.bak
|
||||
mv ./res/128x128@2x.png ./res/128x128@2x.png.bak
|
||||
magick ./res/icon.png -define icon:auto-resize=256,64,48,32,16 ./res/icon.ico
|
||||
cp ./res/icon.ico ./res/tray-icon.ico
|
||||
magick ./res/icon.png -resize 32x32 ./res/32x32.png
|
||||
magick ./res/icon.png -resize 64x64 ./res/64x64.png
|
||||
magick ./res/icon.png -resize 128x128 ./res/128x128.png
|
||||
magick ./res/128x128.png -resize 200% ./res/128x128@2x.png
|
||||
|
||||
|
||||
- name: ui.rs icon
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
cp ./src/ui.rs ./src/ui.rs.bak
|
||||
b64=$(base64 -w0 < ./res/icon.png)
|
||||
perl -0777 -pe "s|iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHL[A-Za-z0-9+/=]+|$b64|g" -i.bak ./src/ui.rs
|
||||
b64=""
|
||||
|
||||
- name: fix connection delay
|
||||
continue-on-error: true
|
||||
if: ${{ env.delayFix == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||
|
||||
- name: add cycle monitors to toolbar
|
||||
if: env.cycleMonitor == 'true'
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
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
|
||||
|
||||
- name: use X for offline display instead of orange circle
|
||||
if: env.xOffline == 'true'
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff -OutFile xoffline.diff
|
||||
git apply xoffline.diff
|
||||
|
||||
- name: removeNewVersionNotif
|
||||
continue-on-error: true
|
||||
if: env.removeNewVersionNotif == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
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
|
||||
|
||||
- name: replace flutter icons
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
cd ./flutter
|
||||
#flutter pub upgrade win32
|
||||
flutter pub get
|
||||
flutter pub run flutter_launcher_icons
|
||||
cd ..
|
||||
|
||||
- name: Build rustdesk
|
||||
run: |
|
||||
# Windows: build RustDesk
|
||||
python3 .\build.py --portable --hwcodec --flutter --vram --skip-portable-pack
|
||||
mv ./flutter/build/windows/x64/runner/Release ./rustdesk
|
||||
|
||||
# Download usbmmidd_v2.zip and extract it to ./rustdesk
|
||||
Invoke-WebRequest -Uri https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip -OutFile usbmmidd_v2.zip
|
||||
Expand-Archive usbmmidd_v2.zip -DestinationPath . -Force
|
||||
Remove-Item -Path usbmmidd_v2\Win32 -Recurse
|
||||
Remove-Item -Path "usbmmidd_v2\deviceinstaller64.exe", "usbmmidd_v2\deviceinstaller.exe", "usbmmidd_v2\usbmmidd.bat"
|
||||
mv -Force .\usbmmidd_v2 ./rustdesk
|
||||
|
||||
# Download printer driver files and extract them to ./rustdesk
|
||||
try {
|
||||
Invoke-WebRequest -Uri https://github.com/rustdesk/hbb_common/releases/download/driver/rustdesk_printer_driver_v4-1.4.zip -OutFile rustdesk_printer_driver_v4-1.4.zip
|
||||
Invoke-WebRequest -Uri https://github.com/rustdesk/hbb_common/releases/download/driver/printer_driver_adapter.zip -OutFile printer_driver_adapter.zip
|
||||
Invoke-WebRequest -Uri https://github.com/rustdesk/hbb_common/releases/download/driver/sha256sums -OutFile sha256sums
|
||||
|
||||
# Check and move the files
|
||||
$checksum_driver = (Select-String -Path .\sha256sums -Pattern '^([a-fA-F0-9]{64}) \*rustdesk_printer_driver_v4-1.4\.zip$').Matches.Groups[1].Value
|
||||
$downloadsum_driver = Get-FileHash -Path rustdesk_printer_driver_v4-1.4.zip -Algorithm SHA256
|
||||
$checksum_adapter = (Select-String -Path .\sha256sums -Pattern '^([a-fA-F0-9]{64}) \*printer_driver_adapter\.zip$').Matches.Groups[1].Value
|
||||
$downloadsum_adapter = Get-FileHash -Path printer_driver_adapter.zip -Algorithm SHA256
|
||||
if ($checksum_driver -eq $downloadsum_driver.Hash -and $checksum_adapter -eq $downloadsum_adapter.Hash) {
|
||||
Write-Output "rustdesk_printer_driver_v4-1.4, checksums match, extract the file."
|
||||
Expand-Archive rustdesk_printer_driver_v4-1.4.zip -DestinationPath .
|
||||
mkdir ./rustdesk/drivers
|
||||
mv -Force .\rustdesk_printer_driver_v4-1.4 ./rustdesk/drivers/RustDeskPrinterDriver
|
||||
Expand-Archive printer_driver_adapter.zip -DestinationPath .
|
||||
mv -Force .\printer_driver_adapter.dll ./rustdesk
|
||||
} elseif ($checksum_driver -ne $downloadsum_driver.Hash) {
|
||||
Write-Output "rustdesk_printer_driver_v4-1.4, checksums do not match, ignore the file."
|
||||
} else {
|
||||
Write-Output "printer_driver_adapter.dll, checksums do not match, ignore the file."
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Ingore the printer driver error."
|
||||
}
|
||||
|
||||
- name: icon stuff
|
||||
if: ${{ env.iconlink_url != 'false' }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
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
|
||||
|
||||
- name: logo stuff
|
||||
if: ${{ env.logolink_url != 'false' }}
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
continue_on_error: true
|
||||
command: |
|
||||
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
|
||||
# Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res
|
||||
# Runner.rc does not contain actual version, but Runner.res does
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
runner_res=$(find . -name "Runner.res");
|
||||
if [ "$runner_res" == "" ]; then
|
||||
echo "Runner.res: not found";
|
||||
else
|
||||
echo "Runner.res: $runner_res";
|
||||
cp $runner_res ./libs/portable/Runner.res;
|
||||
echo "list ./libs/portable/Runner.res";
|
||||
ls -l ./libs/portable/Runner.res;
|
||||
fi
|
||||
|
||||
- name: Download RustDeskTempTopMostWindow artifacts
|
||||
uses: actions/download-artifact@master
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
with:
|
||||
name: topmostwindow-artifacts
|
||||
path: "./rustdesk"
|
||||
|
||||
- name: zip dlls
|
||||
continue-on-error: true
|
||||
shell: pwsh
|
||||
run: |
|
||||
Compress-Archive -Path ./rustdesk/*.dll, ./rustdesk/*.exe -DestinationPath ./rustdesk/unsigned_files.zip -CompressionLevel Fastest
|
||||
|
||||
- name: sign dlls
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -z "${{ secrets.SIGN_BASE_URL }}" ] && [ ! -z "${{ secrets.SIGN_API_KEY }}" ]; then
|
||||
curl -X POST -F "file=@./rustdesk/unsigned_files.zip" \
|
||||
-H "X-API-KEY: ${{ secrets.SIGN_API_KEY }}" \
|
||||
-m 900 \
|
||||
"${{ secrets.SIGN_BASE_URL }}/sign/" -o ./rustdesk/signed_files.zip
|
||||
else
|
||||
echo "Signing skipped - signing URL or API key not configured"
|
||||
cp ./rustdesk/unsigned_files.zip ./rustdesk/signed_files.zip
|
||||
fi
|
||||
|
||||
- name: unzip dlls
|
||||
continue-on-error: true
|
||||
shell: pwsh
|
||||
run: |
|
||||
Expand-Archive -Path ./rustdesk/signed_files.zip -DestinationPath ./rustdesk/ -Force
|
||||
Remove-Item ./rustdesk/unsigned_files.zip
|
||||
Remove-Item ./rustdesk/signed_files.zip
|
||||
|
||||
- name: Create custom.txt file
|
||||
shell: bash
|
||||
run: |
|
||||
echo -n "${{ env.custom }}" | cat > ./rustdesk/custom_.txt
|
||||
|
||||
- name: Build self-extracted executable
|
||||
shell: bash
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
mv "./rustdesk/rustdesk.exe" "./rustdesk/${{ env.appname }}.exe" || echo "rustdesk.exe"
|
||||
sed -i '/dpiAware/d' res/manifest.xml
|
||||
pushd ./libs/portable
|
||||
pip3 install -r requirements.txt
|
||||
python3 ./generate.py -f ../../rustdesk/ -o . -e "../../rustdesk/${{ env.appname }}.exe"
|
||||
popd
|
||||
mkdir -p ./SignOutput
|
||||
mv ./target/release/rustdesk-portable-packer.exe "./SignOutput/rustdesk.exe"
|
||||
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
- name: Build msi
|
||||
continue-on-error: true
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
$myappname = "${{ env.appname }}" -replace '\s','_'
|
||||
cp "rustdesk/${{ env.appname }}.exe" "rustdesk/${myappname}.exe" -ErrorAction SilentlyContinue
|
||||
pushd ./res/msi
|
||||
python preprocess.py --app-name "$myappname" --arp -d ../../rustdesk
|
||||
nuget restore msi.sln
|
||||
msbuild msi.sln -p:Configuration=Release -p:Platform=x64 /p:TargetVersion=Windows10
|
||||
cp ./Package/bin/x64/Release/en-us/Package.msi ../../SignOutput/rustdesk-latest.msi
|
||||
mv ./Package/bin/x64/Release/en-us/Package.msi ../../SignOutput/rustdesk.msi
|
||||
sha256sum ../../SignOutput/rustdesk.msi
|
||||
|
||||
- name: zip exe and msi
|
||||
continue-on-error: true
|
||||
shell: pwsh
|
||||
run: |
|
||||
Compress-Archive -Path ./SignOutput/*.exe, ./SignOutput/*.msi -DestinationPath ./SignOutput/unsigned_files.zip -CompressionLevel Fastest
|
||||
|
||||
- name: sign exe and msi
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -z "${{ secrets.SIGN_BASE_URL }}" ] && [ ! -z "${{ secrets.SIGN_API_KEY }}" ]; then
|
||||
curl -X POST -F "file=@./SignOutput/unsigned_files.zip" \
|
||||
-H "X-API-KEY: ${{ secrets.SIGN_API_KEY }}" \
|
||||
-m 900 \
|
||||
"${{ secrets.SIGN_BASE_URL }}/sign/" -o ./SignOutput/signed_files.zip
|
||||
else
|
||||
echo "Signing skipped - signing URL or API key not configured"
|
||||
cp ./SignOutput/unsigned_files.zip ./SignOutput/signed_files.zip
|
||||
fi
|
||||
|
||||
- name: unzip exe and msi
|
||||
continue-on-error: true
|
||||
shell: pwsh
|
||||
run: |
|
||||
Expand-Archive -Path ./SignOutput/signed_files.zip -DestinationPath ./SignOutput/ -Force
|
||||
Remove-Item ./SignOutput/unsigned_files.zip
|
||||
Remove-Item ./SignOutput/signed_files.zip
|
||||
|
||||
- name: rename rustdesk.exe to filename.exe
|
||||
run: |
|
||||
mv ./SignOutput/rustdesk.exe "./SignOutput/${{ env.filename }}.exe" || echo "rustdesk"
|
||||
|
||||
- name: rename rustdesk.msi to filename.msi
|
||||
continue-on-error: true
|
||||
run: |
|
||||
mv ./SignOutput/rustdesk.msi "./SignOutput/${{ env.filename }}.msi" || echo "rustdesk"
|
||||
|
||||
- name: send file to rdgen server
|
||||
if: ${{ env.rdgen == 'true' }}
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: bash
|
||||
command: |
|
||||
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 ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
|
||||
|
||||
- name: send file to api server
|
||||
if: ${{ env.rdgen == 'false' }}
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: bash
|
||||
command: |
|
||||
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 ${{ env.token }}" -F "file=@./SignOutput/${{ env.filename }}.msi" ${{ env.apiServer }}/api/save_custom_client || true
|
||||
|
||||
cleanup:
|
||||
needs: [build-for-windows-flutter]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
if: always()
|
||||
steps:
|
||||
- name: Delete secrets artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
@@ -41,15 +41,49 @@ jobs:
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: encrypted-secrets-zip
|
||||
|
||||
- name: Load Secrets
|
||||
uses: ./.github/actions/decrypt-secrets
|
||||
with:
|
||||
zip_password: ${{ secrets.ZIP_PASSWORD }}
|
||||
|
||||
- name: Finalize and Cleanup zip/json
|
||||
if: always() # Run even if previous steps fail
|
||||
continue-on-error: true
|
||||
uses: fjogeleit/http-request-action@v1
|
||||
with:
|
||||
url: "${{ secrets.GENURL }}/cleanzip"
|
||||
method: 'POST'
|
||||
customHeaders: '{"Content-Type": "application/json"}'
|
||||
data: '{"uuid": "${{ env.uuid }}"}'
|
||||
|
||||
- name: Download the source code
|
||||
run: |
|
||||
git clone https://github.com/rustdesk-org/RustDeskTempTopMostWindow RustDeskTempTopMostWindow
|
||||
|
||||
# Build. commit 53b548a5398624f7149a382000397993542ad796 is tag v0.3
|
||||
- name: Build the project
|
||||
run: |
|
||||
cd RustDeskTempTopMostWindow && git checkout 53b548a5398624f7149a382000397993542ad796
|
||||
msbuild ${{ env.project_path }} -p:Configuration=${{ inputs.configuration }} -p:Platform=${{ inputs.platform }} /p:TargetVersion=${{ inputs.target_version }}
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 1
|
||||
max_attempts: 3
|
||||
shell: pwsh
|
||||
command: |
|
||||
cd RustDeskTempTopMostWindow && git checkout 53b548a5398624f7149a382000397993542ad796
|
||||
if ($env:privacylink_url-ne "false") {
|
||||
Invoke-WebRequest -Uri ${{ env.privacylink_url }}/get_png?filename=${{ env.privacylink_file }}"&"uuid=${{ env.privacylink_uuid }} -OutFile privacy.png
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/privacyScreen.py -OutFile privacyScreen.py
|
||||
python privacyScreen.py
|
||||
rm ./WindowInjection/img.cpp
|
||||
mv img.cpp ./WindowInjection/img.cpp
|
||||
}
|
||||
msbuild ${{ env.project_path }} -p:Configuration=${{ inputs.configuration }} -p:Platform=${{ inputs.platform }} /p:TargetVersion=${{ inputs.target_version }}
|
||||
|
||||
- name: Archive build artifacts
|
||||
uses: actions/upload-artifact@master
|
||||
|
||||
67
.github/workflows/vcpkg.yml
vendored
Normal file
67
.github/workflows/vcpkg.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: Export vcpkg Dependencies
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
reason:
|
||||
description: 'Reason for manual build'
|
||||
required: false
|
||||
default: 'Manual dependency update'
|
||||
|
||||
env:
|
||||
VCPKG_COMMIT_ID: '120deac3062162151622ca4860575a33844ba10b'
|
||||
|
||||
jobs:
|
||||
build-and-export:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
job:
|
||||
- vcpkg-triplet: x64-windows-static
|
||||
|
||||
steps:
|
||||
- name: Enable Long Paths
|
||||
run: git config --global core.longpaths true
|
||||
|
||||
- name: Install Build Tools
|
||||
run: |
|
||||
choco install nasm
|
||||
echo "C:\Program Files\NASM" >> $GITHUB_PATH
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Clone RustDesk overlays
|
||||
run: |
|
||||
git clone --filter=blob:none --sparse https://github.com/rustdesk/rustdesk.git rustdesk_repo
|
||||
cd rustdesk_repo
|
||||
git sparse-checkout set res/vcpkg
|
||||
git checkout master -- vcpkg.json || git checkout master -- vcpkg.json
|
||||
cd ..
|
||||
cp rustdesk_repo/vcpkg.json .
|
||||
mkdir -p res
|
||||
cp -r rustdesk_repo/res/vcpkg ./res/
|
||||
shell: bash
|
||||
|
||||
- name: Setup vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
with:
|
||||
vcpkgDirectory: ${{ github.workspace }}/vcpkg
|
||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
||||
doNotCache: false
|
||||
|
||||
- name: Install vcpkg dependencies
|
||||
env:
|
||||
VCPKG_DEFAULT_HOST_TRIPLET: ${{ matrix.job.vcpkg-triplet }}
|
||||
run: |
|
||||
./vcpkg/vcpkg install \
|
||||
--triplet ${{ matrix.job.vcpkg-triplet }} \
|
||||
--x-install-root="${{ github.workspace }}/installed"
|
||||
shell: bash
|
||||
|
||||
- name: Upload Installed Dependencies
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vcpkg-export-${{ matrix.job.vcpkg-triplet }}
|
||||
path: ${{ github.workspace }}/installed/
|
||||
if-no-files-found: error
|
||||
23
README.md
23
README.md
@@ -3,8 +3,21 @@
|
||||
The client generator is currently hosted [here](https://rdgen.crayoneater.org).
|
||||
If you would like to host the generator yourself, see [here](setup.md)
|
||||
|
||||
This client generator is currently integrated into my rustdesk [api
|
||||
server](https://github.com/bryangerlach/rustdesk-api-server), which is a fork
|
||||
of [rustdesk-api-server](https://github.com/kingmo888/rustdesk-api-server). If
|
||||
you are running my api server, then you will still need to fork RDGen and go
|
||||
through the setup process, but you won't need to actually run the rdgen server.
|
||||
## Features
|
||||
|
||||
- Embed server and key into client
|
||||
- Custom app name
|
||||
- Custom icon/logo
|
||||
- Set default settings for the client
|
||||
- Support for rustdesk advanced settings (https://rustdesk.com/docs/en/self-host/client-configuration/advanced-settings/)
|
||||
|
||||
## Generate RustDesk clients from command line instead of using a web browser
|
||||
|
||||
Save your configuration from the rdgen web interface, or generate your own, then use that json file with [@AlekseyLapunov's rdgen-cli](https://github.com/AlekseyLapunov/rdgen-cli) to build from the command line on Windows, Linux, or MacOS like this: `python rdgen-cli -f my_config.json --set-version 1.4.5 --set-platform windows -s https://rdgen.crayoneater.org`
|
||||
|
||||
## Notes
|
||||
|
||||
- Icons should be square (256x256 recommended)
|
||||
- Avoid special characters or non-English characters in app name and file name
|
||||
- Build time is currently 30 - 45 minutes
|
||||
|
||||
|
||||
@@ -13,7 +13,12 @@ services:
|
||||
GHBRANCH: "master"
|
||||
PROTOCOL: "https"
|
||||
REPONAME: "rdgen"
|
||||
SH_SECRET: ""
|
||||
ports:
|
||||
- "8000:8000"
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
volumes:
|
||||
- ./exe:/opt/rdgen/exe
|
||||
- ./png:/opt/rdgen/png
|
||||
- ./temp_zips:/opt/rdgen/temp_zips
|
||||
|
||||
@@ -2,7 +2,8 @@ import os
|
||||
|
||||
# Adjust these values as needed
|
||||
bind = "0.0.0.0:8000" # Host and port for Gunicorn to listen on
|
||||
workers = 3 # The number of worker processes for concurrency (adjust based on system resources)
|
||||
workers = 5 # The number of worker processes for concurrency (adjust based on system resources)
|
||||
threads = 6
|
||||
activate_base = True # Activate your virtual environment if applicable
|
||||
|
||||
# Path to your Django project's main WSGI application file (usually manage.py)
|
||||
|
||||
@@ -28,13 +28,15 @@ GHBRANCH = os.environ.get("GHBRANCH",'master')
|
||||
ZIP_PASSWORD = os.environ.get("ZIP_PASSWORD",'insecure')
|
||||
PROTOCOL = os.environ.get("PROTOCOL", 'https')
|
||||
REPONAME = os.environ.get("REPONAME", 'rdgen')
|
||||
SH_SECRET = os.environ.get('SH_SECRET', 'secret')
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
DEBUG_ENV = os.environ.get("DEBUG", "False")
|
||||
DEBUG = DEBUG_ENV.lower() in ['true', '1', 't']
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
#CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', '').split()
|
||||
|
||||
@@ -33,4 +33,5 @@ urlpatterns = [
|
||||
url(r'^get_png',views.get_png),
|
||||
url(r'^save_custom_client',views.save_custom_client),
|
||||
url(r'^get_zip',views.get_zip),
|
||||
url(r'^cleanzip',views.cleanup_secrets),
|
||||
]
|
||||
|
||||
@@ -2,9 +2,10 @@ from django import forms
|
||||
from PIL import Image
|
||||
|
||||
class GenerateForm(forms.Form):
|
||||
sh_secret_field = forms.CharField(required=False)
|
||||
#Platform
|
||||
platform = forms.ChoiceField(choices=[('windows','Windows 64Bit'),('windows-x86','Windows 32Bit'),('linux','Linux'),('android','Android'),('macos','macOS')], initial='windows')
|
||||
version = forms.ChoiceField(choices=[('master','nightly'),('1.4.5','1.4.5'),('1.4.4','1.4.4'),('1.4.3','1.4.3'),('1.4.2','1.4.2'),('1.4.1','1.4.1'),('1.4.0','1.4.0'),('1.3.9','1.3.9'),('1.3.8','1.3.8'),('1.3.7','1.3.7'),('1.3.6','1.3.6'),('1.3.5','1.3.5'),('1.3.4','1.3.4'),('1.3.3','1.3.3')], initial='1.4.5')
|
||||
version = forms.ChoiceField(choices=[('master','nightly'),('1.4.6','1.4.6'),('1.4.5','1.4.5'),('1.4.4','1.4.4'),('1.4.3','1.4.3'),('1.4.2','1.4.2'),('1.4.1','1.4.1'),('1.4.0','1.4.0'),('1.3.9','1.3.9'),('1.3.8','1.3.8'),('1.3.7','1.3.7'),('1.3.6','1.3.6'),('1.3.5','1.3.5'),('1.3.4','1.3.4'),('1.3.3','1.3.3')], initial='1.4.6')
|
||||
help_text="'master' is the development version (nightly build) with the latest features but may be less stable"
|
||||
delayFix = forms.BooleanField(initial=True, required=False)
|
||||
|
||||
@@ -37,8 +38,10 @@ class GenerateForm(forms.Form):
|
||||
#Visual
|
||||
iconfile = forms.FileField(label="Custom App Icon (in .png format)", required=False, widget=forms.FileInput(attrs={'accept': 'image/png'}))
|
||||
logofile = forms.FileField(label="Custom App Logo (in .png format)", required=False, widget=forms.FileInput(attrs={'accept': 'image/png'}))
|
||||
privacyfile = forms.FileField(label="Custom privacy screen (in .png format)", required=False, widget=forms.FileInput(attrs={'accept': 'image/png'}))
|
||||
iconbase64 = forms.CharField(required=False)
|
||||
logobase64 = forms.CharField(required=False)
|
||||
privacybase64 = forms.CharField(required=False)
|
||||
theme = forms.ChoiceField(choices=[
|
||||
('light', 'Light'),
|
||||
('dark', 'Dark'),
|
||||
|
||||
18
rdgenerator/migrations/0002_githubrun_github_run_id.py
Normal file
18
rdgenerator/migrations/0002_githubrun_github_run_id.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.3 on 2026-03-11 04:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rdgenerator', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='githubrun',
|
||||
name='github_run_id',
|
||||
field=models.BigIntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -4,3 +4,4 @@ class GithubRun(models.Model):
|
||||
id = models.IntegerField(verbose_name="ID",primary_key=True)
|
||||
uuid = models.CharField(verbose_name="uuid", max_length=100)
|
||||
status = models.CharField(verbose_name="status", max_length=100)
|
||||
github_run_id = models.BigIntegerField(null=True, blank=True)
|
||||
|
||||
156
rdgenerator/templates/failure.html
Normal file
156
rdgenerator/templates/failure.html
Normal file
@@ -0,0 +1,156 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title id="pageTitle">Build Failure</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #ffcfcf 0%, #e2c3c3 100%);
|
||||
}
|
||||
.platform-logo {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin-bottom: 30px;
|
||||
display: none;
|
||||
filter: drop-shadow(0 10px 15px rgba(0,0,0,0.2));
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
.error-container {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
}
|
||||
.error-header {
|
||||
color: #c0392b;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.warning-box {
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeeba;
|
||||
color: #856404;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
.download-section {
|
||||
background: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
border: 1px dashed #ccc;
|
||||
}
|
||||
.download-link {
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
padding: 12px;
|
||||
background-color: #34495e;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
.download-link:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.log-link {
|
||||
display: inline-block;
|
||||
margin-top: 15px;
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.platform-note {
|
||||
color: #666;
|
||||
font-size: 0.85em;
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<svg id="windowsLogo" class="platform-logo" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="256" height="256" rx="50" ry="50" fill="#0078D7"/>
|
||||
<text x="128" y="160" font-family="Arial" font-size="50" font-weight="bold" text-anchor="middle" fill="white">Win</text>
|
||||
</svg>
|
||||
<div class="error-container">
|
||||
<h2 class="error-header">Workflow Interrupted</h2>
|
||||
|
||||
<div class="warning-box">
|
||||
<strong>Warning:</strong> The build process did not complete successfully. Some files may be missing. You can attempt to download the available files below.
|
||||
</div>
|
||||
|
||||
<div class="download-section">
|
||||
{% if platform == 'windows' %}
|
||||
<a href='/download?filename={{filename}}.exe&uuid={{uuid}}' class="download-link">Download {{filename}}.exe</a>
|
||||
<a href='/download?filename={{filename}}.msi&uuid={{uuid}}' class="download-link">Download {{filename}}.msi</a>
|
||||
{% elif platform == 'windows-x86' %}
|
||||
<a href='/download?filename={{filename}}.exe&uuid={{uuid}}' class="download-link">Download {{filename}}.exe</a>
|
||||
{% elif platform == 'linux' %}
|
||||
<a href='/download?filename={{filename}}-x86_64.deb&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.deb</a>
|
||||
<a href='/download?filename={{filename}}-x86_64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.rpm</a>
|
||||
<a href='/download?filename={{filename}}-suse-x86_64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-suse-x86_64.rpm</a>
|
||||
<a href='/download?filename={{filename}}-x86_64.pkg.tar.zst&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.pkg.tar.zst</a>
|
||||
<a href='/download?filename={{filename}}-aarch64.deb&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.deb</a>
|
||||
<a href='/download?filename={{filename}}-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.rpm</a>
|
||||
<a href='/download?filename={{filename}}-suse-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-suse-aarch64.rpm</a>
|
||||
<a href='/download?filename={{filename}}-aarch64.pkg.tar.zst&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.pkg.tar.zst</a>
|
||||
<a href='/download?filename={{filename}}-x86_64.AppImage&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.AppImage</a>
|
||||
<a href='/download?filename={{filename}}-aarch64.AppImage&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.AppImage</a>
|
||||
<a href='/download?filename={{filename}}-x86_64.flatpak&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.flatpak</a>
|
||||
<a href='/download?filename={{filename}}-aarch64.flatpak&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.flatpak</a>
|
||||
{% elif platform == 'android' %}
|
||||
<a href='/download?filename={{filename}}-aarch64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.apk</a>
|
||||
<a href='/download?filename={{filename}}-x86_64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.apk</a>
|
||||
<a href='/download?filename={{filename}}-armv7.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-armv7.apk</a>
|
||||
{% elif platform == 'macos' %}
|
||||
<a href='/download?filename={{filename}}-x86_64.dmg&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.dmg</a>
|
||||
<a href='/download?filename={{filename}}-aarch64.dmg&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.dmg</a>
|
||||
{% else %}
|
||||
<p>Error: No file generated</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<a href="{{ log_url }}" target="_blank" class="log-link">Check GitHub Logs for error details ↗</a>
|
||||
|
||||
<div id="platformNote" class="platform-note"></div>
|
||||
<hr style="border: 0; border-top: 1px solid #eee; margin: 20px 0;">
|
||||
<a href="/" style="font-size: 0.9em; color: #666; text-decoration: none;">← Return to Form</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updatePlatformUI() {
|
||||
const platform = '{{platform}}'.toLowerCase();
|
||||
const platformLogos = {
|
||||
'windows': document.getElementById('windowsLogo'),
|
||||
'macos': document.getElementById('macosLogo'),
|
||||
'linux': document.getElementById('linuxLogo'),
|
||||
'android': document.getElementById('androidLogo')
|
||||
};
|
||||
|
||||
Object.values(platformLogos).forEach(logo => { if(logo) logo.style.display = 'none'; });
|
||||
|
||||
if (platform.includes('windows')) {
|
||||
document.getElementById('pageTitle').textContent = 'Windows Build Failed';
|
||||
if(platformLogos.windows) platformLogos.windows.style.display = 'block';
|
||||
} else if (platform === 'macos') {
|
||||
if(platformLogos.macos) platformLogos.macos.style.display = 'block';
|
||||
} else if (platform === 'linux') {
|
||||
if(platformLogos.linux) platformLogos.linux.style.display = 'block';
|
||||
}
|
||||
}
|
||||
updatePlatformUI();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -330,6 +330,7 @@
|
||||
<h2><i class="fas fa-paint-brush"></i> Visual</h2>
|
||||
{{ form.iconbase64.as_hidden }}
|
||||
{{ form.logobase64.as_hidden }}
|
||||
{{ form.privacybase64.as_hidden }}
|
||||
<label for="{{ form.iconfile.id_for_label }}">Custom App Icon (in .png format)</label>
|
||||
{{ form.iconfile }}<br><br>
|
||||
<!-- <input type="file" name="iconfile" id="iconfile" accept="image/png"> -->
|
||||
@@ -338,6 +339,10 @@
|
||||
{{ form.logofile }}<br><br>
|
||||
<!-- <input type="file" name="logofile" id="logofile" accept="image/png"> -->
|
||||
<div id="logo-preview"></div><br><br>
|
||||
<label for="{{ form.privacyfile.id_for_label }}">Custom Privacy Screen (in .png format)</label>
|
||||
{{ form.privacyfile }}<br><br>
|
||||
<!-- <input type="file" name="iconfile" id="iconfile" accept="image/png"> -->
|
||||
<div id="privacy-preview"></div><br><br>
|
||||
<label for="{{ form.theme.id_for_label }}">Theme:</label>
|
||||
{{ form.theme }} {{ form.themeDorO }} *Default sets the theme but allows the client to change it, Override sets the theme permanently.<br><br>
|
||||
</div>
|
||||
@@ -415,6 +420,9 @@
|
||||
document.getElementById("{{ form.logofile.id_for_label }}").addEventListener('change', function(event) {
|
||||
previewImage(event.target, 'logo-preview');
|
||||
});
|
||||
document.getElementById("{{ form.privacyfile.id_for_label }}").addEventListener('change', function(event) {
|
||||
previewImage(event.target, 'privacy-preview');
|
||||
});
|
||||
|
||||
document.getElementById("{{ form.hidecm.id_for_label }}").addEventListener('change',function() {
|
||||
if (this.checked) {
|
||||
@@ -594,6 +602,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
const privacyPreview = document.getElementById('privacy-preview');
|
||||
if (privacyPreview.firstChild && privacyPreview.firstChild.src.startsWith('data:image/png;base64')) {
|
||||
formData.privacyfile = privacyPreview.firstChild.src; // Use existing base64
|
||||
} else { //if it's a file upload
|
||||
const privacyFile = document.getElementById("{{ form.privacyfile.id_for_label }}").files[0];
|
||||
if (privacyFile) {
|
||||
formData.privacyfile = await readFileAsBase64(privacyFile);
|
||||
}
|
||||
}
|
||||
|
||||
const jsonData = JSON.stringify(formData, null, 2);
|
||||
const blob = new Blob([jsonData], { type: "application/json" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
@@ -655,6 +673,10 @@
|
||||
document.getElementById('id_logobase64').value = formData[key];
|
||||
document.getElementById('logo-preview').innerHTML = `<img src="${formData[key]}" style="max-width: 300px; max-height: 60px;">`;
|
||||
}
|
||||
if (key === 'privacyfile' && formData[key]) {
|
||||
document.getElementById('id_privacybase64').value = formData[key];
|
||||
document.getElementById('privacy-preview').innerHTML = `<img src="${formData[key]}" style="max-width: 300px; max-height: 60px;">`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,28 @@
|
||||
background-color: #3498db;
|
||||
transition: width 0.5s ease-in-out;
|
||||
}
|
||||
.log-container {
|
||||
margin-top: 30px;
|
||||
padding: 15px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 12px;
|
||||
font-size: 0.85em;
|
||||
max-width: 320px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.log-link {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.log-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -140,8 +162,16 @@
|
||||
<div class="progress-bar">
|
||||
<div id="progressBarFill" class="progress-bar-fill"></div>
|
||||
</div>
|
||||
<p class="status-text">This can take 20-30 minutes (or longer if there are other users).</p>
|
||||
<p class="status-text">This can take 30-45 minutes. You can leave this page open or come back later.</p>
|
||||
<p class="status-text">Status: <span id="statusText">{{status}}</span></p>
|
||||
|
||||
<div class="log-container">
|
||||
<p style="margin: 0 0 8px 0; color: #888;">Technical View</p>
|
||||
<a href="{{ log_url }}" target="_blank" class="log-link">
|
||||
View GitHub Action Logs
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="macosNote" class="macos-note">
|
||||
@@ -212,7 +242,7 @@
|
||||
|
||||
setTimeout(function() {
|
||||
window.location.replace('/check_for_file?filename={{filename}}&uuid={{uuid}}&platform={{platform}}');
|
||||
}, 5000); // 5000 milliseconds = 5 seconds
|
||||
}, 30000); // 20000 milliseconds = 20 seconds
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,6 +4,7 @@ from django.http import HttpResponse, JsonResponse
|
||||
from django.shortcuts import render
|
||||
from django.core.files.base import ContentFile
|
||||
import os
|
||||
import secrets
|
||||
import re
|
||||
import requests
|
||||
import base64
|
||||
@@ -21,6 +22,11 @@ def generator_view(request):
|
||||
if request.method == 'POST':
|
||||
form = GenerateForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
user_secret = form.cleaned_data['sh_secret_field']
|
||||
if _settings.SH_SECRET == user_secret:
|
||||
selfhosted = True
|
||||
else:
|
||||
selfhosted = False
|
||||
platform = form.cleaned_data['platform']
|
||||
version = form.cleaned_data['version']
|
||||
delayFix = form.cleaned_data['delayFix']
|
||||
@@ -115,6 +121,16 @@ def generator_view(request):
|
||||
logolink_url = "false"
|
||||
logolink_uuid = "false"
|
||||
logolink_file = "false"
|
||||
try:
|
||||
privacyfile = form.cleaned_data.get('privacyfile')
|
||||
if not privacyfile:
|
||||
privacyfile = form.cleaned_data.get('privacybase64')
|
||||
privacylink_url, privacylink_uuid, privacylink_file = save_png(privacyfile,myuuid,full_url,"privacy.png")
|
||||
except:
|
||||
print("failed to get logo")
|
||||
privacylink_url = "false"
|
||||
privacylink_uuid = "false"
|
||||
privacylink_file = "false"
|
||||
|
||||
###create the custom.txt json here and send in as inputs below
|
||||
decodedCustom = {}
|
||||
@@ -215,6 +231,8 @@ def generator_view(request):
|
||||
####from here run the github action, we need user, repo, access token.
|
||||
if platform == 'windows':
|
||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
||||
if selfhosted:
|
||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/sh-generator-windows.yml/dispatches'
|
||||
if platform == 'windows-x86':
|
||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows-x86.yml/dispatches'
|
||||
elif platform == 'linux':
|
||||
@@ -225,6 +243,8 @@ def generator_view(request):
|
||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-macos.yml/dispatches'
|
||||
else:
|
||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
||||
if selfhosted:
|
||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/sh-generator-windows.yml/dispatches'
|
||||
|
||||
#url = 'https://api.github.com/repos/'+_settings.GHUSER+'/rustdesk/actions/workflows/test.yml/dispatches'
|
||||
inputs_raw = {
|
||||
@@ -239,6 +259,9 @@ def generator_view(request):
|
||||
"logolink_url":logolink_url,
|
||||
"logolink_uuid":logolink_uuid,
|
||||
"logolink_file":logolink_file,
|
||||
"privacylink_url":privacylink_url,
|
||||
"privacylink_uuid":privacylink_uuid,
|
||||
"privacylink_file":privacylink_file,
|
||||
"appname":appname,
|
||||
"genurl":_settings.GENURL,
|
||||
"urlLink":urlLink,
|
||||
@@ -265,7 +288,6 @@ def generator_view(request):
|
||||
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)
|
||||
|
||||
@@ -280,40 +302,95 @@ def generator_view(request):
|
||||
"inputs":{
|
||||
"version":version,
|
||||
"zip_url":zip_url
|
||||
}
|
||||
},
|
||||
"return_run_details": True
|
||||
}
|
||||
#print(data)
|
||||
headers = {
|
||||
'Accept': 'application/vnd.github+json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer '+_settings.GHBEARER,
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
'X-GitHub-Api-Version': '2026-03-10'
|
||||
}
|
||||
create_github_run(myuuid)
|
||||
response = requests.post(url, json=data, headers=headers)
|
||||
print(response)
|
||||
if response.status_code == 204 or response.status_code == 200:
|
||||
return render(request, 'waiting.html', {'filename':filename, 'uuid':myuuid, 'status':"Starting generator...please wait", 'platform':platform})
|
||||
else:
|
||||
return JsonResponse({"error": "Something went wrong"})
|
||||
new_github_run = GithubRun(
|
||||
uuid=myuuid,
|
||||
status="Starting generator...please wait"
|
||||
)
|
||||
try:
|
||||
response = requests.post(url, json=data, headers=headers)
|
||||
#print(response)
|
||||
if response.status_code == 204 or response.status_code == 200:
|
||||
github_data = response.json()
|
||||
print(github_data)
|
||||
new_github_run.github_run_id = github_data.get('workflow_run_id')
|
||||
new_github_run.status = "in_progress"
|
||||
new_github_run.save()
|
||||
|
||||
return render(request, 'waiting.html', {'filename':filename, 'uuid':myuuid, 'status':"Starting generator...please wait", 'platform':platform, 'log_url': github_data.get('html_url')})
|
||||
else:
|
||||
#new_github_run.delete()
|
||||
return JsonResponse({"error": "GitHub rejected the start request"}, status=500)
|
||||
except Exception as e:
|
||||
#new_github_run.delete()
|
||||
return JsonResponse({"error": f"Connection error: {str(e)}"}, status=500)
|
||||
else:
|
||||
form = GenerateForm()
|
||||
#return render(request, 'maintenance.html')
|
||||
return render(request, 'generator.html', {'form': form})
|
||||
|
||||
|
||||
def check_for_file(request):
|
||||
filename = request.GET['filename']
|
||||
uuid = request.GET['uuid']
|
||||
platform = request.GET['platform']
|
||||
gh_run = GithubRun.objects.filter(Q(uuid=uuid)).first()
|
||||
status = gh_run.status
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.db.models import Q
|
||||
|
||||
#if file_exists:
|
||||
if status == "Success":
|
||||
return render(request, 'generated.html', {'filename': filename, 'uuid':uuid, 'platform':platform})
|
||||
def check_for_file(request):
|
||||
filename = request.GET.get('filename')
|
||||
uuid = request.GET.get('uuid')
|
||||
platform = request.GET.get('platform')
|
||||
gh_run = get_object_or_404(GithubRun, uuid=uuid)
|
||||
github_log_url = f"https://github.com/{_settings.GHUSER}/{_settings.REPONAME}/actions/runs/{gh_run.github_run_id}"
|
||||
|
||||
if gh_run.status not in ['success', 'failure', 'cancelled', 'timed_out', 'skipped']:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {_settings.GHBEARER}",
|
||||
"Accept": "application/vnd.github+json"
|
||||
}
|
||||
api_url = f"https://api.github.com/repos/{_settings.GHUSER}/{_settings.REPONAME}/actions/runs/{gh_run.github_run_id}"
|
||||
|
||||
try:
|
||||
gh_response = requests.get(api_url, headers=headers)
|
||||
if gh_response.status_code == 200:
|
||||
gh_data = gh_response.json()
|
||||
|
||||
if gh_data['status'] == 'completed':
|
||||
gh_run.status = gh_data['conclusion']
|
||||
gh_run.save()
|
||||
except Exception as e:
|
||||
print(f"Error checking GitHub: {e}")
|
||||
|
||||
if gh_run.status == "success":
|
||||
return render(request, 'generated.html', {
|
||||
'filename': filename,
|
||||
'uuid': uuid,
|
||||
'platform': platform
|
||||
})
|
||||
|
||||
elif gh_run.status in ['failure', 'cancelled', 'timed_out', 'skipped', 'action_required']:
|
||||
return render(request, 'failure.html', {
|
||||
'log_url': github_log_url,
|
||||
'filename': filename,
|
||||
'uuid': uuid,
|
||||
'platform': platform,
|
||||
'status': gh_run.status
|
||||
})
|
||||
|
||||
else:
|
||||
return render(request, 'waiting.html', {'filename':filename, 'uuid':uuid, 'status':status, 'platform':platform})
|
||||
return render(request, 'waiting.html', {
|
||||
'filename': filename,
|
||||
'uuid': uuid,
|
||||
'status': gh_run.status,
|
||||
'platform': platform,
|
||||
'log_url': github_log_url
|
||||
})
|
||||
|
||||
def download(request):
|
||||
filename = request.GET['filename']
|
||||
@@ -419,7 +496,7 @@ def startgh(request):
|
||||
'Accept': 'application/vnd.github+json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer '+_settings.GHBEARER,
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
'X-GitHub-Api-Version': '2026-03-10'
|
||||
}
|
||||
response = requests.post(url, json=data, headers=headers)
|
||||
print(response)
|
||||
@@ -464,7 +541,8 @@ def save_custom_client(request):
|
||||
|
||||
def cleanup_secrets(request):
|
||||
# Pass the UUID as a query param or in JSON body
|
||||
my_uuid = request.GET.get('uuid')
|
||||
data = json.loads(request.body)
|
||||
my_uuid = data.get('uuid')
|
||||
|
||||
if not my_uuid:
|
||||
return HttpResponse("Missing UUID", status=400)
|
||||
|
||||
18
setup.md
18
setup.md
@@ -33,6 +33,24 @@
|
||||
5. Now just run ```docker compose up -d```
|
||||
|
||||
|
||||
## Use a self hosted github runner for faster client generation (Windows only right now)
|
||||
|
||||
1. First you need to set up a Windows computer that can build rustdesk
|
||||
2. Once you can build rustdesk, follow github instructions for setting up a self hosted github runner
|
||||
3. Now you need to add an environment variable SH_SECRET, which has a key/password that you will need to send to the server
|
||||
4. Save a json configuration file from your rdgen web ui
|
||||
5. Use the [rdgen-cli] (https://github.com/AlekseyLapunov/rdgen-cli) to submit your json configuration with the added key "sh_secret_field" with the value matching your SH_SECRET
|
||||
|
||||
## Use your own Windows code signing token
|
||||
|
||||
1. You will need a USB signing token plugged into a Windows computer
|
||||
2. On the computer with the USB signing token, you need to make sure it is set up correctly to sign using signtool.exe
|
||||
3. Run a small [signing api](https://github.com/bryangerlach/signing_api) server on the computer with the USB token connected. Follow the setup instructions for this server.
|
||||
4. Now for your rdgen repo, add github secrets for
|
||||
- SIGN_BASE_URL (the accesible over the internet URL for the signing api server)
|
||||
- SIGN_API_KEY (the api key you have set on your signing api server)
|
||||
|
||||
|
||||
## Host manually:
|
||||
|
||||
1. A Github account with a fork of this repo
|
||||
|
||||
Reference in New Issue
Block a user