test: rename cli -> headless (fork re-test) #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| gp_branch: | |
| description: 'GlobalProtect-openconnect branch to use for the snapshot release' | |
| required: true | |
| default: dev | |
| gpgui_branch: | |
| description: 'gpgui branch to use for the snapshot release' | |
| required: true | |
| default: dev | |
| build_bsd: | |
| description: 'Build FreeBSD/OpenBSD packages for the snapshot release' | |
| required: true | |
| default: false | |
| type: boolean | |
| build_bsd_arm64: | |
| description: 'Build optional FreeBSD/OpenBSD arm64 packages for the snapshot release. Slow and disabled by default' | |
| required: true | |
| default: false | |
| type: boolean | |
| push: | |
| paths-ignore: | |
| - LICENSE | |
| - "*.md" | |
| - .vscode | |
| - .devcontainer | |
| branches: | |
| - main | |
| - hotfix/* | |
| - feature/* | |
| - release/* | |
| tags: | |
| - v*.*.* | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| tarball: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: pnpm/action-setup@v5 | |
| with: | |
| version: 9 | |
| - name: Prepare workspace | |
| run: rm -rf source && mkdir -p source/artifacts | |
| - name: Checkout GlobalProtect-openconnect | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/GlobalProtect-openconnect | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gp_branch || github.ref }} | |
| path: source/gp | |
| submodules: recursive | |
| - name: Create tarball | |
| run: | | |
| cd source/gp | |
| # Generate the SNAPSHOT file for non-tagged commits | |
| if [[ "${{ github.ref }}" != "refs/tags/"* ]]; then | |
| touch SNAPSHOT | |
| fi | |
| make tarball | |
| mv -v .build/tarball/*.tar.gz ../artifacts/ | |
| - name: Generate RPM spec file | |
| env: | |
| RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && 'snapshot' || github.ref_name }} | |
| run: | | |
| cd source/gp | |
| make init-rpm \ | |
| REVISION='1%{?dist}' \ | |
| RPM_SOURCE=https://github.com/yuezk/GlobalProtect-openconnect/releases/download/${RELEASE_TAG}/%{name}-%{version}.tar.gz | |
| mv -v .build/rpm/*.spec ../artifacts/ | |
| - name: Upload tarball | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: artifact-source | |
| if-no-files-found: error | |
| path: | | |
| source/artifacts/* | |
| tarball-offline: | |
| if: ${{ github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') }} | |
| runs-on: ubuntu-latest | |
| needs: | |
| - tarball | |
| steps: | |
| - uses: pnpm/action-setup@v5 | |
| with: | |
| version: 9 | |
| - name: Prepare workspace | |
| run: rm -rf source-offline && mkdir source-offline | |
| - name: Download tarball | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: artifact-source | |
| path: source-offline | |
| - name: Create offline tarball | |
| run: | | |
| cd source-offline | |
| offline_tarball=$(basename *.tar.gz .tar.gz).offline.tar.gz | |
| # Extract the tarball | |
| tar -xzf *.tar.gz | |
| cd */ | |
| make tarball OFFLINE=1 | |
| # Rename the tarball to .offline.tar.gz | |
| mv -v .build/tarball/*.tar.gz ../$offline_tarball | |
| - name: Upload offline tarball | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| path: source-offline/*.offline.tar.gz | |
| name: artifact-source-offline | |
| if-no-files-found: error | |
| build-gp: | |
| if: ${{ !startsWith(github.ref, 'refs/tags/') }} | |
| needs: | |
| - tarball | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - runner: ubuntu-latest | |
| arch: amd64 | |
| - runner: ubuntu-24.04-arm | |
| arch: ubuntu-24.04-arm | |
| package: [deb, rpm, pkg, apk, binary, ubuntu-rolling] | |
| runs-on: ${{ matrix.os.runner }} | |
| name: build-gp (${{ matrix.package }}, ${{ matrix.os.arch }}) | |
| steps: | |
| - name: Prepare workspace | |
| run: | | |
| rm -rf build-gp-${{ matrix.package }} | |
| mkdir -p build-gp-${{ matrix.package }} | |
| - name: Download tarball | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: artifact-source | |
| path: build-gp-${{ matrix.package }} | |
| - name: Build ${{ matrix.package }} package in Docker | |
| # LIBXML2_STATIC is needed to avoid the dynamic linking issue on different distros | |
| run: | | |
| docker run --rm \ | |
| -e COREPACK_INTEGRITY_KEYS=0 \ | |
| -e LIBXML2_STATIC=1 \ | |
| -v $(pwd)/build-gp-${{ matrix.package }}:/workspace \ | |
| yuezk/gpdev:${{ matrix.package }}-builder-tauri2 | |
| - name: Install ${{ matrix.package }} package in Docker | |
| run: | | |
| docker run --rm \ | |
| -e COREPACK_INTEGRITY_KEYS=0 \ | |
| -e GPGUI_INSTALLED=0 \ | |
| -v $(pwd)/build-gp-${{ matrix.package }}:/workspace \ | |
| yuezk/gpdev:${{ matrix.package }}-builder-tauri2 \ | |
| bash install.sh | |
| # Don't upload package for ubuntu-rolling because it's duplicate of deb package | |
| - name: Upload ${{ matrix.package }} package | |
| if: ${{ matrix.package != 'ubuntu-rolling' }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: artifact-gp-${{ matrix.package }}-${{ matrix.os.arch }} | |
| if-no-files-found: error | |
| path: | | |
| build-gp-${{ matrix.package }}/artifacts/* | |
| # GUI-free variant, for the headless servers README.md names as the audience | |
| # for `--browser remote`. Same source and same builder images as build-gp; | |
| # only the three GUI flags differ, which #638 made effective for `depends=`. | |
| # | |
| # Scoped to apk and deb: those are the two formats whose depends= is gated on | |
| # the flags today (Makefile `init-apk` / `init-debian`). An rpm built this way | |
| # would still declare the GUI dependencies, so a "CLI" rpm would mislead. | |
| build-gp-headless: | |
| if: ${{ !startsWith(github.ref, 'refs/tags/') }} | |
| needs: | |
| - tarball | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - runner: ubuntu-latest | |
| arch: amd64 | |
| - runner: ubuntu-24.04-arm | |
| arch: ubuntu-24.04-arm | |
| package: [apk, deb] | |
| runs-on: ${{ matrix.os.runner }} | |
| name: build-gp-headless (${{ matrix.package }}, ${{ matrix.os.arch }}) | |
| steps: | |
| - name: Prepare workspace | |
| run: | | |
| rm -rf build-gp-headless-${{ matrix.package }} | |
| mkdir -p build-gp-headless-${{ matrix.package }} | |
| - name: Download tarball | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: artifact-source | |
| path: build-gp-headless-${{ matrix.package }} | |
| - name: Build GUI-free ${{ matrix.package }} package in Docker | |
| run: | | |
| docker run --rm \ | |
| -e COREPACK_INTEGRITY_KEYS=0 \ | |
| -e LIBXML2_STATIC=1 \ | |
| -e INCLUDE_GUI=0 \ | |
| -e BUILD_GUI_HELPER=0 \ | |
| -e BUILD_WEBVIEW_AUTH=0 \ | |
| -v $(pwd)/build-gp-headless-${{ matrix.package }}:/workspace \ | |
| yuezk/gpdev:${{ matrix.package }}-builder-tauri2 | |
| # Not `bash install.sh`: that script checks `gpgui-helper --version` | |
| # unconditionally, and BUILD_GUI_HELPER=0 means it isn't built. Its | |
| # GPGUI_INSTALLED knob covers gpgui but not the helper. Rather than ask for | |
| # a new knob in the builder image, this asserts the property that actually | |
| # matters for the variant — the CLI binaries work and no GUI binary shipped. | |
| - name: Verify GUI-free ${{ matrix.package }} package in Docker | |
| run: | | |
| docker run --rm \ | |
| -e COREPACK_INTEGRITY_KEYS=0 \ | |
| -v $(pwd)/build-gp-headless-${{ matrix.package }}:/workspace \ | |
| --entrypoint /bin/bash \ | |
| yuezk/gpdev:${{ matrix.package }}-builder-tauri2 -lc ' | |
| set -eux | |
| if command -v apk >/dev/null; then | |
| sudo apk add --allow-untrusted /workspace/artifacts/*.apk | |
| else | |
| sudo apt-get install -y /workspace/artifacts/*.deb | |
| fi | |
| gpclient --version | |
| gpservice --version | |
| gpauth --version | |
| ! command -v gpgui-helper | |
| ! command -v gpgui | |
| ' | |
| - name: Upload GUI-free ${{ matrix.package }} package | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: artifact-gp-headless-${{ matrix.package }}-${{ matrix.os.arch }} | |
| if-no-files-found: error | |
| path: | | |
| build-gp-headless-${{ matrix.package }}/artifacts/* | |
| build-docker-image: | |
| if: ${{ !startsWith(github.ref, 'refs/tags/') }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-latest | |
| platform: linux/amd64 | |
| - runner: ubuntu-24.04-arm | |
| platform: linux/arm64 | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - name: Prepare | |
| run: | | |
| platform=${{ matrix.platform }} | |
| echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV" | |
| - name: Checkout GlobalProtect-openconnect | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/GlobalProtect-openconnect | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gp_branch || github.ref }} | |
| submodules: recursive | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| username: ${{ secrets.DOCKER_HUB_USERNAME }} | |
| password: ${{ secrets.DOCKER_HUB_TOKEN }} | |
| - name: Build and push by digest | |
| id: build | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| file: packaging/docker/alpine/Dockerfile | |
| platforms: ${{ matrix.platform }} | |
| outputs: type=image,name=yuezk/globalprotect-openconnect,push-by-digest=true,name-canonical=true,push=true | |
| - name: Verify CLI tools | |
| env: | |
| IMAGE: yuezk/globalprotect-openconnect | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| run: | | |
| docker run --rm "$IMAGE@$DIGEST" --help | |
| docker run --rm --entrypoint gpauth "$IMAGE@$DIGEST" --help | |
| docker run --rm --entrypoint sh "$IMAGE@$DIGEST" -lc 'test "$(id -u gp)" = "1000" && test "$SUDO_UID" = "1000"' | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "/tmp/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: digests-${{ env.PLATFORM_PAIR }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| build-gpgui: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - runner: ubuntu-latest | |
| arch: amd64 | |
| - runner: ubuntu-24.04-arm | |
| arch: ubuntu-24.04-arm | |
| libc: | |
| - name: glibc | |
| builder: gpgui-builder-tauri2 | |
| artifact_suffix: "" | |
| - name: musl | |
| builder: gpgui-alpine-builder-tauri2 | |
| artifact_suffix: "-musl" | |
| runs-on: ${{ matrix.os.runner }} | |
| name: build-gpgui (${{ matrix.libc.name }}, ${{ matrix.os.arch }}) | |
| steps: | |
| - uses: pnpm/action-setup@v5 | |
| with: | |
| version: 9 | |
| - name: Prepare workspace | |
| run: rm -rf gpgui-source && mkdir gpgui-source | |
| - name: Checkout GlobalProtect-openconnect | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/GlobalProtect-openconnect | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gp_branch || github.ref }} | |
| path: gpgui-source/gp | |
| submodules: recursive | |
| - name: Checkout gpgui | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/gpgui | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gpgui_branch || github.ref_name }} | |
| path: gpgui-source/gpgui | |
| - name: Tarball | |
| run: | | |
| cd gpgui-source | |
| tar -czf gpgui.tar.gz gpgui gp | |
| - name: Build gpgui in Docker | |
| run: | | |
| docker run --rm \ | |
| -e COREPACK_INTEGRITY_KEYS=0 \ | |
| -v $(pwd)/gpgui-source:/workspace yuezk/gpdev:${{ matrix.libc.builder }} | |
| - name: Install gpgui in Docker | |
| run: | | |
| cd gpgui-source | |
| tar -xJf *.bin.tar.xz | |
| docker run --rm \ | |
| -e COREPACK_INTEGRITY_KEYS=0 \ | |
| -v $(pwd):/workspace yuezk/gpdev:${{ matrix.libc.builder }} \ | |
| bash -c "cd /workspace/gpgui_*/ && ./gpgui --version" | |
| - name: Upload gpgui | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: artifact-gpgui${{ matrix.libc.artifact_suffix }}-${{ matrix.os.arch }} | |
| if-no-files-found: error | |
| path: | | |
| gpgui-source/*.bin.tar.xz | |
| gpgui-source/*.bin.tar.xz.sha256 | |
| setup-bsd-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| enabled: ${{ steps.matrix.outputs.enabled }} | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| steps: | |
| - name: Build matrix | |
| id: matrix | |
| env: | |
| IS_TAG: ${{ startsWith(github.ref, 'refs/tags/') }} | |
| BUILD_BSD: ${{ github.event_name == 'workflow_dispatch' && inputs.build_bsd }} | |
| BUILD_BSD_ARM64: ${{ github.event_name == 'workflow_dispatch' && inputs.build_bsd_arm64 }} | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| build_bsd = os.environ["IS_TAG"] == "true" or os.environ["BUILD_BSD"] == "true" | |
| build_bsd_arm64 = os.environ["BUILD_BSD_ARM64"] == "true" | |
| include = [] | |
| def add(os_name, arch): | |
| include.append({ | |
| "os": os_name, | |
| "arch": arch, | |
| "workspace": f"{os_name}-{arch}-source", | |
| "artifact": f"artifact-bsd-{os_name}-{arch}", | |
| "package_target": f"package-{os_name}", | |
| "artifact_dir": os_name, | |
| }) | |
| if build_bsd: | |
| add("freebsd", "x86_64") | |
| add("openbsd", "x86_64") | |
| if build_bsd_arm64: | |
| add("freebsd", "arm64") | |
| add("openbsd", "arm64") | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output: | |
| output.write(f"enabled={str(bool(include)).lower()}\n") | |
| output.write(f"matrix={json.dumps({'include': include}, separators=(',', ':'))}\n") | |
| PY | |
| build-gpgui-frontend: | |
| needs: setup-bsd-matrix | |
| if: ${{ needs.setup-bsd-matrix.outputs.enabled == 'true' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: pnpm/action-setup@v5 | |
| with: | |
| version: 9 | |
| - name: Prepare workspace | |
| run: rm -rf gpgui-frontend && mkdir gpgui-frontend | |
| - name: Checkout GlobalProtect-openconnect | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/GlobalProtect-openconnect | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gp_branch || github.ref }} | |
| path: gpgui-frontend/gp | |
| submodules: recursive | |
| - name: Checkout gpgui | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/gpgui | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gpgui_branch || github.ref_name }} | |
| path: gpgui-frontend/gpgui | |
| - name: Build gpgui frontend | |
| run: | | |
| cd gpgui-frontend/gpgui/app | |
| pnpm install --frozen-lockfile | |
| pnpm build | |
| - name: Upload gpgui frontend | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: bsd-gpgui-frontend | |
| if-no-files-found: error | |
| path: gpgui-frontend/gpgui/app/dist/** | |
| build-bsd: | |
| needs: | |
| - setup-bsd-matrix | |
| - build-gpgui-frontend | |
| if: ${{ needs.setup-bsd-matrix.outputs.enabled == 'true' }} | |
| runs-on: ubuntu-latest | |
| name: build-${{ matrix.os }} (${{ matrix.arch }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.setup-bsd-matrix.outputs.matrix) }} | |
| steps: | |
| - name: Prepare workspace | |
| run: rm -rf "${{ matrix.workspace }}" && mkdir "${{ matrix.workspace }}" | |
| - name: Checkout GlobalProtect-openconnect | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/GlobalProtect-openconnect | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gp_branch || github.ref }} | |
| path: ${{ matrix.workspace }}/gp | |
| submodules: recursive | |
| - name: Checkout gpgui | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/gpgui | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gpgui_branch || github.ref_name }} | |
| path: ${{ matrix.workspace }}/gpgui | |
| - name: Download gpgui frontend | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: bsd-gpgui-frontend | |
| path: ${{ matrix.workspace }}/gpgui/app/dist | |
| - name: Build on FreeBSD | |
| if: ${{ matrix.os == 'freebsd' }} | |
| uses: vmactions/freebsd-vm@v1 | |
| with: | |
| release: "14.4" | |
| arch: ${{ matrix.arch }} | |
| usesh: true | |
| prepare: | | |
| pkg install -y \ | |
| git \ | |
| rust \ | |
| libiconv \ | |
| gettext-tools \ | |
| autoconf \ | |
| automake \ | |
| libtool \ | |
| patch \ | |
| gmake \ | |
| pkgconf \ | |
| libxml2 \ | |
| gnutls \ | |
| p11-kit \ | |
| nettle \ | |
| gmp \ | |
| gnome-keyring \ | |
| libayatana-appindicator \ | |
| polkit \ | |
| webkit2-gtk_41 | |
| run: | | |
| set -eu | |
| cd "${{ matrix.workspace }}/gp" | |
| cargo build --release --workspace | |
| cd ../gpgui/app/src-tauri | |
| cargo build --release --workspace | |
| cd ../../../gp | |
| gmake "${{ matrix.package_target }}" GPGUI_BINARY=../gpgui/target/release/gpgui | |
| pkg install -y ".build/${{ matrix.artifact_dir }}"/artifacts/*.pkg | |
| gpclient --version | |
| gpauth --version | |
| gpgui --version | |
| rm -rf target ../gpgui/target | |
| find ".build/${{ matrix.artifact_dir }}" -mindepth 1 -maxdepth 1 ! -name artifacts -exec rm -rf {} + | |
| - name: Build on OpenBSD | |
| if: ${{ matrix.os == 'openbsd' }} | |
| uses: vmactions/openbsd-vm@v1 | |
| with: | |
| release: "7.9" | |
| arch: ${{ matrix.arch }} | |
| usesh: true | |
| prepare: | | |
| pkg_add -z \ | |
| git \ | |
| rust \ | |
| libiconv \ | |
| gettext-tools \ | |
| autoconf-2.72 \ | |
| automake-1.17 \ | |
| libtool \ | |
| patch \ | |
| gmake \ | |
| pkgconf \ | |
| libxml \ | |
| gnutls \ | |
| p11-kit \ | |
| nettle \ | |
| gmp \ | |
| gnome-keyring \ | |
| polkit \ | |
| webkitgtk41 | |
| ln -sf /usr/local/bin/autoreconf-2.72 /usr/local/bin/autoreconf | |
| ln -sf /usr/local/bin/autoconf-2.72 /usr/local/bin/autoconf | |
| ln -sf /usr/local/bin/autoheader-2.72 /usr/local/bin/autoheader | |
| ln -sf /usr/local/bin/autom4te-2.72 /usr/local/bin/autom4te | |
| ln -sf /usr/local/bin/aclocal-1.17 /usr/local/bin/aclocal | |
| ln -sf /usr/local/bin/automake-1.17 /usr/local/bin/automake | |
| run: | | |
| set -eu | |
| export AUTOCONF_VERSION=2.72 | |
| export AUTOMAKE_VERSION=1.17 | |
| cd "${{ matrix.workspace }}/gp" | |
| cargo build --release --workspace | |
| cd ../gpgui/app/src-tauri | |
| cargo build --release --workspace | |
| cd ../../../gp | |
| gmake "${{ matrix.package_target }}" GPGUI_BINARY=../gpgui/target/release/gpgui | |
| pkg_add -D unsigned ".build/${{ matrix.artifact_dir }}"/artifacts/*.tgz | |
| gpclient --version | |
| gpauth --version | |
| gpgui --version | |
| rm -rf target ../gpgui/target | |
| find ".build/${{ matrix.artifact_dir }}" -mindepth 1 -maxdepth 1 ! -name artifacts -exec rm -rf {} + | |
| - name: Upload BSD package | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.artifact }} | |
| if-no-files-found: error | |
| path: | | |
| ${{ matrix.workspace }}/gp/.build/${{ matrix.artifact_dir }}/artifacts/* | |
| gh-release: | |
| if: ${{ always() && (github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/')) }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: read | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| artifact-metadata: write | |
| needs: | |
| - tarball | |
| - tarball-offline | |
| - build-gp | |
| - build-docker-image | |
| - build-gpgui | |
| - setup-bsd-matrix | |
| - build-gpgui-frontend | |
| - build-bsd | |
| steps: | |
| - name: Check required jobs | |
| env: | |
| NEEDS_JSON: ${{ toJson(needs) }} | |
| BSD_MATRIX_ENABLED: ${{ needs.setup-bsd-matrix.outputs.enabled }} | |
| IS_TAG: ${{ startsWith(github.ref, 'refs/tags/') }} | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| needs = json.loads(os.environ["NEEDS_JSON"]) | |
| bsd_matrix_enabled = os.environ["BSD_MATRIX_ENABLED"] == "true" | |
| is_tag = os.environ["IS_TAG"] == "true" | |
| failed = [] | |
| for name, data in needs.items(): | |
| result = data["result"] | |
| if result in {"failure", "cancelled"}: | |
| failed.append(f"{name}: {result}") | |
| elif name in {"build-gp", "build-docker-image"} and result == "skipped" and is_tag: | |
| continue | |
| elif name in {"build-gpgui-frontend", "build-bsd"} and result == "skipped" and not bsd_matrix_enabled: | |
| continue | |
| elif result == "skipped": | |
| failed.append(f"{name}: {result}") | |
| if failed: | |
| print("Required jobs did not complete successfully:") | |
| for item in failed: | |
| print(f" - {item}") | |
| sys.exit(1) | |
| PY | |
| - name: Prepare workspace | |
| run: rm -rf gh-release && mkdir gh-release | |
| - name: Checkout GlobalProtect-openconnect | |
| uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GH_PAT }} | |
| repository: yuezk/GlobalProtect-openconnect | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.gp_branch || github.ref }} | |
| path: gh-release/gp | |
| submodules: recursive | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: gh-release/gp/.build/artifacts | |
| - name: Rename APK artifacts | |
| run: | | |
| shopt -s nullglob | |
| for file in gh-release/gp/.build/artifacts/artifact-gp-apk-amd64/*.apk; do | |
| mv "$file" "${file%.apk}-x86_64.apk" | |
| done | |
| for file in gh-release/gp/.build/artifacts/artifact-gp-apk-ubuntu-24.04-arm/*.apk; do | |
| mv "$file" "${file%.apk}-aarch64.apk" | |
| done | |
| - name: Generate release asset checksums | |
| env: | |
| RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && 'snapshot' || github.ref_name }} | |
| run: | | |
| cd gh-release/gp | |
| mkdir -p .build | |
| scripts/release-assets.sh "$RELEASE_TAG" > .build/release-assets.txt | |
| if [ ! -s .build/release-assets.txt ]; then | |
| echo "No release assets found" | |
| exit 1 | |
| fi | |
| while IFS= read -r file; do | |
| digest=$(sha256sum "$file" | cut -d ' ' -f 1) | |
| printf '%s %s\n' "$digest" "$(basename "$file")" | |
| done < .build/release-assets.txt > .build/release-assets.sha256 | |
| - name: Attest release assets | |
| uses: actions/attest-build-provenance@v4 | |
| with: | |
| subject-checksums: gh-release/gp/.build/release-assets.sha256 | |
| - name: Create GH release | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_PAT }} | |
| RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && 'snapshot' || github.ref_name }} | |
| run: | | |
| cd gh-release/gp/scripts && ./gh-release.sh "$RELEASE_TAG" | |
| publish-docker-image: | |
| needs: | |
| - build-docker-image | |
| if: ${{ github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download digests | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: /tmp/digests | |
| pattern: digests-* | |
| merge-multiple: true | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| username: ${{ secrets.DOCKER_HUB_USERNAME }} | |
| password: ${{ secrets.DOCKER_HUB_TOKEN }} | |
| - name: Publish Docker manifest | |
| working-directory: /tmp/digests | |
| env: | |
| IMAGE: yuezk/globalprotect-openconnect | |
| RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && 'snapshot' || github.ref_name }} | |
| run: | | |
| docker buildx imagetools create -t "$IMAGE:$RELEASE_TAG" \ | |
| $(printf "$IMAGE@sha256:%s " *) | |
| docker buildx imagetools inspect "$IMAGE:$RELEASE_TAG" |