mirror of https://github.com/ospab/ostp.git
Compare commits
5 Commits
master
...
v0.4.5-bet
| Author | SHA1 | Date |
|---|---|---|
|
|
a63c34669b | |
|
|
b18de0379c | |
|
|
96d6bb61d2 | |
|
|
8af4be9b0a | |
|
|
8b5c0a3a8c |
|
|
@ -414,9 +414,32 @@ jobs:
|
|||
Copy-Item "ostp-gui/src-tauri/target/${{ matrix.target }}/release/ostp-gui.exe" $dir
|
||||
Copy-Item "target/${{ matrix.target }}/release/ostp-tun-helper.exe" $dir
|
||||
Copy-Item "target/${{ matrix.target }}/release/wintun.dll" $dir
|
||||
|
||||
|
||||
Compress-Archive -Path "$dir/*" -DestinationPath "ostp-windows-gui-${{ matrix.arch }}.zip" -Force
|
||||
|
||||
# The installer is what removes the per-connect consent prompt: it runs
|
||||
# elevated, so its hook can register the helper's Scheduled Task once.
|
||||
# The portable zip above cannot, and falls back to asking on first connect.
|
||||
# The sidecar and its config are confined to this step: declaring
|
||||
# externalBin in an auto-merged tauri.windows.conf.json would force every
|
||||
# Windows build, down to a bare `cargo check`, to have the helper staged
|
||||
# first, and fail the build script when it is not.
|
||||
- name: Build NSIS Installer
|
||||
working-directory: ostp-gui
|
||||
# Chained, not two lines: pwsh does not abort a run block when a native
|
||||
# command fails, so a staging failure would otherwise be reported far
|
||||
# downstream as a missing sidecar rather than as itself.
|
||||
run: node stage-sidecar.cjs --release --target ${{ matrix.target }} && npx tauri build --bundles nsis --target ${{ matrix.target }} --config src-tauri/tauri.installer.conf.json
|
||||
|
||||
- name: Collect installer
|
||||
shell: pwsh
|
||||
run: |
|
||||
$nsis = Get-ChildItem -Path "ostp-gui/src-tauri/target/${{ matrix.target }}/release/bundle/nsis" -Filter *-setup.exe -ErrorAction SilentlyContinue |
|
||||
Select-Object -First 1
|
||||
if (-not $nsis) { Write-Error "NSIS installer was not produced"; exit 1 }
|
||||
Copy-Item $nsis.FullName "ostp-windows-gui-${{ matrix.arch }}-setup.exe"
|
||||
Write-Host "installer: $($nsis.Name) -> ostp-windows-gui-${{ matrix.arch }}-setup.exe"
|
||||
|
||||
- name: Upload to GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
|
|
@ -426,7 +449,9 @@ jobs:
|
|||
# real stable release.
|
||||
tag_name: ${{ needs.resolve-channel.outputs.tag_name }}
|
||||
prerelease: ${{ needs.resolve-channel.outputs.prerelease }}
|
||||
files: ostp-windows-gui-${{ matrix.arch }}.zip
|
||||
files: |
|
||||
ostp-windows-gui-${{ matrix.arch }}.zip
|
||||
ostp-windows-gui-${{ matrix.arch }}-setup.exe
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,3 +57,6 @@ ostp-control/
|
|||
netstack-smoltcp/
|
||||
dnstt/
|
||||
ostp-web/
|
||||
|
||||
# Tauri sidecar staging area (copied from target/ at build time)
|
||||
ostp-gui/src-tauri/binaries/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"target_version": "0.4.4",
|
||||
"branch": "master",
|
||||
"target_version": "0.4.5",
|
||||
"branch": "beta",
|
||||
"alpha_iteration": 0,
|
||||
"beta_iteration": 0
|
||||
"beta_iteration": 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1386,7 +1386,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
|||
|
||||
[[package]]
|
||||
name = "ostp"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
|
@ -1409,7 +1409,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-client"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
|
@ -1440,7 +1440,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-core"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
|
@ -1474,7 +1474,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-server"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
|
|
@ -1507,7 +1507,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-tun"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"libc",
|
||||
|
|
@ -1519,7 +1519,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-tun-helper"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ resolver = "2"
|
|||
[workspace.package]
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 0.4.4+31
|
||||
version: 0.4.5+33
|
||||
|
||||
environment:
|
||||
sdk: ^3.11.4
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"name": "ostp-gui",
|
||||
"private": true,
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"tauri": "tauri",
|
||||
"dev": "cargo build -p ostp-tun-helper && npx tauri dev",
|
||||
"build": "cargo build -p ostp-tun-helper --release && npx tauri build --no-bundle",
|
||||
"build:installer": "cargo build -p ostp-tun-helper --release && npx tauri build",
|
||||
"build:dist": "npm run build && node build_dist.js"
|
||||
"build:installer": "cargo build -p ostp-tun-helper --release && node stage-sidecar.cjs --release && npx tauri build --bundles nsis --config src-tauri/tauri.installer.conf.json",
|
||||
"build:dist": "npm run build && node build_dist.js",
|
||||
"sidecar": "node stage-sidecar.cjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2"
|
||||
|
|
|
|||
|
|
@ -2665,7 +2665,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-client"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
|
|
@ -2696,7 +2696,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-core"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
|
@ -2713,7 +2713,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-gui"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"json_comments",
|
||||
|
|
@ -2733,7 +2733,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ostp-tun"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"libc",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ostp-gui"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
description = "OSTP desktop GUI"
|
||||
authors = ["ospab"]
|
||||
edition = "2021"
|
||||
|
|
|
|||
|
|
@ -864,8 +864,12 @@ fn xml_unescape(s: &str) -> String {
|
|||
///
|
||||
/// Queried as XML rather than `/FO LIST /V`: the list format's field labels are
|
||||
/// localized (on a Russian Windows "Task To Run" is "Задача для запуска"),
|
||||
/// whereas XML tag names are fixed. schtasks writes UTF-16LE with a BOM here,
|
||||
/// but tolerate UTF-8 in case that ever changes.
|
||||
/// whereas XML tag names are fixed.
|
||||
///
|
||||
/// Encoding depends on where the output goes, which is measured rather than
|
||||
/// assumed: to a console schtasks writes UTF-16LE with a BOM, but into a
|
||||
/// redirected pipe — our case — it writes UTF-8 with no BOM. Both are handled,
|
||||
/// keyed off the BOM, so this keeps working if that ever flips.
|
||||
#[cfg(target_os = "windows")]
|
||||
fn helper_task_command() -> Option<String> {
|
||||
let out = quiet_command("schtasks")
|
||||
|
|
@ -1013,24 +1017,49 @@ fn install_helper_task(exe: &std::path::Path) -> anyhow::Result<()> {
|
|||
.args(["-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden", "-Command", &ps])
|
||||
.status();
|
||||
|
||||
// schtasks has exited by now, so this is safe.
|
||||
// 1223 is ERROR_CANCELLED: the consent prompt was declined. Nothing was
|
||||
// launched, so there is no point waiting for a task to appear.
|
||||
if let Ok(s) = &status {
|
||||
if s.code() == Some(1223) {
|
||||
let _ = std::fs::remove_file(&xml_path);
|
||||
anyhow::bail!("the consent prompt was declined");
|
||||
}
|
||||
}
|
||||
|
||||
// The exit code is advisory only, never proof of success. `-Verb RunAs`
|
||||
// launches through ShellExecute, and a non-elevated parent frequently
|
||||
// cannot read the elevated child's exit code — `$p.ExitCode` then yields
|
||||
// $null, and `exit $null` leaves PowerShell reporting 0. A failed
|
||||
// registration would sail straight through a `s.success()` check.
|
||||
//
|
||||
// Worse, -Wait does not reliably block until the elevated process exits.
|
||||
// Deleting the XML right after the call raced schtasks reading it — the
|
||||
// exact bug that made the previous attempt fail — so wait for the task
|
||||
// itself to show up. These queries are windowless, so unlike the earlier
|
||||
// polling loop they cost the user nothing to watch.
|
||||
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(15);
|
||||
let mut registered = false;
|
||||
while std::time::Instant::now() < deadline {
|
||||
if helper_task_matches(exe) {
|
||||
registered = true;
|
||||
break;
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(250));
|
||||
}
|
||||
|
||||
// Only now is deleting it safe.
|
||||
let _ = std::fs::remove_file(&xml_path);
|
||||
|
||||
if registered {
|
||||
return Ok(());
|
||||
}
|
||||
match status {
|
||||
Ok(s) if s.success() => {}
|
||||
Ok(s) => anyhow::bail!(
|
||||
"registering the scheduled task failed (exit code {:?}). A declined consent prompt \
|
||||
reports 1223.",
|
||||
"the scheduled task did not appear after registration (powershell exit {:?})",
|
||||
s.code()
|
||||
),
|
||||
Err(e) => anyhow::bail!("could not run powershell to register the task: {e}"),
|
||||
}
|
||||
|
||||
if helper_task_matches(exe) {
|
||||
Ok(())
|
||||
} else {
|
||||
anyhow::bail!("schtasks reported success but the task does not point at {}", exe.display())
|
||||
}
|
||||
}
|
||||
|
||||
/// Escape a value for embedding in a PowerShell single-quoted string.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "ostp-gui",
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.5",
|
||||
"identifier": "com.ospab.ostp",
|
||||
"build": {
|
||||
"frontendDist": "../src"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"bundle": {
|
||||
"externalBin": ["binaries/ostp-tun-helper"],
|
||||
"resources": { "binaries/wintun.dll": "wintun.dll" },
|
||||
"windows": {
|
||||
"nsis": {
|
||||
"installMode": "perMachine",
|
||||
"installerHooks": "./windows/hooks.nsh"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
; Registers the Scheduled Task that lets the GUI start the TUN helper elevated
|
||||
; without a consent prompt.
|
||||
;
|
||||
; This belongs in the installer, not in the app. Registering a task that runs
|
||||
; with elevated rights is itself a privileged operation, so an unprivileged GUI
|
||||
; can only get one by raising a UAC prompt — which is the very thing we are
|
||||
; trying to remove. The installer already runs elevated, so here it costs
|
||||
; nothing: the user consents once, to the install, and never again per connect.
|
||||
;
|
||||
; The task carries no usable trigger (a one-shot dated in the past), because it
|
||||
; exists solely to be started on demand by the app.
|
||||
|
||||
!macro OSTP_WRITE_TASK_XML OUTFILE
|
||||
; NSIS is built in Unicode mode here, so FileWrite emits UTF-16LE — which is
|
||||
; what `schtasks /XML` requires. It still needs the byte-order mark itself.
|
||||
FileOpen $R1 "${OUTFILE}" w
|
||||
FileWriteWord $R1 65279
|
||||
FileWrite $R1 '<?xml version="1.0" encoding="UTF-16"?>$\r$\n'
|
||||
FileWrite $R1 '<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">$\r$\n'
|
||||
FileWrite $R1 ' <RegistrationInfo>$\r$\n'
|
||||
FileWrite $R1 ' <Description>Starts the OSTP TUN helper elevated so connecting does not prompt for consent every time.</Description>$\r$\n'
|
||||
FileWrite $R1 ' </RegistrationInfo>$\r$\n'
|
||||
FileWrite $R1 ' <Principals>$\r$\n'
|
||||
FileWrite $R1 ' <Principal id="Author">$\r$\n'
|
||||
; S-1-5-32-545 is BUILTIN\Users by SID rather than by name: the name is
|
||||
; localized ("Пользователи" on a Russian Windows) and would not resolve.
|
||||
; Combined with InteractiveToken this makes the task run as whichever user
|
||||
; actually launches it, so a machine-wide install still works for every
|
||||
; account instead of only the one that happened to run the installer.
|
||||
FileWrite $R1 ' <GroupId>S-1-5-32-545</GroupId>$\r$\n'
|
||||
FileWrite $R1 ' <LogonType>InteractiveToken</LogonType>$\r$\n'
|
||||
FileWrite $R1 ' <RunLevel>HighestAvailable</RunLevel>$\r$\n'
|
||||
FileWrite $R1 ' </Principal>$\r$\n'
|
||||
FileWrite $R1 ' </Principals>$\r$\n'
|
||||
FileWrite $R1 ' <Settings>$\r$\n'
|
||||
; Parallel: reconnecting before a previous helper has fully exited must not
|
||||
; be silently dropped as a duplicate instance.
|
||||
FileWrite $R1 ' <MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>$\r$\n'
|
||||
; A VPN is most needed on battery, and a tunnel must not be killed on unplug.
|
||||
FileWrite $R1 ' <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>$\r$\n'
|
||||
FileWrite $R1 ' <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>$\r$\n'
|
||||
FileWrite $R1 ' <StartWhenAvailable>false</StartWhenAvailable>$\r$\n'
|
||||
FileWrite $R1 ' <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>$\r$\n'
|
||||
; PT0S disables the execution time limit; the default would tear the tunnel
|
||||
; down after three days.
|
||||
FileWrite $R1 ' <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>$\r$\n'
|
||||
FileWrite $R1 ' <Enabled>true</Enabled>$\r$\n'
|
||||
FileWrite $R1 ' <Hidden>false</Hidden>$\r$\n'
|
||||
FileWrite $R1 ' <AllowHardTerminate>true</AllowHardTerminate>$\r$\n'
|
||||
FileWrite $R1 ' </Settings>$\r$\n'
|
||||
FileWrite $R1 ' <Actions Context="Author">$\r$\n'
|
||||
FileWrite $R1 ' <Exec>$\r$\n'
|
||||
FileWrite $R1 ' <Command>$INSTDIR\ostp-tun-helper.exe</Command>$\r$\n'
|
||||
; The port and auth token change per launch and a task stores a fixed command
|
||||
; line, so they travel in this file instead. %LOCALAPPDATA% is deliberately
|
||||
; left unexpanded: Task Scheduler expands it when the task runs, which lands
|
||||
; on the profile of whoever launched it rather than the installing user's.
|
||||
FileWrite $R1 ' <Arguments>--args-file "%LOCALAPPDATA%\OSTP\helper-args.json"</Arguments>$\r$\n'
|
||||
FileWrite $R1 ' </Exec>$\r$\n'
|
||||
FileWrite $R1 ' </Actions>$\r$\n'
|
||||
FileWrite $R1 '</Task>$\r$\n'
|
||||
FileClose $R1
|
||||
!macroend
|
||||
|
||||
!macro NSIS_HOOK_POSTINSTALL
|
||||
; Bundled resources land in $INSTDIR\resources, but the helper loads wintun
|
||||
; with a plain LoadLibrary, which searches its own directory — so put a copy
|
||||
; beside the executables.
|
||||
DetailPrint "Placing wintun.dll next to the helper..."
|
||||
CopyFiles /SILENT "$INSTDIR\resources\wintun.dll" "$INSTDIR\wintun.dll"
|
||||
|
||||
DetailPrint "Registering the OSTP TUN helper task..."
|
||||
!insertmacro OSTP_WRITE_TASK_XML "$PLUGINSDIR\ostp-helper-task.xml"
|
||||
|
||||
; /F overwrites an existing registration, so reinstalling or upgrading to a
|
||||
; different directory repoints the task instead of leaving a stale path — the
|
||||
; app verifies the registered path at runtime and would otherwise have to
|
||||
; re-register it with a prompt.
|
||||
nsExec::ExecToLog 'schtasks.exe /Create /TN "OSTP TUN Helper" /XML "$PLUGINSDIR\ostp-helper-task.xml" /F'
|
||||
Pop $R0
|
||||
Delete "$PLUGINSDIR\ostp-helper-task.xml"
|
||||
|
||||
${If} $R0 == 0
|
||||
DetailPrint "Helper task registered; connecting will not prompt for consent."
|
||||
${Else}
|
||||
; Not fatal. The app keeps a fallback that registers the task itself on
|
||||
; first connect, at the cost of the one prompt this was meant to avoid.
|
||||
DetailPrint "Could not register the helper task (schtasks returned $R0)."
|
||||
DetailPrint "OSTP will still work, but the first connect will ask for consent."
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
||||
!macro NSIS_HOOK_PREUNINSTALL
|
||||
; Leaving the task behind would point at a deleted executable, and the app
|
||||
; treats a mismatched path as grounds to re-register.
|
||||
DetailPrint "Removing the OSTP TUN helper task..."
|
||||
nsExec::ExecToLog 'schtasks.exe /Delete /TN "OSTP TUN Helper" /F'
|
||||
Pop $R0
|
||||
|
||||
; This copy was made by the install hook, so the uninstaller does not know
|
||||
; about it and would otherwise leave it behind.
|
||||
Delete "$INSTDIR\wintun.dll"
|
||||
!macroend
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// Stages ostp-tun-helper where Tauri expects a sidecar.
|
||||
//
|
||||
// tauri.installer.conf.json declares `externalBin: ["binaries/ostp-tun-helper"]`,
|
||||
// and Tauri resolves that to `binaries/ostp-tun-helper-<target-triple>.exe` at
|
||||
// build time, failing the build outright when the file is absent. Cargo writes
|
||||
// the plain name instead, so it has to be copied across first.
|
||||
//
|
||||
// Only the installer build needs this. That config is passed explicitly with
|
||||
// --config rather than being named tauri.windows.conf.json, which Tauri would
|
||||
// merge into every Windows build automatically — and then even a bare
|
||||
// `cargo check` would fail on the missing sidecar.
|
||||
//
|
||||
// A no-op off Windows: the Linux and macOS GUI builds have no helper sidecar.
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execFileSync } = require('child_process');
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// --target may be passed through; fall back to the host triple rustc reports.
|
||||
const targetFlag = process.argv.indexOf('--target');
|
||||
const triple =
|
||||
targetFlag !== -1 && process.argv[targetFlag + 1]
|
||||
? process.argv[targetFlag + 1]
|
||||
: execFileSync('rustc', ['-vV'], { encoding: 'utf8' })
|
||||
.split('\n')
|
||||
.find((l) => l.startsWith('host:'))
|
||||
.slice('host:'.length)
|
||||
.trim();
|
||||
|
||||
const profile = process.argv.includes('--release') ? 'release' : 'debug';
|
||||
const repoRoot = path.resolve(__dirname, '..');
|
||||
|
||||
// Cargo drops a --target build under target/<triple>/, and a host build
|
||||
// straight into target/. CI always passes --target; local builds usually do not.
|
||||
const candidates = [
|
||||
path.join(repoRoot, 'target', triple, profile, 'ostp-tun-helper.exe'),
|
||||
path.join(repoRoot, 'target', profile, 'ostp-tun-helper.exe'),
|
||||
];
|
||||
const src = candidates.find((p) => fs.existsSync(p));
|
||||
if (!src) {
|
||||
console.error(
|
||||
'stage-sidecar: ostp-tun-helper.exe not found. Looked in:\n ' +
|
||||
candidates.join('\n ') +
|
||||
`\nBuild it first: cargo build -p ostp-tun-helper${profile === 'release' ? ' --release' : ''}`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const destDir = path.join(__dirname, 'src-tauri', 'binaries');
|
||||
fs.mkdirSync(destDir, { recursive: true });
|
||||
const dest = path.join(destDir, `ostp-tun-helper-${triple}.exe`);
|
||||
fs.copyFileSync(src, dest);
|
||||
console.log(`stage-sidecar: ${path.relative(repoRoot, src)} -> ${path.relative(repoRoot, dest)}`);
|
||||
|
||||
// wintun.dll rides along as a bundled resource. It is only fetched by the
|
||||
// release workflow, so a local build without it should warn rather than fail —
|
||||
// the installer just ends up unable to bring a tunnel up.
|
||||
const dllSrc = [
|
||||
path.join(repoRoot, 'target', triple, profile, 'wintun.dll'),
|
||||
path.join(repoRoot, 'target', profile, 'wintun.dll'),
|
||||
].find((p) => fs.existsSync(p));
|
||||
if (dllSrc) {
|
||||
fs.copyFileSync(dllSrc, path.join(destDir, 'wintun.dll'));
|
||||
console.log(`stage-sidecar: ${path.relative(repoRoot, dllSrc)} -> binaries/wintun.dll`);
|
||||
} else if (fs.existsSync(path.join(destDir, 'wintun.dll'))) {
|
||||
console.log('stage-sidecar: reusing the previously staged binaries/wintun.dll');
|
||||
} else {
|
||||
console.warn('stage-sidecar: WARNING wintun.dll not found; a bundle build will fail on the missing resource');
|
||||
}
|
||||
Loading…
Reference in New Issue