Skip to content

Commit 2a589fe

Browse files
authored
add dabgent_mcp binary build job to CI (#512)
1 parent 6ca4d95 commit 2a589fe

File tree

12 files changed

+317
-81
lines changed

12 files changed

+317
-81
lines changed

.github/workflows/release.yml

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version tag (e.g., v0.0.1)'
8+
required: true
9+
type: string
10+
commit_sha:
11+
description: 'Commit SHA to release'
12+
required: true
13+
type: string
14+
release_notes:
15+
description: 'Release notes'
16+
required: false
17+
type: string
18+
default: ''
19+
20+
jobs:
21+
validate-and-tag:
22+
name: Validate and Create Tag
23+
runs-on: ubuntu-latest
24+
outputs:
25+
run_id: ${{ steps.find_run.outputs.run_id }}
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v3
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Validate version format
33+
run: |
34+
if [[ ! "${{ inputs.version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
35+
echo "Error: Version must follow format v0.0.0"
36+
exit 1
37+
fi
38+
39+
- name: Validate commit exists
40+
run: |
41+
if ! git rev-parse "${{ inputs.commit_sha }}" >/dev/null 2>&1; then
42+
echo "Error: Commit ${{ inputs.commit_sha }} not found"
43+
exit 1
44+
fi
45+
46+
- name: Check if tag already exists
47+
run: |
48+
if git rev-parse "${{ inputs.version }}" >/dev/null 2>&1; then
49+
echo "Error: Tag ${{ inputs.version }} already exists"
50+
exit 1
51+
fi
52+
53+
- name: Find successful CI run for commit
54+
id: find_run
55+
env:
56+
GH_TOKEN: ${{ github.token }}
57+
run: |
58+
echo "Finding CI run for commit ${{ inputs.commit_sha }}..."
59+
RUN_ID=$(gh run list --commit "${{ inputs.commit_sha }}" \
60+
--workflow="Rust" \
61+
--status=success \
62+
--json databaseId \
63+
--jq '.[0].databaseId')
64+
65+
if [ -z "$RUN_ID" ]; then
66+
echo "Error: No successful CI run found for commit ${{ inputs.commit_sha }}"
67+
echo "Make sure the commit has been pushed and CI completed successfully"
68+
exit 1
69+
fi
70+
71+
echo "Found CI run: $RUN_ID"
72+
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
73+
74+
- name: Create and push tag
75+
run: |
76+
git config user.name "github-actions[bot]"
77+
git config user.email "github-actions[bot]@users.noreply.github.com"
78+
79+
NOTES="${{ inputs.release_notes }}"
80+
if [ -z "$NOTES" ]; then
81+
NOTES="Release ${{ inputs.version }}"
82+
fi
83+
84+
git tag -a "${{ inputs.version }}" "${{ inputs.commit_sha }}" -m "$NOTES"
85+
git push origin "${{ inputs.version }}"
86+
87+
create-release:
88+
name: Create GitHub Release
89+
runs-on: ubuntu-latest
90+
needs: validate-and-tag
91+
steps:
92+
- name: Download Linux artifact
93+
uses: actions/download-artifact@v4
94+
with:
95+
name: dabgent-mcp-linux-x86_64
96+
path: artifacts/linux
97+
run-id: ${{ needs.validate-and-tag.outputs.run_id }}
98+
github-token: ${{ github.token }}
99+
100+
- name: Download macOS artifact
101+
uses: actions/download-artifact@v4
102+
with:
103+
name: dabgent-mcp-macos-arm64
104+
path: artifacts/macos
105+
run-id: ${{ needs.validate-and-tag.outputs.run_id }}
106+
github-token: ${{ github.token }}
107+
108+
- name: Prepare artifacts for release
109+
run: |
110+
mkdir -p release
111+
mv artifacts/linux/dabgent_mcp release/dabgent_mcp-linux-x86_64
112+
mv artifacts/macos/dabgent_mcp release/dabgent_mcp-macos-arm64
113+
chmod +x release/*
114+
ls -lh release/
115+
116+
- name: Create GitHub release
117+
env:
118+
GH_TOKEN: ${{ github.token }}
119+
run: |
120+
NOTES="${{ inputs.release_notes }}"
121+
if [ -z "$NOTES" ]; then
122+
NOTES="Release ${{ inputs.version }}"
123+
fi
124+
125+
CI_URL="https://github.com/${{ github.repository }}/actions/runs/${{ needs.validate-and-tag.outputs.run_id }}"
126+
127+
cat > release_notes.md <<EOF
128+
$NOTES
129+
130+
---
131+
**Build Verification:**
132+
- Built from commit: \`${{ inputs.commit_sha }}\`
133+
- CI Run: $CI_URL
134+
- Artifacts can be verified against the CI build
135+
EOF
136+
137+
gh release create "${{ inputs.version }}" \
138+
--repo "${{ github.repository }}" \
139+
--title "${{ inputs.version }}" \
140+
--notes-file release_notes.md \
141+
release/*
142+
143+
- name: Output release URL
144+
run: |
145+
echo "Release created successfully!"
146+
echo "View at: https://github.com/${{ github.repository }}/releases/tag/${{ inputs.version }}"

.github/workflows/rust.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,71 @@ jobs:
6666
working-directory: ./dabgent
6767
# Run with single thread due to Dagger connection race conditions
6868
run: cargo nextest run --tests --workspace --test-threads=1
69+
70+
check-release-condition:
71+
name: Check Release Condition
72+
runs-on: ubuntu-latest
73+
timeout-minutes: 5
74+
outputs:
75+
should_build: ${{ steps.check.outputs.should_build }}
76+
steps:
77+
- name: Checkout repository
78+
uses: actions/checkout@v3
79+
with:
80+
fetch-depth: 2
81+
82+
- name: Check if release build needed
83+
id: check
84+
run: |
85+
should_build="false"
86+
# we check two commits because the first commit is the merge commit
87+
if git log -2 --pretty=%s | tail -n 1 | grep -q "build-rust"; then
88+
should_build="true"
89+
echo "Rust build detected based on commit message."
90+
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]]; then
91+
should_build="true"
92+
echo "Rust build detected based on push to main branch."
93+
fi
94+
95+
echo "should_build=${should_build}" >> $GITHUB_OUTPUT
96+
97+
build-dabgent-mcp:
98+
name: Build dabgent_mcp (${{ matrix.platform }})
99+
runs-on: ${{ matrix.runner }}
100+
timeout-minutes: 15
101+
needs: [rust-checks, rust-tests, check-release-condition]
102+
if: needs.check-release-condition.outputs.should_build == 'true'
103+
strategy:
104+
matrix:
105+
include:
106+
- platform: linux-x86_64
107+
runner: ubuntu-latest
108+
- platform: macos-arm64
109+
runner: macos-15-xlarge
110+
steps:
111+
- name: Checkout repository
112+
uses: actions/checkout@v3
113+
114+
- name: Setup Rust
115+
uses: dtolnay/rust-toolchain@stable
116+
117+
- name: Cache cargo dependencies
118+
uses: Swatinem/rust-cache@v2
119+
with:
120+
workspaces: dabgent
121+
122+
- name: Build release binary
123+
run: |
124+
cd dabgent
125+
cargo build --release -p dabgent_mcp
126+
ls -la target/release/
127+
env:
128+
# Disable LTO on macOS for faster builds
129+
CARGO_PROFILE_RELEASE_LTO: ${{ matrix.platform == 'macos-arm64' && 'off' || 'thin' }}
130+
131+
- name: Upload binary artifact
132+
uses: actions/upload-artifact@v4
133+
with:
134+
name: dabgent-mcp-${{ matrix.platform }}
135+
path: dabgent/target/release/dabgent_mcp
136+
retention-days: 30

dabgent/Cargo.lock

Lines changed: 6 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dabgent/dabgent_agent/src/processor/databricks.rs

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,19 @@
11
use super::agent::{Agent, AgentState, Command, Event};
22
use crate::toolbox::ToolCallExt;
33
use dabgent_integrations::{
4-
DatabricksRestClient, DescribeTableRequest, ExecuteSqlRequest, ListSchemasRequest,
5-
ListTablesRequest, ToolResultDisplay,
4+
DatabricksDescribeTableArgs, DatabricksExecuteQueryArgs, DatabricksListCatalogsArgs,
5+
DatabricksListSchemasArgs, DatabricksListTablesArgs, DatabricksRestClient,
6+
DescribeTableRequest, ExecuteSqlRequest, ListSchemasRequest, ListTablesRequest,
7+
ToolResultDisplay,
68
};
79
use dabgent_mq::{Envelope, EventHandler, EventStore, Handler};
810
use dabgent_sandbox::FutureBoxed;
911
use eyre::Result;
1012
use rig::message::{ToolCall, ToolResult};
11-
use schemars::JsonSchema;
1213
use serde::{Deserialize, Serialize};
1314
use std::future::Future;
1415
use std::sync::Arc;
1516

16-
// ============================================================================
17-
// Argument Structs
18-
// ============================================================================
19-
20-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
21-
#[serde(default)]
22-
pub struct DatabricksListCatalogsArgs {
23-
// No parameters needed - lists all available catalogs
24-
}
25-
26-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
27-
pub struct DatabricksListSchemasArgs {
28-
pub catalog_name: String,
29-
#[serde(skip_serializing_if = "Option::is_none")]
30-
pub filter: Option<String>,
31-
#[serde(default = "default_limit")]
32-
pub limit: usize,
33-
#[serde(default)]
34-
pub offset: usize,
35-
}
36-
37-
fn default_limit() -> usize {
38-
1000
39-
}
40-
41-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
42-
pub struct DatabricksListTablesArgs {
43-
pub catalog_name: String,
44-
pub schema_name: String,
45-
#[serde(default = "default_exclude_inaccessible")]
46-
pub exclude_inaccessible: bool,
47-
}
48-
49-
fn default_exclude_inaccessible() -> bool {
50-
true
51-
}
52-
53-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
54-
pub struct DatabricksDescribeTableArgs {
55-
pub table_full_name: String,
56-
#[serde(default = "default_sample_size")]
57-
pub sample_size: usize,
58-
}
59-
60-
fn default_sample_size() -> usize {
61-
10
62-
}
63-
64-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
65-
pub struct DatabricksExecuteQueryArgs {
66-
pub query: String,
67-
}
68-
6917
#[derive(Debug, Clone, Serialize, Deserialize)]
7018
pub struct FinishDelegationArgs {
7119
pub summary: String,

dabgent/dabgent_integrations/src/databricks.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::{Result, anyhow};
22
use log::{debug, info};
33
use reqwest;
4+
use schemars::JsonSchema;
45
use serde::{Deserialize, Serialize};
56
use serde_json::Value;
67
use std::collections::HashMap;
@@ -82,7 +83,48 @@ fn apply_pagination<T>(items: Vec<T>, limit: usize, offset: usize) -> (Vec<T>, u
8283
}
8384

8485
// ============================================================================
85-
// Request Types
86+
// Argument Types (shared between agent and MCP)
87+
// ============================================================================
88+
89+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
90+
#[serde(default)]
91+
pub struct DatabricksListCatalogsArgs {
92+
// no parameters needed - lists all available catalogs
93+
}
94+
95+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
96+
pub struct DatabricksListSchemasArgs {
97+
pub catalog_name: String,
98+
#[serde(skip_serializing_if = "Option::is_none")]
99+
pub filter: Option<String>,
100+
#[serde(default = "default_limit")]
101+
pub limit: usize,
102+
#[serde(default)]
103+
pub offset: usize,
104+
}
105+
106+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
107+
pub struct DatabricksListTablesArgs {
108+
pub catalog_name: String,
109+
pub schema_name: String,
110+
#[serde(default = "default_exclude_inaccessible")]
111+
pub exclude_inaccessible: bool,
112+
}
113+
114+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115+
pub struct DatabricksDescribeTableArgs {
116+
pub table_full_name: String,
117+
#[serde(default = "default_sample_size")]
118+
pub sample_size: usize,
119+
}
120+
121+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
122+
pub struct DatabricksExecuteQueryArgs {
123+
pub query: String,
124+
}
125+
126+
// ============================================================================
127+
// Request Types (internal to client)
86128
// ============================================================================
87129

88130
#[derive(Debug, Clone, Serialize, Deserialize)]

0 commit comments

Comments
 (0)