Repository navigation
feat: add audience controls, verified updates, and device enrollment #1094
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 8 * * *" | |
| permissions: | |
| contents: read | |
| env: | |
| DOTNET_VERSION: "10.0.x" | |
| DOTNET_NOLOGO: true | |
| DOTNET_CLI_TELEMETRY_OPTOUT: true | |
| NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages | |
| FAST_BUILD_PROPERTIES: "-p:OpenClawSkipDashboardBuild=true" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| go-whatsapp-security: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Go | |
| uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e | |
| with: | |
| go-version: "1.26.6" | |
| cache-dependency-path: src/whatsapp-whatsmeow-worker/go.sum | |
| - name: Check Go module tidiness | |
| working-directory: src/whatsapp-whatsmeow-worker | |
| run: | | |
| go mod tidy | |
| git diff --exit-code -- go.mod go.sum | |
| - name: Test WhatsApp whatsmeow worker | |
| working-directory: src/whatsapp-whatsmeow-worker | |
| run: go test ./... | |
| - name: Run govulncheck | |
| working-directory: src/whatsapp-whatsmeow-worker | |
| run: go run golang.org/x/vuln/cmd/govulncheck@v1.3.0 ./... | |
| build-and-test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 | |
| with: | |
| path: ${{ env.NUGET_PACKAGES }} | |
| key: nuget-${{ runner.os }}-${{ hashFiles('OpenClaw.Net.slnx', '**/*.csproj', '**/*.props', '**/*.targets') }} | |
| restore-keys: | | |
| nuget-${{ runner.os }}- | |
| - name: Setup Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 | |
| with: | |
| node-version: "20" | |
| - name: Restore solution | |
| run: dotnet restore OpenClaw.Net.slnx | |
| - name: Build solution | |
| run: dotnet build OpenClaw.Net.slnx --no-restore -c Release | |
| - name: Verify Vault publish boundary | |
| run: python3 eng/verify-vault-publish-boundary.py | |
| - name: Test standard targets | |
| run: dotnet test --no-build -c Release --verbosity normal --logger "trx;LogFileName=results.trx" src/OpenClaw.Tests | |
| - name: HelloAgent smoke | |
| run: dotnet run --project samples/OpenClaw.HelloAgent -c Release --no-build | |
| - name: Restore optional integrations | |
| run: dotnet restore OpenClaw.Net.slnx -p:OpenClawEnableOpenSandbox=true -p:OpenClawEnableMempalace=true | |
| - name: Build optional integrations | |
| run: dotnet build OpenClaw.Net.slnx --no-restore -c Release -p:OpenClawEnableOpenSandbox=true -p:OpenClawEnableMempalace=true | |
| - name: Test optional integrations | |
| run: dotnet test --no-build -c Release -p:OpenClawEnableOpenSandbox=true -p:OpenClawEnableMempalace=true --verbosity normal --logger "trx;LogFileName=results-sandbox.trx" src/OpenClaw.Tests | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: test-results | |
| path: "**/*.trx" | |
| capability-adapters: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Verify default dependency isolation and optional adapter builds | |
| run: bash eng/verify-capability-adapters.sh | |
| publish-aot: | |
| needs: build-and-test | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'schedule' | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 | |
| with: | |
| path: ${{ env.NUGET_PACKAGES }} | |
| key: nuget-${{ runner.os }}-${{ hashFiles('OpenClaw.Net.slnx', '**/*.csproj', '**/*.props', '**/*.targets') }} | |
| restore-keys: | | |
| nuget-${{ runner.os }}- | |
| - name: Ensure AOT prerequisites | |
| timeout-minutes: 8 | |
| run: bash .github/scripts/install-nativeaot-prereqs.sh | |
| - name: Publish and smoke-test standard NativeAOT binaries | |
| run: | | |
| chmod +x ./eng/verify-aot-smoke.sh | |
| ./eng/verify-aot-smoke.sh | |
| - name: Publish and smoke-test MAF NativeAOT gateway | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| chmod +x ./eng/verify-aot-maf-smoke.sh | |
| ./eng/verify-aot-maf-smoke.sh | |
| - name: Upload gateway artifact | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: gateway-aot-linux-x64 | |
| path: ./artifacts/aot/gateway/ | |
| - name: Upload CLI artifact | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: openclaw-cli-aot-linux-x64 | |
| path: ./artifacts/aot/cli/ | |
| macos-gateway-linker-probe: | |
| permissions: | |
| contents: read | |
| needs: build-and-test | |
| runs-on: macos-15 | |
| if: github.event_name == 'pull_request' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 | |
| with: | |
| path: ${{ env.NUGET_PACKAGES }} | |
| key: nuget-${{ runner.os }}-${{ hashFiles('OpenClaw.Net.slnx', '**/*.csproj', '**/*.props', '**/*.targets') }} | |
| restore-keys: | | |
| nuget-${{ runner.os }}- | |
| - name: Configure macOS Swift library path | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| developer_dir="$(xcode-select -p)" | |
| sdk_path="$(xcrun --sdk macosx --show-sdk-path)" | |
| library_paths=() | |
| for candidate in \ | |
| "/usr/lib/swift" \ | |
| "$developer_dir/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx" \ | |
| "$sdk_path/usr/lib/swift"; do | |
| if [[ -d "$candidate" ]]; then | |
| library_paths+=("$candidate") | |
| fi | |
| done | |
| if [[ -n "${LIBRARY_PATH:-}" ]]; then | |
| library_paths+=("$LIBRARY_PATH") | |
| fi | |
| joined="$(IFS=:; echo "${library_paths[*]}")" | |
| echo "LIBRARY_PATH=$joined" >> "$GITHUB_ENV" | |
| echo "Using macOS Swift library paths: $joined" | |
| - name: Verify gateway NativeAOT with modern linker | |
| id: probe | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p artifacts/linker-probe | |
| dotnet publish src/OpenClaw.Gateway/OpenClaw.Gateway.csproj \ | |
| -c Release \ | |
| -r osx-arm64 \ | |
| --self-contained true \ | |
| -p:PublishAot=true \ | |
| -p:OpenClawUseClassicMacLd=false \ | |
| -o artifacts/linker-probe/gateway \ | |
| 2>&1 | tee artifacts/linker-probe/publish.log | |
| - name: Report linker probe outcome | |
| if: always() | |
| shell: bash | |
| run: | | |
| if [[ "${{ steps.probe.outcome }}" == "success" ]]; then | |
| echo "::notice title=Gateway linked with modern linker::Keep the explicit classic-linker override only until one published release completes successfully." | |
| else | |
| echo "::warning title=Modern linker regression::The macos-15 gateway publish failed; use the scoped classic-linker override only for emergency diagnosis." | |
| fi | |
| - name: Upload linker probe log | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: macos-gateway-linker-probe | |
| path: artifacts/linker-probe/ | |
| publish-jit: | |
| needs: build-and-test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 | |
| with: | |
| path: ${{ env.NUGET_PACKAGES }} | |
| key: nuget-${{ runner.os }}-${{ hashFiles('OpenClaw.Net.slnx', '**/*.csproj', '**/*.props', '**/*.targets') }} | |
| restore-keys: | | |
| nuget-${{ runner.os }}- | |
| - name: Publish and smoke-test JIT binaries | |
| run: | | |
| chmod +x ./eng/verify-jit-smoke.sh | |
| chmod +x ./eng/verify-jit-maf-smoke.sh | |
| ./eng/verify-jit-smoke.sh | |
| ./eng/verify-jit-maf-smoke.sh | |
| - name: Upload gateway artifact | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: gateway-jit-linux-x64 | |
| path: ./artifacts/jit/gateway/ | |
| - name: Upload CLI artifact | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: openclaw-cli-jit-linux-x64 | |
| path: ./artifacts/jit/cli/ | |
| docker: | |
| needs: build-and-test | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push | |
| uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc | |
| with: | |
| context: . | |
| push: true | |
| tags: | | |
| ghcr.io/${{ github.repository }}:latest | |
| ghcr.io/${{ github.repository }}:${{ github.sha }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| public-compatibility-smoke: | |
| permissions: | |
| contents: read | |
| needs: build-and-test | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| env: | |
| OPENCLAW_PUBLIC_SMOKE: "1" | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 | |
| with: | |
| path: ${{ env.NUGET_PACKAGES }} | |
| key: nuget-${{ runner.os }}-${{ hashFiles('OpenClaw.Net.slnx', '**/*.csproj', '**/*.props', '**/*.targets') }} | |
| restore-keys: | | |
| nuget-${{ runner.os }}- | |
| - name: Setup Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 | |
| with: | |
| node-version: "22" | |
| - name: Restore | |
| run: dotnet restore src/OpenClaw.Tests | |
| - name: Build | |
| run: dotnet build --no-restore -c Release src/OpenClaw.Tests ${{ env.FAST_BUILD_PROPERTIES }} | |
| - name: Run Public Compatibility Smoke | |
| run: dotnet test --no-build -c Release --filter "Category=PublicSmoke" --verbosity normal --logger "trx;LogFileName=public-smoke.trx" src/OpenClaw.Tests | |
| - name: Probe latest public plugin packages | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| id: latest_plugin_canary | |
| continue-on-error: true | |
| env: | |
| OPENCLAW_LATEST_CANARY: "1" | |
| run: dotnet test --no-build -c Release --filter "Category=LatestCanary" --verbosity normal --logger "trx;LogFileName=latest-plugin-canary.trx" src/OpenClaw.Tests | |
| - name: Report latest-package compatibility canary | |
| if: always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') | |
| shell: bash | |
| run: | | |
| if [[ "${{ steps.latest_plugin_canary.outcome }}" == "success" ]]; then | |
| echo "### Latest plugin compatibility canary: passing" >> "$GITHUB_STEP_SUMMARY" | |
| echo "Current npm releases still match the pinned compatibility expectations." >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| result="${{ steps.latest_plugin_canary.outcome }}" | |
| echo "::warning title=Latest plugin compatibility canary failed::The canary result was '${result}'. This may indicate package compatibility drift or a Node, npm, process, or test-infrastructure failure. Review the latest-plugin-canary artifact; the pinned release gate remains authoritative." | |
| echo "### Latest plugin compatibility canary: ${result}" >> "$GITHUB_STEP_SUMMARY" | |
| echo "Review the latest-plugin-canary test artifact to classify the failure. This signal is intentionally non-blocking; pinned public-smoke scenarios remain the release gate." >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| - name: Upload smoke results | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: public-smoke-results | |
| path: | | |
| **/public-smoke.trx | |
| **/latest-plugin-canary.trx | |
| vault-integration: | |
| name: Vault integration tests (opt-in) | |
| runs-on: ubuntu-latest | |
| if: github.event.repository.fork == false && vars.RUN_VAULT_INTEGRATION == 'true' | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 | |
| with: | |
| path: ${{ env.NUGET_PACKAGES }} | |
| key: nuget-${{ runner.os }}-${{ hashFiles('OpenClaw.Net.slnx', '**/*.csproj', '**/*.props', '**/*.targets') }} | |
| restore-keys: | | |
| nuget-${{ runner.os }}- | |
| - name: Start OpenBao | |
| run: docker compose -f deploy/docker-compose/openbao.yml up -d | |
| - name: Wait for OpenBao | |
| run: | | |
| for i in {1..30}; do | |
| if curl -sf http://127.0.0.1:8200/v1/sys/health >/dev/null; then | |
| echo "OpenBao is healthy after ${i}s" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "::error::OpenBao did not become healthy within 30s" | |
| exit 1 | |
| - name: Run integration tests | |
| env: | |
| OPENBAO_ADDR: http://127.0.0.1:8200 | |
| OPENBAO_TOKEN: root | |
| run: dotnet test src/OpenClaw.Tests/OpenClaw.Tests.csproj --filter "Category=Integration" | |
| - name: Tear down OpenBao | |
| if: always() | |
| run: docker compose -f deploy/docker-compose/openbao.yml down -v |