name: Agents Release on: push: tags: ["agents-v*"] permissions: contents: write concurrency: group: agents-release cancel-in-progress: false jobs: bump-versions: runs-on: ubuntu-latest outputs: versions: ${{ steps.bump.outputs.versions }} prev_versions: ${{ steps.bump.outputs.prev_versions }} prev_tag: ${{ steps.bump.outputs.prev_tag }} effective_prev_ref: ${{ steps.bump.outputs.effective_prev_ref }} changed_modules: ${{ steps.bump.outputs.changed_modules }} java_modules: ${{ steps.bump.outputs.java_modules }} native_modules: ${{ steps.bump.outputs.native_modules }} reuse_modules: ${{ steps.bump.outputs.reuse_modules }} build_jre: ${{ steps.bump.outputs.build_jre }} reuse_jre: ${{ steps.bump.outputs.reuse_jre }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Detect changes and bump versions id: bump shell: bash run: | LEGACY_REPO="https://github.com/t8y2/dbx-agents.git" LEGACY_BASE_TAG="v0.2.33" PREV_TAG=$(git tag --sort=-creatordate | grep '^agents-v' | sed -n '2p') SKIP_BUMP=false MIGRATED_FIRST_RELEASE=false PREV_VERSIONS_FILE="" if [ -z "$PREV_TAG" ]; then echo "No previous agents-v tag found; treating this as the first migrated agents release" PREV_TAG=$(git rev-list --max-parents=0 HEAD) TMP_LEGACY="$(mktemp -d)" git clone --depth 1 --branch "$LEGACY_BASE_TAG" "$LEGACY_REPO" "$TMP_LEGACY" PREV_VERSIONS_FILE="$(mktemp)" cp "$TMP_LEGACY/versions.json" "$PREV_VERSIONS_FILE" rm -rf "$TMP_LEGACY" SKIP_BUMP=true MIGRATED_FIRST_RELEASE=true fi echo "Comparing $PREV_TAG..HEAD" ARGS=(--prev-tag "$PREV_TAG" --migrated-first-release "$MIGRATED_FIRST_RELEASE" --write) if [ "$SKIP_BUMP" = "true" ]; then ARGS+=(--skip-bump) fi if [ -n "$PREV_VERSIONS_FILE" ]; then ARGS+=(--prev-versions-file "$PREV_VERSIONS_FILE") fi node .github/scripts/bump-agent-versions.mjs "${ARGS[@]}" - name: Create agent version patch run: git diff --binary -- agents/versions.json > agent-version-bump.patch - name: Upload agent version patch uses: actions/upload-artifact@v4 with: name: agent-version-bump path: agent-version-bump.patch retention-days: 1 commit-versions: name: Commit agent version bump needs: bump-versions runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.MCP_RELEASE_TOKEN }} - name: Download agent version patch uses: actions/download-artifact@v4 with: name: agent-version-bump - name: Apply and push agent version bump shell: bash run: | set -euo pipefail git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git fetch origin main --no-tags git switch --detach origin/main if [ ! -s agent-version-bump.patch ]; then echo "Agent versions are unchanged." exit 0 fi if git apply --check agent-version-bump.patch; then git apply --index agent-version-bump.patch elif git apply --reverse --check agent-version-bump.patch; then echo "Agent version bump is already present on main." exit 0 else echo "::error::Agent version patch no longer applies cleanly to main." exit 1 fi git commit -m "chore: bump module versions [skip ci]" for attempt in 1 2 3; do if git push origin HEAD:main; then exit 0 fi if [ "$attempt" -eq 3 ]; then echo "::error::Unable to push agent version bump after ${attempt} attempts." exit 1 fi git fetch origin main --no-tags git rebase origin/main done build-agents: needs: [bump-versions] if: ${{ needs.bump-versions.outputs.java_modules != '[]' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: temurin java-version: "21" - uses: gradle/actions/setup-gradle@v4 - name: Build changed Java agents env: JAVA_MODULES: ${{ needs.bump-versions.outputs.java_modules }} run: | mapfile -t MODULES < <(echo "$JAVA_MODULES" | python3 -c 'import json,sys; print("\n".join(json.load(sys.stdin)))') TASKS=() for module in "${MODULES[@]}"; do TASKS+=(":${module}:shadowJar") done # agents/common changes trigger a parallel mass rebuild of every # packaged module; the Gradle daemon default heap is too small for # ~25 shadowJar fat jars at once on a 16 GB runner. ./gradlew "${TASKS[@]}" --parallel \ -Dorg.gradle.jvmargs="-Xmx4g -XX:MaxMetaspaceSize=1g" working-directory: agents - run: python3 scripts/validate_agent_jars.py working-directory: agents - uses: actions/upload-artifact@v4 with: name: agent-jars path: | agents/drivers/*/build/libs/dbx-agent-*.jar build-oracle-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'oracle') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22.x" - name: Test Oracle native agent working-directory: agents/drivers/oracle-go run: go test ./... - name: Cross-compile Oracle native agent shell: bash run: | mkdir -p release-native cd agents/drivers/oracle-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-oracle-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native # Go 1.20 is the last release that supports Windows 7; keep other targets on Go 1.22. - name: Set up Go for Windows 7-compatible Oracle agent uses: actions/setup-go@v5 with: go-version: "1.20.14" cache-dependency-path: agents/drivers/oracle-go/go.sum - name: Build Windows 7-compatible Oracle agent shell: bash working-directory: agents/drivers/oracle-go run: | output="../../../release-native/dbx-agent-oracle-windows-x64.exe" CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o "$output" . go version -m "$output" | tee /tmp/oracle-windows-x64-build-info.txt grep -q ': go1\.20\.14$' /tmp/oracle-windows-x64-build-info.txt - uses: actions/upload-artifact@v4 with: name: oracle-native path: "release-native/dbx-agent-oracle-*" build-xugu-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'xugu') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22.x" - name: Test Xugu native agent working-directory: agents/drivers/xugu run: GONOSUMDB=gitee.com/XuguDB/go-xugu-driver go test ./... - name: Cross-compile Xugu native agent shell: bash run: | mkdir -p release-native cd agents/drivers/xugu declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-xugu-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" GONOSUMDB=gitee.com/XuguDB/go-xugu-driver CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: xugu-native path: "release-native/dbx-agent-xugu-*" build-rabbitmq-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'rabbitmq') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22.x" - name: Test RabbitMQ native agent working-directory: agents/drivers/rabbitmq run: go test ./... - name: Cross-compile RabbitMQ native agent shell: bash run: | mkdir -p release-native cd agents/drivers/rabbitmq declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-rabbitmq-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native # Go 1.20 is the last release that supports Windows 7; keep other targets on Go 1.22. - name: Set up Go for Windows 7-compatible RabbitMQ agent uses: actions/setup-go@v5 with: go-version: "1.20.14" cache-dependency-path: agents/drivers/rabbitmq/go.sum - name: Build Windows 7-compatible RabbitMQ agent shell: bash working-directory: agents/drivers/rabbitmq run: | output="../../../release-native/dbx-agent-rabbitmq-windows-x64.exe" CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o "$output" . go version -m "$output" | tee /tmp/rabbitmq-windows-x64-build-info.txt grep -q ': go1\.20\.14$' /tmp/rabbitmq-windows-x64-build-info.txt - uses: actions/upload-artifact@v4 with: name: rabbitmq-native path: "release-native/dbx-agent-rabbitmq-*" build-rocketmq-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'rocketmq') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.25.x" - name: Test RocketMQ native agent working-directory: agents/drivers/rocketmq run: go test -race ./... - name: Cross-compile RocketMQ native agent shell: bash run: | mkdir -p release-native cd agents/drivers/rocketmq declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-rocketmq-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: rocketmq-native path: "release-native/dbx-agent-rocketmq-*" build-etcd-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'etcd') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.26.x" - name: Test etcd native agent working-directory: agents/drivers/etcd-go run: go test ./... - name: Cross-compile etcd native agent shell: bash run: | mkdir -p release-native cd agents/drivers/etcd-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-etcd-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: etcd-native path: "release-native/dbx-agent-etcd-*" build-etcd2-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'etcd2') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.24.x" - name: Test etcd v2 native agent working-directory: agents/drivers/etcd2-go run: go test ./... - name: Cross-compile etcd v2 native agent shell: bash run: | mkdir -p release-native cd agents/drivers/etcd2-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-etcd2-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: etcd2-native path: "release-native/dbx-agent-etcd2-*" build-zookeeper-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'zookeeper') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.25.x" - name: Test ZooKeeper native agent working-directory: agents/drivers/zookeeper run: go test -race ./... - name: Cross-compile ZooKeeper native agent shell: bash run: | mkdir -p release-native cd agents/drivers/zookeeper declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-zookeeper-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: zookeeper-native path: "release-native/dbx-agent-zookeeper-*" build-cassandra-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'cassandra') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22.x" - name: Test Cassandra native agent working-directory: agents/drivers/cassandra-go run: go test ./... - name: Cross-compile Cassandra native agent shell: bash run: | mkdir -p release-native cd agents/drivers/cassandra-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-cassandra-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: cassandra-native path: "release-native/dbx-agent-cassandra-*" build-hive-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'hive') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.23.x" - name: Test Hive native agent working-directory: agents/drivers/hive-go run: go test ./... - name: Cross-compile Hive native agent shell: bash run: | mkdir -p release-native cd agents/drivers/hive-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-hive-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: hive-native path: "release-native/dbx-agent-hive-*" build-argo-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'argo') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.23.x" - name: Test Argo native agent working-directory: agents/drivers/argo-go run: go test ./... - name: Cross-compile Argo native agent shell: bash run: | mkdir -p release-native cd agents/drivers/argo-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-argo-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: argo-native path: "release-native/dbx-agent-argo-*" build-kingbase-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'kingbase') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22.x" - name: Test Kingbase native agent working-directory: agents/drivers/kingbase-go run: go test ./... - name: Cross-compile Kingbase native agent shell: bash run: | mkdir -p release-native cd agents/drivers/kingbase-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-kingbase-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: kingbase-native path: "release-native/dbx-agent-kingbase-*" build-vastbase-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'vastbase') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.22.x" - name: Test Vastbase native agent working-directory: agents/drivers/vastbase-go run: go test ./... - name: Cross-compile Vastbase native agent shell: bash run: | mkdir -p release-native cd agents/drivers/vastbase-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-vastbase-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: vastbase-native path: "release-native/dbx-agent-vastbase-*" build-neo4j-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'neo4j') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.24.x" - name: Test Neo4j native agent working-directory: agents/drivers/neo4j-go run: go test ./... - name: Cross-compile Neo4j native agent shell: bash run: | mkdir -p release-native cd agents/drivers/neo4j-go declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-neo4j-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: neo4j-native path: "release-native/dbx-agent-neo4j-*" build-iotdb-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'iotdb') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.25.x" - name: Test IoTDB native agent working-directory: agents/drivers/iotdb run: go test ./... - name: Cross-compile IoTDB native agent shell: bash run: | mkdir -p release-native cd agents/drivers/iotdb declare -A TARGETS=( ["macos-aarch64"]="darwin/arm64" ["macos-x64"]="darwin/amd64" ["linux-aarch64"]="linux/arm64" ["linux-x64"]="linux/amd64" ["windows-aarch64"]="windows/arm64" ["windows-x64"]="windows/amd64" ) for platform in "${!TARGETS[@]}"; do IFS=/ read -r goos goarch <<< "${TARGETS[$platform]}" output="../../../release-native/dbx-agent-iotdb-${platform}" if [[ "$goos" == "windows" ]]; then output="${output}.exe" fi echo "Building $platform ($goos/$goarch)" CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -trimpath -ldflags="-s -w" -o "$output" . done ls -lh ../../../release-native - uses: actions/upload-artifact@v4 with: name: iotdb-native path: "release-native/dbx-agent-iotdb-*" build-duckdb-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'duckdb') }} strategy: fail-fast: false matrix: include: - runner: macos-latest target: aarch64-apple-darwin platform: macos-aarch64 extension: "" - runner: macos-15-intel target: x86_64-apple-darwin platform: macos-x64 extension: "" - runner: ubuntu-22.04-arm target: aarch64-unknown-linux-gnu platform: linux-aarch64 extension: "" manylinux_image: quay.io/pypa/manylinux_2_28_aarch64 - runner: ubuntu-22.04 target: x86_64-unknown-linux-gnu platform: linux-x64 extension: "" manylinux_image: quay.io/pypa/manylinux_2_28_x86_64 - runner: windows-2022 target: aarch64-pc-windows-msvc platform: windows-aarch64 extension: .exe - runner: windows-2022 target: x86_64-win7-windows-msvc platform: windows-x64 extension: .exe win7: true runs-on: ${{ matrix.runner }} env: CARGO_INCREMENTAL: "0" CARGO_TARGET_DIR: ${{ github.workspace }}/target/duckdb-driver RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: ${{ secrets.SCCACHE_S3_BUCKET == '' && 'true' || 'false' }} steps: - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@1.97.1 if: runner.os != 'Linux' && matrix.win7 != true with: targets: ${{ matrix.target }} - name: Setup Rust for Windows 7 if: matrix.win7 == true uses: dtolnay/rust-toolchain@nightly with: toolchain: nightly-2026-07-22 components: rust-src - uses: actions/setup-python@v5 if: runner.os == 'Windows' with: python-version: "3.13" - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 with: version: "v0.10.0" - name: Configure S3 sccache if: env.SCCACHE_GHA_ENABLED != 'true' shell: bash env: CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }} CACHE_ENDPOINT: ${{ secrets.SCCACHE_S3_ENDPOINT }} CACHE_REGION: ${{ secrets.SCCACHE_S3_REGION }} CACHE_KEY_PREFIX: ${{ secrets.SCCACHE_S3_KEY_PREFIX }} CACHE_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }} CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }} run: | { echo "SCCACHE_BUCKET=${CACHE_BUCKET}" echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}" echo "SCCACHE_REGION=${CACHE_REGION}" echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}" echo "SCCACHE_S3_USE_SSL=true" echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}" echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}" echo "SCCACHE_IDLE_TIMEOUT=0" # libduckdb C++ compilation dominates this build. The manylinux # legs build inside a container and enable CC/CXX wrapping there; # MSVC stays unwrapped. case "${RUNNER_OS}" in macOS) echo "CC=${SCCACHE_PATH} clang" echo "CXX=${SCCACHE_PATH} clang++" ;; esac } >> "$GITHUB_ENV" - name: Build DuckDB native driver shell: bash run: | if [ "${{ runner.os }}" = "Windows" ]; then export RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-C target-feature=+crt-static" fi if [ -n "${{ matrix.manylinux_image }}" ]; then docker run --rm \ --user "$(id -u):$(id -g)" \ -e HOME=/tmp/dbx-rust-home \ -e CARGO_INCREMENTAL=0 \ -e CARGO_TARGET_DIR=/workspace/target/duckdb-driver \ -e RUSTC_WRAPPER \ -e SCCACHE_BUCKET \ -e SCCACHE_ENDPOINT \ -e SCCACHE_REGION \ -e SCCACHE_S3_KEY_PREFIX \ -e SCCACHE_S3_USE_SSL \ -e AWS_ACCESS_KEY_ID \ -e AWS_SECRET_ACCESS_KEY \ -e SCCACHE_IDLE_TIMEOUT \ -v "${{ github.workspace }}:/workspace" \ -w /workspace/agents/drivers/duckdb \ "${{ matrix.manylinux_image }}" \ bash -lc ' mkdir -p "$HOME" curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1 source "$HOME/.cargo/env" if [ -n "${SCCACHE_BUCKET:-}" ]; then case "$(uname -m)" in x86_64) SCCACHE_ARCH=x86_64-unknown-linux-musl ;; aarch64) SCCACHE_ARCH=aarch64-unknown-linux-musl ;; esac curl -sSfL "https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-${SCCACHE_ARCH}.tar.gz" \ | tar -xz --strip-components=1 -C "$HOME/.cargo/bin" export CC="sccache cc" CXX="sccache c++" sccache --version else unset RUSTC_WRAPPER fi cargo build \ --manifest-path Cargo.toml \ --locked \ --release \ --bin dbx-duckdb-driver \ --target "${{ matrix.target }}" if [ -n "${SCCACHE_BUCKET:-}" ]; then sccache --show-stats || true fi ' else BUILD_STD=() if [ "${{ matrix.win7 }}" = "true" ]; then BUILD_STD=(-Z build-std=std,panic_abort) fi pushd agents/drivers/duckdb cargo build \ --manifest-path Cargo.toml \ --locked \ --release \ --bin dbx-duckdb-driver \ --target "${{ matrix.target }}" \ "${BUILD_STD[@]}" popd fi mkdir -p release-native cp \ "target/duckdb-driver/${{ matrix.target }}/release/dbx-duckdb-driver${{ matrix.extension }}" \ "release-native/dbx-agent-duckdb-${{ matrix.platform }}${{ matrix.extension }}" if [ "${{ runner.os }}" = "Windows" ]; then python agents/scripts/validate_windows_pe_dependencies.py \ "release-native/dbx-agent-duckdb-${{ matrix.platform }}${{ matrix.extension }}" fi if [ -n "${{ matrix.manylinux_image }}" ]; then docker run --rm \ --user "$(id -u):$(id -g)" \ -v "${{ github.workspace }}/release-native:/driver:ro" \ "${{ matrix.manylinux_image }}" \ "/driver/dbx-agent-duckdb-${{ matrix.platform }}" < /dev/null fi - name: Show sccache stats if: always() continue-on-error: true shell: bash run: ${SCCACHE_PATH} --show-stats - uses: actions/upload-artifact@v4 with: name: duckdb-native-${{ matrix.platform }} path: "release-native/dbx-agent-duckdb-*" build-sqlite-worker-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'sqlite-worker') }} strategy: fail-fast: false matrix: include: - runner: ubuntu-22.04 target: x86_64-unknown-linux-musl platform: linux-x64 rustflags: "-C target-feature=+crt-static" - runner: ubuntu-22.04-arm target: aarch64-unknown-linux-musl platform: linux-aarch64 rustflags: "-C target-feature=+crt-static -C link-arg=-z -C link-arg=max-page-size=65536" runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 - name: Setup Rust uses: dtolnay/rust-toolchain@1.97.1 with: targets: ${{ matrix.target }} - name: Install cargo-zigbuild run: pip3 install cargo-zigbuild - name: Rust cache uses: swatinem/rust-cache@v2 with: workspaces: "./ -> target" shared-key: sqlite-worker-${{ matrix.target }} cache-on-failure: true - name: Build musl SQLite SSH worker env: RUSTFLAGS: ${{ matrix.rustflags }} run: cargo zigbuild --release -p dbx-sqlite-worker --target ${{ matrix.target }} - name: Stage SQLite SSH worker run: | mkdir -p release-native cp \ "target/${{ matrix.target }}/release/dbx-sqlite-worker" \ "release-native/dbx-agent-sqlite-worker-${{ matrix.platform }}" - uses: actions/upload-artifact@v4 with: name: sqlite-worker-native-${{ matrix.platform }} path: "release-native/dbx-agent-sqlite-worker-*" build-tdengine-native: needs: [bump-versions] if: ${{ contains(fromJSON(needs.bump-versions.outputs.native_modules), 'tdengine') }} strategy: fail-fast: false matrix: include: - runner: macos-latest target: aarch64-apple-darwin platform: macos-aarch64 extension: "" smoke: true - runner: macos-15-intel target: x86_64-apple-darwin platform: macos-x64 extension: "" smoke: true - runner: ubuntu-22.04-arm target: aarch64-unknown-linux-gnu platform: linux-aarch64 extension: "" manylinux_image: quay.io/pypa/manylinux_2_28_aarch64 - runner: ubuntu-22.04 target: x86_64-unknown-linux-gnu platform: linux-x64 extension: "" manylinux_image: quay.io/pypa/manylinux_2_28_x86_64 - runner: windows-2022 target: aarch64-pc-windows-msvc platform: windows-aarch64 extension: .exe - runner: windows-2022 target: x86_64-win7-windows-msvc platform: windows-x64 extension: .exe smoke: true win7: true runs-on: ${{ matrix.runner }} env: CARGO_INCREMENTAL: "0" CARGO_TARGET_DIR: ${{ github.workspace }}/target/tdengine-driver RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: ${{ secrets.SCCACHE_S3_BUCKET == '' && 'true' || 'false' }} steps: - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@1.97.1 if: runner.os != 'Linux' && matrix.win7 != true with: targets: ${{ matrix.target }} - name: Setup Rust for Windows 7 if: matrix.win7 == true uses: dtolnay/rust-toolchain@nightly with: toolchain: nightly-2026-07-22 components: rust-src - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 with: version: "v0.10.0" - name: Configure S3 sccache if: env.SCCACHE_GHA_ENABLED != 'true' shell: bash env: CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }} CACHE_ENDPOINT: ${{ secrets.SCCACHE_S3_ENDPOINT }} CACHE_REGION: ${{ secrets.SCCACHE_S3_REGION }} CACHE_KEY_PREFIX: ${{ secrets.SCCACHE_S3_KEY_PREFIX }} CACHE_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }} CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }} run: | { echo "SCCACHE_BUCKET=${CACHE_BUCKET}" echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}" echo "SCCACHE_REGION=${CACHE_REGION}" echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}" echo "SCCACHE_S3_USE_SSL=true" echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}" echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}" echo "SCCACHE_IDLE_TIMEOUT=0" # taos client C/C++ compilation dominates this build. The manylinux # legs build inside a container and enable CC/CXX wrapping there; # MSVC stays unwrapped. case "${RUNNER_OS}" in macOS) echo "CC=${SCCACHE_PATH} clang" echo "CXX=${SCCACHE_PATH} clang++" ;; esac } >> "$GITHUB_ENV" - name: Build TDengine native driver shell: bash run: | if [ -n "${{ matrix.manylinux_image }}" ]; then docker run --rm \ --user "$(id -u):$(id -g)" \ -e HOME=/tmp/dbx-rust-home \ -e CARGO_INCREMENTAL=0 \ -e CARGO_TARGET_DIR=/workspace/target/tdengine-driver \ -e RUSTC_WRAPPER \ -e SCCACHE_BUCKET \ -e SCCACHE_ENDPOINT \ -e SCCACHE_REGION \ -e SCCACHE_S3_KEY_PREFIX \ -e SCCACHE_S3_USE_SSL \ -e AWS_ACCESS_KEY_ID \ -e AWS_SECRET_ACCESS_KEY \ -e SCCACHE_IDLE_TIMEOUT \ -v "${{ github.workspace }}:/workspace" \ -w /workspace \ "${{ matrix.manylinux_image }}" \ bash -lc ' mkdir -p "$HOME" curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1 source "$HOME/.cargo/env" if [ -n "${SCCACHE_BUCKET:-}" ]; then case "$(uname -m)" in x86_64) SCCACHE_ARCH=x86_64-unknown-linux-musl ;; aarch64) SCCACHE_ARCH=aarch64-unknown-linux-musl ;; esac curl -sSfL "https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-${SCCACHE_ARCH}.tar.gz" \ | tar -xz --strip-components=1 -C "$HOME/.cargo/bin" export CC="sccache cc" CXX="sccache c++" sccache --version else unset RUSTC_WRAPPER fi cargo build \ --manifest-path agents/drivers/tdengine/Cargo.toml \ --locked \ --release \ --bin dbx-tdengine-driver \ --target "${{ matrix.target }}" if [ -n "${SCCACHE_BUCKET:-}" ]; then sccache --show-stats || true fi ' else BUILD_STD=() if [ "${{ matrix.win7 }}" = "true" ]; then BUILD_STD=(-Z build-std=std,panic_abort) fi cargo build \ --manifest-path agents/drivers/tdengine/Cargo.toml \ --locked \ --release \ --bin dbx-tdengine-driver \ --target "${{ matrix.target }}" \ "${BUILD_STD[@]}" fi mkdir -p release-native cp \ "target/tdengine-driver/${{ matrix.target }}/release/dbx-tdengine-driver${{ matrix.extension }}" \ "release-native/dbx-agent-tdengine-${{ matrix.platform }}${{ matrix.extension }}" if [ -n "${{ matrix.manylinux_image }}" ]; then docker run --rm \ --user "$(id -u):$(id -g)" \ -v "${{ github.workspace }}/release-native:/driver:ro" \ "${{ matrix.manylinux_image }}" \ "/driver/dbx-agent-tdengine-${{ matrix.platform }}" < /dev/null elif [ "${{ matrix.smoke }}" = "true" ]; then "release-native/dbx-agent-tdengine-${{ matrix.platform }}${{ matrix.extension }}" < /dev/null fi - name: Show sccache stats if: always() continue-on-error: true shell: bash run: ${SCCACHE_PATH} --show-stats - uses: actions/upload-artifact@v4 with: name: tdengine-native-${{ matrix.platform }} path: "release-native/dbx-agent-tdengine-*" build-jre: needs: [bump-versions] if: ${{ needs.bump-versions.outputs.build_jre == 'true' }} runs-on: ubuntu-latest strategy: matrix: include: - jre-key: "21" java-version: "21" modules: "java.base,java.sql,java.sql.rowset,java.naming,java.management,java.desktop,java.security.jgss,java.security.sasl,jdk.security.auth,jdk.security.jgss,jdk.charsets,jdk.unsupported,java.scripting,java.compiler,jdk.crypto.ec" steps: - uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{ matrix.java-version }} - name: Build JRE for all platforms shell: bash run: | sudo apt-get update sudo apt-get install -y zstd MODULES="${{ matrix.modules }}" JLINK_OPTS="--strip-debug --no-header-files --no-man-pages --compress=zip-6" JRE_KEY="${{ matrix.jre-key }}" jlink --add-modules $MODULES $JLINK_OPTS --output dbx-jre tar cf - dbx-jre | zstd -q -19 -T0 -o dbx-jre-${JRE_KEY}-linux-x64.tar.zst rm -rf dbx-jre ADOPTIUM="https://api.adoptium.net/v3/binary/latest/${{ matrix.java-version }}/ga" declare -A PLATFORMS=( ["macos-aarch64"]="mac/aarch64" ["macos-x64"]="mac/x64" ["linux-aarch64"]="linux/aarch64" ["windows-aarch64"]="windows/aarch64" ["windows-x64"]="windows/x64" ) for platform in "${!PLATFORMS[@]}"; do os_arch="${PLATFORMS[$platform]}" echo "=== Downloading JDK for $platform ($os_arch) ===" if [[ "$platform" == windows-* ]]; then curl -L -o jdk-$platform.zip "$ADOPTIUM/$os_arch/jdk/hotspot/normal/eclipse?project=jdk" mkdir -p jdk-$platform unzip -q jdk-$platform.zip -d jdk-$platform-tmp mv jdk-$platform-tmp/*/* jdk-$platform/ || mv jdk-$platform-tmp/* jdk-$platform/ rm -rf jdk-$platform-tmp jdk-$platform.zip else curl -L -o jdk-$platform.tar.gz "$ADOPTIUM/$os_arch/jdk/hotspot/normal/eclipse?project=jdk" mkdir -p jdk-$platform tar xzf jdk-$platform.tar.gz -C jdk-$platform --strip-components=1 rm -f jdk-$platform.tar.gz fi JAVA_HOME_CROSS="jdk-$platform" if [ -d "$JAVA_HOME_CROSS/Contents/Home/jmods" ]; then JMODS="$JAVA_HOME_CROSS/Contents/Home/jmods" else JMODS="$JAVA_HOME_CROSS/jmods" fi LLVM_OBJCOPY=$(ls /usr/bin/llvm-objcopy-* 2>/dev/null | sort -V | tail -1) if [ -z "$LLVM_OBJCOPY" ]; then LLVM_OBJCOPY=$(which llvm-objcopy 2>/dev/null || true); fi CROSS_OPTS="" if [ -n "$LLVM_OBJCOPY" ]; then CROSS_OPTS="--strip-native-debug-symbols=objcopy=$LLVM_OBJCOPY" else CROSS_OPTS="--disable-plugin strip-native-debug-symbols" fi jlink --module-path "$JMODS" --add-modules $MODULES $JLINK_OPTS $CROSS_OPTS --output dbx-jre tar cf - dbx-jre | zstd -q -19 -T0 -o dbx-jre-${JRE_KEY}-$platform.tar.zst rm -rf dbx-jre jdk-$platform done ls -lh dbx-jre-*.tar.zst - uses: actions/upload-artifact@v4 with: name: jre-${{ matrix.jre-key }} path: "dbx-jre-*.tar.zst" reuse-previous-assets: name: Reuse unchanged agent artifacts needs: [bump-versions] if: ${{ needs.bump-versions.outputs.reuse_modules != '[]' || needs.bump-versions.outputs.reuse_jre == 'true' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install artifact tools run: | sudo apt-get update sudo apt-get install -y zstd - name: Download and verify previous release artifacts env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PREV_TAG: ${{ needs.bump-versions.outputs.prev_tag }} PREV_VERSIONS: ${{ needs.bump-versions.outputs.prev_versions }} REUSE_MODULES: ${{ needs.bump-versions.outputs.reuse_modules }} REUSE_JRE: ${{ needs.bump-versions.outputs.reuse_jre }} run: | node .github/scripts/reuse-agent-release-assets.mjs \ --repo "$GITHUB_REPOSITORY" \ --tag "$PREV_TAG" \ --versions "$PREV_VERSIONS" \ --modules "$REUSE_MODULES" \ --reuse-jre "$REUSE_JRE" \ --output reused-release - uses: actions/upload-artifact@v4 with: name: reused-agent-artifacts path: reused-release/* retention-days: 1 release: needs: [bump-versions, commit-versions, build-agents, build-oracle-native, build-xugu-native, build-rabbitmq-native, build-rocketmq-native, build-etcd-native, build-etcd2-native, build-zookeeper-native, build-cassandra-native, build-hive-native, build-argo-native, build-kingbase-native, build-vastbase-native, build-neo4j-native, build-iotdb-native, build-duckdb-native, build-sqlite-worker-native, build-tdengine-native, build-jre, reuse-previous-assets] if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} runs-on: ubuntu-latest steps: - name: Create DBX bot release token id: release-token uses: actions/create-github-app-token@v3 with: app-id: ${{ vars.DBX_BOT_APP_ID }} private-key: ${{ secrets.DBX_BOT_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: dbx permission-contents: write # Moving agents-latest across commits that modify workflow files # requires the GitHub App's dedicated Workflows permission. permission-workflows: write - uses: actions/checkout@v4 with: token: ${{ steps.release-token.outputs.token }} fetch-depth: 0 - uses: actions/setup-java@v4 with: distribution: temurin java-version: "21" - uses: gradle/actions/setup-gradle@v4 - uses: actions/download-artifact@v4 with: path: artifacts - name: Install artifact tools run: | sudo apt-get update sudo apt-get install -y zstd - name: Flatten artifacts run: | mkdir -p release find artifacts -type f -name 'dbx-agent-*.jar' -exec cp {} release/ \; find artifacts -type f -name 'dbx-agent-*' ! -name '*.jar' ! -name '*.tar.zst' -exec cp {} release/ \; find artifacts -type f -name 'dbx-agent-*.tar.zst' -exec cp {} release/ \; find artifacts -name 'dbx-jre-*.tar.zst' -exec cp {} release/ \; ls -lh release/ - name: Extract reused raw agent artifacts if: ${{ needs.bump-versions.outputs.reuse_modules != '[]' }} env: PREV_VERSIONS: ${{ needs.bump-versions.outputs.prev_versions }} REUSE_MODULES: ${{ needs.bump-versions.outputs.reuse_modules }} run: | node .github/scripts/reuse-agent-release-assets.mjs \ --extract-packages release \ --versions "$PREV_VERSIONS" \ --modules "$REUSE_MODULES" \ --output release - name: Add versions to agent artifact filenames env: MODULE_VERSIONS: ${{ needs.bump-versions.outputs.versions }} run: python3 agents/scripts/version_agent_artifacts.py release "$MODULE_VERSIONS" - name: Generate agent-registry.json env: MODULE_VERSIONS: ${{ needs.bump-versions.outputs.versions }} run: | TAG="${GITHUB_REF_NAME}" REPO="${GITHUB_REPOSITORY}" RELEASE_VERSION="${TAG#agents-v}" CURRENT_APP_VERSION=$(awk -F'"' '/^version = "/ { print $2; exit }' src-tauri/Cargo.toml) get_module_version() { local name="$1" echo "$MODULE_VERSIONS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('$name','${RELEASE_VERSION}'))" } module_names() { echo "$MODULE_VERSIONS" | python3 -c 'import sys,json; print("\n".join(sorted(json.load(sys.stdin))))' } generate_jar_entry() { local name="$1" label="$2" file="$3" jre_key="$4" version="$5" external_driver="$6" native_json="$7" local sha256=$(sha256sum "$file" | cut -d' ' -f1) local size=$(stat -c%s "$file") local url="https://github.com/${REPO}/releases/download/${TAG}/$(basename $file)" local native_line="" if [ -n "$native_json" ]; then native_line=" \"native\": {${native_json} }," fi cat < release/agent-registry.json < /dev/null echo "=== agent-registry.json ===" cat release/agent-registry.json - name: Build managed JDBC offline payload shell: bash run: | ./plugins/jdbc/package.sh JDBC_VERSION="$(sed -nE "s/^version[[:space:]]*=[[:space:]]*'([^']+)'.*/\1/p" plugins/jdbc/build.gradle | head -n 1)" node agents/scripts/build_offline_jdbc_payload.mjs \ release \ "plugins/jdbc/dist/dbx-jdbc-plugin-${JDBC_VERSION}.zip" \ "plugins/jdbc/dist/dbx-jdbc-plugin-${JDBC_VERSION}/bin/dbx-maven-resolver" - name: Build offline ZIP bundles run: bash agents/scripts/build_offline_zip.sh release - name: Verify managed JDBC assets in all offline ZIPs run: node agents/scripts/verify_offline_jdbc_release.mjs release - name: Build single-driver packages run: | python3 agents/scripts/build_driver_zips.py release --cleanup-sources python3 -m json.tool release/agent-registry.json > /dev/null echo "=== final agent-registry.json ===" cat release/agent-registry.json - name: Generate release notes env: MODULE_VERSIONS: ${{ needs.bump-versions.outputs.versions }} PREV_VERSIONS: ${{ needs.bump-versions.outputs.prev_versions }} PREV_TAG: ${{ needs.bump-versions.outputs.prev_tag }} run: | set -euo pipefail git rev-parse --verify "${PREV_TAG}^{commit}" > /dev/null NOTES="" DRIVER_NAMES=() module_names() { echo "$MODULE_VERSIONS" | python3 -c 'import sys,json; print("\n".join(sorted(json.load(sys.stdin))))' } for name in $(module_names); do version=$(echo "$MODULE_VERSIONS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('$name',''))") compgen -G "release/dbx-agent-${name}-${version}*.tar.zst" > /dev/null && DRIVER_NAMES+=("$name") done native_only_label() { local name="$1" case "$name" in kingbase) echo "金仓KingbaseES" ;; vastbase) echo "Vastbase" ;; duckdb) echo "DuckDB" ;; sqlite-worker) echo "SQLite SSH Worker" ;; oracle) echo "Oracle" ;; xugu) echo "虚谷 XuguDB" ;; rabbitmq) echo "RabbitMQ" ;; rocketmq) echo "Apache RocketMQ" ;; zookeeper) echo "Apache ZooKeeper" ;; cassandra) echo "Apache Cassandra" ;; hive) echo "Apache Hive" ;; argo) echo "星环Argo" ;; neo4j) echo "Neo4j" ;; iotdb) echo "Apache IoTDB" ;; tdengine) echo "TDengine" ;; etcd) echo "etcd" ;; etcd2) echo "etcd 2.x (v2 API)" ;; *) echo "$name" ;; esac } # agents/common rebuilds every packaging driver; report common-only # commits once in a shared section instead of duplicating them under # every driver. Commits that also touch driver code stay attributed # to that driver alone. COMMON_NOTES="" while IFS= read -r line; do sha="${line%% *}" subject="${line#* }" if git diff-tree --no-commit-id --name-only -r "$sha" | grep -qv '^agents/common/'; then continue fi COMMON_NOTES="${COMMON_NOTES}- ${subject}"$'\n' done < <(git log --no-merges --format='%H %s' "$PREV_TAG"..HEAD -- agents/common/build.gradle agents/common/src/main/) if [ -n "$COMMON_NOTES" ]; then NOTES="${NOTES}### 公共组件 (agents/common)"$'\n'"${COMMON_NOTES}"$'\n' fi for name in "${DRIVER_NAMES[@]}"; do old_ver=$(echo "$PREV_VERSIONS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('$name',''))") new_ver=$(echo "$MODULE_VERSIONS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('$name',''))") [ "$old_ver" = "$new_ver" ] && continue jar_file="release/dbx-agent-${name}-${new_ver}.jar" if [ -f "$jar_file" ]; then label=$(unzip -p "$jar_file" META-INF/MANIFEST.MF | awk -F': ' 'BEGIN{IGNORECASE=1} /^Agent-Label:/ {sub(/\r$/, "", $2); print $2; exit}' || echo "$name") [ -z "$label" ] && label="$name" else label=$(native_only_label "$name") fi if [ "$name" = "oracle" ]; then LOG_PATH="agents/drivers/oracle-go/" elif [ "$name" = "kingbase" ]; then LOG_PATH="agents/drivers/kingbase-go/" elif [ "$name" = "vastbase" ]; then LOG_PATH="agents/drivers/vastbase-go/" elif [ "$name" = "cassandra" ]; then LOG_PATH="agents/drivers/cassandra-go/" elif [ "$name" = "hive" ]; then LOG_PATH="agents/drivers/hive-go/" elif [ "$name" = "argo" ]; then LOG_PATH="agents/drivers/argo-go/" elif [ "$name" = "neo4j" ]; then LOG_PATH="agents/drivers/neo4j-go/" elif [ "$name" = "iotdb" ]; then LOG_PATH="agents/drivers/iotdb/" elif [ "$name" = "sqlite-worker" ]; then LOG_PATH="crates/dbx-sqlite-worker/" elif [ -d "agents/drivers/$name" ]; then LOG_PATH="agents/drivers/$name/" else LOG_PATH="agents/$name/" fi LOG_PATHS=("$LOG_PATH") if [ "$name" = "hive" ]; then LOG_PATHS+=( "agents/go-common/go-gssapi/" "agents/go-common/gohive/" "agents/go-common/gosasl/" ) elif [ "$name" = "argo" ]; then LOG_PATHS+=( "agents/go-common/go-gssapi/" "agents/go-common/gohive/" "agents/go-common/gosasl/" ) elif [ "$name" = "zookeeper" ]; then LOG_PATHS+=( "agents/go-common/go-gssapi/" "agents/go-common/gosasl/" ) fi DRIVER_NOTES="" while IFS= read -r line; do [ -n "$line" ] && DRIVER_NOTES="${DRIVER_NOTES}- ${line}"$'\n' done < <(git log --oneline "$PREV_TAG"..HEAD -- "${LOG_PATHS[@]}" | sed 's/^[0-9a-f]* //') if [ -z "$DRIVER_NOTES" ]; then DRIVER_NOTES="- 无驱动专属变更"$'\n' fi NOTES="${NOTES}### ${label} (${old_ver} → ${new_ver})"$'\n'"${DRIVER_NOTES}"$'\n' done if [ -z "$NOTES" ]; then NOTES="Routine rebuild, no agent-specific changes."$'\n' fi printf "## 更新内容\n\n%s" "$NOTES" > RELEASE_NOTES.md echo "=== Release Notes ===" cat RELEASE_NOTES.md - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: token: ${{ steps.release-token.outputs.token }} files: release/* body_path: RELEASE_NOTES.md make_latest: false - name: Update agents-latest GitHub release env: GH_TOKEN: ${{ steps.release-token.outputs.token }} run: | git tag -f agents-latest "$GITHUB_SHA" git push origin refs/tags/agents-latest --force if gh release view agents-latest --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then # agents-latest is only the stable registry entry point. Actual artifacts # stay on the immutable agents-v* release referenced by the registry. gh release view agents-latest --repo "$GITHUB_REPOSITORY" --json assets --jq '.assets[].name' | while IFS= read -r asset; do [ "$asset" = "agent-registry.json" ] && continue gh release delete-asset agents-latest "$asset" --repo "$GITHUB_REPOSITORY" --yes done gh release upload agents-latest release/agent-registry.json --repo "$GITHUB_REPOSITORY" --clobber gh release edit agents-latest \ --repo "$GITHUB_REPOSITORY" \ --title "Agents latest" \ --notes "Moving entry point for the latest DBX agent registry. Artifacts are stored on the referenced versioned agents release." \ --latest=false else gh release create agents-latest release/agent-registry.json \ --repo "$GITHUB_REPOSITORY" \ --title "Agents latest" \ --notes "Moving entry point for the latest DBX agent registry. Artifacts are stored on the referenced versioned agents release." \ --latest=false fi - name: Upload to R2 env: AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} R2_ENDPOINT: "https://${{ secrets.R2_ACCOUNT_ID }}.r2.cloudflarestorage.com" R2_BUCKET: "s3://${{ secrets.R2_BUCKET_NAME }}" run: | # Always upload the current registry. aws s3 cp release/agent-registry.json \ "$R2_BUCKET/agents/agent-registry.json" \ --endpoint-url "$R2_ENDPOINT" echo "Uploaded agent-registry.json" # Upload all single-driver packages concurrently. aws s3 cp release/ "$R2_BUCKET/agents/drivers/" \ --recursive \ --exclude "*" \ --include "dbx-agent-*.tar.zst" \ --endpoint-url "$R2_ENDPOINT" echo "Uploaded single-driver packages" # Upload JRE packages concurrently, always overwriting the stable names. aws s3 cp release/ "$R2_BUCKET/agents/jre/" \ --recursive \ --exclude "*" \ --include "dbx-jre-*.tar.zst" \ --endpoint-url "$R2_ENDPOINT" echo "Uploaded JRE packages" sync-release-to-cnb: name: Sync agents releases to CNB needs: release if: ${{ always() && needs.release.result == 'success' }} runs-on: ubuntu-latest continue-on-error: true strategy: fail-fast: false matrix: tag: ["${{ github.ref_name }}", "agents-latest"] steps: - name: Checkout repository uses: actions/checkout@v5 - name: Download GitHub release assets env: TAG_NAME: ${{ matrix.tag }} GITHUB_REPOSITORY: ${{ github.repository }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail mkdir -p "$RUNNER_TEMP/github-release" "$RUNNER_TEMP/release-assets" gh release view "$TAG_NAME" \ --repo "$GITHUB_REPOSITORY" \ --json tagName,name,body,targetCommitish,isPrerelease,isDraft,assets \ > "$RUNNER_TEMP/github-release/release.json" gh release download "$TAG_NAME" \ --repo "$GITHUB_REPOSITORY" \ --dir "$RUNNER_TEMP/release-assets" \ --clobber - name: Sync release assets to CNB env: CNB_TOKEN: ${{ secrets.CNB_TOKEN }} CNB_UPLOAD_CONCURRENCY: "3" OVERWRITE_EXISTING: ${{ matrix.tag == 'agents-latest' }} run: | set -euo pipefail args=( --github-release "$RUNNER_TEMP/github-release/release.json" --assets-dir "$RUNNER_TEMP/release-assets" ) # agents-latest is mutable, so its stable asset names must replace the previous release contents. if [[ "$OVERWRITE_EXISTING" == "true" ]]; then args+=(--overwrite-existing --prune-assets) fi node .github/scripts/sync-cnb-release.mjs "${args[@]}" - name: Keep latest five versioned agent releases in CNB if: ${{ matrix.tag != 'agents-latest' }} continue-on-error: true env: CNB_TOKEN: ${{ secrets.CNB_TOKEN }} CURRENT_TAG: ${{ matrix.tag }} run: | node .github/scripts/cleanup-cnb-releases.mjs \ --current-tag "$CURRENT_TAG" \ --tag-pattern '^agents-v[0-9]+[.][0-9]+[.][0-9]+$' \ --retain 5 \ --apply