diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a9073548..67e125a6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -3,7 +3,6 @@ on: push: tags: - v*.*.* - jobs: build-wireguard-go: strategy: @@ -57,6 +56,83 @@ jobs: uses: ./.github/workflows/sbom.yml with: upload_url: ${{ needs.create-release.outputs.upload_url }} + ubuntu-22-04-build: + needs: + - create-release + runs-on: + - self-hosted + - Linux + - ${{ matrix.architecture }} + strategy: + fail-fast: false + matrix: + architecture: [ARM64, X64] + include: + - architecture: ARM64 + deb_arch: arm64 + binary_arch: aarch64 + - architecture: X64 + deb_arch: amd64 + binary_arch: x86_64 + container: + image: ubuntu:22.04 + env: + DEBIAN_FRONTEND: noninteractive + HOME: /root + RUSTUP_HOME: /root/.rustup + CARGO_HOME: /root/.cargo + steps: + - name: git install + run: | + apt-get update + apt-get install -y git curl ca-certificates + git config --global --add safe.directory '*' + - uses: actions/checkout@v5 + with: + submodules: "recursive" + - uses: pnpm/action-setup@v4 + with: + version: 10.17 + run_install: false + - uses: actions/setup-node@v5 + with: + node-version: "24" + - name: Get pnpm store directory + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> ${GITHUB_ENV} + - name: Write release version + run: | + VERSION=$(echo ${GITHUB_REF_NAME#v} | cut -d '-' -f1) + echo Version: $VERSION + echo "VERSION=$VERSION" >> ${GITHUB_ENV} + - uses: actions/cache@v4 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-build-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-build-store- + - name: Install Node dependencies + run: pnpm install --frozen-lockfile + - uses: dtolnay/rust-toolchain@stable + - name: Install dependencies + run: | + apt-get install -y build-essential libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf libssl-dev libxdo-dev unzip protobuf-compiler libprotobuf-dev rpm + - name: Build packages + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: "--bundles deb" + - name: Upload DEB + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} + asset_path: src-tauri/target/release/bundle/deb/defguard-client_${{ env.VERSION }}_${{ matrix.deb_arch }}.deb + asset_name: defguard-client_${{ env.VERSION }}_${{ matrix.deb_arch }}_ubuntu-22-04-lts.deb + asset_content_type: application/octet-stream build-linux: needs: @@ -85,12 +161,12 @@ jobs: VERSION=$(echo ${GITHUB_REF_NAME#v} | cut -d '-' -f1) echo Version: $VERSION echo "VERSION=$VERSION" >> ${GITHUB_ENV} - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: - node-version: "22" + node-version: "24" - uses: pnpm/action-setup@v4 with: - version: 10 + version: 10.17 run_install: false - name: Get pnpm store directory shell: bash diff --git a/.github/workflows/sbom-regenerate.yml b/.github/workflows/sbom-regenerate.yml index d3c7522c..3ecb2e6e 100644 --- a/.github/workflows/sbom-regenerate.yml +++ b/.github/workflows/sbom-regenerate.yml @@ -17,7 +17,9 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | RELEASES_JSON=$(gh api repos/${{ github.repository }}/releases \ - --jq '[.[] | select(.draft == false) | {tagName: .tag_name, uploadUrl: .upload_url}][:1]') + --jq '[.[] + | select(.draft == false and (.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))) + | {tagName: .tag_name, uploadUrl: .upload_url}][:1]') echo "releases=$RELEASES_JSON" >> $GITHUB_OUTPUT regenerate-for-release: name: Regenerate SBOM for release diff --git a/README.md b/README.md index 3d94ae36..64c52278 100644 --- a/README.md +++ b/README.md @@ -72,12 +72,6 @@ Built packages are available after in `src-tauri/target/release/bundle`. Remove `default-run` line from `[package]` section in `Cargo.toml` to build the project. -# Built and sponsored by - -

- build by teonite -

- # Legal WireGuard® is [registered trademarks](https://www.wireguard.com/trademark-policy/) of Jason A. Donenfeld. diff --git a/nix/package.nix b/nix/package.nix index cad9c48b..0ec4456a 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -6,7 +6,7 @@ makeDesktopItem, }: let pname = "defguard-client"; - version = "1.5.1"; # TODO: Get this from Cargo.toml or git + version = "1.5.2"; # TODO: Get this from Cargo.toml or git desktopItem = makeDesktopItem { name = pname; diff --git a/package.json b/package.json index ee8a6109..83aa787e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "defguard-client", "private": false, - "version": "1.5.1", + "version": "1.5.2", "type": "module", "scripts": { "dev": "npm-run-all --parallel vite typesafe-i18n", @@ -64,6 +64,7 @@ "@tauri-apps/plugin-notification": "^2.3.1", "@tauri-apps/plugin-opener": "^2.5.0", "@tauri-apps/plugin-os": "^2.3.1", + "@tauri-apps/plugin-process": "^2.3.0", "@tauri-apps/plugin-window-state": "^2.4.0", "@types/byte-size": "^8.1.2", "@use-gesture/react": "^10.3.1", @@ -92,6 +93,7 @@ "react-click-away-listener": "^2.4.0", "react-dom": "^19.1.1", "react-hook-form": "^7.63.0", + "react-hotkeys-hook": "^5.2.1", "react-loading-skeleton": "^3.5.0", "react-markdown": "^10.1.0", "react-qr-code": "^2.0.18", @@ -132,4 +134,4 @@ "volta": { "node": "20.5.1" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b2cd5ffb..524c4d09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@tauri-apps/plugin-os': specifier: ^2.3.1 version: 2.3.1 + '@tauri-apps/plugin-process': + specifier: ^2.3.0 + version: 2.3.0 '@tauri-apps/plugin-window-state': specifier: ^2.4.0 version: 2.4.0 @@ -143,6 +146,9 @@ importers: react-hook-form: specifier: ^7.63.0 version: 7.63.0(react@19.1.1) + react-hotkeys-hook: + specifier: ^5.2.1 + version: 5.2.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-loading-skeleton: specifier: ^3.5.0 version: 3.5.0(react@19.1.1) @@ -1207,6 +1213,9 @@ packages: '@tauri-apps/plugin-os@2.3.1': resolution: {integrity: sha512-ty5V8XDUIFbSnrk3zsFoP3kzN+vAufYzalJSlmrVhQTImIZa1aL1a03bOaP2vuBvfR+WDRC6NgV2xBl8G07d+w==} + '@tauri-apps/plugin-process@2.3.0': + resolution: {integrity: sha512-0DNj6u+9csODiV4seSxxRbnLpeGYdojlcctCuLOCgpH9X3+ckVZIEj6H7tRQ7zqWr7kSTEWnrxtAdBb0FbtrmQ==} + '@tauri-apps/plugin-window-state@2.4.0': resolution: {integrity: sha512-hRSzPNi2NG0lPFthfVY0V5C1MyWN/gGaQtQYw7i9zZhLzrhZveHZ2omHG1rIiIsjfTGbO7fhjydSoeTTK9GqLw==} @@ -2458,6 +2467,12 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 + react-hotkeys-hook@5.2.1: + resolution: {integrity: sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -3845,6 +3860,10 @@ snapshots: dependencies: '@tauri-apps/api': 2.8.0 + '@tauri-apps/plugin-process@2.3.0': + dependencies: + '@tauri-apps/api': 2.8.0 + '@tauri-apps/plugin-window-state@2.4.0': dependencies: '@tauri-apps/api': 2.8.0 @@ -5285,6 +5304,11 @@ snapshots: dependencies: react: 19.1.1 + react-hotkeys-hook@5.2.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + dependencies: + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-is@16.13.1: {} react-is@18.3.1: {} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 778c9e01..dc335b73 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -909,7 +909,7 @@ dependencies = [ [[package]] name = "common" -version = "1.5.1" +version = "1.5.2" dependencies = [ "nix", ] @@ -1263,7 +1263,7 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "defguard-client" -version = "1.5.1" +version = "1.5.2" dependencies = [ "anyhow", "base64 0.22.1", @@ -1298,6 +1298,7 @@ dependencies = [ "tauri-plugin-notification", "tauri-plugin-opener", "tauri-plugin-os", + "tauri-plugin-process", "tauri-plugin-single-instance", "tauri-plugin-window-state", "thiserror 2.0.16", @@ -1321,7 +1322,7 @@ dependencies = [ [[package]] name = "defguard-dg" -version = "1.5.1" +version = "1.5.2" dependencies = [ "clap", "common", @@ -2428,12 +2429,6 @@ dependencies = [ "foldhash", ] -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" - [[package]] name = "hashlink" version = "0.10.0" @@ -2826,7 +2821,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.15.5", "serde", "serde_core", ] @@ -6402,6 +6397,16 @@ dependencies = [ "thiserror 2.0.16", ] +[[package]] +name = "tauri-plugin-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7461c622a5ea00eb9cd9f7a08dbd3bf79484499fd5c21aa2964677f64ca651ab" +dependencies = [ + "tauri", + "tauri-plugin", +] + [[package]] name = "tauri-plugin-single-instance" version = "2.3.4" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e7ec0f43..6fc6485b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -31,7 +31,7 @@ edition = "2021" homepage = "https://github.com/DefGuard/client" license-file = "../LICENSE.md" rust-version = "1.80" -version = "1.5.1" +version = "1.5.2" [package] name = "defguard-client" @@ -110,6 +110,7 @@ x25519-dalek = { version = "2", features = [ "serde", "static_secrets", ] } +tauri-plugin-process = "2.3.0" [target.'cfg(unix)'.dependencies] hyper-util = "0.1" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index c171d2b6..d8b4de1b 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -48,6 +48,7 @@ "os:allow-hostname", "dialog:default", "clipboard-manager:allow-write-text", + "process:allow-exit", { "identifier": "http:default", "allow": [ diff --git a/src-tauri/deny.toml b/src-tauri/deny.toml index f0d3f368..d7769622 100644 --- a/src-tauri/deny.toml +++ b/src-tauri/deny.toml @@ -87,6 +87,11 @@ ignore = [ { id = "RUSTSEC-2024-0420", reason = "Tauri v2 GTK3 dependency (unmaintained)" }, { id = "RUSTSEC-2025-0052", reason = "Discontinued, but dark-light v2.0.0 needs it" }, { id = "RUSTSEC-2025-0057", reason = "Tauri needs it" }, + { id = "RUSTSEC-2025-0075", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0080", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0081", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0098", reason = "Tauri v2 dependency (unmaintained)" }, + { id = "RUSTSEC-2025-0100", reason = "Tauri v2 dependency (unmaintained)" }, ] # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index c9a337d3..0b4411e6 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -184,6 +184,7 @@ fn main() { .plugin(tauri_plugin_window_state::Builder::new().build()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_os::init()) + .plugin(tauri_plugin_process::init()) .setup(|app| { // Register for linux and dev windows builds #[cfg(any(target_os = "linux", all(debug_assertions, windows)))] diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a9a3ed85..8c9b8904 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -72,7 +72,7 @@ "productName": "defguard-client", "mainBinaryName": "defguard-client", "identifier": "net.defguard", - "version": "1.5.1", + "version": "1.5.2", "app": { "security": { "capabilities": [ @@ -107,4 +107,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index 5bc83de6..df7132cf 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -4,7 +4,7 @@ import '../../shared/scss/index.scss'; import { QueryClient } from '@tanstack/query-core'; import { QueryClientProvider } from '@tanstack/react-query'; -import { debug } from '@tauri-apps/plugin-log'; +import { debug, info } from '@tauri-apps/plugin-log'; import { openUrl } from '@tauri-apps/plugin-opener'; import dayjs from 'dayjs'; import customParseData from 'dayjs/plugin/customParseFormat'; @@ -38,6 +38,8 @@ import { useTheme } from '../../shared/defguard-ui/hooks/theme/useTheme'; import { ThemeProvider } from '../../shared/providers/ThemeProvider/ThemeProvider'; import { routes } from '../../shared/routes'; import { ApplicationUpdateManager } from '../ApplicationUpdateManager/ApplicationUpdateManager'; +import { exit } from '@tauri-apps/plugin-process'; +import { useHotkeys } from 'react-hotkeys-hook'; dayjs.extend(duration); dayjs.extend(utc); @@ -186,6 +188,12 @@ export const App = () => { }; }, []); + // register ctrl+q keyboard shortcut + useHotkeys('ctrl+q', () => { + info("Ctrl-Q pressed, exiting."); + exit(0); + }); + if (!appLoaded) return null; return (