From e50cacf3338583f66cc45b23bf8bf790cd1a85ab Mon Sep 17 00:00:00 2001 From: Kevin Yue Date: Tue, 20 Feb 2024 08:27:51 -0500 Subject: [PATCH] Add packaging --- .editorconfig | 3 + .github/workflows/build.yaml | 482 ++++++++---------- .gitignore | 5 + Cargo.lock | 36 +- Cargo.toml | 1 + Makefile | 234 +++++++++ apps/gpgui-helper/.gitignore | 1 + apps/gpgui-helper/src-tauri/Cargo.toml | 1 - apps/gpgui-helper/src-tauri/src/updater.rs | 18 +- apps/gpservice/Cargo.toml | 2 + apps/gpservice/src/handlers.rs | 36 +- changelog.md | 9 + packaging/binary/Makefile.in | 30 ++ packaging/deb/control.in | 14 + packaging/deb/rules | 6 + .../usr/share/applications/gpgui.desktop | 11 + .../icons/hicolor/128x128/apps/gpgui.png | Bin 0 -> 13579 bytes .../icons/hicolor/256x256@2/apps/gpgui.png | Bin 0 -> 28726 bytes .../share/icons/hicolor/32x32/apps/gpgui.png | Bin 0 -> 2563 bytes .../icons/hicolor/scalable/apps/gpgui.svg | 99 ++++ .../polkit-1/actions/com.yuezk.gpgui.policy | 18 + packaging/pkgbuild/PKGBUILD.in | 35 ++ .../rpm/globalprotect-openconnect.changes.in | 5 + .../rpm/globalprotect-openconnect.spec.in | 72 +++ 24 files changed, 833 insertions(+), 285 deletions(-) create mode 100644 Makefile create mode 100644 changelog.md create mode 100644 packaging/binary/Makefile.in create mode 100644 packaging/deb/control.in create mode 100755 packaging/deb/rules create mode 100644 packaging/files/usr/share/applications/gpgui.desktop create mode 100644 packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png create mode 100644 packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png create mode 100644 packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png create mode 100644 packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg create mode 100644 packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy create mode 100644 packaging/pkgbuild/PKGBUILD.in create mode 100644 packaging/rpm/globalprotect-openconnect.changes.in create mode 100644 packaging/rpm/globalprotect-openconnect.spec.in diff --git a/.editorconfig b/.editorconfig index 9d08a1a..b200914 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true + +[Makefile] +indent_style = tab diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8b858af..c4372fa 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,4 +1,4 @@ -name: Build GPGUI +name: Build on: push: paths-ignore: @@ -8,6 +8,7 @@ on: - .devcontainer branches: - main + - dev tags: - latest - v*.*.* @@ -22,287 +23,244 @@ jobs: id: set-matrix run: | if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - echo "matrix=[\"amd64\", \"arm64\"]" >> $GITHUB_OUTPUT + echo "matrix=[\"ubuntu-latest\", \"arm64\"]" >> $GITHUB_OUTPUT else - echo "matrix=[\"amd64\"]" >> $GITHUB_OUTPUT + echo "matrix=[\"ubuntu-latest\"]" >> $GITHUB_OUTPUT fi - build-fe: + tarball: runs-on: ubuntu-latest + needs: [setup-matrix] steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui + - uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Prepare workspace + run: rm -rf source && mkdir source + - name: Checkout GlobalProtect-openconnect + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: yuezk/GlobalProtect-openconnect + path: source/gp + - name: Create tarball + run: | + cd source/gp + make tarball + - name: Upload tarball + uses: actions/upload-artifact@v3 + with: + name: artifact-source + if-no-files-found: error + path: | + source/gp/.build/tarball/*.tar.gz - - name: Install Node.js - uses: actions/setup-node@v4 - with: - node-version: 18 - - - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Install dependencies - run: | - cd app - pnpm install - - name: Build - run: | - cd app - pnpm run build - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: gpgui-fe - path: app/dist - - build-tauri-amd64: - needs: [build-fe] - runs-on: ubuntu-latest - steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui - - - name: Checkout gp repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/GlobalProtect-openconnect - path: gp - - - name: Download gpgui-fe artifact - uses: actions/download-artifact@v3 - with: - name: gpgui-fe - path: gpgui/app/dist - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Build Tauri in Docker - run: | - docker run \ - --rm \ - -v $(pwd):/${{ github.workspace }} \ - -w ${{ github.workspace }} \ - -e CI=true \ - yuezk/gpdev:main \ - "./gpgui/scripts/build.sh" - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-amd64-tauri - path: | - gpgui/.tmp/artifact - - build-tauri-arm64: - if: startsWith(github.ref, 'refs/tags/') - needs: [build-fe] - runs-on: self-hosted - steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui - - - name: Checkout gp repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/GlobalProtect-openconnect - path: gp - - - name: Download gpgui-fe artifact - uses: actions/download-artifact@v3 - with: - name: gpgui-fe - path: gpgui/app/dist - - name: Build Tauri - run: | - ./gpgui/scripts/build.sh - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-arm64-tauri - path: | - gpgui/.tmp/artifact - - package-tarball: - needs: [build-tauri-amd64, build-tauri-arm64] - runs-on: ubuntu-latest - steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui - - - name: Download artifact-amd64-tauri - uses: actions/download-artifact@v3 - with: - name: artifact-amd64-tauri - path: gpgui/.tmp/artifact - - - name: Download artifact-arm64-tauri - uses: actions/download-artifact@v3 - with: - name: artifact-arm64-tauri - path: gpgui/.tmp/artifact - - - name: Create tarball - run: | - ./gpgui/scripts/build-tarball.sh - - - name: Upload tarball - uses: actions/upload-artifact@v3 - with: - name: artifact-tarball - path: | - gpgui/.tmp/tarball/*.tar.gz - - package-rpm: - needs: [setup-matrix, package-tarball] - runs-on: ubuntu-latest + build-deb: + needs: + - setup-matrix + - tarball strategy: matrix: - arch: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui + - name: Prepare workspace + run: rm -rf build-deb && mkdir build-deb + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-deb + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build DEB package in Docker + run: | + docker run --rm -v $(pwd)/build-deb:/deb yuezk/gpdev:deb-builder + - name: Install DEB package in Docker + run: | + docker run --rm -v $(pwd)/build-deb:/deb yuezk/gpdev:deb-builder \ + bash -c "sudo dpkg -i /deb/*.deb; gpclient --version; gpservice --version; gpauth --version; gpgui-helper --version;" + - name: Upload DEB package + uses: actions/upload-artifact@v3 + with: + name: artifact-deb-${{ matrix.os }} + if-no-files-found: error + path: | + build-deb/*.deb - - name: Download package tarball - uses: actions/download-artifact@v3 - with: - name: artifact-tarball - path: gpgui/.tmp/artifact - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: ${{ matrix.arch }} - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Create RPM package - run: | - docker run \ - --rm \ - -v $(pwd):/${{ github.workspace }} \ - -w ${{ github.workspace }} \ - --platform linux/${{ matrix.arch }} \ - yuezk/gpdev:rpm-builder \ - "./gpgui/scripts/build-rpm.sh" - - - name: Upload rpm artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-${{ matrix.arch }}-rpm - path: | - gpgui/.tmp/artifact/*.rpm - - package-pkgbuild: - needs: [setup-matrix, build-tauri-amd64, build-tauri-arm64] - runs-on: ubuntu-latest + build-rpm: + needs: + - setup-matrix + - tarball strategy: matrix: - arch: ${{ fromJson(needs.setup-matrix.outputs.matrix) }} + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} steps: - - name: Checkout gpgui repo - uses: actions/checkout@v3 - with: - token: ${{ secrets.GH_PAT }} - repository: yuezk/gpgui - path: gpgui + - name: Prepare workspace + run: rm -rf build-rpm && mkdir build-rpm + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-rpm + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build RPM package in Docker + run: | + docker run --rm -v $(pwd)/build-rpm:/rpm yuezk/gpdev:rpm-builder + - name: Install RPM package in Docker + run: | + docker run --rm -v $(pwd)/build-rpm:/rpm yuezk/gpdev:rpm-builder \ + bash -c "sudo rpm -i /rpm/*.$(uname -m).rpm; gpclient --version; gpservice --version; gpauth --version; gpgui-helper --version;" + - name: Upload RPM package + uses: actions/upload-artifact@v3 + with: + name: artifact-rpm-${{ matrix.os }} + if-no-files-found: error + path: | + build-rpm/*.rpm - - name: Download artifact-${{ matrix.arch }} - uses: actions/download-artifact@v3 - with: - name: artifact-${{ matrix.arch }}-tauri - path: gpgui/.tmp/artifact + build-pkgbuild: + needs: + - setup-matrix + - tarball + strategy: + matrix: + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} + steps: + - name: Prepare workspace + run: rm -rf build-pkgbuild && mkdir build-pkgbuild + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-pkgbuild + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build PKGBUILD package in Docker + run: | + docker run --rm -v $(pwd)/build-pkgbuild:/pkgbuild yuezk/gpdev:pkgbuild + - name: Install PKGBUILD package in Docker + run: | + docker run --rm -v $(pwd)/build-pkgbuild:/pkgbuild yuezk/gpdev:pkgbuild \ + bash -c "sudo pacman -U --noconfirm /pkgbuild/*.pkg.tar.zst; gpclient --version; gpservice --version; gpauth --version; gpgui-helper --version;" + - name: Upload PKGBUILD package + uses: actions/upload-artifact@v3 + with: + name: artifact-pkgbuild-${{ matrix.os }} + if-no-files-found: error + path: | + build-pkgbuild/*.pkg.tar.zst - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: ${{ matrix.arch }} + build-binary: + needs: + - setup-matrix + - tarball + strategy: + matrix: + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} + steps: + - name: Prepare workspace + run: rm -rf build-binary && mkdir build-binary + - name: Download tarball + uses: actions/download-artifact@v3 + with: + name: artifact-source + path: build-binary + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build binary in Docker + run: | + docker run --rm -v $(pwd)/build-binary:/binary yuezk/gpdev:binary-builder + - name: Install binary in Docker + run: | + cd build-binary + tar -xJf ./*.bin.tar.xz + docker run --rm -v $(pwd):/binary yuezk/gpdev:binary-builder \ + bash -c "cd /binary/globalprotect-openconnect*/ && sudo make install && gpclient --version && gpservice --version && gpauth --version && gpgui-helper --version;" + - name: Upload binary + uses: actions/upload-artifact@v3 + with: + name: artifact-binary-${{ matrix.os }} + if-no-files-found: error + path: | + build-binary/*.bin.tar.xz + build-binary/*.bin.tar.xz.sha256 - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Generate PKGBUILD - run: | - export CI_ARCH=${{ matrix.arch }} - ./gpgui/scripts/generate-pkgbuild.sh - - - name: Build PKGBUILD package - run: | - # Build package - docker run \ - --rm \ - -v $(pwd)/gpgui/.tmp/pkgbuild:/pkgbuild \ - --platform linux/${{ matrix.arch }} \ - yuezk/gpdev:pkgbuild - - - name: Upload pkgbuild artifacts - uses: actions/upload-artifact@v3 - with: - name: artifact-${{ matrix.arch }}-pkgbuild - path: | - gpgui/.tmp/pkgbuild/*.pkg.tar.zst + build-gpgui: + needs: + - setup-matrix + strategy: + matrix: + os: ${{fromJson(needs.setup-matrix.outputs.matrix)}} + runs-on: ${{ matrix.os }} + steps: + - uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Prepare workspace + run: rm -rf gpgui-source && mkdir gpgui-source + - name: Checkout GlobalProtect-openconnect + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: yuezk/GlobalProtect-openconnect + path: gpgui-source/gp + - name: Checkout gpgui + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: yuezk/gpgui + path: gpgui-source/gpgui + - name: Tarball + run: | + cd gpgui-source + tar -czf gpgui.tar.gz gpgui gp + - name: Docker Login + run: echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + - name: Build gpgui in Docker + run: | + docker run --rm -v $(pwd)/gpgui-source:/gpgui yuezk/gpdev:gpgui-builder + - name: Install gpgui in Docker + run: | + cd gpgui-source + tar -xJf *.bin.tar.xz + docker run --rm -v $(pwd):/gpgui yuezk/gpdev:gpgui-builder \ + bash -c "cd /gpgui/gpgui_*/ && ./gpgui --version" + - name: Upload gpgui + uses: actions/upload-artifact@v3 + with: + name: artifact-gpgui-${{ matrix.os }} + if-no-files-found: error + path: | + gpgui-source/*.bin.tar.xz + gpgui-source/*.bin.tar.xz.sha256 gh-release: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest needs: - - package-rpm - - package-pkgbuild + - build-deb + - build-rpm + - build-pkgbuild + - build-binary + - build-gpgui steps: - - name: Download artifact - uses: actions/download-artifact@v3 - with: - path: artifact - # pattern: artifact-* - # merge-multiple: true - - # - name: Generate checksum - # uses: jmgilman/actions-generate-checksum@v1 - # with: - # output: checksums.txt - # patterns: | - # artifact/* - - - name: Create GH release - uses: softprops/action-gh-release@v1 - with: - token: ${{ secrets.GH_PAT }} - prerelease: ${{ contains(github.ref, 'latest') }} - fail_on_unmatched_files: true - files: | - artifact/artifact-*/* + - name: Prepare workspace + run: rm -rf build-artifact && mkdir build-artifact + - name: Download all artifacts + uses: actions/download-artifact@v3 + with: + path: build-artifact + - name: Create GH release + uses: softprops/action-gh-release@v1 + with: + token: ${{ secrets.GH_PAT }} + prerelease: ${{ contains(github.ref, 'latest') }} + fail_on_unmatched_files: true + files: | + build-artifact/artifact-*/* diff --git a/.gitignore b/.gitignore index 20282f4..498e6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,8 @@ /target .pnpm-store .env +.vendor +*.tar.xz + +.cargo +.build diff --git a/Cargo.lock b/Cargo.lock index f85ac8b..6529415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -903,19 +903,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "downloader" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05213e96f184578b5f70105d4d0a644a168e99e12d7bea0b200c15d67b5c182" -dependencies = [ - "futures", - "rand 0.8.5", - "reqwest", - "thiserror", - "tokio", -] - [[package]] name = "dtoa" version = "1.0.9" @@ -1514,7 +1501,6 @@ dependencies = [ "anyhow", "clap", "compile-time", - "downloader", "env_logger", "futures-util", "gpapi", @@ -1541,8 +1527,10 @@ dependencies = [ "openconnect", "serde", "serde_json", + "tar", "tokio", "tokio-util", + "xz2", ] [[package]] @@ -2212,6 +2200,17 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "mac" version = "0.1.1" @@ -5138,6 +5137,15 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 17124e7..9d158c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ resolver = "2" members = ["crates/*", "apps/gpclient", "apps/gpservice", "apps/gpauth", "apps/gpgui-helper/src-tauri"] [workspace.package] +rust-version = "1.70" version = "2.0.0" authors = ["Kevin Yue "] homepage = "https://github.com/yuezk/GlobalProtect-openconnect" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..78a0f80 --- /dev/null +++ b/Makefile @@ -0,0 +1,234 @@ +OFFLINE ?= 0 +BUILD_FE ?= 1 +CARGO ?= cargo + +VERSION = $(shell $(CARGO) metadata --no-deps --format-version 1 | jq -r '.packages[0].version') +REVISION ?= 1 +PPA_REVISION ?= 1 +PKG_NAME = globalprotect-openconnect +PKG = $(PKG_NAME)-$(VERSION) +SERIES ?= $(shell lsb_release -cs) +PUBLISH ?= 0 + +export DEBEMAIL = k3vinyue@gmail.com +export DEBFULLNAME = Kevin Yue + +CARGO_BUILD_ARGS = --release + +ifeq ($(OFFLINE), 1) + CARGO_BUILD_ARGS += --frozen +endif + +default: build + +version: + @echo $(VERSION) + +clean-tarball: + rm -rf .build/tarball + rm -rf .vendor + rm -rf vendor.tar.xz + rm -rf .cargo + +# Create a tarball, include the cargo dependencies if OFFLINE is set to 1 +tarball: clean-tarball + if [ $(BUILD_FE) -eq 1 ]; then \ + cd apps/gpgui-helper && pnpm install && pnpm build; \ + fi + + # Remove node_modules to reduce the tarball size + rm -rf apps/gpgui-helper/node_modules + + mkdir -p .cargo + mkdir -p .build/tarball + + # If OFFLINE is set to 1, vendor all cargo dependencies + if [ $(OFFLINE) -eq 1 ]; then \ + $(CARGO) vendor .vendor > .cargo/config.toml; \ + tar -cJf vendor.tar.xz .vendor; \ + fi + + tar --exclude .vendor --exclude target --transform 's,^,${PKG}/,' -czf .build/tarball/${PKG}.tar.gz * .cargo + +build: build-fe build-rs + +# Install and build the frontend +# If OFFLINE is set to 1, skip it +build-fe: + if [ $(OFFLINE) -eq 1 ] || [ $(BUILD_FE) -eq 0 ]; then \ + echo "Skipping frontend build (OFFLINE=1 or BUILD_FE=0)"; \ + else \ + cd apps/gpgui-helper && pnpm install && pnpm build; \ + fi + + if [ ! -d apps/gpgui-helper/dist ]; then \ + echo "Error: frontend build failed"; \ + exit 1; \ + fi + +build-rs: + if [ $(OFFLINE) -eq 1 ]; then \ + tar -xJf vendor.tar.xz; \ + fi + + $(CARGO) build $(CARGO_BUILD_ARGS) -p gpclient -p gpservice -p gpauth + $(CARGO) build $(CARGO_BUILD_ARGS) -p gpgui-helper --features "tauri/custom-protocol" + +clean: + $(CARGO) clean + rm -rf .build + rm -rf .vendor + rm -rf apps/gpgui-helper/node_modules + +install: + @echo "Installing $(PKG_NAME)..." + + install -Dm755 target/release/gpclient $(DESTDIR)/usr/bin/gpclient + install -Dm755 target/release/gpauth $(DESTDIR)/usr/bin/gpauth + install -Dm755 target/release/gpservice $(DESTDIR)/usr/bin/gpservice + install -Dm755 target/release/gpgui-helper $(DESTDIR)/usr/bin/gpgui-helper + + install -Dm644 packaging/files/usr/share/applications/gpgui.desktop $(DESTDIR)/usr/share/applications/gpgui.desktop + install -Dm644 packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + install -Dm644 packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + install -Dm644 packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + install -Dm644 packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + install -Dm644 packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy + +uninstall: + @echo "Uninstalling $(PKG_NAME)..." + + rm -f $(DESTDIR)/usr/bin/gpclient + rm -f $(DESTDIR)/usr/bin/gpauth + rm -f $(DESTDIR)/usr/bin/gpservice + rm -f $(DESTDIR)/usr/bin/gpgui-helper + rm -f $(DESTDIR)/usr/bin/gpgui + + rm -f $(DESTDIR)/usr/share/applications/gpgui.desktop + rm -f $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + rm -f $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy + +clean-debian: + rm -rf .build/deb + +# Generate the debian package structure, without the changelog +init-debian: clean-debian tarball + mkdir -p .build/deb + cp .build/tarball/${PKG}.tar.gz .build/deb + + tar -xzf .build/deb/${PKG}.tar.gz -C .build/deb + cd .build/deb/${PKG} && debmake + + cp -f packaging/deb/control.in .build/deb/$(PKG)/debian/control + cp -f packaging/deb/rules .build/deb/$(PKG)/debian/rules + + sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/deb/$(PKG)/debian/rules + + rm -f .build/deb/$(PKG)/debian/changelog + +deb: init-debian + # Remove the rust build depdency from the control file + sed -i "s/@RUST@//g" .build/deb/$(PKG)/debian/control + + cd .build/deb/$(PKG) && dch --create --distribution unstable --package $(PKG_NAME) --newversion $(VERSION)-$(REVISION) "Bugfix and improvements." + + cd .build/deb/$(PKG) && debuild --preserve-env -e PATH -us -uc -b + +check-ppa: + if [ $(OFFLINE) -eq 0 ]; then \ + echo "Error: ppa build requires offline mode (OFFLINE=1)"; \ + fi + +# Usage: make ppa SERIES=focal OFFLINE=1 PUBLISH=1 +ppa: check-ppa init-debian + cd .build/deb/${PKG} + + sed -i "s/@RUST@/rust-all(>=1.70)/g" debian/control + + $(eval SERIES_VER = $(shell distro-info --series $(SERIES) -r | cut -d' ' -f1)) + @echo "Building for $(SERIES) $(SERIES_VER)" + + dch --create --distribution $(SERIES) --package $(PKG_NAME) --newversion $(VERSION)-$(REVISION)ppa$(PPA_REVISION)~ubuntu$(SERIES_VER) "Bugfix and improvements." + + echo "y" | debuild -e PATH -S -sa -k"$(GPG_KEY_ID)" -p"gpg --batch --passphrase $(GPG_KEY_PASS) --pinentry-mode loopback" + + if [ $(PUBLISH) -eq 1 ]; then \ + dput ppa:yuezk/globalprotect-openconnect ../*.changes; \ + else + echo "Skipping ppa publish (PUBLISH=0)" + fi + +clean-rpm: + rm -rf .build/rpm + +# Generate RPM sepc file +init-rpm: clean-rpm + mkdir -p .build/rpm + + cp packaging/rpm/globalprotect-openconnect.spec.in .build/rpm/globalprotect-openconnect.spec + cp packaging/rpm/globalprotect-openconnect.changes.in .build/rpm/globalprotect-openconnect.changes + + sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.spec + sed -i "s/@REVISION@/$(REVISION)/g" .build/rpm/globalprotect-openconnect.spec + sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/rpm/globalprotect-openconnect.spec + sed -i "s/@DATE@/$(shell date "+%a %b %d %Y")/g" .build/rpm/globalprotect-openconnect.spec + + sed -i "s/@VERSION@/$(VERSION)/g" .build/rpm/globalprotect-openconnect.changes + sed -i "s/@DATE@/$(shell LC_ALL=en.US date -u "+%a %b %e %T %Z %Y")/g" .build/rpm/globalprotect-openconnect.changes + +rpm: init-rpm tarball + rm -rf $(HOME)/rpmbuild + rpmdev-setuptree + + cp .build/tarball/${PKG}.tar.gz $(HOME)/rpmbuild/SOURCES/${PKG_NAME}.tar.gz + rpmbuild -ba .build/rpm/globalprotect-openconnect.spec + + # Copy RPM package from build directory + cp $(HOME)/rpmbuild/RPMS/$(shell uname -m)/$(PKG_NAME)*.rpm .build/rpm + + # Copy the SRPM only for x86_64. + if [ "$(shell uname -m)" = "x86_64" ]; then \ + cp $(HOME)/rpmbuild/SRPMS/$(PKG_NAME)*.rpm .build/rpm; \ + fi + +clean-pkgbuild: + rm -rf .build/pkgbuild + +init-pkgbuild: clean-pkgbuild tarball + mkdir -p .build/pkgbuild + + cp .build/tarball/${PKG}.tar.gz .build/pkgbuild + cp packaging/pkgbuild/PKGBUILD.in .build/pkgbuild/PKGBUILD + + sed -i "s/@PKG_NAME@/$(PKG_NAME)/g" .build/pkgbuild/PKGBUILD + sed -i "s/@VERSION@/$(VERSION)/g" .build/pkgbuild/PKGBUILD + sed -i "s/@REVISION@/$(REVISION)/g" .build/pkgbuild/PKGBUILD + sed -i "s/@OFFLINE@/$(OFFLINE)/g" .build/pkgbuild/PKGBUILD + +pkgbuild: init-pkgbuild + cd .build/pkgbuild && makepkg -s --noconfirm + +clean-binary: + rm -rf .build/binary + +binary: clean-binary tarball + mkdir -p .build/binary + + cp .build/tarball/${PKG}.tar.gz .build/binary + tar -xzf .build/binary/${PKG}.tar.gz -C .build/binary + + mkdir -p .build/binary/$(PKG_NAME)_$(VERSION)/artifacts + + make -C .build/binary/${PKG} build OFFLINE=$(OFFLINE) BUILD_FE=0 + make -C .build/binary/${PKG} install DESTDIR=$(PWD)/.build/binary/$(PKG_NAME)_$(VERSION)/artifacts + + cp packaging/binary/Makefile.in .build/binary/$(PKG_NAME)_$(VERSION)/Makefile + + # Create a tarball for the binary package + tar -cJf .build/binary/$(PKG_NAME)_$(VERSION)_$(shell uname -m).bin.tar.xz -C .build/binary $(PKG_NAME)_$(VERSION) + + # Generate sha256sum + cd .build/binary && sha256sum $(PKG_NAME)_$(VERSION)_$(shell uname -m).bin.tar.xz | cut -d' ' -f1 > $(PKG_NAME)_$(VERSION)_$(shell uname -m).bin.tar.xz.sha256 diff --git a/apps/gpgui-helper/.gitignore b/apps/gpgui-helper/.gitignore index a547bf3..f52de67 100644 --- a/apps/gpgui-helper/.gitignore +++ b/apps/gpgui-helper/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.vite diff --git a/apps/gpgui-helper/src-tauri/Cargo.toml b/apps/gpgui-helper/src-tauri/Cargo.toml index 839e1f6..51d972c 100644 --- a/apps/gpgui-helper/src-tauri/Cargo.toml +++ b/apps/gpgui-helper/src-tauri/Cargo.toml @@ -18,7 +18,6 @@ clap.workspace = true compile-time.workspace = true env_logger.workspace = true futures-util.workspace = true -downloader = "0.2" tempfile.workspace = true reqwest = { workspace = true, features = ["stream"] } diff --git a/apps/gpgui-helper/src-tauri/src/updater.rs b/apps/gpgui-helper/src-tauri/src/updater.rs index 83275c3..ec479a5 100644 --- a/apps/gpgui-helper/src-tauri/src/updater.rs +++ b/apps/gpgui-helper/src-tauri/src/updater.rs @@ -80,12 +80,20 @@ impl GuiUpdater { pub async fn update(&self) { info!("Update GUI, version: {}", self.version); - #[cfg(target_arch = "x86_64")] - let arch = "amd64"; - #[cfg(target_arch = "aarch64")] - let arch = "arm64"; + #[cfg(debug_assertions)] + let release_tag = "latest"; + #[cfg(not(debug_assertions))] + let release_tag = format!("v{}", self.version); - let file_url = format!("https://github.com/yuezk/GlobalProtect-openconnect/releases/download/v{}/gpgui-linux-{}", self.version, arch); + #[cfg(target_arch = "x86_64")] + let arch = "x86_64"; + #[cfg(target_arch = "aarch64")] + let arch = "aarch64"; + + let file_url = format!( + "https://github.com/yuezk/GlobalProtect-openconnect/releases/download/{}/gpgui_{}_{}.bin.tar.xz", + release_tag, self.version, arch + ); let checksum_url = format!("{}.sha256", file_url); info!("Downloading file: {}", file_url); diff --git a/apps/gpservice/Cargo.toml b/apps/gpservice/Cargo.toml index 5a38524..4212f43 100644 --- a/apps/gpservice/Cargo.toml +++ b/apps/gpservice/Cargo.toml @@ -18,3 +18,5 @@ serde_json.workspace = true env_logger.workspace = true log.workspace = true compile-time.workspace = true +xz2 = "0.1" +tar = "0.4" diff --git a/apps/gpservice/src/handlers.rs b/apps/gpservice/src/handlers.rs index 1b2fa72..643eeb0 100644 --- a/apps/gpservice/src/handlers.rs +++ b/apps/gpservice/src/handlers.rs @@ -1,4 +1,12 @@ -use std::{borrow::Cow, fs::Permissions, ops::ControlFlow, os::unix::fs::PermissionsExt, path::PathBuf, sync::Arc}; +use std::{ + borrow::Cow, + fs::{File, Permissions}, + io::BufReader, + ops::ControlFlow, + os::unix::fs::PermissionsExt, + path::PathBuf, + sync::Arc, +}; use anyhow::bail; use axum::{ @@ -17,7 +25,9 @@ use gpapi::{ GP_GUI_BINARY, }; use log::{info, warn}; +use tar::Archive; use tokio::fs; +use xz2::read::XzDecoder; use crate::ws_server::WsServerContext; @@ -60,6 +70,7 @@ pub async fn update_gui(State(ctx): State>, body: Bytes) -> Ok(()) } +// Unpack GPGUI archive, gpgui_2.0.0_{arch}.bin.tar.xz and install it async fn install_gui(src: &str) -> anyhow::Result<()> { let path = PathBuf::from(GP_GUI_BINARY); let Some(dir) = path.parent() else { @@ -68,8 +79,27 @@ async fn install_gui(src: &str) -> anyhow::Result<()> { fs::create_dir_all(dir).await?; - // Copy the file to the final location and make it executable - fs::copy(src, GP_GUI_BINARY).await?; + // Unpack the archive + info!("Unpacking GUI archive"); + let tar = XzDecoder::new(BufReader::new(File::open(src)?)); + let mut ar = Archive::new(tar); + + for entry in ar.entries()? { + let mut entry = entry?; + let path = entry.path()?; + + if let Some(name) = path.file_name() { + let name = name.to_string_lossy(); + + if name == "gpgui" { + let mut file = File::create(GP_GUI_BINARY)?; + std::io::copy(&mut entry, &mut file)?; + break; + } + } + } + + // Make the binary executable fs::set_permissions(GP_GUI_BINARY, Permissions::from_mode(0o755)).await?; Ok(()) diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..b1bda96 --- /dev/null +++ b/changelog.md @@ -0,0 +1,9 @@ +# Changelog + +## 2.0.0 - 2024-02-05 + +- Refactor using Tauri +- Support HIP report +- Support pass vpn-slice command +- Do not error when the region field is empty +- Update the auth window icon diff --git a/packaging/binary/Makefile.in b/packaging/binary/Makefile.in new file mode 100644 index 0000000..96b7faa --- /dev/null +++ b/packaging/binary/Makefile.in @@ -0,0 +1,30 @@ +install: + @echo "===> Installing..." + + install -Dm755 artifacts/usr/bin/gpclient $(DESTDIR)/usr/bin/gpclient + install -Dm755 artifacts/usr/bin/gpservice $(DESTDIR)/usr/bin/gpservice + install -Dm755 artifacts/usr/bin/gpauth $(DESTDIR)/usr/bin/gpauth + install -Dm755 artifacts/usr/bin/gpgui-helper $(DESTDIR)/usr/bin/gpgui-helper + + install -Dm644 artifacts/usr/share/applications/gpgui.desktop $(DESTDIR)/usr/share/applications/gpgui.desktop + install -Dm644 artifacts/usr/share/icons/hicolor/scalable/apps/gpgui.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + install -Dm644 artifacts/usr/share/icons/hicolor/32x32/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + install -Dm644 artifacts/usr/share/icons/hicolor/128x128/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + install -Dm644 artifacts/usr/share/icons/hicolor/256x256@2/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + install -Dm644 artifacts/usr/share/polkit-1/actions/com.yuezk.gpgui.policy $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy + +uninstall: + @echo "===> Uninstalling from $(DESTDIR)..." + + rm -f $(DESTDIR)/usr/bin/gpclient + rm -f $(DESTDIR)/usr/bin/gpservice + rm -f $(DESTDIR)/usr/bin/gpauth + rm -f $(DESTDIR)/usr/bin/gpgui-helper + rm -f $(DESTDIR)/usr/bin/gpgui + + rm -f $(DESTDIR)/usr/share/applications/gpgui.desktop + rm -f $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg + rm -f $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/128x128/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/icons/hicolor/256x256@2/apps/gpgui.png + rm -f $(DESTDIR)/usr/share/polkit-1/actions/com.yuezk.gpgui.policy diff --git a/packaging/deb/control.in b/packaging/deb/control.in new file mode 100644 index 0000000..c789fb9 --- /dev/null +++ b/packaging/deb/control.in @@ -0,0 +1,14 @@ +Source: globalprotect-openconnect +Section: net +Priority: optional +Maintainer: Kevin Yue +Standards-Version: 4.1.4 +Build-Depends: debhelper (>= 9), pkg-config, jq (>= 1), make (>= 4), openconnect (>= 8.20), libxml2, libsecret-1-0, libayatana-appindicator3-1, libwebkit2gtk-4.0-37, libgtk-3-0, gnome-keyring, @RUST@ +Homepage: https://github.com/yuezk/GlobalProtect-openconnect + +Package: globalprotect-openconnect +Architecture: any +Multi-Arch: foreign +Depends: ${misc:Depends}, ${shlibs:Depends}, openconnect (>=8.20), libxml2, libsecret-1-0, libayatana-appindicator3-1, gnome-keyring +Description: A GUI for GlobalProtect VPN + A GUI for GlobalProtect VPN, based on OpenConnect, supports the SSO authentication method. diff --git a/packaging/deb/rules b/packaging/deb/rules new file mode 100755 index 0000000..ca3f834 --- /dev/null +++ b/packaging/deb/rules @@ -0,0 +1,6 @@ +#!/usr/bin/make -f + +export OFFLINE = @OFFLINE@ BUILD_FE=0 + +%: + dh $@ diff --git a/packaging/files/usr/share/applications/gpgui.desktop b/packaging/files/usr/share/applications/gpgui.desktop new file mode 100644 index 0000000..8ad6418 --- /dev/null +++ b/packaging/files/usr/share/applications/gpgui.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] + +Type=Application +Name=GlobalProtect Openconnect VPN Client +Comment=A GUI for GlobalProtect VPN +GenericName=GlobalProtect VPN Client +Categories=Network;Dialup; +Exec=/usr/bin/gpclient launch-gui %u +MimeType=x-scheme-handler/globalprotectcallback; +Icon=gpgui +Keywords=GlobalProtect;Openconnect;SAML;connection;VPN; diff --git a/packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png b/packaging/files/usr/share/icons/hicolor/128x128/apps/gpgui.png new file mode 100644 index 0000000000000000000000000000000000000000..d7e973029865245d86f5b4a8f2d7c8858baed9ac GIT binary patch literal 13579 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 R6QckC002ovPDHLkV1mnIBklkI literal 0 HcmV?d00001 diff --git a/packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png b/packaging/files/usr/share/icons/hicolor/256x256@2/apps/gpgui.png new file mode 100644 index 0000000000000000000000000000000000000000..301c18a899d291ee6e19b2b94281e3ce34af295f GIT binary patch literal 28726 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 Z{~w_yj}Ht%n416q002ovPDHLkV1i0kPtpJY literal 0 HcmV?d00001 diff --git a/packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png b/packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png new file mode 100644 index 0000000000000000000000000000000000000000..a29d98a03a93fd596d7eff748528d8e480dc0238 GIT binary patch literal 2563 zcmV+e3jFnnP)oMm%YqpFWJn@&ZVcjPapr&GrLJ7O4O<8 zneNl4&;OtA`~FLFT*!yfhYLfWUC?wva~Z#|xu0^E40EAm;Lp#tI$M@SmbR@n+w6WL zmTrj{Yb<}tpRS!6J6fH7f2evqcL1s}ot##IepdYt4sa$AD5+14L~BcG!2JUPr zfAZy>Kbm-H`%mjm7=(uJf2srX#?AI*SLglL{x-HYy*@aw8W_98V^&Q-nG8zv8-UYk zG}Emg!UD{m6)5INZdfMIdMFMZd~5jeZ{6&k8k^MGP*R@b1V5i~yEnVCXUC2EqRZ3k z{Tatq9q%Zl$4p3@gZoSvv<8=OeFZPj8r6(77O@=8OlHy@<;4Hs#y475T=L*6L$R(k z{n~ga(DOP#oQFGKlq1uDez_+Ik5i?+&w<1&+5@FQTk_28pd zz^Jri&h>Hox(puK(t{9R4_A!&e+D(j03u0=p)BoT_k$rWq)!2$dW`5Ss=scX2frWzl7Q zgR{Ro^n|SDOL`$b&qwOofxC=!B(8`)2#>L`jbPKuiT63;mcj9W&-5gScMGo^I*rG6 zEvyQ@JAJp*Pq(nB#aCwJ7&8K~lUfjW-hg4WYcf#DajTs-@=9^8)c>0DFUvK0G z!AW?uv_SKf{kH}LDKjL68VAcSB|#YrQsKl=I!fbA;owx6ULp0NK5Z&=}|J#9Cwq?z&yuRDqPCg~-yD<&mD)DixH;Xq>ZS zR|8Ix=6E{6ghoA*i>o3u7D2#mR00dOv}h3$oY}$5$&@tjjdR`w({}l-p~O%yL`16{W5%cLQ=d7R>_bdQWP20Qmv7(v~e13 z7=bD&WHE{r(Fr8&2yDXxk%^Q?X`*N$(MreliaW!QU#i( zp;9O6%r{Sv_?oaTdK^7=4sJlxl|#`Zb%7`bXCILp6&e+!>2_Jf<)s2@ypG_R zj|x$RWH8#|tzn@Hhto%x>Y&r(9bjXZ(Wo0{GnE_#;(1!SjDTp+79$X$VNX*-|1EU& zcXH!iRl+J-?qSx1I62|dB&N<+hE=$Z@&dVlfSicT=xnFD-mWJ{X@<&W#ZI8mMME-t zkYtA4Wcnd8MhOwE^!QtJ{av~yV37%<tsl)pM$~1gLr$u@kfd0E_!s9c78J~JV3@>T}&D&ONX$SS_5*%ab}17>s=1B7{*u> zN2yvLa~EOUAHcZk#F*^FsO-XI(1v%tjd-?tD?M2c*^p7k@T}-XV(L%7+%fy&(6f5? zx(c%eS!y2Wx9{$!_Sl=soBY;SJtmVT8r)WCG4U_$wK#GEVzCWWz=E?nZ$&s6giMWo z{g4(VUC)T8&Em0LZyk8#md#XgLp5p$#F^Nn9)Jc)!+TyzU3AAbgD+|h>=93wYwcx} z+|VcxKQM`3gX)+?LW{+kU{Zf*5I%+;rz67Lkh+F(SHzN5?bPVRfk*GSGN_iTx(w@P zp{1^9rlLTJ9;1`oKZ8~Y9@j4|^sZ46i(z_FDuKt?s+_YN6EZs}$ zw;jaVmWKaC6{J&A)!d;EPQCNeuV>zTW~W~|ov-I6YS{mqSF>~9irJZ$Q<7jL+tC;4 z=wEFn+WL*Amb8_~aKAW{ccxApuI3Kzb50%|KBMdZ=jHVLj!68c)#hglL+E}_)ADIc Z{}cb}gJTAQa@YU>002ovPDHLkV1kbt`@{eM literal 0 HcmV?d00001 diff --git a/packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg b/packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg new file mode 100644 index 0000000..bccc611 --- /dev/null +++ b/packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + \ No newline at end of file diff --git a/packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy b/packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy new file mode 100644 index 0000000..8c8af09 --- /dev/null +++ b/packaging/files/usr/share/polkit-1/actions/com.yuezk.gpgui.policy @@ -0,0 +1,18 @@ + + + + The GlobalProtect-openconnect Project + https://github.com/yuezk/GlobalProtect-openconnect + gpgui + + Run GPService as root + Authentication is required to run the GPService as root + + auth_admin + auth_admin + yes + + /usr/bin/gpservice + true + + diff --git a/packaging/pkgbuild/PKGBUILD.in b/packaging/pkgbuild/PKGBUILD.in new file mode 100644 index 0000000..a238afb --- /dev/null +++ b/packaging/pkgbuild/PKGBUILD.in @@ -0,0 +1,35 @@ +# Maintainer: Keinv Yue + +_pkgname=@PKG_NAME@ +pkgname=${_pkgname} +pkgver="@VERSION@" +pkgrel=@REVISION@ +pkgdesc="A GUI for GlobalProtect VPN, based on OpenConnect, supports the SSO authentication method." +arch=('x86_64' 'aarch64') +url="https://github.com/yuezk/GlobalProtect-openconnect" +license=('GPL3') +makedepends=('make' 'pkg-config' 'rust' 'cargo' 'jq' 'webkit2gtk' 'curl' 'wget' 'file' 'openssl' 'appmenu-gtk-module' 'gtk3' 'libappindicator-gtk3' 'librsvg' 'libvips' 'libayatana-appindicator' 'openconnect' 'libsecret') +depends=('openconnect>=8.20' webkit2gtk libappindicator-gtk3 libayatana-appindicator libsecret libxml2) +optdepends=('wmctrl: for window management') + +provides=('globalprotect-openconnect' 'gpclient' 'gpservice' 'gpauth' 'gpgui') + +source=("${_pkgname}-${pkgver}.tar.gz") +sha256sums=('SKIP') + +options=('!strip') + +build() { + cd "$pkgname-$pkgver" + + # Must unset the CFLAGS, otherwise the build fails + unset CFLAGS + + make build OFFLINE=@OFFLINE@ BUILD_FE=0 +} + +package() { + cd "$pkgname-$pkgver" + + make install DESTDIR="$pkgdir" +} diff --git a/packaging/rpm/globalprotect-openconnect.changes.in b/packaging/rpm/globalprotect-openconnect.changes.in new file mode 100644 index 0000000..3d9280d --- /dev/null +++ b/packaging/rpm/globalprotect-openconnect.changes.in @@ -0,0 +1,5 @@ +------------------------------------------------------------------- +@DATE@ - k3vinyue@gmail.com - @VERSION@ + +- Update to @VERSION@ + * Bugfix and improvements. diff --git a/packaging/rpm/globalprotect-openconnect.spec.in b/packaging/rpm/globalprotect-openconnect.spec.in new file mode 100644 index 0000000..7314944 --- /dev/null +++ b/packaging/rpm/globalprotect-openconnect.spec.in @@ -0,0 +1,72 @@ +Name: globalprotect-openconnect +Version: @VERSION@ +Release: @REVISION@ +Summary: A GlobalProtect VPN client powered by OpenConnect +Group: Productivity/Networking/PPP + +License: GPL-3.0 +URL: https://github.com/yuezk/GlobalProtect-openconnect +Source: %{name}.tar.gz + +BuildRequires: make +BuildRequires: rust +BuildRequires: cargo +BuildRequires: jq +BuildRequires: pkg-config +BuildRequires: openconnect-devel +BuildRequires: openssl-devel +BuildRequires: curl +BuildRequires: wget +BuildRequires: file + +BuildRequires: (webkit2gtk4.0-devel or webkit2gtk3-soup2-devel) +BuildRequires: (libappindicator-gtk3-devel or libappindicator3-1) +BuildRequires: (librsvg2-devel or librsvg-devel) + +Requires: openconnect >= 8.20, (libayatana-appindicator or libappindicator-gtk3) +Conflicts: globalprotect-openconnect-snapshot + +%global debug_package %{nil} + +%description +A GUI for GlobalProtect VPN, based on OpenConnect, supports the SSO authentication method. + +%prep +%setup + +%build +# The injected RUSTFLAGS could fail the build +unset RUSTFLAGS +make build OFFLINE=@OFFLINE@ BUILD_FE=0 + +%install +%make_install + +%files +%defattr(-,root,root) +%{_bindir}/gpclient +%{_bindir}/gpservice +%{_bindir}/gpauth +%{_bindir}/gpgui-helper +%{_datadir}/applications/gpgui.desktop +%{_datadir}/icons/hicolor/32x32/apps/gpgui.png +%{_datadir}/icons/hicolor/128x128/apps/gpgui.png +%{_datadir}/icons/hicolor/256x256@2/apps/gpgui.png +%{_datadir}/icons/hicolor/scalable/apps/gpgui.svg +%{_datadir}/polkit-1/actions/com.yuezk.gpgui.policy + +%dir %{_datadir}/icons/hicolor +%dir %{_datadir}/icons/hicolor/32x32 +%dir %{_datadir}/icons/hicolor/32x32/apps +%dir %{_datadir}/icons/hicolor/128x128 +%dir %{_datadir}/icons/hicolor/128x128/apps +%dir %{_datadir}/icons/hicolor/256x256@2 +%dir %{_datadir}/icons/hicolor/256x256@2/apps +%dir %{_datadir}/icons/hicolor/scalable +%dir %{_datadir}/icons/hicolor/scalable/apps +%dir %{_datadir}/polkit-1 +%dir %{_datadir}/polkit-1/actions + +%changelog +* @DATE@ Kevin Yue - @VERSION@ +- Bugfix and improvements