Compare commits
160 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 | ||
|
|
1650994efa | ||
|
|
c74dd0a2e4 | ||
|
|
5fb84b739c | ||
|
|
278234dd08 | ||
|
|
54ff4d8c8b | ||
|
|
ceaf44f71d | ||
|
|
1287e7e5df | ||
|
|
d6d6165c4b | ||
|
|
b133ba0d66 | ||
|
|
47da6243dd | ||
|
|
661f39543c | ||
|
|
f72d9be70c | ||
|
|
88dca7235b | ||
|
|
05906539d7 | ||
|
|
851d8e9771 | ||
|
|
e4420c24c8 | ||
|
|
fae826ef53 | ||
|
|
5052bec676 | ||
|
|
e46d0bd0ef | ||
|
|
67e2bc7df9 | ||
|
|
2e229d0800 | ||
|
|
89ee4822dd | ||
|
|
c429836057 | ||
|
|
6f1bb528bd | ||
|
|
13114d0bc3 | ||
|
|
56c4d9f0b7 | ||
|
|
6c7c1ed3e7 | ||
|
|
abbf4d899b | ||
|
|
3e22a34906 | ||
|
|
b4ec36c59a | ||
|
|
7d578df4c2 | ||
|
|
3169440af6 | ||
|
|
12b5fe1e30 | ||
|
|
23e91a5ea7 | ||
|
|
be47bcbe46 | ||
|
|
668998e390 | ||
|
|
fabbc91fae | ||
|
|
50082d5566 | ||
|
|
ac3d60cae1 | ||
|
|
6755dc1fa0 | ||
|
|
c53548dcce | ||
|
|
e36790addc | ||
|
|
94f1560196 | ||
|
|
6ac5f4b283 | ||
|
|
606a5ee956 | ||
|
|
2548477390 | ||
|
|
885523e2f9 | ||
|
|
253749df21 | ||
|
|
050f4b3130 | ||
|
|
cc59f1d58d | ||
|
|
a56f965344 | ||
|
|
a45bc0acdd | ||
|
|
5ea49e7a00 | ||
|
|
131ec1759d | ||
|
|
bcef3a4026 | ||
|
|
0240a905f9 | ||
|
|
8577a25657 | ||
|
|
465a9d3554 | ||
|
|
f0f67f5be1 | ||
|
|
2c1a5f93b5 | ||
|
|
55c41599be | ||
|
|
9f23f1c94a | ||
|
|
7479fbbd8f | ||
|
|
c0ede165ab | ||
|
|
78ec60d272 | ||
|
|
807f26360e | ||
|
|
bad75caf0b | ||
|
|
b76e34aa1c | ||
|
|
e3c41ee258 | ||
|
|
c76a63d269 | ||
|
|
88918cde01 | ||
|
|
6725aa21b0 | ||
|
|
1978be9edf | ||
|
|
4edff33ebd | ||
|
|
49fd150fe5 | ||
|
|
c8c1fac268 | ||
|
|
a91d66007d | ||
|
|
ca1aa3fcc5 | ||
|
|
409ed5cfa3 | ||
|
|
2ca25d3a39 | ||
|
|
0e975e73db | ||
|
|
62ac82ec2e | ||
|
|
fc239ef7b5 | ||
|
|
71eb691a52 | ||
|
|
256d647f04 | ||
|
|
7644222adf | ||
|
|
fdfebbb01a | ||
|
|
cd1915a4bf |
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.")
|
||||||
63
.github/patches/allowCustom.py
vendored
Normal file
63
.github/patches/allowCustom.py
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
def remove_line_block(filepath, start_phrase, lines_to_remove_after_start):
|
||||||
|
"""
|
||||||
|
Removes a starting line and a fixed number of lines immediately following it.
|
||||||
|
|
||||||
|
:param filepath: The path to the file to modify.
|
||||||
|
:param start_phrase: The unique string to identify the first line of the block.
|
||||||
|
:param lines_to_remove_after_start: The number of lines to remove after the starting line.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 1. Configuration for the removal logic
|
||||||
|
# The starting line is: const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";
|
||||||
|
# The block contains this line plus 8 following lines, so we want to skip 9 lines in total.
|
||||||
|
total_lines_to_skip = 1 + lines_to_remove_after_start # 1 (start line) + 8 (following lines) = 9
|
||||||
|
|
||||||
|
lines_to_keep = []
|
||||||
|
skip_count = 0
|
||||||
|
|
||||||
|
# 2. Read and filter the file content
|
||||||
|
try:
|
||||||
|
with open(filepath, 'r') as file:
|
||||||
|
for line in file:
|
||||||
|
|
||||||
|
# If we are currently in the process of skipping lines, decrement the counter and continue
|
||||||
|
if skip_count > 0:
|
||||||
|
skip_count -= 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check if the line matches the start phrase (we use .strip() to ignore indentation/whitespace)
|
||||||
|
if line.strip().startswith(start_phrase.strip()):
|
||||||
|
# Start skipping the block (including the current line)
|
||||||
|
skip_count = total_lines_to_skip - 1
|
||||||
|
# Note: We subtract 1 because the 'continue' will handle the first line removal immediately
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If we are not skipping, keep the line, but change custom.txt to custom_.txt
|
||||||
|
line = line.replace("custom.txt", "custom_.txt")
|
||||||
|
lines_to_keep.append(line)
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Error: File not found at {filepath}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 3. Write the remaining lines back to the file
|
||||||
|
try:
|
||||||
|
with open(filepath, 'w') as file:
|
||||||
|
file.writelines(lines_to_keep)
|
||||||
|
|
||||||
|
print(f"Success! Removed the 9-line block starting with '{start_phrase.strip()}' from {filepath}.")
|
||||||
|
|
||||||
|
except IOError as e:
|
||||||
|
print(f"An error occurred while writing to the file: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
file_path = 'src/common.rs'
|
||||||
|
start_phrase = 'const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";'
|
||||||
|
lines_to_remove_after_start = 8
|
||||||
|
remove_line_block(file_path, start_phrase, lines_to_remove_after_start)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
16
.github/patches/cycle_monitor.diff
vendored
16
.github/patches/cycle_monitor.diff
vendored
@@ -1,8 +1,8 @@
|
|||||||
diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart
|
diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart
|
||||||
index 839ea1a81..9cee52263 100644
|
index bc3757f1e..ba6509802 100644
|
||||||
--- a/flutter/lib/desktop/widgets/remote_toolbar.dart
|
--- a/flutter/lib/desktop/widgets/remote_toolbar.dart
|
||||||
+++ b/flutter/lib/desktop/widgets/remote_toolbar.dart
|
+++ b/flutter/lib/desktop/widgets/remote_toolbar.dart
|
||||||
@@ -437,6 +437,7 @@ class _RemoteToolbarState extends State<RemoteToolbar> {
|
@@ -317,6 +317,7 @@ class _RemoteToolbarState extends State<RemoteToolbar> {
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
child: _DraggableShowHide(
|
child: _DraggableShowHide(
|
||||||
id: widget.id,
|
id: widget.id,
|
||||||
@@ -10,7 +10,7 @@ index 839ea1a81..9cee52263 100644
|
|||||||
sessionId: widget.ffi.sessionId,
|
sessionId: widget.ffi.sessionId,
|
||||||
dragging: _dragging,
|
dragging: _dragging,
|
||||||
fractionX: _fractionX,
|
fractionX: _fractionX,
|
||||||
@@ -2234,6 +2235,7 @@ class RdoMenuButton<T> extends StatelessWidget {
|
@@ -2460,6 +2461,7 @@ class RdoMenuButton<T> extends StatelessWidget {
|
||||||
|
|
||||||
class _DraggableShowHide extends StatefulWidget {
|
class _DraggableShowHide extends StatefulWidget {
|
||||||
final String id;
|
final String id;
|
||||||
@@ -18,7 +18,7 @@ index 839ea1a81..9cee52263 100644
|
|||||||
final SessionID sessionId;
|
final SessionID sessionId;
|
||||||
final RxDouble fractionX;
|
final RxDouble fractionX;
|
||||||
final RxBool dragging;
|
final RxBool dragging;
|
||||||
@@ -2246,6 +2248,7 @@ class _DraggableShowHide extends StatefulWidget {
|
@@ -2472,6 +2474,7 @@ class _DraggableShowHide extends StatefulWidget {
|
||||||
const _DraggableShowHide({
|
const _DraggableShowHide({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -26,7 +26,7 @@ index 839ea1a81..9cee52263 100644
|
|||||||
required this.sessionId,
|
required this.sessionId,
|
||||||
required this.fractionX,
|
required this.fractionX,
|
||||||
required this.dragging,
|
required this.dragging,
|
||||||
@@ -2357,6 +2360,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
|
@@ -2583,6 +2586,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
_buildDraggable(context),
|
_buildDraggable(context),
|
||||||
@@ -34,9 +34,9 @@ index 839ea1a81..9cee52263 100644
|
|||||||
Obx(() => buttonWrapper(
|
Obx(() => buttonWrapper(
|
||||||
() {
|
() {
|
||||||
widget.setFullscreen(!isFullscreen.value);
|
widget.setFullscreen(!isFullscreen.value);
|
||||||
@@ -2463,3 +2467,50 @@ Widget _buildPointerTrackWidget(Widget child, FFI? ffi) {
|
@@ -2742,3 +2746,50 @@ class EdgeThicknessControl extends StatelessWidget {
|
||||||
),
|
return slider;
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+class _CycleMonitorMenu extends StatelessWidget {
|
+class _CycleMonitorMenu extends StatelessWidget {
|
||||||
|
|||||||
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")
|
||||||
69
.github/workflows/build-web.yml
vendored
Normal file
69
.github/workflows/build-web.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
name: Build web
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
FLUTTER_VERSION: "3.24.5"
|
||||||
|
TAG_NAME: "nightly"
|
||||||
|
VERSION: "1.3.9"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-rustdesk-web:
|
||||||
|
name: build-rustdesk-web
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
RELEASE_NAME: web-basic
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Prepare env
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y wget npm
|
||||||
|
|
||||||
|
- name: Install flutter
|
||||||
|
uses: subosito/flutter-action@v2.12.0 #https://github.com/subosito/flutter-action/issues/277
|
||||||
|
with:
|
||||||
|
channel: "stable"
|
||||||
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
|
|
||||||
|
# https://rustdesk.com/docs/en/dev/build/web/
|
||||||
|
- name: Build web
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pushd flutter/web/v2
|
||||||
|
npm install yarn -g
|
||||||
|
npm install typescript -g
|
||||||
|
npm install protoc -g
|
||||||
|
# Install protoc first, see: https://google.github.io/proto-lens/installing-protoc.html
|
||||||
|
npm install ts-proto
|
||||||
|
# Only works with vite <= 2.8, see: https://github.com/vitejs/vite/blob/main/docs/guide/build.md#chunking-strategy
|
||||||
|
npm install vite@2.8
|
||||||
|
yarn install && yarn build
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd flutter/web/v2
|
||||||
|
wget https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/web_deps.tar.gz
|
||||||
|
tar xzf web_deps.tar.gz
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd flutter
|
||||||
|
flutter build web --release
|
||||||
|
cd build
|
||||||
|
#cp ../web/README.md web
|
||||||
|
# TODO: Remove the following line when the web is almost complete.
|
||||||
|
#echo -e "\n\nThis build is for preview and not full functionality." >> web/README.md
|
||||||
|
dir_name="rustdesk-${{ env.VERSION }}-${{ env.RELEASE_NAME }}"
|
||||||
|
mv web "${dir_name}" && tar czf "${dir_name}".tar.gz "${dir_name}"
|
||||||
|
sha256sum "${dir_name}".tar.gz
|
||||||
|
popd
|
||||||
|
|
||||||
|
- name: Upload APK artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: web
|
||||||
|
path: flutter/build/rustdesk-${{ env.VERSION }}-${{ env.RELEASE_NAME }}.tar.gz
|
||||||
3
.github/workflows/docker-build.yml
vendored
3
.github/workflows/docker-build.yml
vendored
@@ -20,6 +20,9 @@ jobs:
|
|||||||
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
|
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
|
||||||
echo "IMAGE_TAG=${{ github.ref_name }}" >> "$GITHUB_ENV"
|
echo "IMAGE_TAG=${{ github.ref_name }}" >> "$GITHUB_ENV"
|
||||||
echo "CREATE_IMAGE=true" >> "$GITHUB_ENV"
|
echo "CREATE_IMAGE=true" >> "$GITHUB_ENV"
|
||||||
|
elif [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
|
||||||
|
echo "IMAGE_TAG=latest" >> "$GITHUB_ENV"
|
||||||
|
echo "CREATE_IMAGE=true" >> "$GITHUB_ENV"
|
||||||
else
|
else
|
||||||
echo "CREATE_IMAGE=false" >> "$GITHUB_ENV"
|
echo "CREATE_IMAGE=false" >> "$GITHUB_ENV"
|
||||||
fi
|
fi
|
||||||
|
|||||||
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
|
||||||
392
.github/workflows/generator-android.yml
vendored
392
.github/workflows/generator-android.yml
vendored
@@ -3,56 +3,16 @@ run-name: Custom Android Client Generator
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
server:
|
version:
|
||||||
description: 'Rendezvous Server'
|
description: 'version to buld'
|
||||||
required: true
|
required: true
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
key:
|
zip_url:
|
||||||
description: 'Public Key'
|
description: 'url to zip of json'
|
||||||
required: true
|
required: true
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
apiServer:
|
|
||||||
description: 'API Server'
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
custom:
|
|
||||||
description: "Custom JSON"
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
uuid:
|
|
||||||
description: "uuid of request"
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
iconlink:
|
|
||||||
description: "icon link"
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
type: string
|
|
||||||
logolink:
|
|
||||||
description: "logo link"
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
type: string
|
|
||||||
appname:
|
|
||||||
description: "app name"
|
|
||||||
required: true
|
|
||||||
default: 'rustdesk'
|
|
||||||
type: string
|
|
||||||
filename:
|
|
||||||
description: "Filename"
|
|
||||||
required: true
|
|
||||||
default: 'rustdesk'
|
|
||||||
type: string
|
|
||||||
extras:
|
|
||||||
description: "extra inputs in json"
|
|
||||||
required: true
|
|
||||||
default: '{}'
|
|
||||||
type: string
|
|
||||||
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -69,8 +29,9 @@ env:
|
|||||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
# vcpkg version: 2024.07.12
|
# vcpkg version: 2024.07.12
|
||||||
VCPKG_COMMIT_ID: "460551b0ec06be1ba6b918448bf3b0f44add813d"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||||
|
VERSION: "${{ inputs.version }}"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r27c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||||
@@ -80,13 +41,18 @@ env:
|
|||||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
setup:
|
||||||
|
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||||
|
with:
|
||||||
|
zip_url_json: ${{ inputs.zip_url }}
|
||||||
|
|
||||||
generate-bridge-linux:
|
generate-bridge-linux:
|
||||||
uses: ./.github/workflows/bridge.yml
|
uses: ./.github/workflows/bridge.yml
|
||||||
with:
|
with:
|
||||||
version: ${{ fromJson(inputs.extras).version }}
|
version: ${{ inputs.version }}
|
||||||
|
|
||||||
build-rustdesk-android:
|
build-rustdesk-android:
|
||||||
needs: [generate-bridge-linux]
|
needs: [generate-bridge-linux, setup]
|
||||||
name: build rustdesk android apk ${{ matrix.job.target }}
|
name: build rustdesk android apk ${{ matrix.job.target }}
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
strategy:
|
strategy:
|
||||||
@@ -115,6 +81,28 @@ jobs:
|
|||||||
suffix: "",
|
suffix: "",
|
||||||
}
|
}
|
||||||
steps:
|
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: Free Disk Space (Ubuntu)
|
- name: Free Disk Space (Ubuntu)
|
||||||
uses: jlumbroso/free-disk-space@main
|
uses: jlumbroso/free-disk-space@main
|
||||||
with:
|
with:
|
||||||
@@ -134,22 +122,14 @@ jobs:
|
|||||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||||
|
|
||||||
- name: Set rdgen value
|
- name: Set rdgen value
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
if: ${{ env.rdgen == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set rdgen value
|
- name: Set rdgen value
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
if: ${{ env.rdgen == 'false' }}
|
||||||
run: |
|
run: |
|
||||||
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV
|
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@@ -167,6 +147,7 @@ jobs:
|
|||||||
libasound2-dev \
|
libasound2-dev \
|
||||||
libc6-dev \
|
libc6-dev \
|
||||||
libclang-dev \
|
libclang-dev \
|
||||||
|
libunwind-dev \
|
||||||
libgstreamer1.0-dev \
|
libgstreamer1.0-dev \
|
||||||
libgstreamer-plugins-base1.0-dev \
|
libgstreamer-plugins-base1.0-dev \
|
||||||
libgtk-3-dev \
|
libgtk-3-dev \
|
||||||
@@ -187,6 +168,11 @@ jobs:
|
|||||||
tree \
|
tree \
|
||||||
wget
|
wget
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y potrace
|
||||||
|
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
if: ${{ env.VERSION != 'master' }}
|
if: ${{ env.VERSION != 'master' }}
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -228,14 +214,6 @@ jobs:
|
|||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
||||||
doNotCache: false
|
doNotCache: false
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}'
|
|
||||||
|
|
||||||
- name: Install vcpkg dependencies
|
- name: Install vcpkg dependencies
|
||||||
run: |
|
run: |
|
||||||
case ${{ matrix.job.target }} in
|
case ${{ matrix.job.target }} in
|
||||||
@@ -281,16 +259,19 @@ jobs:
|
|||||||
prefix-key: rustdesk-lib-cache-android # TODO: drop '-android' part after caches are invalidated
|
prefix-key: rustdesk-lib-cache-android # TODO: drop '-android' part after caches are invalidated
|
||||||
key: ${{ matrix.job.target }}
|
key: ${{ matrix.job.target }}
|
||||||
|
|
||||||
###########################################################echo "${{ inputs.iconbase64 }}" | base64 -d > ./res/icon.png
|
###########################################################echo "${{ env.iconbase64 }}" | base64 -d > ./res/icon.png
|
||||||
- name: icon stuff
|
- name: icon stuff
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: true
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
command: |
|
||||||
mv ./res/icon.ico ./res/icon.ico.bak
|
mv ./res/icon.ico ./res/icon.ico.bak
|
||||||
mv ./res/icon.png ./res/icon.png.bak
|
mv ./res/icon.png ./res/icon.png.bak
|
||||||
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
||||||
wget -O ./res/icon.png ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }}
|
wget -T 30 -t 2 -O ./res/icon.png ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }}
|
||||||
mv ./res/32x32.png ./res/32x32.png.bak
|
mv ./res/32x32.png ./res/32x32.png.bak
|
||||||
mv ./res/64x64.png ./res/64x64.png.bak
|
mv ./res/64x64.png ./res/64x64.png.bak
|
||||||
mv ./res/128x128.png ./res/128x128.png.bak
|
mv ./res/128x128.png ./res/128x128.png.bak
|
||||||
@@ -315,66 +296,75 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs
|
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
|
||||||
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs
|
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
|
||||||
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
|
sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
|
||||||
# ./flutter/pubspec.yaml
|
# ./flutter/pubspec.yaml
|
||||||
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
|
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
|
||||||
|
|
||||||
- name: change appname to custom
|
- name: change appname to custom
|
||||||
if: inputs.appname != 'rustdesk'
|
if: env.appname != 'rustdesk'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml
|
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml
|
||||||
sed -i 's|name = "RustDesk"|name = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i 's|name = "RustDesk"|name = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|"RustDesk Remote Desktop"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc
|
sed -i -e 's|const APP_PREFIX: \&str = "rustdesk";|const APP_PREFIX: \&str = "${{ env.appname }}";|' ./libs/portable/src/main.rs
|
||||||
sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ inputs.appname }}" "\0"|' ./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|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025"|' ./flutter/windows/runner/Runner.rc
|
sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025"|' ./flutter/windows/runner/Runner.rc
|
||||||
sed -i -e 's|"rustdesk.exe"|"${{ inputs.filename }}"|' ./flutter/windows/runner/Runner.rc
|
sed -i -e 's|"rustdesk.exe"|"${{ env.filename }}"|' ./flutter/windows/runner/Runner.rc
|
||||||
sed -i -e 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc
|
sed -i -e 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc
|
||||||
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \;
|
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
|
||||||
sed -i -e 's|RustDesk|${{ inputs.appname }}|' ./flutter/android/app/src/main/res/values/strings.xml
|
sed -i -e 's|RustDesk|${{ env.appname }}|' ./flutter/android/app/src/main/res/values/strings.xml
|
||||||
sed -i -e "s|title: 'RustDesk'|title: '${{ inputs.appname }}'|" ./flutter/lib/main.dart
|
sed -i -e "s|title: 'RustDesk'|title: '${{ env.appname }}'|" ./flutter/lib/main.dart
|
||||||
sed -i -e "s|return 'RustDesk';|return '${{ inputs.appname }}';|" ./flutter/lib/web/bridge.dart
|
sed -i -e "s|return 'RustDesk';|return '${{ env.appname }}';|" ./flutter/lib/web/bridge.dart
|
||||||
sed -i 's|android:label="RustDesk"|android:label="${{ inputs.appname }}"|' ./flutter/android/app/src/main/AndroidManifest.xml
|
sed -i 's|android:label="RustDesk"|android:label="${{ env.appname }}"|' ./flutter/android/app/src/main/AndroidManifest.xml
|
||||||
sed -i 's|android:label="RustDesk Input"|android:label="${{ inputs.appname }} Input"|' ./flutter/android/app/src/main/AndroidManifest.xml
|
sed -i 's|android:label="RustDesk Input"|android:label="${{ env.appname }} Input"|' ./flutter/android/app/src/main/AndroidManifest.xml
|
||||||
sed -i 's|RustDesk is Open|${{ inputs.appname }} is Open|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt
|
sed -i 's|RustDesk is Open|${{ env.appname }} is Open|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt
|
||||||
sed -i 's|Show Rustdesk|Show ${{ inputs.appname }}|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/FloatingWindowService.kt
|
sed -i 's|Show Rustdesk|Show ${{ env.appname }}|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/FloatingWindowService.kt
|
||||||
sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
|
sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
|
||||||
sed -i 's|"RustDesk Service|"${{ inputs.appname }} Service|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
|
sed -i 's|"RustDesk Service|"${{ env.appname }} Service|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
|
||||||
sed -i 's|RustDesk|${{ inputs.appname }}|' ./flutter/lib/main.dart
|
sed -i 's|RustDesk|${{ env.appname }}|' ./flutter/lib/main.dart
|
||||||
sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/lib/desktop/widgets/tabbar_widget.dart
|
sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/lib/desktop/widgets/tabbar_widget.dart
|
||||||
sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./libs/hbb_common/src/config.rs
|
sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./libs/hbb_common/src/config.rs
|
||||||
|
|
||||||
- name: change url to custom
|
- name: change url to custom
|
||||||
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com'
|
if: env.urlLink != 'https://rustdesk.com'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
|
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py
|
||||||
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
|
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
sed -i -e "s|child: Text('rustdesk.com',|child: Text('${{ env.urlLink }}',|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
|
sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
||||||
|
|
||||||
|
- name: change app id to custom
|
||||||
|
if: env.androidappid != 'com.carriez.flutter_hbb'
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sed -i -e 's|com.carriez.flutter_hbb|${{ env.androidappid }}|' ./flutter/android/app/build.gradle
|
||||||
|
|
||||||
- name: change download link to custom
|
- name: change download link to custom
|
||||||
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download'
|
if: env.downloadLink != 'https://rustdesk.com/download'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
|
||||||
|
|
||||||
- name: allow custom.txt
|
- name: allow custom.txt
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -386,48 +376,56 @@ jobs:
|
|||||||
|
|
||||||
- name: fix connection delay
|
- name: fix connection delay
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
if: ${{ env.delayFix == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs
|
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||||
|
|
||||||
- name: add cycle monitors to toolbar
|
- name: add cycle monitors to toolbar
|
||||||
continue-on-error: true
|
if: env.cycleMonitor == 'true'
|
||||||
if: fromJson(inputs.extras).cycleMonitor == 'true'
|
uses: nick-fields/retry@v3
|
||||||
run: |
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: bash
|
||||||
|
continue_on_error: true
|
||||||
|
command: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
|
||||||
git apply cycle_monitor.diff
|
git apply cycle_monitor.diff
|
||||||
|
|
||||||
- name: use X for offline display instead of orange circle
|
- name: use X for offline display instead of orange circle
|
||||||
continue-on-error: true
|
if: env.xOffline == 'true'
|
||||||
if: fromJson(inputs.extras).xOffline == 'true'
|
uses: nick-fields/retry@v3
|
||||||
run: |
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: bash
|
||||||
|
continue_on_error: true
|
||||||
|
command: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
|
||||||
git apply xoffline.diff
|
git apply xoffline.diff
|
||||||
|
|
||||||
- name: hide-cm
|
- name: hide-cm
|
||||||
continue-on-error: true
|
if: env.hidecm == 'true'
|
||||||
if: fromJson(inputs.extras).hidecm == 'true'
|
uses: nick-fields/retry@v3
|
||||||
run: |
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: bash
|
||||||
|
continue_on_error: true
|
||||||
|
command: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
|
||||||
git apply hidecm.diff
|
git apply hidecm.diff
|
||||||
|
|
||||||
- name: removeNewVersionNotif
|
- name: removeNewVersionNotif
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
if: env.removeNewVersionNotif == 'true'
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
|
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "35% complete"}'
|
|
||||||
|
|
||||||
- name: replace flutter icons
|
- name: replace flutter icons
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
run: |
|
run: |
|
||||||
pushd ./flutter
|
pushd ./flutter
|
||||||
flutter pub get
|
flutter pub get
|
||||||
@@ -472,16 +470,8 @@ jobs:
|
|||||||
name: librustdesk.so.${{ matrix.job.target }}
|
name: librustdesk.so.${{ matrix.job.target }}
|
||||||
path: ./target/${{ matrix.job.target }}/release/liblibrustdesk.so
|
path: ./target/${{ matrix.job.target }}/release/liblibrustdesk.so
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "45% complete"}'
|
|
||||||
|
|
||||||
- name: icons
|
- name: icons
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
|
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
|
||||||
@@ -495,6 +485,8 @@ jobs:
|
|||||||
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
|
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
|
||||||
run: |
|
run: |
|
||||||
export PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH
|
export PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH
|
||||||
|
# Increase Gradle JVM memory for CI builds
|
||||||
|
sed -i "s/org.gradle.jvmargs=-Xmx1024M/org.gradle.jvmargs=-Xmx2g/g" ./flutter/android/gradle.properties
|
||||||
# temporary use debug sign config
|
# temporary use debug sign config
|
||||||
sed -i "s/signingConfigs.release/signingConfigs.debug/g" ./flutter/android/app/build.gradle
|
sed -i "s/signingConfigs.release/signingConfigs.debug/g" ./flutter/android/app/build.gradle
|
||||||
case ${{ matrix.job.target }} in
|
case ${{ matrix.job.target }} in
|
||||||
@@ -502,8 +494,8 @@ jobs:
|
|||||||
mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a
|
mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a
|
||||||
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/
|
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/
|
||||||
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
|
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
|
||||||
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
|
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
|
||||||
#sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
|
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
|
||||||
# build flutter
|
# build flutter
|
||||||
pushd flutter
|
pushd flutter
|
||||||
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm64 --split-per-abi
|
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm64 --split-per-abi
|
||||||
@@ -513,8 +505,8 @@ jobs:
|
|||||||
mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
|
mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
|
||||||
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/
|
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/
|
||||||
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so
|
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so
|
||||||
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
|
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
|
||||||
#sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
|
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
|
||||||
# build flutter
|
# build flutter
|
||||||
pushd flutter
|
pushd flutter
|
||||||
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm --split-per-abi
|
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm --split-per-abi
|
||||||
@@ -524,8 +516,8 @@ jobs:
|
|||||||
mkdir -p ./flutter/android/app/src/main/jniLibs/x86_64
|
mkdir -p ./flutter/android/app/src/main/jniLibs/x86_64
|
||||||
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86_64/
|
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86_64/
|
||||||
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86_64/librustdesk.so
|
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86_64/librustdesk.so
|
||||||
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
|
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
|
||||||
#sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
|
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
|
||||||
# build flutter
|
# build flutter
|
||||||
pushd flutter
|
pushd flutter
|
||||||
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x64 --split-per-abi
|
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x64 --split-per-abi
|
||||||
@@ -535,8 +527,8 @@ jobs:
|
|||||||
mkdir -p ./flutter/android/app/src/main/jniLibs/x86
|
mkdir -p ./flutter/android/app/src/main/jniLibs/x86
|
||||||
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86/
|
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86/
|
||||||
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86/librustdesk.so
|
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86/librustdesk.so
|
||||||
echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
|
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt
|
||||||
#sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
|
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml
|
||||||
# build flutter
|
# build flutter
|
||||||
pushd flutter
|
pushd flutter
|
||||||
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x86 --split-per-abi
|
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x86 --split-per-abi
|
||||||
@@ -545,17 +537,9 @@ jobs:
|
|||||||
esac
|
esac
|
||||||
popd
|
popd
|
||||||
mkdir -p signed-apk; pushd signed-apk
|
mkdir -p signed-apk; pushd signed-apk
|
||||||
mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.apk ./${{ inputs.filename }}-${{ matrix.job.arch }}.apk
|
mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.apk ./${{ env.filename }}-${{ matrix.job.arch }}.apk
|
||||||
popd
|
popd
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "75% complete"}'
|
|
||||||
|
|
||||||
- uses: r0adkll/sign-android-release@v1
|
- uses: r0adkll/sign-android-release@v1
|
||||||
name: Sign app APK
|
name: Sign app APK
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -572,39 +556,73 @@ jobs:
|
|||||||
BUILD_TOOLS_VERSION: "30.0.2"
|
BUILD_TOOLS_VERSION: "30.0.2"
|
||||||
|
|
||||||
- name: send file to rdgen server
|
- name: send file to rdgen server
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
if: ${{ env.rdgen == 'true' }}
|
||||||
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
command: |
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./signed-apk/${{ inputs.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
|
|
||||||
- name: send file to api server
|
- name: send file to api server
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
if: ${{ env.rdgen == 'false' }}
|
||||||
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
shell: bash
|
shell: bash
|
||||||
|
command: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" ${{ env.apiServer }}/api/save_custom_client
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: [build-rustdesk-android]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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: Set rdgen value
|
||||||
|
if: ${{ env.rdgen == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./signed-apk/${{ inputs.filename }}-${{ matrix.job.arch }}.apk" ${{ inputs.apiServer }}/api/save_custom_client
|
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Report Status
|
- name: Set rdgen value
|
||||||
uses: fjogeleit/http-request-action@v1
|
if: ${{ env.rdgen == 'false' }}
|
||||||
with:
|
run: |
|
||||||
url: ${{ env.STATUS_URL }}
|
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
|
|
||||||
|
|
||||||
- name: failed
|
- uses: geekyeggo/delete-artifact@v5
|
||||||
if: failure()
|
continue-on-error: true
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
name: ${{ env.filename }}-*.deb
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}'
|
|
||||||
|
|
||||||
- name: failed
|
cleanup:
|
||||||
if: cancelled()
|
needs: [build-rustdesk-android, deploy]
|
||||||
uses: fjogeleit/http-request-action@v1
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
if: always()
|
||||||
|
steps:
|
||||||
|
- name: Delete secrets artifact
|
||||||
|
uses: geekyeggo/delete-artifact@v5
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
name: encrypted-secrets-zip
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'
|
|
||||||
544
.github/workflows/generator-linux.yml
vendored
544
.github/workflows/generator-linux.yml
vendored
@@ -3,56 +3,16 @@ run-name: Custom Linux Client Generator
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
server:
|
version:
|
||||||
description: 'Rendezvous Server'
|
description: 'version to buld'
|
||||||
required: true
|
required: true
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
key:
|
zip_url:
|
||||||
description: 'Public Key'
|
description: 'url to zip of json'
|
||||||
required: true
|
required: true
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
apiServer:
|
|
||||||
description: 'API Server'
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
custom:
|
|
||||||
description: "Custom JSON"
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
uuid:
|
|
||||||
description: "uuid of request"
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
iconlink:
|
|
||||||
description: "icon link"
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
type: string
|
|
||||||
logolink:
|
|
||||||
description: "logo link"
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
type: string
|
|
||||||
appname:
|
|
||||||
description: "app name"
|
|
||||||
required: true
|
|
||||||
default: 'rustdesk'
|
|
||||||
type: string
|
|
||||||
filename:
|
|
||||||
description: "Filename"
|
|
||||||
required: true
|
|
||||||
default: 'rustdesk'
|
|
||||||
type: string
|
|
||||||
extras:
|
|
||||||
description: "extra inputs in json"
|
|
||||||
required: true
|
|
||||||
default: '{}'
|
|
||||||
type: string
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
|
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
|
||||||
@@ -69,8 +29,9 @@ env:
|
|||||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
# vcpkg version: 2024.07.12
|
# vcpkg version: 2024.07.12
|
||||||
VCPKG_COMMIT_ID: "460551b0ec06be1ba6b918448bf3b0f44add813d"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||||
|
VERSION: "${{ inputs.version }}"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r27c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||||
@@ -80,13 +41,18 @@ env:
|
|||||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
setup:
|
||||||
|
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||||
|
with:
|
||||||
|
zip_url_json: ${{ inputs.zip_url }}
|
||||||
|
|
||||||
generate-bridge-linux:
|
generate-bridge-linux:
|
||||||
uses: ./.github/workflows/bridge.yml
|
uses: ./.github/workflows/bridge.yml
|
||||||
with:
|
with:
|
||||||
version: ${{ fromJson(inputs.extras).version }}
|
version: ${{ inputs.version }}
|
||||||
|
|
||||||
build-rustdesk-linux:
|
build-rustdesk-linux:
|
||||||
needs: [generate-bridge-linux]
|
needs: [generate-bridge-linux, setup]
|
||||||
name: build rustdesk linux ${{ matrix.job.target }}
|
name: build rustdesk linux ${{ matrix.job.target }}
|
||||||
runs-on: ${{ matrix.job.on }}
|
runs-on: ${{ matrix.job.on }}
|
||||||
strategy:
|
strategy:
|
||||||
@@ -98,7 +64,7 @@ jobs:
|
|||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
distro: ubuntu18.04,
|
distro: ubuntu18.04,
|
||||||
on: ubuntu-20.04,
|
on: ubuntu-22.04,
|
||||||
deb_arch: amd64,
|
deb_arch: amd64,
|
||||||
vcpkg-triplet: x64-linux,
|
vcpkg-triplet: x64-linux,
|
||||||
}
|
}
|
||||||
@@ -111,6 +77,18 @@ jobs:
|
|||||||
vcpkg-triplet: arm64-linux,
|
vcpkg-triplet: arm64-linux,
|
||||||
}
|
}
|
||||||
steps:
|
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: Export GitHub Actions cache environment variables
|
- name: Export GitHub Actions cache environment variables
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
@@ -119,22 +97,14 @@ jobs:
|
|||||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||||
|
|
||||||
- name: Set rdgen value
|
- name: Set rdgen value
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
if: ${{ env.rdgen == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set rdgen value
|
- name: Set rdgen value
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
if: ${{ env.rdgen == 'false' }}
|
||||||
run: |
|
run: |
|
||||||
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV
|
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
|
|
||||||
|
|
||||||
- name: Maximize build space
|
- name: Maximize build space
|
||||||
run: |
|
run: |
|
||||||
@@ -196,14 +166,6 @@ jobs:
|
|||||||
# only build cdylib
|
# only build cdylib
|
||||||
sed -i "s/\[\"cdylib\", \"staticlib\", \"rlib\"\]/\[\"cdylib\"\]/g" Cargo.toml
|
sed -i "s/\[\"cdylib\", \"staticlib\", \"rlib\"\]/\[\"cdylib\"\]/g" Cargo.toml
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}'
|
|
||||||
|
|
||||||
- name: Restore bridge files
|
- name: Restore bridge files
|
||||||
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
||||||
uses: actions/download-artifact@master
|
uses: actions/download-artifact@master
|
||||||
@@ -222,7 +184,7 @@ jobs:
|
|||||||
- name: Install vcpkg dependencies
|
- name: Install vcpkg dependencies
|
||||||
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
||||||
run: |
|
run: |
|
||||||
sudo apt install -y libva-dev libvdpau-dev
|
sudo apt install -y libva-dev && apt show libva-dev
|
||||||
if ! $VCPKG_ROOT/vcpkg \
|
if ! $VCPKG_ROOT/vcpkg \
|
||||||
install \
|
install \
|
||||||
--triplet ${{ matrix.job.vcpkg-triplet }} \
|
--triplet ${{ matrix.job.vcpkg-triplet }} \
|
||||||
@@ -240,14 +202,17 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: icon stuff
|
- name: icon stuff
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: true
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
command: |
|
||||||
mv ./res/icon.ico ./res/icon.ico.bak
|
mv ./res/icon.ico ./res/icon.ico.bak
|
||||||
mv ./res/icon.png ./res/icon.png.bak
|
mv ./res/icon.png ./res/icon.png.bak
|
||||||
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
|
||||||
wget -O ./res/icon.png ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }}
|
wget -O ./res/icon.png ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }}
|
||||||
mv ./res/32x32.png ./res/32x32.png.bak
|
mv ./res/32x32.png ./res/32x32.png.bak
|
||||||
mv ./res/64x64.png ./res/64x64.png.bak
|
mv ./res/64x64.png ./res/64x64.png.bak
|
||||||
mv ./res/128x128.png ./res/128x128.png.bak
|
mv ./res/128x128.png ./res/128x128.png.bak
|
||||||
@@ -265,99 +230,116 @@ jobs:
|
|||||||
b64=""
|
b64=""
|
||||||
|
|
||||||
- name: change appname to custom
|
- name: change appname to custom
|
||||||
if: inputs.appname != 'rustdesk'
|
if: env.appname != 'rustdesk'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml
|
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml
|
||||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml
|
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml
|
||||||
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml
|
||||||
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml
|
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml
|
||||||
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \;
|
sed -i -e 's|const APP_PREFIX: \&str = "rustdesk";|const APP_PREFIX: \&str = "${{ env.appname }}";|' ./libs/portable/src/main.rs
|
||||||
|
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \;
|
||||||
sed -i -e '/-p tmpdeb\/usr\/lib\/rustdesk/d' ./build.py
|
sed -i -e '/-p tmpdeb\/usr\/lib\/rustdesk/d' ./build.py
|
||||||
|
|
||||||
- name: change company name
|
- name: change company name
|
||||||
if: fromJson(inputs.extras).compname != 'Purslane Ltd'
|
if: env.compname != 'Purslane Ltd'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./Cargo.toml
|
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml
|
||||||
sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./libs/portable/Cargo.toml
|
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml
|
||||||
|
|
||||||
- name: allow custom.txt
|
- name: allow custom.txt
|
||||||
continue-on-error: true
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
command: |
|
||||||
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs
|
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
|
||||||
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs
|
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.py
|
||||||
git apply allowCustom.diff
|
python allowCustom.py
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
|
||||||
git apply removeSetupServerTip.diff
|
git apply removeSetupServerTip.diff
|
||||||
echo -n "${{ inputs.custom }}" | cat > ./custom.txt
|
echo -n "${{ env.custom }}" | cat > ./custom_.txt
|
||||||
# sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
|
# sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
|
||||||
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
|
sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
|
||||||
|
|
||||||
- name: change url to custom
|
- name: change url to custom
|
||||||
if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com'
|
if: env.urlLink != 'https://rustdesk.com'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
|
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py
|
||||||
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
|
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
||||||
|
|
||||||
- name: change download link to custom
|
- name: change download link to custom
|
||||||
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download'
|
if: env.downloadLink != 'https://rustdesk.com/download'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
|
||||||
|
|
||||||
- name: fix connection delay
|
- name: fix connection delay
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
if: ${{ env.delayFix == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs
|
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||||
|
|
||||||
- name: add cycle monitors to toolbar
|
- name: add cycle monitors to toolbar
|
||||||
continue-on-error: true
|
if: env.cycleMonitor == 'true'
|
||||||
if: fromJson(inputs.extras).cycleMonitor == 'true'
|
uses: nick-fields/retry@v3
|
||||||
run: |
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: bash
|
||||||
|
command: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
|
||||||
git apply cycle_monitor.diff
|
git apply cycle_monitor.diff
|
||||||
|
|
||||||
- name: use X for offline display instead of orange circle
|
- name: use X for offline display instead of orange circle
|
||||||
continue-on-error: true
|
if: env.xOffline == 'true'
|
||||||
if: fromJson(inputs.extras).xOffline == 'true'
|
uses: nick-fields/retry@v3
|
||||||
run: |
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: bash
|
||||||
|
command: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
|
||||||
git apply xoffline.diff
|
git apply xoffline.diff
|
||||||
|
|
||||||
- name: hide-cm
|
- name: hide-cm
|
||||||
continue-on-error: true
|
if: env.hidecm == 'true'
|
||||||
if: fromJson(inputs.extras).hidecm == 'true'
|
uses: nick-fields/retry@v3
|
||||||
run: |
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: bash
|
||||||
|
command: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
|
||||||
git apply hidecm.diff
|
git apply hidecm.diff
|
||||||
|
|
||||||
- name: removeNewVersionNotif
|
- name: removeNewVersionNotif
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
if: env.removeNewVersionNotif == 'true'
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
|
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||||
|
|
||||||
- name: Restore bridge files
|
- name: Restore bridge files
|
||||||
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
||||||
@@ -366,14 +348,6 @@ jobs:
|
|||||||
name: bridge-artifact
|
name: bridge-artifact
|
||||||
path: ./
|
path: ./
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "65% complete"}'
|
|
||||||
|
|
||||||
- uses: rustdesk-org/run-on-arch-action@amd64-support
|
- uses: rustdesk-org/run-on-arch-action@amd64-support
|
||||||
name: Build rustdesk
|
name: Build rustdesk
|
||||||
id: vcpkg
|
id: vcpkg
|
||||||
@@ -403,20 +377,19 @@ jobs:
|
|||||||
imagemagick \
|
imagemagick \
|
||||||
libayatana-appindicator3-dev \
|
libayatana-appindicator3-dev \
|
||||||
libasound2-dev \
|
libasound2-dev \
|
||||||
libclang-dev \
|
libclang-10-dev \
|
||||||
libgstreamer1.0-dev \
|
libgstreamer1.0-dev \
|
||||||
libgstreamer-plugins-base1.0-dev \
|
libgstreamer-plugins-base1.0-dev \
|
||||||
libgtk-3-dev \
|
libgtk-3-dev \
|
||||||
libpam0g-dev \
|
libpam0g-dev \
|
||||||
libpulse-dev \
|
libpulse-dev \
|
||||||
libva-dev \
|
libva-dev \
|
||||||
libvdpau-dev \
|
|
||||||
libxcb-randr0-dev \
|
libxcb-randr0-dev \
|
||||||
libxcb-shape0-dev \
|
libxcb-shape0-dev \
|
||||||
libxcb-xfixes0-dev \
|
libxcb-xfixes0-dev \
|
||||||
libxdo-dev \
|
libxdo-dev \
|
||||||
libxfixes-dev \
|
libxfixes-dev \
|
||||||
llvm-dev \
|
llvm-10-dev \
|
||||||
nasm \
|
nasm \
|
||||||
ninja-build \
|
ninja-build \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
@@ -425,7 +398,8 @@ jobs:
|
|||||||
rpm \
|
rpm \
|
||||||
unzip \
|
unzip \
|
||||||
wget \
|
wget \
|
||||||
xz-utils
|
xz-utils \
|
||||||
|
libssl-dev
|
||||||
# we have libopus compiled by us.
|
# we have libopus compiled by us.
|
||||||
apt-get remove -y libopus-dev || true
|
apt-get remove -y libopus-dev || true
|
||||||
# output devs
|
# output devs
|
||||||
@@ -517,11 +491,11 @@ jobs:
|
|||||||
export CARGO_INCREMENTAL=0
|
export CARGO_INCREMENTAL=0
|
||||||
export DEB_ARCH=${{ matrix.job.deb_arch }}
|
export DEB_ARCH=${{ matrix.job.deb_arch }}
|
||||||
mkdir -p flutter/tmpdeb/usr/share/rustdesk
|
mkdir -p flutter/tmpdeb/usr/share/rustdesk
|
||||||
cp ./custom.txt ./flutter/tmpdeb/usr/share/rustdesk/custom.txt
|
cp ./custom_.txt ./flutter/tmpdeb/usr/share/rustdesk/custom_.txt
|
||||||
if [[ "${{ inputs.logolink }}" != "false" ]]; then
|
if [[ "${{ env.logolink_url }}" != "false" ]]; then
|
||||||
wget -O ./flutter/assets/logo.png ${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}"&"uuid=${{ fromJson(inputs.logolink).uuid }}
|
wget -O ./flutter/assets/logo.png ${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}"&"uuid=${{ env.logolink_uuid }}
|
||||||
fi
|
fi
|
||||||
if [[ "${{ inputs.iconlink }}" != "false" ]]; then
|
if [[ "${{ env.iconlink_url }}" != "false" ]]; then
|
||||||
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
|
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
|
||||||
convert ./res/icon.png ./flutter/assets/icon.svg
|
convert ./res/icon.png ./flutter/assets/icon.svg
|
||||||
convert ./res/128x128.png -resize 200% ./flutter/assets/128x128@2x.png || true
|
convert ./res/128x128.png -resize 200% ./flutter/assets/128x128@2x.png || true
|
||||||
@@ -536,7 +510,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
python3 ./build.py --flutter --skip-cargo
|
python3 ./build.py --flutter --skip-cargo
|
||||||
for name in rustdesk*??.deb; do
|
for name in rustdesk*??.deb; do
|
||||||
mv "$name" /workspace/output/"${{ inputs.filename }}-${{ matrix.job.arch }}.deb"
|
mv "$name" /workspace/output/"${{ env.filename }}-${{ matrix.job.arch }}.deb"
|
||||||
done
|
done
|
||||||
|
|
||||||
# rpm package
|
# rpm package
|
||||||
@@ -550,7 +524,7 @@ jobs:
|
|||||||
HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
|
HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
|
||||||
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
|
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
|
||||||
for name in rustdesk*??.rpm; do
|
for name in rustdesk*??.rpm; do
|
||||||
mv "$name" /workspace/output/"${{ inputs.filename }}-${{ matrix.job.arch }}.rpm"
|
mv "$name" /workspace/output/"${{ env.filename }}-${{ matrix.job.arch }}.rpm"
|
||||||
done
|
done
|
||||||
|
|
||||||
# rpm suse package
|
# rpm suse package
|
||||||
@@ -564,7 +538,7 @@ jobs:
|
|||||||
HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb
|
HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb
|
||||||
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
|
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
|
||||||
for name in rustdesk*??.rpm; do
|
for name in rustdesk*??.rpm; do
|
||||||
mv "$name" /workspace/output/"${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm"
|
mv "$name" /workspace/output/"${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm"
|
||||||
done
|
done
|
||||||
|
|
||||||
# only x86_64 for arch since we can not find newest arm64 docker image to build
|
# only x86_64 for arch since we can not find newest arm64 docker image to build
|
||||||
@@ -592,60 +566,282 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: matrix.job.arch == 'x86_64' && env.UPLOAD_ARTIFACT == 'true' && env.VERSION != 'master'
|
if: matrix.job.arch == 'x86_64' && env.UPLOAD_ARTIFACT == 'true' && env.VERSION != 'master'
|
||||||
run: |
|
run: |
|
||||||
cp ./res/rustdesk-${{ env.VERSION }}-0-x86_64.pkg.tar.zst ./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst
|
cp ./res/rustdesk-${{ env.VERSION }}-0-x86_64.pkg.tar.zst ./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst
|
||||||
|
|
||||||
- name: send file to rdgen server
|
- name: send file to rdgen server
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
if: ${{ env.rdgen == 'true' }}
|
||||||
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
command: |
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
|
||||||
|
|
||||||
- name: send file to api server
|
- name: send file to api server
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
if: ${{ env.rdgen == 'false' }}
|
||||||
|
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=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" ${{ env.apiServer }}/api/save_custom_client
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ env.apiServer }}/api/save_custom_client || true
|
||||||
|
|
||||||
|
- name: Upload deb
|
||||||
|
uses: actions/upload-artifact@master
|
||||||
|
if: env.UPLOAD_ARTIFACT == 'true'
|
||||||
|
with:
|
||||||
|
name: ${{ env.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
path: ./output/${{ env.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
|
||||||
|
build-appimage:
|
||||||
|
name: Build appimage ${{ matrix.job.target }}
|
||||||
|
needs: [build-rustdesk-linux]
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { target: x86_64-unknown-linux-gnu, arch: x86_64 }
|
||||||
|
- { target: aarch64-unknown-linux-gnu, 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: 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: Download Binary
|
||||||
|
uses: actions/download-artifact@master
|
||||||
|
with:
|
||||||
|
name: ${{ env.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Rename Binary
|
||||||
|
run: |
|
||||||
|
mv ${{ env.filename }}-${{ matrix.job.arch }}.deb appimage/rustdesk.deb
|
||||||
|
|
||||||
|
- name: Build appimage package
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb" ${{ inputs.apiServer }}/api/save_custom_client
|
# install libarchive-tools for bsdtar command used in AppImageBuilder.yml
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client
|
sudo apt-get update -y
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client
|
sudo apt-get install -y libarchive-tools libfuse2
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ inputs.apiServer }}/api/save_custom_client || true
|
# set-up appimage-builder
|
||||||
|
sudo pip3 install git+https://github.com/rustdesk-org/appimage-builder.git
|
||||||
|
# run appimage-builder
|
||||||
|
pushd appimage
|
||||||
|
sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml
|
||||||
|
sudo mv ./rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.AppImage ./${{ env.filename }}-${{ matrix.job.arch }}.AppImage
|
||||||
|
|
||||||
- name: Report Status
|
- name: send file to rdgen server
|
||||||
uses: fjogeleit/http-request-action@v1
|
if: ${{ env.rdgen == 'true' }}
|
||||||
|
uses: nick-fields/retry@v3
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
timeout_minutes: 1
|
||||||
method: 'POST'
|
max_attempts: 3
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
shell: bash
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Finished ${{ matrix.job.arch }}"}'
|
command: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
|
|
||||||
- name: failed
|
- name: send file to api server
|
||||||
if: failure()
|
if: ${{ env.rdgen == 'false' }}
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: nick-fields/retry@v3
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
timeout_minutes: 1
|
||||||
method: 'POST'
|
max_attempts: 3
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
shell: bash
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}'
|
command: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" ${{ env.apiServer }}/api/save_custom_client
|
||||||
|
|
||||||
- name: failed
|
build-flatpak:
|
||||||
if: cancelled()
|
name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }}
|
||||||
uses: fjogeleit/http-request-action@v1
|
needs:
|
||||||
|
- build-rustdesk-linux
|
||||||
|
runs-on: ${{ matrix.job.on }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- {
|
||||||
|
target: x86_64-unknown-linux-gnu,
|
||||||
|
distro: ubuntu18.04,
|
||||||
|
on: ubuntu-22.04,
|
||||||
|
arch: x86_64,
|
||||||
|
suffix: "",
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
target: aarch64-unknown-linux-gnu,
|
||||||
|
# try out newer flatpak since error of "error: Nothing matches org.freedesktop.Platform in remote flathub"
|
||||||
|
distro: ubuntu22.04,
|
||||||
|
on: ubuntu-22.04-arm,
|
||||||
|
arch: aarch64,
|
||||||
|
suffix: "",
|
||||||
|
}
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
name: encrypted-secrets-zip
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
- name: Load Secrets
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'
|
uses: ./.github/actions/decrypt-secrets
|
||||||
|
with:
|
||||||
|
zip_password: ${{ secrets.ZIP_PASSWORD }}
|
||||||
|
|
||||||
|
- 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: Download Binary
|
||||||
|
uses: actions/download-artifact@master
|
||||||
|
with:
|
||||||
|
name: ${{ env.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Rename Binary
|
||||||
|
run: |
|
||||||
|
mv ${{ env.filename }}-${{ matrix.job.arch }}.deb flatpak/rustdesk.deb
|
||||||
|
|
||||||
|
- uses: rustdesk-org/run-on-arch-action@amd64-support
|
||||||
|
name: Build rustdesk flatpak package for ${{ matrix.job.arch }}
|
||||||
|
continue-on-error: true
|
||||||
|
timeout-minutes: 30
|
||||||
|
id: flatpak
|
||||||
|
with:
|
||||||
|
arch: ${{ matrix.job.arch }}
|
||||||
|
distro: ${{ matrix.job.distro }}
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
setup: |
|
||||||
|
ls -l "${PWD}"
|
||||||
|
dockerRunArgs: |
|
||||||
|
--volume "${PWD}:/workspace"
|
||||||
|
shell: /bin/bash
|
||||||
|
install: |
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y git flatpak flatpak-builder
|
||||||
|
run: |
|
||||||
|
# disable git safe.directory
|
||||||
|
git config --global --add safe.directory "*"
|
||||||
|
pushd /workspace
|
||||||
|
# flatpak deps
|
||||||
|
flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
# package
|
||||||
|
pushd flatpak
|
||||||
|
git clone https://github.com/flathub/shared-modules.git --depth=1
|
||||||
|
flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json
|
||||||
|
flatpak build-bundle ./repo ${{ env.filename }}-${{ matrix.job.arch }}.flatpak com.rustdesk.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=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
|
|
||||||
|
- 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=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" ${{ env.apiServer }}/api/save_custom_client
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
needs: build-rustdesk-linux
|
needs: [build-rustdesk-linux,build-flatpak,build-appimage]
|
||||||
|
if: always()
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Report Status
|
- 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
|
uses: fjogeleit/http-request-action@v1
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: "${{ secrets.GENURL }}/cleanzip"
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
|
data: '{"uuid": "${{ env.uuid }}"}'
|
||||||
|
|
||||||
|
- name: Set rdgen value
|
||||||
|
if: ${{ env.rdgen == 'true' }}
|
||||||
|
run: |
|
||||||
|
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set rdgen value
|
||||||
|
if: ${{ env.rdgen == 'false' }}
|
||||||
|
run: |
|
||||||
|
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: geekyeggo/delete-artifact@v5
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
name: ${{ env.filename }}-*.deb
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
needs: [build-rustdesk-linux,build-flatpak,build-appimage,deploy]
|
||||||
|
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
|
||||||
|
|||||||
423
.github/workflows/generator-macos.yml
vendored
423
.github/workflows/generator-macos.yml
vendored
@@ -3,56 +3,16 @@ run-name: Custom macOS Client Generator
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
server:
|
version:
|
||||||
description: 'Rendezvous Server'
|
description: 'version to buld'
|
||||||
required: true
|
required: true
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
key:
|
zip_url:
|
||||||
description: 'Public Key'
|
description: 'url to zip of json'
|
||||||
required: true
|
required: true
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
apiServer:
|
|
||||||
description: 'API Server'
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
custom:
|
|
||||||
description: "Custom JSON"
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
uuid:
|
|
||||||
description: "uuid of request"
|
|
||||||
required: true
|
|
||||||
default: ''
|
|
||||||
type: string
|
|
||||||
iconlink:
|
|
||||||
description: "icon link"
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
type: string
|
|
||||||
logolink:
|
|
||||||
description: "logo link"
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
type: string
|
|
||||||
appname:
|
|
||||||
description: "app name"
|
|
||||||
required: true
|
|
||||||
default: 'rustdesk'
|
|
||||||
type: string
|
|
||||||
filename:
|
|
||||||
description: "Filename"
|
|
||||||
required: true
|
|
||||||
default: 'rustdesk'
|
|
||||||
type: string
|
|
||||||
extras:
|
|
||||||
description: "extra inputs in json"
|
|
||||||
required: true
|
|
||||||
default: '{}'
|
|
||||||
type: string
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
|
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
|
||||||
@@ -69,47 +29,76 @@ env:
|
|||||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
# vcpkg version: 2024.07.12
|
# vcpkg version: 2024.07.12
|
||||||
VCPKG_COMMIT_ID: "460551b0ec06be1ba6b918448bf3b0f44add813d"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||||
|
VERSION: "${{ inputs.version }}"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r27c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||||
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
||||||
UPLOAD_ARTIFACT: 'true'
|
UPLOAD_ARTIFACT: 'true'
|
||||||
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}"
|
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}"
|
||||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
setup:
|
||||||
|
uses: ./.github/workflows/fetch-encrypted-secrets.yml
|
||||||
|
with:
|
||||||
|
zip_url_json: ${{ inputs.zip_url }}
|
||||||
|
|
||||||
generate-bridge:
|
generate-bridge:
|
||||||
uses: ./.github/workflows/bridge.yml
|
uses: ./.github/workflows/bridge.yml
|
||||||
with:
|
with:
|
||||||
version: ${{ fromJson(inputs.extras).version }}
|
version: ${{ inputs.version }}
|
||||||
|
|
||||||
build-for-macos-flutter:
|
build-for-macos:
|
||||||
name: Build macOS
|
name: ${{ matrix.job.target }}
|
||||||
runs-on: macos-latest
|
runs-on: ${{ matrix.job.os }}
|
||||||
needs: [generate-bridge]
|
needs: [generate-bridge, setup]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
- {
|
- {
|
||||||
target: x86_64-apple-darwin,
|
target: x86_64-apple-darwin,
|
||||||
os: macos-13, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel
|
os: macos-15-intel, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel
|
||||||
extra-build-args: "",
|
extra-build-args: "",
|
||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
vcpkg-triplet: x64-osx,
|
vcpkg-triplet: x64-osx,
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
target: aarch64-apple-darwin,
|
target: aarch64-apple-darwin,
|
||||||
os: macos-latest,
|
os: macos-14,
|
||||||
# extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
# extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
||||||
extra-build-args: "--screencapturekit",
|
extra-build-args: "--screencapturekit",
|
||||||
arch: aarch64,
|
arch: aarch64,
|
||||||
vcpkg-triplet: arm64-osx,
|
vcpkg-triplet: arm64-osx,
|
||||||
}
|
}
|
||||||
|
env:
|
||||||
|
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
||||||
|
|
||||||
steps:
|
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
|
- name: Export GitHub Actions cache environment variables
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v6
|
||||||
with:
|
with:
|
||||||
@@ -117,24 +106,6 @@ jobs:
|
|||||||
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
||||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||||
|
|
||||||
- name: Set rdgen value
|
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
|
||||||
run: |
|
|
||||||
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set rdgen value
|
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
|
||||||
run: |
|
|
||||||
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $env:GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
|
|
||||||
|
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
if: ${{ env.VERSION != 'master' }}
|
if: ${{ env.VERSION != 'master' }}
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -150,12 +121,6 @@ jobs:
|
|||||||
repository: rustdesk/rustdesk
|
repository: rustdesk/rustdesk
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Restore bridge files
|
|
||||||
uses: actions/download-artifact@master
|
|
||||||
with:
|
|
||||||
name: bridge-artifact
|
|
||||||
path: ./
|
|
||||||
|
|
||||||
- name: Install imagemagick and potrace and nasm and and
|
- name: Install imagemagick and potrace and nasm and and
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -172,76 +137,76 @@ jobs:
|
|||||||
cp ./flutter/macos/Runner/Configs/AppInfo.xcconfig ./flutter/macos/Runner/Configs/AppInfo.xcconfig.bak
|
cp ./flutter/macos/Runner/Configs/AppInfo.xcconfig ./flutter/macos/Runner/Configs/AppInfo.xcconfig.bak
|
||||||
|
|
||||||
# MACSTUFF Update Info.plist
|
# MACSTUFF Update Info.plist
|
||||||
sed -i '' -e 's|<key>CFBundleName</key>.*<string>.*</string>|<key>CFBundleName</key>\n\t<string>${{ inputs.appname }}</string>|' ./flutter/macos/Runner/Info.plist
|
sed -i '' -e 's|<key>CFBundleName</key>.*<string>.*</string>|<key>CFBundleName</key>\n\t<string>${{ env.appname }}</string>|' ./flutter/macos/Runner/Info.plist
|
||||||
sed -i '' -e 's|<key>CFBundleDisplayName</key>.*<string>.*</string>|<key>CFBundleDisplayName</key>\n\t<string>${{ inputs.appname }}</string>|' ./flutter/macos/Runner/Info.plist
|
sed -i '' -e 's|<key>CFBundleDisplayName</key>.*<string>.*</string>|<key>CFBundleDisplayName</key>\n\t<string>${{ env.appname }}</string>|' ./flutter/macos/Runner/Info.plist
|
||||||
sed -i '' -e 's|<key>CFBundleIdentifier</key>.*<string>.*</string>|<key>CFBundleIdentifier</key>\n\t<string>com.${{ inputs.appname }}.app</string>|' ./flutter/macos/Runner/Info.plist
|
sed -i '' -e 's|<key>CFBundleIdentifier</key>.*<string>.*</string>|<key>CFBundleIdentifier</key>\n\t<string>com.${{ env.appname }}.app</string>|' ./flutter/macos/Runner/Info.plist
|
||||||
# sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ inputs.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
|
# sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ env.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
|
||||||
|
|
||||||
# MACSTUFF Update AppInfo.xcconfig
|
# MACSTUFF Update AppInfo.xcconfig
|
||||||
sed -i '' -e 's|PRODUCT_NAME = .*|PRODUCT_NAME = ${{ inputs.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
|
sed -i '' -e 's|PRODUCT_NAME = .*|PRODUCT_NAME = ${{ env.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
|
||||||
sed -i '' -e 's|PRODUCT_BUNDLE_IDENTIFIER = .*|PRODUCT_BUNDLE_IDENTIFIER = com.${{ inputs.appname }}.app|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
|
sed -i '' -e 's|PRODUCT_BUNDLE_IDENTIFIER = .*|PRODUCT_BUNDLE_IDENTIFIER = com.${{ env.appname }}.app|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
|
||||||
sed -i '' -e 's|Purslane Ltd.|${{ inputs.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
|
sed -i '' -e 's|Purslane Ltd.|${{ env.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
|
||||||
# Keep DEVELOPMENT_TEAM if it exists, don't blank it out
|
# Keep DEVELOPMENT_TEAM if it exists, don't blank it out
|
||||||
|
|
||||||
sed -i -e 's|Purslane Ltd.|${{ inputs.appname }}|' ./Cargo.toml
|
sed -i -e 's|Purslane Ltd.|${{ env.appname }}|' ./Cargo.toml
|
||||||
sed -i -e 's|Purslane Ltd|${{ inputs.appname }}|' ./libs/portable/Cargo.toml
|
sed -i -e 's|Purslane Ltd|${{ env.appname }}|' ./libs/portable/Cargo.toml
|
||||||
|
|
||||||
# Update Xcode project settings
|
# Update Xcode project settings
|
||||||
sed -i '' -e 's/PRODUCT_NAME = "RustDesk"/PRODUCT_NAME = "${{ inputs.appname }}"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
|
sed -i '' -e 's/PRODUCT_NAME = "RustDesk"/PRODUCT_NAME = "${{ env.appname }}"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
|
||||||
sed -i '' -e 's/PRODUCT_BUNDLE_IDENTIFIER = ".*"/PRODUCT_BUNDLE_IDENTIFIER = "com.${{ inputs.appname }}.app"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
|
sed -i '' -e 's/PRODUCT_BUNDLE_IDENTIFIER = ".*"/PRODUCT_BUNDLE_IDENTIFIER = "com.${{ env.appname }}.app"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
|
||||||
# Don't modify DEVELOPMENT_TEAM in project.pbxproj
|
# Don't modify DEVELOPMENT_TEAM in project.pbxproj
|
||||||
|
|
||||||
# Update CMake settings
|
# Update CMake settings
|
||||||
if [ -f "./flutter/macos/CMakeLists.txt" ]; then
|
if [ -f "./flutter/macos/CMakeLists.txt" ]; then
|
||||||
sed -i '' -e 's/set(BINARY_NAME ".*")/set(BINARY_NAME "${{ inputs.appname }}")/' ./flutter/macos/CMakeLists.txt
|
sed -i '' -e 's/set(BINARY_NAME ".*")/set(BINARY_NAME "${{ env.appname }}")/' ./flutter/macos/CMakeLists.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Update Podfile - keep the target as 'Runner'
|
# Update Podfile - keep the target as 'Runner'
|
||||||
# sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'${{ inputs.appname }}'"'"' do/' ./flutter/macos/Podfile
|
# sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'${{ env.appname }}'"'"' do/' ./flutter/macos/Podfile
|
||||||
sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'Runner'"'"' do/' ./flutter/macos/Podfile
|
sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'Runner'"'"' do/' ./flutter/macos/Podfile
|
||||||
|
|
||||||
cp ./src/lang/en.rs ./src/lang/en.rs.bak
|
cp ./src/lang/en.rs ./src/lang/en.rs.bak
|
||||||
cp ./src/lang/nl.rs ./src/lang/nl.rs.bak
|
cp ./src/lang/nl.rs ./src/lang/nl.rs.bak
|
||||||
find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' {} \;
|
find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ env.appname }}|' {} \;
|
||||||
sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' ./src/lang/nl.rs
|
sed -i '' -e 's|RustDesk|${{ env.appname }}|' ./src/lang/nl.rs
|
||||||
|
|
||||||
sed -i '' -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
|
sed -i '' -e 's|https://rustdesk.com|${{ env.urlLink }}|' ./build.py
|
||||||
sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
|
sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart
|
||||||
sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i '' -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i '' -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i '' -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
sed -i '' -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
||||||
|
|
||||||
- name: change download link to custom
|
- name: change download link to custom
|
||||||
if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download'
|
if: env.downloadLink != 'https://rustdesk.com/download'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
|
||||||
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
|
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis
|
||||||
|
|
||||||
# Update slogan
|
# Update slogan
|
||||||
#sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ inputs.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
|
#sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ env.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
|
||||||
|
|
||||||
# Update slogan - About in en.rs
|
# Update slogan - About in en.rs
|
||||||
sed -i '' -e 's/("Slogan_tip", "Made with heart in this chaotic world!")/("Slogan_tip", "Powered by ${{ inputs.appname }}")/' ./src/lang/en.rs
|
sed -i '' -e 's/("Slogan_tip", "Made with heart in this chaotic world!")/("Slogan_tip", "Powered by ${{ env.appname }}")/' ./src/lang/en.rs
|
||||||
sed -i '' -e 's/("About RustDesk", "")/("About RustDesk", "About ${{ inputs.appname }}")/' ./src/lang/en.rs
|
sed -i '' -e 's/("About RustDesk", "")/("About RustDesk", "About ${{ env.appname }}")/' ./src/lang/en.rs
|
||||||
|
|
||||||
|
|
||||||
# Update slogan - About in nl.rs
|
# Update slogan - About in nl.rs
|
||||||
sed -i '' -e 's/("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!")/("Slogan_tip", "Powered by ${{ inputs.appname }}")/' ./src/lang/nl.rs
|
sed -i '' -e 's/("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!")/("Slogan_tip", "Powered by ${{ env.appname }}")/' ./src/lang/nl.rs
|
||||||
sed -i '' -e 's/("Your Desktop", "Uw Bureaublad")/("Your Desktop", "Uw ${{ inputs.appname }}")/' ./src/lang/nl.rs
|
sed -i '' -e 's/("Your Desktop", "Uw Bureaublad")/("Your Desktop", "Uw ${{ env.appname }}")/' ./src/lang/nl.rs
|
||||||
sed -i '' -e 's/("About RustDesk", "Over RustDesk")/("About RustDesk", "Over ${{ inputs.appname }}")/' ./src/lang/nl.rs
|
sed -i '' -e 's/("About RustDesk", "Over RustDesk")/("About RustDesk", "Over ${{ env.appname }}")/' ./src/lang/nl.rs
|
||||||
sed -i '' -e 's/("About", "Over")/("About", "Over ${{ inputs.appname }}")/' ./src/lang/nl.rs
|
sed -i '' -e 's/("About", "Over")/("About", "Over ${{ env.appname }}")/' ./src/lang/nl.rs
|
||||||
|
|
||||||
sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs
|
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs
|
||||||
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs
|
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs
|
||||||
sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
|
sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs
|
||||||
|
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.py
|
||||||
git apply allowCustom.diff
|
python allowCustom.py
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
|
||||||
git apply removeSetupServerTip.diff
|
git apply removeSetupServerTip.diff
|
||||||
|
|
||||||
@@ -252,33 +217,44 @@ jobs:
|
|||||||
mv ./flutter/pubspec.yaml.tmp ./flutter/pubspec.yaml
|
mv ./flutter/pubspec.yaml.tmp ./flutter/pubspec.yaml
|
||||||
rm ./flutter/temp_dependency.txt
|
rm ./flutter/temp_dependency.txt
|
||||||
|
|
||||||
- name: Report Status
|
- name: Install build runtime
|
||||||
uses: fjogeleit/http-request-action@v1
|
run: |
|
||||||
with:
|
brew install llvm create-dmg
|
||||||
url: ${{ env.STATUS_URL }}
|
# pkg-config is handled in a separate step, because it may be already installed by `macos-latest`(14.7.1) runner
|
||||||
method: 'POST'
|
if command -v pkg-config &>/dev/null; then
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
echo "pkg-config is already installed"
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}'
|
else
|
||||||
|
brew install pkg-config
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install NASM
|
||||||
|
run: |
|
||||||
|
# Install NASM 2.16.x from official release.
|
||||||
|
# Do NOT use `brew install nasm` which installs NASM 3.x.
|
||||||
|
# NASM 3.x is a complete rewrite with incompatible CLI options and removed features.
|
||||||
|
# aom and other multimedia libraries require NASM 2.x for x86/x86_64 assembly.
|
||||||
|
wget https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/macosx/nasm-2.16.03-macosx.zip
|
||||||
|
unzip nasm-2.16.03-macosx.zip
|
||||||
|
sudo cp nasm-2.16.03/nasm /usr/local/bin/nasm
|
||||||
|
nasm --version
|
||||||
|
|
||||||
- name: Install flutter
|
- name: Install flutter
|
||||||
uses: subosito/flutter-action@v2.12.0
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Patch flutter
|
- name: Patch flutter
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
cp .github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff $(dirname $(dirname $(which flutter)))
|
|
||||||
cd $(dirname $(dirname $(which flutter)))
|
cd $(dirname $(dirname $(which flutter)))
|
||||||
[[ "3.24.4" == 3.24.5 ]] && git apply flutter_3.24.4_dropdown_menu_enableFilter.diff
|
[[ "3.24.5" == ${{env.FLUTTER_VERSION}} ]] && git apply ${{ github.workspace }}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff
|
||||||
|
|
||||||
- name: Workaround for flutter issue
|
- name: Workaround for flutter issue
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd "$(dirname "$(which flutter)")"
|
cd "$(dirname "$(which flutter)")"
|
||||||
# https://github.com/flutter/flutter/issues/1.3.43
|
# https://github.com/flutter/flutter/issues/133533
|
||||||
sed -i -e 's/_setFramesEnabledState(false);/\/\/_setFramesEnabledState(false);/g' ../packages/flutter/lib/src/scheduler/binding.dart
|
sed -i -e 's/_setFramesEnabledState(false);/\/\/_setFramesEnabledState(false);/g' ../packages/flutter/lib/src/scheduler/binding.dart
|
||||||
grep -n '_setFramesEnabledState(false);' ../packages/flutter/lib/src/scheduler/binding.dart
|
grep -n '_setFramesEnabledState(false);' ../packages/flutter/lib/src/scheduler/binding.dart
|
||||||
|
|
||||||
@@ -289,13 +265,12 @@ jobs:
|
|||||||
targets: ${{ matrix.job.target }}
|
targets: ${{ matrix.job.target }}
|
||||||
components: "rustfmt"
|
components: "rustfmt"
|
||||||
|
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
prefix-key: ${{ matrix.job.os }}
|
prefix-key: ${{ matrix.job.os }}
|
||||||
|
|
||||||
- name: Magick stuff for macOS
|
- name: Magick stuff for macOS
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -309,8 +284,8 @@ jobs:
|
|||||||
# Download icon using curl with additional SSL options
|
# Download icon using curl with additional SSL options
|
||||||
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
|
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
|
||||||
-H "User-Agent: Mozilla/5.0" \
|
-H "User-Agent: Mozilla/5.0" \
|
||||||
"${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}&uuid=${{ fromJson(inputs.iconlink).uuid }}" \
|
"${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}&uuid=${{ env.iconlink_uuid }}" \
|
||||||
-o ./res/icon.png || wget --no-check-certificate -O ./res/icon.png "${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}&uuid=${{ fromJson(inputs.iconlink).uuid }}"
|
-o ./res/icon.png || wget --no-check-certificate -O ./res/icon.png "${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}&uuid=${{ env.iconlink_uuid }}"
|
||||||
|
|
||||||
# Backup existing files (if they exist)
|
# Backup existing files (if they exist)
|
||||||
[ -f "./res/32x32.png" ] && mv ./res/32x32.png ./res/32x32.png.bak
|
[ -f "./res/32x32.png" ] && mv ./res/32x32.png ./res/32x32.png.bak
|
||||||
@@ -405,7 +380,7 @@ jobs:
|
|||||||
ls -lh rustdesk/data/flutter_assets/assets/
|
ls -lh rustdesk/data/flutter_assets/assets/
|
||||||
|
|
||||||
- name: replace flutter icons
|
- name: replace flutter icons
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -413,8 +388,8 @@ jobs:
|
|||||||
# Create required directories and files
|
# Create required directories and files
|
||||||
mkdir -p web
|
mkdir -p web
|
||||||
mkdir -p assets
|
mkdir -p assets
|
||||||
echo '{"name":"${{ inputs.appname }}","short_name":"${{ inputs.appname }}","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#ffffff","description":"A remote desktop software."}' > web/manifest.json
|
echo '{"name":"${{ env.appname }}","short_name":"${{ env.appname }}","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#ffffff","description":"A remote desktop software."}' > web/manifest.json
|
||||||
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${{ inputs.appname }}</title></head><body></body></html>' > web/index.html
|
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${{ env.appname }}</title></head><body></body></html>' > web/index.html
|
||||||
|
|
||||||
# Ensure the AppIcon.appiconset directory exists
|
# Ensure the AppIcon.appiconset directory exists
|
||||||
mkdir -p macos/Runner/Assets.xcassets/AppIcon.appiconset
|
mkdir -p macos/Runner/Assets.xcassets/AppIcon.appiconset
|
||||||
@@ -429,7 +404,7 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: ui.rs
|
- name: ui.rs
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -442,58 +417,44 @@ jobs:
|
|||||||
|
|
||||||
- name: fix connection delay
|
- name: fix connection delay
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
if: ${{ env.delayFix == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i '' -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs
|
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||||
|
|
||||||
- name: add cycle monitors to toolbar
|
- name: add cycle monitors to toolbar
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: fromJson(inputs.extras).cycleMonitor == 'true'
|
if: env.cycleMonitor == 'true'
|
||||||
run: |
|
run: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
|
||||||
git apply cycle_monitor.diff
|
git apply cycle_monitor.diff
|
||||||
|
|
||||||
- name: use X for offline display instead of orange circle
|
- name: use X for offline display instead of orange circle
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: fromJson(inputs.extras).xOffline == 'true'
|
if: env.xOffline == 'true'
|
||||||
run: |
|
run: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
|
||||||
git apply xoffline.diff
|
git apply xoffline.diff
|
||||||
|
|
||||||
- name: hide-cm
|
- name: hide-cm
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: fromJson(inputs.extras).hidecm == 'true'
|
if: env.hidecm == 'true'
|
||||||
run: |
|
run: |
|
||||||
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
|
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
|
||||||
git apply hidecm.diff
|
git apply hidecm.diff
|
||||||
|
|
||||||
- name: removeNewVersionNotif
|
- name: removeNewVersionNotif
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
if: env.removeNewVersionNotif == 'true'
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
|
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||||
|
|
||||||
- name: Report Status
|
- name: Restore bridge files
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: actions/download-artifact@master
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
name: bridge-artifact
|
||||||
method: 'POST'
|
path: ./
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}'
|
|
||||||
|
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
prefix-key: ${{ matrix.job.os }}
|
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
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
|
- name: Setup vcpkg with Github Actions binary cache
|
||||||
uses: lukka/run-vcpkg@v11
|
uses: lukka/run-vcpkg@v11
|
||||||
@@ -515,14 +476,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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": "${{ inputs.uuid }}", "status": "25% complete"}'
|
|
||||||
|
|
||||||
- name: Create MacOS directory structure
|
- name: Create MacOS directory structure
|
||||||
run: |
|
run: |
|
||||||
@@ -537,21 +491,13 @@ jobs:
|
|||||||
sed -i -e "s/osx_minimum_system_version = \"[0-9]*.[0-9]*\"/osx_minimum_system_version = \"${MIN_MACOS_VERSION}\"/" Cargo.toml
|
sed -i -e "s/osx_minimum_system_version = \"[0-9]*.[0-9]*\"/osx_minimum_system_version = \"${MIN_MACOS_VERSION}\"/" Cargo.toml
|
||||||
sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj
|
sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj
|
||||||
fi
|
fi
|
||||||
sed -i -e "s/RustDesk.app/\"${{ inputs.appname }}.app\"/" build.py
|
sed -i -e "s/RustDesk.app/\"${{ env.appname }}.app\"/" build.py
|
||||||
./build.py --flutter --hwcodec ${{ matrix.job.extra-build-args }}
|
./build.py --flutter --hwcodec --unix-file-copy-paste ${{ matrix.job.extra-build-args }}
|
||||||
|
|
||||||
# - name: Copy service file
|
# - name: Copy service file
|
||||||
# run: |
|
# run: |
|
||||||
# cp -rf ../target/release/service ./build/macos/Build/Products/Release/RustDesk.app/Contents/MacOS/
|
# 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": "${{ inputs.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
|
|
||||||
|
|
||||||
- name: Install rcodesign tool
|
- name: Install rcodesign tool
|
||||||
if: env.MACOS_P12_BASE64 != null
|
if: env.MACOS_P12_BASE64 != null
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -572,14 +518,6 @@ jobs:
|
|||||||
brew install pkg-config
|
brew install pkg-config
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
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: Show version information (Rust, cargo, Clang)
|
- name: Show version information (Rust, cargo, Clang)
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -591,7 +529,7 @@ jobs:
|
|||||||
rustc -V
|
rustc -V
|
||||||
|
|
||||||
- name: icon svg handling
|
- name: icon svg handling
|
||||||
if: ${{ inputs.iconlink != 'false' }}
|
if: ${{ env.iconlink_url != 'false' }}
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -607,7 +545,7 @@ jobs:
|
|||||||
rm ./temp_icon.pbm
|
rm ./temp_icon.pbm
|
||||||
|
|
||||||
- name: logo handling
|
- name: logo handling
|
||||||
if: ${{ inputs.logolink != 'false' }}
|
if: ${{ env.logolink_url != 'false' }}
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -615,19 +553,11 @@ jobs:
|
|||||||
mkdir -p "$ASSETS_DIR"
|
mkdir -p "$ASSETS_DIR"
|
||||||
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
|
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
|
||||||
-H "User-Agent: Mozilla/5.0" \
|
-H "User-Agent: Mozilla/5.0" \
|
||||||
"${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}&uuid=${{ fromJson(inputs.logolink).uuid }}" \
|
"${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}" \
|
||||||
-o "$ASSETS_DIR/logo.png" || \
|
-o "$ASSETS_DIR/logo.png" || \
|
||||||
wget --no-check-certificate \
|
wget --no-check-certificate \
|
||||||
-O "$ASSETS_DIR/logo.png" \
|
-O "$ASSETS_DIR/logo.png" \
|
||||||
"${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}&uuid=${{ fromJson(inputs.logolink).uuid }}"
|
"${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}"
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "85% complete"}'
|
|
||||||
|
|
||||||
- name: Sign macOS app bundle
|
- name: Sign macOS app bundle
|
||||||
if: env.MACOS_P12_BASE64 != ''
|
if: env.MACOS_P12_BASE64 != ''
|
||||||
@@ -640,21 +570,21 @@ jobs:
|
|||||||
# Rename RustDesk.app to the custom app name first
|
# Rename RustDesk.app to the custom app name first
|
||||||
if [ -d "RustDesk.app" ]; then
|
if [ -d "RustDesk.app" ]; then
|
||||||
# First rename the app if it's still called RustDesk.app
|
# First rename the app if it's still called RustDesk.app
|
||||||
mv "RustDesk.app" "${{ inputs.appname }}.app"
|
mv "RustDesk.app" "${{ env.appname }}.app"
|
||||||
echo "Renamed RustDesk.app to ${{ inputs.appname }}.app"
|
echo "Renamed RustDesk.app to ${{ env.appname }}.app"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "App bundle contents after rename:"
|
echo "App bundle contents after rename:"
|
||||||
ls -la "${{ inputs.appname }}.app" || echo "App not found"
|
ls -la "${{ env.appname }}.app" || echo "App not found"
|
||||||
ls -la "${{ inputs.appname }}.app/Contents" || echo "Contents not found"
|
ls -la "${{ env.appname }}.app/Contents" || echo "Contents not found"
|
||||||
|
|
||||||
# Decode the certificate
|
# Decode the certificate
|
||||||
echo "${{ secrets.MACOS_P12_BASE64 }}" | base64 --decode > certificate.p12
|
echo "${{ secrets.MACOS_P12_BASE64 }}" | base64 --decode > certificate.p12
|
||||||
|
|
||||||
# Sign the app bundle and its contents
|
# Sign the app bundle and its contents
|
||||||
if [ -d "${{ inputs.appname }}.app/Contents/MacOS" ]; then
|
if [ -d "${{ env.appname }}.app/Contents/MacOS" ]; then
|
||||||
echo "Signing main executable..."
|
echo "Signing main executable..."
|
||||||
MAIN_EXECUTABLE="${{ inputs.appname }}.app/Contents/MacOS/${{ inputs.appname }}"
|
MAIN_EXECUTABLE="${{ env.appname }}.app/Contents/MacOS/${{ env.appname }}"
|
||||||
if [ -f "$MAIN_EXECUTABLE" ]; then
|
if [ -f "$MAIN_EXECUTABLE" ]; then
|
||||||
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
||||||
--code-signature-flags runtime "$MAIN_EXECUTABLE"
|
--code-signature-flags runtime "$MAIN_EXECUTABLE"
|
||||||
@@ -662,23 +592,23 @@ jobs:
|
|||||||
echo "Main executable not found at expected path: $MAIN_EXECUTABLE"
|
echo "Main executable not found at expected path: $MAIN_EXECUTABLE"
|
||||||
# Try to find the actual executable
|
# Try to find the actual executable
|
||||||
echo "Available executables in MacOS directory:"
|
echo "Available executables in MacOS directory:"
|
||||||
ls -la "${{ inputs.appname }}.app/Contents/MacOS/"
|
ls -la "${{ env.appname }}.app/Contents/MacOS/"
|
||||||
ACTUAL_EXECUTABLE=$(ls "${{ inputs.appname }}.app/Contents/MacOS/" | head -n 1)
|
ACTUAL_EXECUTABLE=$(ls "${{ env.appname }}.app/Contents/MacOS/" | head -n 1)
|
||||||
if [ -n "$ACTUAL_EXECUTABLE" ]; then
|
if [ -n "$ACTUAL_EXECUTABLE" ]; then
|
||||||
echo "Found executable: $ACTUAL_EXECUTABLE"
|
echo "Found executable: $ACTUAL_EXECUTABLE"
|
||||||
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
||||||
--code-signature-flags runtime "${{ inputs.appname }}.app/Contents/MacOS/$ACTUAL_EXECUTABLE"
|
--code-signature-flags runtime "${{ env.appname }}.app/Contents/MacOS/$ACTUAL_EXECUTABLE"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Signing frameworks..."
|
echo "Signing frameworks..."
|
||||||
find "${{ inputs.appname }}.app/Contents/Frameworks" -type f -not -name ".*" -exec \
|
find "${{ env.appname }}.app/Contents/Frameworks" -type f -not -name ".*" -exec \
|
||||||
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
||||||
--code-signature-flags runtime {} \;
|
--code-signature-flags runtime {} \;
|
||||||
|
|
||||||
echo "Signing main bundle..."
|
echo "Signing main bundle..."
|
||||||
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
|
||||||
--code-signature-flags runtime "${{ inputs.appname }}.app"
|
--code-signature-flags runtime "${{ env.appname }}.app"
|
||||||
else
|
else
|
||||||
echo "Error: Invalid app bundle structure"
|
echo "Error: Invalid app bundle structure"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -696,24 +626,24 @@ jobs:
|
|||||||
# Find the actual .app bundle
|
# Find the actual .app bundle
|
||||||
if [ -d "RustDesk.app" ]; then
|
if [ -d "RustDesk.app" ]; then
|
||||||
# First rename the app if it's still called RustDesk.app
|
# First rename the app if it's still called RustDesk.app
|
||||||
mv "RustDesk.app" "${{ inputs.appname }}.app"
|
mv "RustDesk.app" "${{ env.appname }}.app"
|
||||||
fi
|
fi
|
||||||
if [ ! -d "${{ inputs.appname }}.app" ]; then
|
if [ ! -d "${{ env.appname }}.app" ]; then
|
||||||
echo "Could not find .app bundle!"
|
echo "Could not find .app bundle!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Creating DMG for ${{ inputs.appname }}.app"
|
echo "Creating DMG for ${{ env.appname }}.app"
|
||||||
create-dmg \
|
create-dmg \
|
||||||
--volname "${{ inputs.appname }}" \
|
--volname "${{ env.appname }}" \
|
||||||
--window-pos 200 120 \
|
--window-pos 200 120 \
|
||||||
--window-size 800 400 \
|
--window-size 800 400 \
|
||||||
--icon-size 100 \
|
--icon-size 100 \
|
||||||
--icon "${{ inputs.appname }}.app" 200 190 \
|
--icon "${{ env.appname }}.app" 200 190 \
|
||||||
--hide-extension "${{ inputs.appname }}.app" \
|
--hide-extension "${{ env.appname }}.app" \
|
||||||
--app-drop-link 600 185 \
|
--app-drop-link 600 185 \
|
||||||
"${{ inputs.appname }}-${{ matrix.job.arch }}.dmg" \
|
"${{ env.appname }}-${{ matrix.job.arch }}.dmg" \
|
||||||
"${{ inputs.appname }}.app"
|
"${{ env.appname }}.app"
|
||||||
mv "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg" $GITHUB_WORKSPACE/
|
mv "${{ env.appname }}-${{ matrix.job.arch }}.dmg" $GITHUB_WORKSPACE/
|
||||||
|
|
||||||
- name: Rename rustdesk
|
- name: Rename rustdesk
|
||||||
if: env.UPLOAD_ARTIFACT == 'true'
|
if: env.UPLOAD_ARTIFACT == 'true'
|
||||||
@@ -723,61 +653,46 @@ jobs:
|
|||||||
ls -la
|
ls -la
|
||||||
|
|
||||||
# Find the DMG file dynamically
|
# Find the DMG file dynamically
|
||||||
DMG_FILE=$(find . -name "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg")
|
DMG_FILE=$(find . -name "${{ env.appname }}-${{ matrix.job.arch }}.dmg")
|
||||||
|
|
||||||
if [ -n "$DMG_FILE" ]; then
|
if [ -n "$DMG_FILE" ]; then
|
||||||
echo "Found DMG file: $DMG_FILE"
|
echo "Found DMG file: $DMG_FILE"
|
||||||
mv "$DMG_FILE" "${{ inputs.filename }}-${{ matrix.job.arch }}.dmg"
|
mv "$DMG_FILE" "${{ env.filename }}-${{ matrix.job.arch }}.dmg"
|
||||||
echo "Renamed to ${{ inputs.filename }}-${{ matrix.job.arch }}.dmg"
|
echo "Renamed to ${{ env.filename }}-${{ matrix.job.arch }}.dmg"
|
||||||
else
|
else
|
||||||
echo "No DMG file found matching the pattern"
|
echo "No DMG file found matching the pattern"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: send file to rdgen server
|
- name: send file to rdgen server
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
if: ${{ env.rdgen == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -i -X POST \
|
curl -i -X POST \
|
||||||
-H "Content-Type: multipart/form-data" \
|
-H "Content-Type: multipart/form-data" \
|
||||||
-H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" \
|
-H "Authorization: Bearer ${{ env.token }}" \
|
||||||
-F "file=@$GITHUB_WORKSPACE/${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" \
|
-F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \
|
||||||
-F "uuid=${{ inputs.uuid }}" \
|
-F "uuid=${{ env.uuid }}" \
|
||||||
"${{ secrets.GENURL }}/save_custom_client"
|
"${{ secrets.GENURL }}/save_custom_client"
|
||||||
|
|
||||||
|
|
||||||
- name: send file to api server
|
- name: send file to api server
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
if: ${{ env.rdgen == 'false' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -i -X POST \
|
curl -i -X POST \
|
||||||
-H "Content-Type: multipart/form-data" \
|
-H "Content-Type: multipart/form-data" \
|
||||||
-H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" \
|
-H "Authorization: Bearer ${{ env.token }}" \
|
||||||
-F "file=@$GITHUB_WORKSPACE/${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" \
|
-F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \
|
||||||
"${{ inputs.apiServer }}/api/save_custom_client"
|
"${{ env.apiServer }}/api/save_custom_client"
|
||||||
|
|
||||||
- name: Report Status
|
cleanup:
|
||||||
uses: fjogeleit/http-request-action@v1
|
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:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
name: encrypted-secrets-zip
|
||||||
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"}'
|
|
||||||
|
|||||||
454
.github/workflows/generator-windows-x86.yml
vendored
Normal file
454
.github/workflows/generator-windows-x86.yml
vendored
Normal file
File diff suppressed because one or more lines are too long
470
.github/workflows/generator-windows.yml
vendored
470
.github/workflows/generator-windows.yml
vendored
File diff suppressed because one or more lines are too long
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,14 +41,48 @@ jobs:
|
|||||||
- name: Add MSBuild to PATH
|
- name: Add MSBuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v2
|
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
|
- name: Download the source code
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/rustdesk-org/RustDeskTempTopMostWindow RustDeskTempTopMostWindow
|
git clone https://github.com/rustdesk-org/RustDeskTempTopMostWindow RustDeskTempTopMostWindow
|
||||||
|
|
||||||
# Build. commit 53b548a5398624f7149a382000397993542ad796 is tag v0.3
|
# Build. commit 53b548a5398624f7149a382000397993542ad796 is tag v0.3
|
||||||
- name: Build the project
|
- name: Build the project
|
||||||
run: |
|
uses: nick-fields/retry@v3
|
||||||
|
with:
|
||||||
|
timeout_minutes: 1
|
||||||
|
max_attempts: 3
|
||||||
|
shell: pwsh
|
||||||
|
command: |
|
||||||
cd RustDeskTempTopMostWindow && git checkout 53b548a5398624f7149a382000397993542ad796
|
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 }}
|
msbuild ${{ env.project_path }} -p:Configuration=${{ inputs.configuration }} -p:Platform=${{ inputs.platform }} /p:TargetVersion=${{ inputs.target_version }}
|
||||||
|
|
||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
|
|||||||
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).
|
The client generator is currently hosted [here](https://rdgen.crayoneater.org).
|
||||||
If you would like to host the generator yourself, see [here](setup.md)
|
If you would like to host the generator yourself, see [here](setup.md)
|
||||||
|
|
||||||
This client generator is currently integrated into my rustdesk [api
|
## Features
|
||||||
server](https://github.com/bryangerlach/rustdesk-api-server), which is a fork
|
|
||||||
of [rustdesk-api-server](https://github.com/kingmo888/rustdesk-api-server). If
|
- Embed server and key into client
|
||||||
you are running my api server, then you will still need to fork RDGen and go
|
- Custom app name
|
||||||
through the setup process, but you won't need to actually run the rdgen server.
|
- 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
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
services:
|
services:
|
||||||
rdgen:
|
rdgen:
|
||||||
# use bryangerlach/rdgen:dev for the latest dev build
|
# use bryangerlach/rdgen:latest for the latest build
|
||||||
image: bryangerlach/rdgen:v0.3.1
|
#build: .
|
||||||
|
image: bryangerlach/rdgen:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
SECRET_KEY: "django-insecure-!(t-!f#6g#sr%yfded9(xha)g+=!6craeez^cp+*&bz_7vdk61"
|
SECRET_KEY: "django-insecure-!(t-!f#6g#sr%yfded9(xha)g+=!6craeez^cp+*&bz_7vdk61"
|
||||||
GHUSER: "github_username"
|
GHUSER: "github_username"
|
||||||
GHBEARER: "github_access_token"
|
GHBEARER: "github_access_token"
|
||||||
GENURL: "accessible_url_of_server"
|
GENURL: "accessible_url_of_server"
|
||||||
|
ZIP_PASSWORD: ""
|
||||||
|
GHBRANCH: "master"
|
||||||
PROTOCOL: "https"
|
PROTOCOL: "https"
|
||||||
REPONAME: "rdgen"
|
REPONAME: "rdgen"
|
||||||
|
SH_SECRET: ""
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
dns:
|
dns:
|
||||||
- 8.8.8.8
|
- 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
|
# Adjust these values as needed
|
||||||
bind = "0.0.0.0:8000" # Host and port for Gunicorn to listen on
|
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
|
activate_base = True # Activate your virtual environment if applicable
|
||||||
|
|
||||||
# Path to your Django project's main WSGI application file (usually manage.py)
|
# Path to your Django project's main WSGI application file (usually manage.py)
|
||||||
|
|||||||
@@ -24,15 +24,19 @@ SECRET_KEY = os.environ.get('SECRET_KEY','django-insecure-!(t-!f#6g#sr%yfded9(xh
|
|||||||
GHUSER = os.environ.get("GHUSER", '')
|
GHUSER = os.environ.get("GHUSER", '')
|
||||||
GHBEARER = os.environ.get("GHBEARER", '')
|
GHBEARER = os.environ.get("GHBEARER", '')
|
||||||
GENURL = os.environ.get("GENURL", '')
|
GENURL = os.environ.get("GENURL", '')
|
||||||
|
GHBRANCH = os.environ.get("GHBRANCH",'master')
|
||||||
|
ZIP_PASSWORD = os.environ.get("ZIP_PASSWORD",'insecure')
|
||||||
PROTOCOL = os.environ.get("PROTOCOL", 'https')
|
PROTOCOL = os.environ.get("PROTOCOL", 'https')
|
||||||
REPONAME = os.environ.get("REPONAME", 'rdgen')
|
REPONAME = os.environ.get("REPONAME", 'rdgen')
|
||||||
|
SH_SECRET = os.environ.get('SH_SECRET', 'secret')
|
||||||
|
|
||||||
MEDIA_URL = '/media/'
|
MEDIA_URL = '/media/'
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||||
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# 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 = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
#CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', '').split()
|
#CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', '').split()
|
||||||
@@ -131,3 +135,5 @@ STATIC_URL = 'static/'
|
|||||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
DATA_UPLOAD_MAX_MEMORY_SIZE = None
|
||||||
|
|||||||
@@ -32,4 +32,6 @@ urlpatterns = [
|
|||||||
url(r'^startgh',views.startgh),
|
url(r'^startgh',views.startgh),
|
||||||
url(r'^get_png',views.get_png),
|
url(r'^get_png',views.get_png),
|
||||||
url(r'^save_custom_client',views.save_custom_client),
|
url(r'^save_custom_client',views.save_custom_client),
|
||||||
|
url(r'^get_zip',views.get_zip),
|
||||||
|
url(r'^cleanzip',views.cleanup_secrets),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ from django import forms
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
class GenerateForm(forms.Form):
|
class GenerateForm(forms.Form):
|
||||||
|
sh_secret_field = forms.CharField(required=False)
|
||||||
#Platform
|
#Platform
|
||||||
platform = forms.ChoiceField(choices=[('windows','Windows'),('linux','Linux (currently unavailable)'),('android','Android'),('macos','macOS')], initial='windows')
|
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.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.3.9')
|
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"
|
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)
|
delayFix = forms.BooleanField(initial=True, required=False)
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ class GenerateForm(forms.Form):
|
|||||||
('settingsY', 'No, enable settings'),
|
('settingsY', 'No, enable settings'),
|
||||||
('settingsN', 'Yes, DISABLE settings')
|
('settingsN', 'Yes, DISABLE settings')
|
||||||
], initial='settingsY')
|
], initial='settingsY')
|
||||||
|
androidappid = forms.CharField(label="Custom Android App ID (replaces 'com.carriez.flutter_hbb')", required=False)
|
||||||
|
|
||||||
#Custom Server
|
#Custom Server
|
||||||
serverIP = forms.CharField(label="Host", required=False)
|
serverIP = forms.CharField(label="Host", required=False)
|
||||||
@@ -36,8 +38,10 @@ class GenerateForm(forms.Form):
|
|||||||
#Visual
|
#Visual
|
||||||
iconfile = forms.FileField(label="Custom App Icon (in .png format)", required=False, widget=forms.FileInput(attrs={'accept': 'image/png'}))
|
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'}))
|
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)
|
iconbase64 = forms.CharField(required=False)
|
||||||
logobase64 = forms.CharField(required=False)
|
logobase64 = forms.CharField(required=False)
|
||||||
|
privacybase64 = forms.CharField(required=False)
|
||||||
theme = forms.ChoiceField(choices=[
|
theme = forms.ChoiceField(choices=[
|
||||||
('light', 'Light'),
|
('light', 'Light'),
|
||||||
('dark', 'Dark'),
|
('dark', 'Dark'),
|
||||||
@@ -48,7 +52,7 @@ class GenerateForm(forms.Form):
|
|||||||
#Security
|
#Security
|
||||||
passApproveMode = forms.ChoiceField(choices=[('password','Accept sessions via password'),('click','Accept sessions via click'),('password-click','Accepts sessions via both')],initial='password-click')
|
passApproveMode = forms.ChoiceField(choices=[('password','Accept sessions via password'),('click','Accept sessions via click'),('password-click','Accepts sessions via both')],initial='password-click')
|
||||||
permanentPassword = forms.CharField(widget=forms.PasswordInput(), required=False)
|
permanentPassword = forms.CharField(widget=forms.PasswordInput(), required=False)
|
||||||
runasadmin = forms.ChoiceField(choices=[('false','No'),('true','Yes')], initial='false')
|
#runasadmin = forms.ChoiceField(choices=[('false','No'),('true','Yes')], initial='false')
|
||||||
denyLan = forms.BooleanField(initial=False, required=False)
|
denyLan = forms.BooleanField(initial=False, required=False)
|
||||||
enableDirectIP = forms.BooleanField(initial=False, required=False)
|
enableDirectIP = forms.BooleanField(initial=False, required=False)
|
||||||
#ipWhitelist = forms.BooleanField(initial=False, required=False)
|
#ipWhitelist = forms.BooleanField(initial=False, required=False)
|
||||||
@@ -66,6 +70,10 @@ class GenerateForm(forms.Form):
|
|||||||
enableRecording = forms.BooleanField(initial=True, required=False)
|
enableRecording = forms.BooleanField(initial=True, required=False)
|
||||||
enableBlockingInput = forms.BooleanField(initial=True, required=False)
|
enableBlockingInput = forms.BooleanField(initial=True, required=False)
|
||||||
enableRemoteModi = forms.BooleanField(initial=False, required=False)
|
enableRemoteModi = forms.BooleanField(initial=False, required=False)
|
||||||
|
hidecm = forms.BooleanField(initial=False, required=False)
|
||||||
|
enablePrinter = forms.BooleanField(initial=True, required=False)
|
||||||
|
enableCamera = forms.BooleanField(initial=True, required=False)
|
||||||
|
enableTerminal = forms.BooleanField(initial=True, required=False)
|
||||||
|
|
||||||
#Other
|
#Other
|
||||||
removeWallpaper = forms.BooleanField(initial=True, required=False)
|
removeWallpaper = forms.BooleanField(initial=True, required=False)
|
||||||
@@ -76,7 +84,6 @@ class GenerateForm(forms.Form):
|
|||||||
#custom added features
|
#custom added features
|
||||||
cycleMonitor = forms.BooleanField(initial=False, required=False)
|
cycleMonitor = forms.BooleanField(initial=False, required=False)
|
||||||
xOffline = forms.BooleanField(initial=False, required=False)
|
xOffline = forms.BooleanField(initial=False, required=False)
|
||||||
hidecm = forms.BooleanField(initial=False, required=False)
|
|
||||||
removeNewVersionNotif = forms.BooleanField(initial=False, required=False)
|
removeNewVersionNotif = forms.BooleanField(initial=False, required=False)
|
||||||
|
|
||||||
def clean_iconfile(self):
|
def clean_iconfile(self):
|
||||||
|
|||||||
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)
|
id = models.IntegerField(verbose_name="ID",primary_key=True)
|
||||||
uuid = models.CharField(verbose_name="uuid", max_length=100)
|
uuid = models.CharField(verbose_name="uuid", max_length=100)
|
||||||
status = models.CharField(verbose_name="status", 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>
|
||||||
@@ -129,6 +129,8 @@
|
|||||||
{% if platform == 'windows' %}
|
{% if platform == 'windows' %}
|
||||||
<a href='/download?filename={{filename}}.exe&uuid={{uuid}}' class="download-link">Download {{filename}}.exe</a>
|
<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>
|
<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' %}
|
{% 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.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}}-x86_64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.rpm</a>
|
||||||
@@ -138,6 +140,10 @@
|
|||||||
<a href='/download?filename={{filename}}-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.rpm</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}}-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}}-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' %}
|
{% 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}}-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}}-x86_64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.apk</a>
|
||||||
@@ -173,7 +179,7 @@
|
|||||||
platformLogos.macos.style.display = 'block';
|
platformLogos.macos.style.display = 'block';
|
||||||
platformNote.textContent = 'Note: For macOS, you may need to adjust security settings to run the application.';
|
platformNote.textContent = 'Note: For macOS, you may need to adjust security settings to run the application.';
|
||||||
platformNote.style.display = 'block';
|
platformNote.style.display = 'block';
|
||||||
} else if (platform === 'windows') {
|
} else if (platform === 'windows' || platform === 'windows-x86') {
|
||||||
document.getElementById('pageTitle').textContent = 'Windows Build Generated';
|
document.getElementById('pageTitle').textContent = 'Windows Build Generated';
|
||||||
platformLogos.windows.style.display = 'block';
|
platformLogos.windows.style.display = 'block';
|
||||||
platformNote.textContent = 'Note: You might need to disable SmartScreen or adjust Windows security settings.';
|
platformNote.textContent = 'Note: You might need to disable SmartScreen or adjust Windows security settings.';
|
||||||
|
|||||||
@@ -90,7 +90,26 @@
|
|||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
}
|
}
|
||||||
.platform-icon:hover, .platform-icon.active {
|
.platform-icon:hover, .platform-icon.active {
|
||||||
color: #fff;
|
color: #2e52f7;
|
||||||
|
}
|
||||||
|
.text-64 {
|
||||||
|
font-size: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
bottom: -0.2em;
|
||||||
|
right: -0.2em;
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-32 {
|
||||||
|
font-size: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
bottom: -0.2em;
|
||||||
|
right: -0.2em;
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
.checkbox-group {
|
.checkbox-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -150,6 +169,58 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-requirement {
|
||||||
|
display: none; /* Hidden by default */
|
||||||
|
color: orange;
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg, #00457C 0%, #0079C1 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 50px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 69, 124, 0.2);
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 8px 25px rgba(0, 69, 124, 0.3);
|
||||||
|
background: linear-gradient(135deg, #005AA7 0%, #0095EA 100%);
|
||||||
|
border-color: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button i {
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: 20px;
|
||||||
|
background: white;
|
||||||
|
color: #00457C;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button:hover i {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
color: #0095EA;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -175,13 +246,21 @@
|
|||||||
<div class="platform">
|
<div class="platform">
|
||||||
<h2><i class="fas fa-desktop"></i> Select Platform</h2>
|
<h2><i class="fas fa-desktop"></i> Select Platform</h2>
|
||||||
<div class="platform-icons">
|
<div class="platform-icons">
|
||||||
<i class="fab fa-windows platform-icon active" data-platform="windows"></i>
|
<span class="fa-stack fa-lg">
|
||||||
|
<i class="fab fa-windows fa-stack-2x platform-icon active" data-platform="windows"></i>
|
||||||
|
<strong class="fa-stack-1x text-64">64</strong>
|
||||||
|
</span>
|
||||||
|
<span class="fa-stack fa-lg">
|
||||||
|
<i class="fab fa-windows fa-stack-2x platform-icon" data-platform="windows-x86"></i>
|
||||||
|
<strong class="fa-stack-1x text-32">32</strong>
|
||||||
|
</span>
|
||||||
<i class="fab fa-linux platform-icon" data-platform="linux"></i>
|
<i class="fab fa-linux platform-icon" data-platform="linux"></i>
|
||||||
<i class="fab fa-android platform-icon" data-platform="android"></i>
|
<i class="fab fa-android platform-icon" data-platform="android"></i>
|
||||||
<i class="fab fa-apple platform-icon" data-platform="macos"></i>
|
<i class="fab fa-apple platform-icon" data-platform="macos"></i>
|
||||||
</div>
|
</div>
|
||||||
<select name="platform" id="id_platform">
|
<select name="platform" id="id_platform">
|
||||||
<option value="windows" selected>Windows</option>
|
<option value="windows" selected>Windows 64Bit</option>
|
||||||
|
<option value="windows-x86">Windows 32Bit</option>
|
||||||
<option value="linux">Linux</option>
|
<option value="linux">Linux</option>
|
||||||
<option value="android">Android</option>
|
<option value="android">Android</option>
|
||||||
<option value="macos">macOS</option>
|
<option value="macos">macOS</option>
|
||||||
@@ -208,6 +287,8 @@
|
|||||||
{{ form.installation }}<br><br>
|
{{ form.installation }}<br><br>
|
||||||
<label for="{{ form.settings.id_for_label }}">Disable Settings:</label>
|
<label for="{{ form.settings.id_for_label }}">Disable Settings:</label>
|
||||||
{{ form.settings }}<br><br>
|
{{ form.settings }}<br><br>
|
||||||
|
<label for="{{ form.androidappid.id_for_label }}">Custom Android App ID (replaces 'com.carriez.flutter_hbb', leave blank to use default):</label>
|
||||||
|
{{ form.androidappid }}<br><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
@@ -229,10 +310,9 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><i class="fas fa-shield-alt"></i> Security</h2>
|
<h2><i class="fas fa-shield-alt"></i> Security</h2>
|
||||||
<label for="{{ form.runasadmin.id_for_label }}">Always run as Administrator?</label>
|
|
||||||
{{ form.runasadmin }}<br><br>
|
|
||||||
<label for="{{ form.passApproveMode.id_for_label }}">Password Approve mode:</label>
|
<label for="{{ form.passApproveMode.id_for_label }}">Password Approve mode:</label>
|
||||||
{{ form.passApproveMode }}<br><br>
|
{{ form.passApproveMode }}<br><br>
|
||||||
|
<div id="passwordRequirement" class="password-requirement">To use the hide connection window feature, please set a permanent password.</div>
|
||||||
<label for="{{ form.permanentPassword.id_for_label }}">Set Permanent Password:</label>
|
<label for="{{ form.permanentPassword.id_for_label }}">Set Permanent Password:</label>
|
||||||
{{ form.permanentPassword }} *The password is used as default, but can be changed by the client<br><br>
|
{{ form.permanentPassword }} *The password is used as default, but can be changed by the client<br><br>
|
||||||
|
|
||||||
@@ -242,12 +322,15 @@
|
|||||||
<label for="{{ form.enableDirectIP.id_for_label }}">{{ form.enableDirectIP }} Enable direct IP access</label><br>
|
<label for="{{ form.enableDirectIP.id_for_label }}">{{ form.enableDirectIP }} Enable direct IP access</label><br>
|
||||||
|
|
||||||
<label for="{{ form.autoClose.id_for_label }}">{{ form.autoClose }} Automatically close incoming sessions on user inactivity</label><br>
|
<label for="{{ form.autoClose.id_for_label }}">{{ form.autoClose }} Automatically close incoming sessions on user inactivity</label><br>
|
||||||
|
|
||||||
|
<label for="{{ form.hidecm.id_for_label }}">{{ form.hidecm }} Allow hiding the connection window from remote screen.</label><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><i class="fas fa-paint-brush"></i> Visual</h2>
|
<h2><i class="fas fa-paint-brush"></i> Visual</h2>
|
||||||
{{ form.iconbase64.as_hidden }}
|
{{ form.iconbase64.as_hidden }}
|
||||||
{{ form.logobase64.as_hidden }}
|
{{ form.logobase64.as_hidden }}
|
||||||
|
{{ form.privacybase64.as_hidden }}
|
||||||
<label for="{{ form.iconfile.id_for_label }}">Custom App Icon (in .png format)</label>
|
<label for="{{ form.iconfile.id_for_label }}">Custom App Icon (in .png format)</label>
|
||||||
{{ form.iconfile }}<br><br>
|
{{ form.iconfile }}<br><br>
|
||||||
<!-- <input type="file" name="iconfile" id="iconfile" accept="image/png"> -->
|
<!-- <input type="file" name="iconfile" id="iconfile" accept="image/png"> -->
|
||||||
@@ -256,6 +339,10 @@
|
|||||||
{{ form.logofile }}<br><br>
|
{{ form.logofile }}<br><br>
|
||||||
<!-- <input type="file" name="logofile" id="logofile" accept="image/png"> -->
|
<!-- <input type="file" name="logofile" id="logofile" accept="image/png"> -->
|
||||||
<div id="logo-preview"></div><br><br>
|
<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>
|
<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>
|
{{ form.theme }} {{ form.themeDorO }} *Default sets the theme but allows the client to change it, Override sets the theme permanently.<br><br>
|
||||||
</div>
|
</div>
|
||||||
@@ -263,7 +350,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><i class="fas fa-lock"></i> Permissions</h2>
|
<h2><i class="fas fa-lock"></i> Permissions</h2>
|
||||||
The following Permissions can be set as default (the user can change the settins) or override (the settings cannot be changed).<br>
|
The following Permissions can be set as default (the user can change the settings) or override (the settings cannot be changed).<br>
|
||||||
{{ form.permissionsDorO }}
|
{{ form.permissionsDorO }}
|
||||||
<label for="{{ form.permissionsType.id_for_label }}">Permission type:</label>
|
<label for="{{ form.permissionsType.id_for_label }}">Permission type:</label>
|
||||||
{{ form.permissionsType }}<br><br>
|
{{ form.permissionsType }}<br><br>
|
||||||
@@ -277,17 +364,20 @@
|
|||||||
<label for="{{ form.enableRecording.id_for_label }}">{{ form.enableRecording }} Enable recording session</label>
|
<label for="{{ form.enableRecording.id_for_label }}">{{ form.enableRecording }} Enable recording session</label>
|
||||||
<label for="{{ form.enableBlockingInput.id_for_label }}">{{ form.enableBlockingInput }} Enable blocking user input</label>
|
<label for="{{ form.enableBlockingInput.id_for_label }}">{{ form.enableBlockingInput }} Enable blocking user input</label>
|
||||||
<label for="{{ form.enableRemoteModi.id_for_label }}">{{ form.enableRemoteModi }} Enable remote configuration modification</label>
|
<label for="{{ form.enableRemoteModi.id_for_label }}">{{ form.enableRemoteModi }} Enable remote configuration modification</label>
|
||||||
|
<label for="{{ form.enablePrinter.id_for_label }}">{{ form.enablePrinter }} Enable remote printer</label>
|
||||||
|
<label for="{{ form.enableCamera.id_for_label }}">{{ form.enableCamera }} Enable remote camera</label>
|
||||||
|
<label for="{{ form.enableTerminal.id_for_label }}">{{ form.enableTerminal }} Enable remote terminal</label>
|
||||||
</div><br>
|
</div><br>
|
||||||
<h2><i class="fas fa-code"></i> Code Changes</h2>
|
<h2><i class="fas fa-code"></i> Code Changes</h2>
|
||||||
<label for="{{ form.cycleMonitor.id_for_label }}">{{ form.cycleMonitor }} Add a button to cycle through available monitors to the minimized toolbar.</label><br>
|
<label for="{{ form.cycleMonitor.id_for_label }}">{{ form.cycleMonitor }} Add a button to cycle through available monitors to the minimized toolbar.</label><br>
|
||||||
<label for="{{ form.xOffline.id_for_label }}">{{ form.xOffline }} Display an X for offline devices in the addressbook.</label><br>
|
<label for="{{ form.xOffline.id_for_label }}">{{ form.xOffline }} Display an X for offline devices in the addressbook.</label><br>
|
||||||
<label for="{{ form.hidecm.id_for_label }}">{{ form.hidecm }} Allow hiding the connection window from remote screen.</label><br>
|
|
||||||
<label for="{{ form.removeNewVersionNotif.id_for_label }}">{{ form.removeNewVersionNotif }} Remove notification for new versions.</label><br>
|
<label for="{{ form.removeNewVersionNotif.id_for_label }}">{{ form.removeNewVersionNotif }} Remove notification for new versions.</label><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><i class="fas fa-cog"></i> Other</h2>
|
<h2><i class="fas fa-cog"></i> Other</h2>
|
||||||
<label for="{{ form.removeWallpaper.id_for_label }}">{{ form.removeWallpaper }} Remove wallpaper during incoming sessions</label><br>
|
<label for="{{ form.removeWallpaper.id_for_label }}">{{ form.removeWallpaper }} Remove wallpaper during incoming sessions</label><br>
|
||||||
|
<a href="https://rustdesk.com/docs/en/self-host/client-configuration/advanced-settings/">Click here for a list of Default/Override settings</a>
|
||||||
<label for="{{ form.defaultManual.id_for_label }}">Default settings</label><br>
|
<label for="{{ form.defaultManual.id_for_label }}">Default settings</label><br>
|
||||||
{{ form.defaultManual }}<br><br>
|
{{ form.defaultManual }}<br><br>
|
||||||
<label for="{{ form.overrideManual.id_for_label }}">Override settings</label><br>
|
<label for="{{ form.overrideManual.id_for_label }}">Override settings</label><br>
|
||||||
@@ -297,10 +387,24 @@
|
|||||||
<div class="platform">
|
<div class="platform">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<button type="submit"><i class="fas fa-rocket"></i> Generate Custom Client</button>
|
<button type="submit"><i class="fas fa-rocket"></i> Generate Custom Client</button>
|
||||||
<a href="https://github.com/bryangerlach/rdgen">Source Code on github</a>
|
|
||||||
<iframe src="https://github.com/sponsors/bryangerlach/button" title="Sponsor bryangerlach" height="32" width="114" style="border: 0; border-radius: 6px;"></iframe>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="text-align: center; margin: 30px 0;">
|
||||||
|
<a href="https://github.com/bryangerlach/rdgen"
|
||||||
|
target="_blank"
|
||||||
|
class="sponsor-button">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
Source Code on Github
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center; margin: 30px 0;">
|
||||||
|
<a href="https://github.com/sponsors/bryangerlach?o=esb"
|
||||||
|
target="_blank"
|
||||||
|
class="sponsor-button">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
Donate
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<script>
|
<script>
|
||||||
document.querySelectorAll('.platform-icon').forEach(icon => {
|
document.querySelectorAll('.platform-icon').forEach(icon => {
|
||||||
@@ -316,6 +420,101 @@
|
|||||||
document.getElementById("{{ form.logofile.id_for_label }}").addEventListener('change', function(event) {
|
document.getElementById("{{ form.logofile.id_for_label }}").addEventListener('change', function(event) {
|
||||||
previewImage(event.target, 'logo-preview');
|
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) {
|
||||||
|
document.getElementById("passwordRequirement").style.display = 'block';
|
||||||
|
document.getElementById("{{ form.permanentPassword.id_for_label }}").focus();
|
||||||
|
document.getElementById("{{ form.passApproveMode.id_for_label }}").value = 'password';
|
||||||
|
} else {
|
||||||
|
document.getElementById("passwordRequirement").style.display = 'none';
|
||||||
|
document.getElementById("{{ form.passApproveMode.id_for_label }}").value = 'password-click';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const enableKeyboard = document.getElementById("{{ form.enableKeyboard.id_for_label }}");
|
||||||
|
const enableClipboard = document.getElementById("{{ form.enableClipboard.id_for_label }}");
|
||||||
|
const enableFileTransfer = document.getElementById("{{ form.enableFileTransfer.id_for_label }}");
|
||||||
|
const enableAudio = document.getElementById("{{ form.enableAudio.id_for_label }}");
|
||||||
|
const enableTCP = document.getElementById("{{ form.enableTCP.id_for_label }}");
|
||||||
|
const enableRemoteRestart = document.getElementById("{{ form.enableRemoteRestart.id_for_label }}");
|
||||||
|
const enableRecording = document.getElementById("{{ form.enableRecording.id_for_label }}");
|
||||||
|
const enableBlockingInput = document.getElementById("{{ form.enableBlockingInput.id_for_label }}");
|
||||||
|
const enableRemoteModi = document.getElementById("{{ form.enableRemoteModi.id_for_label }}");
|
||||||
|
const enablePrinter = document.getElementById("{{ form.enablePrinter.id_for_label }}");
|
||||||
|
const enableCamera = document.getElementById("{{ form.enableCamera.id_for_label }}");
|
||||||
|
const enableTerminal = document.getElementById("{{ form.enableTerminal.id_for_label }}");
|
||||||
|
|
||||||
|
document.getElementById("{{ form.permissionsType.id_for_label }}").addEventListener('change', function() {
|
||||||
|
if (this.value === 'full') {
|
||||||
|
enableKeyboard.checked = true;
|
||||||
|
enableClipboard.checked = true;
|
||||||
|
enableFileTransfer.checked = true;
|
||||||
|
enableAudio.checked = true;
|
||||||
|
enableTCP.checked = true;
|
||||||
|
enableRemoteRestart.checked = true;
|
||||||
|
enableRecording.checked = true;
|
||||||
|
enableBlockingInput.checked = true;
|
||||||
|
enableRemoteModi.checked = true;
|
||||||
|
enablePrinter.checked = true;
|
||||||
|
enableCamera.checked = true;
|
||||||
|
enableTerminal.checked = true;
|
||||||
|
|
||||||
|
enableKeyboard.disabled = true;
|
||||||
|
enableClipboard.disabled = true;
|
||||||
|
enableFileTransfer.disabled = true;
|
||||||
|
enableAudio.disabled = true;
|
||||||
|
enableTCP.disabled = true;
|
||||||
|
enableRemoteRestart.disabled = true;
|
||||||
|
enableRecording.disabled = true;
|
||||||
|
enableBlockingInput.disabled = true;
|
||||||
|
enableRemoteModi.disabled = true;
|
||||||
|
enablePrinter.disabled = true;
|
||||||
|
enableCamera.disabled = true;
|
||||||
|
enableTerminal.disable = true;
|
||||||
|
} else if (this.value === 'view') {
|
||||||
|
enableKeyboard.checked = false;
|
||||||
|
enableClipboard.checked = false;
|
||||||
|
enableFileTransfer.checked = false;
|
||||||
|
enableAudio.checked = false;
|
||||||
|
enableTCP.checked = false;
|
||||||
|
enableRemoteRestart.checked = false;
|
||||||
|
enableRecording.checked = false;
|
||||||
|
enableBlockingInput.checked = false;
|
||||||
|
enableRemoteModi.checked = false;
|
||||||
|
enablePrinter.checked = false;
|
||||||
|
enableCamera.checked = false;
|
||||||
|
enableTerminal.checked = false;
|
||||||
|
|
||||||
|
enableKeyboard.disabled = true;
|
||||||
|
enableClipboard.disabled = true;
|
||||||
|
enableFileTransfer.disabled = true;
|
||||||
|
enableAudio.disabled = true;
|
||||||
|
enableTCP.disabled = true;
|
||||||
|
enableRemoteRestart.disabled = true;
|
||||||
|
enableRecording.disabled = true;
|
||||||
|
enableBlockingInput.disabled = true;
|
||||||
|
enableRemoteModi.disabled = true;
|
||||||
|
enablePrinter.disabled = true;
|
||||||
|
enableCamera.disabled = true;
|
||||||
|
enableTerminal.disable = true;
|
||||||
|
} else if (this.value === 'custom') {
|
||||||
|
enableKeyboard.disabled = false;
|
||||||
|
enableClipboard.disabled = false;
|
||||||
|
enableFileTransfer.disabled = false;
|
||||||
|
enableAudio.disabled = false;
|
||||||
|
enableTCP.disabled = false;
|
||||||
|
enableRemoteRestart.disabled = false;
|
||||||
|
enableRecording.disabled = false;
|
||||||
|
enableBlockingInput.disabled = false;
|
||||||
|
enableRemoteModi.disabled = false;
|
||||||
|
enablePrinter.checked = false;
|
||||||
|
enableCamera.checked = false;
|
||||||
|
enableTerminal.checked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
function previewImage(input, previewContainerId) {
|
function previewImage(input, previewContainerId) {
|
||||||
if (input.files && input.files[0]) {
|
if (input.files && input.files[0]) {
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
@@ -403,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 jsonData = JSON.stringify(formData, null, 2);
|
||||||
const blob = new Blob([jsonData], { type: "application/json" });
|
const blob = new Blob([jsonData], { type: "application/json" });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
@@ -464,6 +673,10 @@
|
|||||||
document.getElementById('id_logobase64').value = formData[key];
|
document.getElementById('id_logobase64').value = formData[key];
|
||||||
document.getElementById('logo-preview').innerHTML = `<img src="${formData[key]}" style="max-width: 300px; max-height: 60px;">`;
|
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;
|
background-color: #3498db;
|
||||||
transition: width 0.5s ease-in-out;
|
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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -140,8 +162,16 @@
|
|||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<div id="progressBarFill" class="progress-bar-fill"></div>
|
<div id="progressBarFill" class="progress-bar-fill"></div>
|
||||||
</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>
|
<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>
|
||||||
|
|
||||||
<div id="macosNote" class="macos-note">
|
<div id="macosNote" class="macos-note">
|
||||||
@@ -154,6 +184,7 @@
|
|||||||
const platform = '{{platform}}'.toLowerCase();
|
const platform = '{{platform}}'.toLowerCase();
|
||||||
const platformLogos = {
|
const platformLogos = {
|
||||||
'windows': document.getElementById('windowsLogo'),
|
'windows': document.getElementById('windowsLogo'),
|
||||||
|
'windows-x86': document.getElementById('windowsLogo'),
|
||||||
'macos': document.getElementById('macosLogo'),
|
'macos': document.getElementById('macosLogo'),
|
||||||
'linux': document.getElementById('linuxLogo'),
|
'linux': document.getElementById('linuxLogo'),
|
||||||
'android': document.getElementById('androidLogo')
|
'android': document.getElementById('androidLogo')
|
||||||
@@ -167,7 +198,7 @@
|
|||||||
document.getElementById('pageTitle').textContent = 'Generating MacOS Build';
|
document.getElementById('pageTitle').textContent = 'Generating MacOS Build';
|
||||||
platformLogos.macos.style.display = 'block';
|
platformLogos.macos.style.display = 'block';
|
||||||
document.getElementById('macosNote').style.display = 'block';
|
document.getElementById('macosNote').style.display = 'block';
|
||||||
} else if (platform === 'windows') {
|
} else if (platform === 'windows' | platform === 'windows-x86') {
|
||||||
document.getElementById('pageTitle').textContent = 'Generating Windows Build';
|
document.getElementById('pageTitle').textContent = 'Generating Windows Build';
|
||||||
platformLogos.windows.style.display = 'block';
|
platformLogos.windows.style.display = 'block';
|
||||||
} else if (platform === 'linux') {
|
} else if (platform === 'linux') {
|
||||||
@@ -211,7 +242,7 @@
|
|||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
window.location.replace('/check_for_file?filename={{filename}}&uuid={{uuid}}&platform={{platform}}');
|
window.location.replace('/check_for_file?filename={{filename}}&uuid={{uuid}}&platform={{platform}}');
|
||||||
}, 5000); // 5000 milliseconds = 5 seconds
|
}, 30000); // 20000 milliseconds = 20 seconds
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -4,11 +4,13 @@ from django.http import HttpResponse, JsonResponse
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
import os
|
import os
|
||||||
|
import secrets
|
||||||
import re
|
import re
|
||||||
import requests
|
import requests
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
|
import pyzipper
|
||||||
from django.conf import settings as _settings
|
from django.conf import settings as _settings
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from .forms import GenerateForm
|
from .forms import GenerateForm
|
||||||
@@ -20,6 +22,11 @@ def generator_view(request):
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = GenerateForm(request.POST, request.FILES)
|
form = GenerateForm(request.POST, request.FILES)
|
||||||
if form.is_valid():
|
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']
|
platform = form.cleaned_data['platform']
|
||||||
version = form.cleaned_data['version']
|
version = form.cleaned_data['version']
|
||||||
delayFix = form.cleaned_data['delayFix']
|
delayFix = form.cleaned_data['delayFix']
|
||||||
@@ -46,14 +53,20 @@ def generator_view(request):
|
|||||||
installation = form.cleaned_data['installation']
|
installation = form.cleaned_data['installation']
|
||||||
settings = form.cleaned_data['settings']
|
settings = form.cleaned_data['settings']
|
||||||
appname = form.cleaned_data['appname']
|
appname = form.cleaned_data['appname']
|
||||||
|
if not appname:
|
||||||
|
appname = "rustdesk"
|
||||||
filename = form.cleaned_data['exename']
|
filename = form.cleaned_data['exename']
|
||||||
compname = form.cleaned_data['compname']
|
compname = form.cleaned_data['compname']
|
||||||
if not compname:
|
if not compname:
|
||||||
compname = "Purslane Ltd"
|
compname = "Purslane Ltd"
|
||||||
|
androidappid = form.cleaned_data['androidappid']
|
||||||
|
if not androidappid:
|
||||||
|
androidappid = "com.carriez.flutter_hbb"
|
||||||
|
compname = compname.replace("&","\\&")
|
||||||
permPass = form.cleaned_data['permanentPassword']
|
permPass = form.cleaned_data['permanentPassword']
|
||||||
theme = form.cleaned_data['theme']
|
theme = form.cleaned_data['theme']
|
||||||
themeDorO = form.cleaned_data['themeDorO']
|
themeDorO = form.cleaned_data['themeDorO']
|
||||||
runasadmin = form.cleaned_data['runasadmin']
|
#runasadmin = form.cleaned_data['runasadmin']
|
||||||
passApproveMode = form.cleaned_data['passApproveMode']
|
passApproveMode = form.cleaned_data['passApproveMode']
|
||||||
denyLan = form.cleaned_data['denyLan']
|
denyLan = form.cleaned_data['denyLan']
|
||||||
enableDirectIP = form.cleaned_data['enableDirectIP']
|
enableDirectIP = form.cleaned_data['enableDirectIP']
|
||||||
@@ -73,6 +86,9 @@ def generator_view(request):
|
|||||||
removeWallpaper = form.cleaned_data['removeWallpaper']
|
removeWallpaper = form.cleaned_data['removeWallpaper']
|
||||||
defaultManual = form.cleaned_data['defaultManual']
|
defaultManual = form.cleaned_data['defaultManual']
|
||||||
overrideManual = form.cleaned_data['overrideManual']
|
overrideManual = form.cleaned_data['overrideManual']
|
||||||
|
enablePrinter = form.cleaned_data['enablePrinter']
|
||||||
|
enableCamera = form.cleaned_data['enableCamera']
|
||||||
|
enableTerminal = form.cleaned_data['enableTerminal']
|
||||||
|
|
||||||
if all(char.isascii() for char in filename):
|
if all(char.isascii() for char in filename):
|
||||||
filename = re.sub(r'[^\w\s-]', '_', filename).strip()
|
filename = re.sub(r'[^\w\s-]', '_', filename).strip()
|
||||||
@@ -89,18 +105,32 @@ def generator_view(request):
|
|||||||
iconfile = form.cleaned_data.get('iconfile')
|
iconfile = form.cleaned_data.get('iconfile')
|
||||||
if not iconfile:
|
if not iconfile:
|
||||||
iconfile = form.cleaned_data.get('iconbase64')
|
iconfile = form.cleaned_data.get('iconbase64')
|
||||||
iconlink = save_png(iconfile,myuuid,full_url,"icon.png")
|
iconlink_url, iconlink_uuid, iconlink_file = save_png(iconfile,myuuid,full_url,"icon.png")
|
||||||
except:
|
except:
|
||||||
print("failed to get icon, using default")
|
print("failed to get icon, using default")
|
||||||
iconlink = "false"
|
iconlink_url = "false"
|
||||||
|
iconlink_uuid = "false"
|
||||||
|
iconlink_file = "false"
|
||||||
try:
|
try:
|
||||||
logofile = form.cleaned_data.get('logofile')
|
logofile = form.cleaned_data.get('logofile')
|
||||||
if not logofile:
|
if not logofile:
|
||||||
logofile = form.cleaned_data.get('logobase64')
|
logofile = form.cleaned_data.get('logobase64')
|
||||||
logolink = save_png(logofile,myuuid,full_url,"logo.png")
|
logolink_url, logolink_uuid, logolink_file = save_png(logofile,myuuid,full_url,"logo.png")
|
||||||
except:
|
except:
|
||||||
print("failed to get logo")
|
print("failed to get logo")
|
||||||
logolink = "false"
|
logolink_url = "false"
|
||||||
|
logolink_uuid = "false"
|
||||||
|
logolink_file = "false"
|
||||||
|
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
|
###create the custom.txt json here and send in as inputs below
|
||||||
decodedCustom = {}
|
decodedCustom = {}
|
||||||
@@ -118,14 +148,18 @@ def generator_view(request):
|
|||||||
decodedCustom['password'] = permPass
|
decodedCustom['password'] = permPass
|
||||||
if theme != "system":
|
if theme != "system":
|
||||||
if themeDorO == "default":
|
if themeDorO == "default":
|
||||||
|
if platform == "windows-x86":
|
||||||
|
decodedCustom['default-settings']['allow-darktheme'] = 'Y' if theme == "dark" else 'N'
|
||||||
|
else:
|
||||||
decodedCustom['default-settings']['theme'] = theme
|
decodedCustom['default-settings']['theme'] = theme
|
||||||
elif themeDorO == "override":
|
elif themeDorO == "override":
|
||||||
|
if platform == "windows-x86":
|
||||||
|
decodedCustom['override-settings']['allow-darktheme'] = 'Y' if theme == "dark" else 'N'
|
||||||
|
else:
|
||||||
decodedCustom['override-settings']['theme'] = theme
|
decodedCustom['override-settings']['theme'] = theme
|
||||||
decodedCustom['approve-mode'] = passApproveMode
|
|
||||||
decodedCustom['enable-lan-discovery'] = 'N' if denyLan else 'Y'
|
decodedCustom['enable-lan-discovery'] = 'N' if denyLan else 'Y'
|
||||||
decodedCustom['direct-server'] = 'Y' if enableDirectIP else 'N'
|
#decodedCustom['direct-server'] = 'Y' if enableDirectIP else 'N'
|
||||||
decodedCustom['allow-auto-disconnect'] = 'Y' if autoClose else 'N'
|
decodedCustom['allow-auto-disconnect'] = 'Y' if autoClose else 'N'
|
||||||
decodedCustom['allow-remove-wallpaper'] = 'Y' if removeWallpaper else 'N'
|
|
||||||
if permissionsDorO == "default":
|
if permissionsDorO == "default":
|
||||||
decodedCustom['default-settings']['access-mode'] = permissionsType
|
decodedCustom['default-settings']['access-mode'] = permissionsType
|
||||||
decodedCustom['default-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
decodedCustom['default-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
||||||
@@ -137,6 +171,14 @@ def generator_view(request):
|
|||||||
decodedCustom['default-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
decodedCustom['default-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
||||||
decodedCustom['default-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
decodedCustom['default-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
||||||
decodedCustom['default-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
decodedCustom['default-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
||||||
|
decodedCustom['default-settings']['direct-server'] = 'Y' if enableDirectIP else 'N'
|
||||||
|
decodedCustom['default-settings']['verification-method'] = 'use-permanent-password' if hidecm else 'use-both-passwords'
|
||||||
|
decodedCustom['default-settings']['approve-mode'] = passApproveMode
|
||||||
|
decodedCustom['default-settings']['allow-hide-cm'] = 'Y' if hidecm else 'N'
|
||||||
|
decodedCustom['default-settings']['allow-remove-wallpaper'] = 'Y' if removeWallpaper else 'N'
|
||||||
|
decodedCustom['default-settings']['enable-remote-printer'] = 'Y' if enablePrinter else 'N'
|
||||||
|
decodedCustom['default-settings']['enable-camera'] = 'Y' if enableCamera else 'N'
|
||||||
|
decodedCustom['default-settings']['enable-terminal'] = 'Y' if enableTerminal else 'N'
|
||||||
else:
|
else:
|
||||||
decodedCustom['override-settings']['access-mode'] = permissionsType
|
decodedCustom['override-settings']['access-mode'] = permissionsType
|
||||||
decodedCustom['override-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
decodedCustom['override-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
||||||
@@ -148,6 +190,14 @@ def generator_view(request):
|
|||||||
decodedCustom['override-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
decodedCustom['override-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
||||||
decodedCustom['override-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
decodedCustom['override-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
||||||
decodedCustom['override-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
decodedCustom['override-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
||||||
|
decodedCustom['override-settings']['direct-server'] = 'Y' if enableDirectIP else 'N'
|
||||||
|
decodedCustom['override-settings']['verification-method'] = 'use-permanent-password' if hidecm else 'use-both-passwords'
|
||||||
|
decodedCustom['override-settings']['approve-mode'] = passApproveMode
|
||||||
|
decodedCustom['override-settings']['allow-hide-cm'] = 'Y' if hidecm else 'N'
|
||||||
|
decodedCustom['override-settings']['allow-remove-wallpaper'] = 'Y' if removeWallpaper else 'N'
|
||||||
|
decodedCustom['override-settings']['enable-remote-printer'] = 'Y' if enablePrinter else 'N'
|
||||||
|
decodedCustom['override-settings']['enable-camera'] = 'Y' if enableCamera else 'N'
|
||||||
|
decodedCustom['override-settings']['enable-terminal'] = 'Y' if enableTerminal else 'N'
|
||||||
|
|
||||||
for line in defaultManual.splitlines():
|
for line in defaultManual.splitlines():
|
||||||
k, value = line.split('=')
|
k, value = line.split('=')
|
||||||
@@ -163,25 +213,28 @@ def generator_view(request):
|
|||||||
base64_bytes = base64.b64encode(string_bytes)
|
base64_bytes = base64.b64encode(string_bytes)
|
||||||
encodedCustom = base64_bytes.decode("ascii")
|
encodedCustom = base64_bytes.decode("ascii")
|
||||||
|
|
||||||
#github limits inputs to 10, so lump extras into one with json
|
# #github limits inputs to 10, so lump extras into one with json
|
||||||
extras = {}
|
# extras = {}
|
||||||
extras['genurl'] = _settings.GENURL
|
# extras['genurl'] = _settings.GENURL
|
||||||
extras['runasadmin'] = runasadmin
|
# #extras['runasadmin'] = runasadmin
|
||||||
extras['urlLink'] = urlLink
|
# extras['urlLink'] = urlLink
|
||||||
extras['downloadLink'] = downloadLink
|
# extras['downloadLink'] = downloadLink
|
||||||
extras['delayFix'] = 'true' if delayFix else 'false'
|
# extras['delayFix'] = 'true' if delayFix else 'false'
|
||||||
extras['version'] = version
|
# extras['rdgen'] = 'true'
|
||||||
extras['rdgen'] = 'true'
|
# extras['cycleMonitor'] = 'true' if cycleMonitor else 'false'
|
||||||
extras['cycleMonitor'] = 'true' if cycleMonitor else 'false'
|
# extras['xOffline'] = 'true' if xOffline else 'false'
|
||||||
extras['xOffline'] = 'true' if xOffline else 'false'
|
# extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false'
|
||||||
extras['hidecm'] = 'true' if hidecm else 'false'
|
# extras['compname'] = compname
|
||||||
extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false'
|
# extras['androidappid'] = androidappid
|
||||||
extras['compname'] = compname
|
# extra_input = json.dumps(extras)
|
||||||
extra_input = json.dumps(extras)
|
|
||||||
|
|
||||||
####from here run the github action, we need user, repo, access token.
|
####from here run the github action, we need user, repo, access token.
|
||||||
if platform == 'windows':
|
if platform == 'windows':
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
||||||
|
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':
|
elif platform == 'linux':
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-linux.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-linux.yml/dispatches'
|
||||||
elif platform == 'android':
|
elif platform == 'android':
|
||||||
@@ -190,57 +243,154 @@ def generator_view(request):
|
|||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-macos.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-macos.yml/dispatches'
|
||||||
else:
|
else:
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
||||||
|
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'
|
#url = 'https://api.github.com/repos/'+_settings.GHUSER+'/rustdesk/actions/workflows/test.yml/dispatches'
|
||||||
data = {
|
inputs_raw = {
|
||||||
"ref":"master",
|
|
||||||
"inputs":{
|
|
||||||
"server":server,
|
"server":server,
|
||||||
"key":key,
|
"key":key,
|
||||||
"apiServer":apiServer,
|
"apiServer":apiServer,
|
||||||
"custom":encodedCustom,
|
"custom":encodedCustom,
|
||||||
"uuid":myuuid,
|
"uuid":myuuid,
|
||||||
#"iconbase64":iconbase64.decode("utf-8"),
|
"iconlink_url":iconlink_url,
|
||||||
#"logobase64":logobase64.decode("utf-8") if logobase64 else "",
|
"iconlink_uuid":iconlink_uuid,
|
||||||
"iconlink":iconlink,
|
"iconlink_file":iconlink_file,
|
||||||
"logolink":logolink,
|
"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,
|
"appname":appname,
|
||||||
"extras":extra_input,
|
"genurl":_settings.GENURL,
|
||||||
|
"urlLink":urlLink,
|
||||||
|
"downloadLink":downloadLink,
|
||||||
|
"delayFix": 'true' if delayFix else 'false',
|
||||||
|
"rdgen":'true',
|
||||||
|
"cycleMonitor": 'true' if cycleMonitor else 'false',
|
||||||
|
"xOffline": 'true' if xOffline else 'false',
|
||||||
|
"removeNewVersionNotif": 'true' if removeNewVersionNotif else 'false',
|
||||||
|
"compname": compname,
|
||||||
|
"androidappid":androidappid,
|
||||||
"filename":filename
|
"filename":filename
|
||||||
}
|
}
|
||||||
|
|
||||||
|
temp_json_path = f"data_{uuid.uuid4()}.json"
|
||||||
|
zip_filename = f"secrets_{uuid.uuid4()}.zip"
|
||||||
|
zip_path = "temp_zips/%s" % (zip_filename)
|
||||||
|
Path("temp_zips").mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
with open(temp_json_path, "w") as f:
|
||||||
|
json.dump(inputs_raw, f)
|
||||||
|
|
||||||
|
with pyzipper.AESZipFile(zip_path, 'w', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) as zf:
|
||||||
|
zf.setpassword(_settings.ZIP_PASSWORD.encode())
|
||||||
|
zf.write(temp_json_path, arcname="secrets.json")
|
||||||
|
|
||||||
|
if os.path.exists(temp_json_path):
|
||||||
|
os.remove(temp_json_path)
|
||||||
|
|
||||||
|
zipJson = {}
|
||||||
|
zipJson['url'] = full_url
|
||||||
|
zipJson['file'] = zip_filename
|
||||||
|
|
||||||
|
zip_url = json.dumps(zipJson)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"ref":_settings.GHBRANCH,
|
||||||
|
"inputs":{
|
||||||
|
"version":version,
|
||||||
|
"zip_url":zip_url
|
||||||
|
},
|
||||||
|
"return_run_details": True
|
||||||
}
|
}
|
||||||
#print(data)
|
#print(data)
|
||||||
headers = {
|
headers = {
|
||||||
'Accept': 'application/vnd.github+json',
|
'Accept': 'application/vnd.github+json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer '+_settings.GHBEARER,
|
'Authorization': 'Bearer '+_settings.GHBEARER,
|
||||||
'X-GitHub-Api-Version': '2022-11-28'
|
'X-GitHub-Api-Version': '2026-03-10'
|
||||||
}
|
}
|
||||||
create_github_run(myuuid)
|
new_github_run = GithubRun(
|
||||||
|
uuid=myuuid,
|
||||||
|
status="Starting generator...please wait"
|
||||||
|
)
|
||||||
|
try:
|
||||||
response = requests.post(url, json=data, headers=headers)
|
response = requests.post(url, json=data, headers=headers)
|
||||||
print(response)
|
#print(response)
|
||||||
if response.status_code == 204:
|
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})
|
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:
|
else:
|
||||||
return JsonResponse({"error": "Something went wrong"})
|
#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:
|
else:
|
||||||
form = GenerateForm()
|
form = GenerateForm()
|
||||||
#return render(request, 'maintenance.html')
|
#return render(request, 'maintenance.html')
|
||||||
return render(request, 'generator.html', {'form': form})
|
return render(request, 'generator.html', {'form': form})
|
||||||
|
|
||||||
|
|
||||||
def check_for_file(request):
|
from django.shortcuts import render, get_object_or_404
|
||||||
filename = request.GET['filename']
|
from django.db.models import Q
|
||||||
uuid = request.GET['uuid']
|
|
||||||
platform = request.GET['platform']
|
def check_for_file(request):
|
||||||
gh_run = GithubRun.objects.filter(Q(uuid=uuid)).first()
|
filename = request.GET.get('filename')
|
||||||
status = gh_run.status
|
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
|
||||||
|
})
|
||||||
|
|
||||||
#if file_exists:
|
|
||||||
if status == "Success":
|
|
||||||
return render(request, 'generated.html', {'filename': filename, 'uuid':uuid, 'platform':platform})
|
|
||||||
else:
|
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):
|
def download(request):
|
||||||
filename = request.GET['filename']
|
filename = request.GET['filename']
|
||||||
@@ -328,7 +478,7 @@ def startgh(request):
|
|||||||
####from here run the github action, we need user, repo, access token.
|
####from here run the github action, we need user, repo, access token.
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-'+data_.get('platform')+'.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-'+data_.get('platform')+'.yml/dispatches'
|
||||||
data = {
|
data = {
|
||||||
"ref":"master",
|
"ref": _settings.GHBRANCH,
|
||||||
"inputs":{
|
"inputs":{
|
||||||
"server":data_.get('server'),
|
"server":data_.get('server'),
|
||||||
"key":data_.get('key'),
|
"key":data_.get('key'),
|
||||||
@@ -346,7 +496,7 @@ def startgh(request):
|
|||||||
'Accept': 'application/vnd.github+json',
|
'Accept': 'application/vnd.github+json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer '+_settings.GHBEARER,
|
'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)
|
response = requests.post(url, json=data, headers=headers)
|
||||||
print(response)
|
print(response)
|
||||||
@@ -371,12 +521,12 @@ def save_png(file, uuid, domain, name):
|
|||||||
with open(file_save_path, "wb+") as f:
|
with open(file_save_path, "wb+") as f:
|
||||||
for chunk in file.chunks():
|
for chunk in file.chunks():
|
||||||
f.write(chunk)
|
f.write(chunk)
|
||||||
imageJson = {}
|
# imageJson = {}
|
||||||
imageJson['url'] = domain
|
# imageJson['url'] = domain
|
||||||
imageJson['uuid'] = uuid
|
# imageJson['uuid'] = uuid
|
||||||
imageJson['file'] = name
|
# imageJson['file'] = name
|
||||||
#return "%s/%s" % (domain, file_save_path)
|
#return "%s/%s" % (domain, file_save_path)
|
||||||
return json.dumps(imageJson)
|
return domain, uuid, name
|
||||||
|
|
||||||
def save_custom_client(request):
|
def save_custom_client(request):
|
||||||
file = request.FILES['file']
|
file = request.FILES['file']
|
||||||
@@ -388,3 +538,38 @@ def save_custom_client(request):
|
|||||||
f.write(chunk)
|
f.write(chunk)
|
||||||
|
|
||||||
return HttpResponse("File saved successfully!")
|
return HttpResponse("File saved successfully!")
|
||||||
|
|
||||||
|
def cleanup_secrets(request):
|
||||||
|
# Pass the UUID as a query param or in JSON body
|
||||||
|
data = json.loads(request.body)
|
||||||
|
my_uuid = data.get('uuid')
|
||||||
|
|
||||||
|
if not my_uuid:
|
||||||
|
return HttpResponse("Missing UUID", status=400)
|
||||||
|
|
||||||
|
# 1. Find the files in your temp directory matching the UUID
|
||||||
|
temp_dir = os.path.join('temp_zips')
|
||||||
|
|
||||||
|
# We look for any file starting with 'secrets_' and containing the uuid
|
||||||
|
for filename in os.listdir(temp_dir):
|
||||||
|
if my_uuid in filename and filename.endswith('.zip'):
|
||||||
|
file_path = os.path.join(temp_dir, filename)
|
||||||
|
try:
|
||||||
|
os.remove(file_path)
|
||||||
|
print(f"Successfully deleted {file_path}")
|
||||||
|
except OSError as e:
|
||||||
|
print(f"Error deleting file: {e}")
|
||||||
|
|
||||||
|
return HttpResponse("Cleanup successful", status=200)
|
||||||
|
|
||||||
|
def get_zip(request):
|
||||||
|
filename = request.GET['filename']
|
||||||
|
#filename = filename+".exe"
|
||||||
|
file_path = os.path.join('temp_zips',filename)
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
response = HttpResponse(file, headers={
|
||||||
|
'Content-Type': 'application/vnd.microsoft.portable-executable',
|
||||||
|
'Content-Disposition': f'attachment; filename="{filename}"'
|
||||||
|
})
|
||||||
|
|
||||||
|
return response
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ django
|
|||||||
requests
|
requests
|
||||||
pillow
|
pillow
|
||||||
gunicorn
|
gunicorn
|
||||||
|
pyzipper
|
||||||
22
setup.md
22
setup.md
@@ -20,15 +20,37 @@
|
|||||||
* Now click New repository secret
|
* Now click New repository secret
|
||||||
* Set the Name to GENURL
|
* Set the Name to GENURL
|
||||||
* Set the Secret to https://rdgen.hostname.com (or whatever your server will be accessed from)
|
* Set the Secret to https://rdgen.hostname.com (or whatever your server will be accessed from)
|
||||||
|
* Now click New repository secret again
|
||||||
|
* Set the Name to ZIP_PASSWORD
|
||||||
|
* Set the Secret to any password you want (use this in the next step as well) - generate a password by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
|
||||||
4. Now download the docker-compose.yml file and fill in the environment variables:
|
4. Now download the docker-compose.yml file and fill in the environment variables:
|
||||||
* SECRET_KEY="your secret key" - generate a secret key by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
|
* SECRET_KEY="your secret key" - generate a secret key by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
|
||||||
* GHUSER="your github username"
|
* GHUSER="your github username"
|
||||||
* GHBEARER="your fine-grained access token"
|
* GHBEARER="your fine-grained access token"
|
||||||
|
* ZIP_PASSWORD="the same password that you entered as a github secret"
|
||||||
* PROTOCOL="https" *optional - defaults to "https", change to "http" if you need to
|
* PROTOCOL="https" *optional - defaults to "https", change to "http" if you need to
|
||||||
* REPONAME="rdgen" *optional - defaults to "rdgen", change this if you renamed the repo when you forked it
|
* REPONAME="rdgen" *optional - defaults to "rdgen", change this if you renamed the repo when you forked it
|
||||||
5. Now just run ```docker compose up -d```
|
5. Now just run ```docker compose up -d```
|
||||||
|
|
||||||
|
|
||||||
|
## 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:
|
## Host manually:
|
||||||
|
|
||||||
1. A Github account with a fork of this repo
|
1. A Github account with a fork of this repo
|
||||||
|
|||||||
Reference in New Issue
Block a user