Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/build-broker-binary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,28 @@ jobs:
# crates/broker/src/telemetry.rs reads and bakes into the binary. Unset
# variable → telemetry ships disabled (acceptable for forks and
# pre-release pipelines).
#
# `AGENT_RELAY_VERSION` is consumed by `option_env!` in
# crates/broker/src/util/version.rs. The standalone build is fed
# from the dispatch tag input (or the repo's package.json version
# for branch pushes) so the broker reports a release-line version
# rather than the Cargo crate version.
env:
AGENT_RELAY_POSTHOG_KEY: ${{ vars.POSTHOG_PROJECT_KEY }}
run: |
# Resolve a release-line version for AGENT_RELAY_VERSION. Prefer the
# workflow_dispatch tag (e.g. "v6.2.2" → "6.2.2"); fall back to
# package.json on branch pushes.
TAG_INPUT="${{ inputs.tag }}"
if [[ -n "$TAG_INPUT" && "$TAG_INPUT" != "latest" ]]; then
VERSION="${TAG_INPUT#v}"
else
# `npm pkg get` is available on the default GitHub runner image;
# the value is quoted JSON, so strip the quotes.
VERSION="$(npm pkg get version | tr -d '"')"
fi
export AGENT_RELAY_VERSION="$VERSION"
echo "AGENT_RELAY_VERSION=$VERSION"
if [[ "${{ matrix.target }}" == "aarch64-unknown-linux-musl" ]]; then
RUSTFLAGS="-C target-feature=+crt-static" cross build --release --target ${{ matrix.target }} --bin agent-relay-broker
aarch64-linux-gnu-strip target/${{ matrix.target }}/release/agent-relay-broker 2>/dev/null || true
Expand Down
25 changes: 24 additions & 1 deletion .github/workflows/package-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,15 @@ jobs:
run: npm run build

- name: Build broker binary
run: cargo build --release --bin agent-relay-broker
# Pin the broker's reported version to the same release line as
# `agent-relay` / `@agent-relay/sdk`. `option_env!` in
# crates/broker/src/util/version.rs consumes this at compile time
# and falls back to `CARGO_PKG_VERSION` when unset.
run: |
AGENT_RELAY_VERSION="$(node -p "require('./package.json').version")"
export AGENT_RELAY_VERSION
echo "Building broker with AGENT_RELAY_VERSION=$AGENT_RELAY_VERSION"
cargo build --release --bin agent-relay-broker

- name: Verify broker binary
run: |
Expand All @@ -285,6 +293,21 @@ jobs:
echo "STANDALONE_BROKER=$STANDALONE_BROKER" >> "$GITHUB_ENV"
echo "Verified broker binary: $STANDALONE_BROKER"

- name: Verify broker version matches release version
# Acceptance criteria from #904: released broker binaries must
# report the same version as the `agent-relay` / `@agent-relay/sdk`
# release that shipped them.
run: |
EXPECTED_VERSION="$(node -p "require('./package.json').version")"
REPORTED="$(./target/release/agent-relay-broker --version | awk '{print $NF}')"
echo "expected: $EXPECTED_VERSION"
echo "reported: $REPORTED"
if [ "$EXPECTED_VERSION" != "$REPORTED" ]; then
echo "ERROR: broker --version reported '$REPORTED' but package.json is '$EXPECTED_VERSION'." >&2
echo "AGENT_RELAY_VERSION did not propagate at compile time. See crates/broker/src/util/version.rs." >&2
exit 1
fi

- name: Build standalone binary
run: |
mkdir -p release-binaries
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ jobs:
# Build Rust broker binary for all platforms (needed by SDK's AgentRelayClient)
build-broker:
name: Build broker (${{ matrix.target }})
# Depends on `build` so we can pass the shipped product version into the
# broker at compile time via `AGENT_RELAY_VERSION`. See
# crates/broker/src/util/version.rs — released binaries report this
# version through health/session/telemetry payloads.
needs: build
runs-on: ${{ matrix.os }}
if: github.event.inputs.package == 'all' || github.event.inputs.package == 'main' || github.event.inputs.package == 'cli-prerelease' || github.event.inputs.package == 'sdk' || github.event.inputs.package == 'sdk-py'
strategy:
Expand Down Expand Up @@ -141,8 +146,15 @@ jobs:
# `option_env!` in crates/broker/src/telemetry.rs consumes at compile time.
# Unset variable → telemetry ships disabled (acceptable for
# forks / pre-release pipelines).
#
# `AGENT_RELAY_VERSION` is consumed by `option_env!` in
# crates/broker/src/util/version.rs and becomes the broker version
# reported through health/session/telemetry payloads. We pin it to
# the release-line version so a `6.2.x` artifact does not report
# the Cargo crate version (`3.0.0`).
env:
AGENT_RELAY_POSTHOG_KEY: ${{ vars.POSTHOG_PROJECT_KEY }}
AGENT_RELAY_VERSION: ${{ needs.build.outputs.new_version }}
run: |
if [[ "${{ matrix.target }}" == "aarch64-unknown-linux-musl" ]]; then
RUSTFLAGS="-C target-feature=+crt-static" cross build --release --bin agent-relay-broker --target ${{ matrix.target }}
Expand All @@ -156,6 +168,7 @@ jobs:
shell: pwsh
env:
AGENT_RELAY_POSTHOG_KEY: ${{ vars.POSTHOG_PROJECT_KEY }}
AGENT_RELAY_VERSION: ${{ needs.build.outputs.new_version }}
run: |
$env:RUSTFLAGS = "-C target-feature=+crt-static"
cargo build --release --bin agent-relay-broker --target ${{ matrix.target }}
Expand Down
11 changes: 6 additions & 5 deletions Cross.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
[build.env]
# Forward the PostHog write key from the host into the cross-compile
# container so `option_env!("AGENT_RELAY_POSTHOG_KEY")` in src/telemetry.rs
# resolves the same way it does for native cargo builds. Unset on forks /
# CI, set via secret on release pipelines.
passthrough = ["AGENT_RELAY_POSTHOG_KEY"]
# Forward the PostHog write key and product-release version from the host
# into the cross-compile container so `option_env!` in
# src/telemetry.rs and src/util/version.rs resolves the same way it does
# for native cargo builds. Unset on forks / CI, set via secret /
# release pipelines.
passthrough = ["AGENT_RELAY_POSTHOG_KEY", "AGENT_RELAY_VERSION"]

[target.aarch64-unknown-linux-musl]
image = "ghcr.io/cross-rs/aarch64-unknown-linux-musl:main"
1 change: 1 addition & 0 deletions crates/broker/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub(crate) mod command_parse;
#[derive(Debug, Parser)]
#[command(name = "agent-relay-broker")]
#[command(about = "Agent relay broker and worker runtime")]
#[command(version = crate::util::version::BROKER_VERSION)]
struct Cli {
#[command(subcommand)]
command: Commands,
Expand Down
4 changes: 2 additions & 2 deletions crates/broker/src/listen_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ fn listen_api_router_with_auth(
.filter(|value| !value.is_empty()),
memberships: config.memberships,
default_workspace_id: config.default_workspace_id,
broker_version: env!("CARGO_PKG_VERSION").to_string(),
broker_version: crate::util::version::broker_version().to_string(),
persist: config.persist,
started_at: std::time::Instant::now(),
};
Expand Down Expand Up @@ -403,7 +403,7 @@ pub(crate) fn listen_api_health_payload(
json!({
"status": status,
"service": "agent-relay-listen",
"version": env!("CARGO_PKG_VERSION"),
"version": crate::util::version::broker_version(),
"uptimeMs": 0,
"workspaceId": workspace_id,
"defaultWorkspaceId": default_workspace_id,
Expand Down
2 changes: 1 addition & 1 deletion crates/broker/src/swarm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ impl BrokerClient {
"hello",
json!({
"client_name": "broker-swarm",
"client_version": env!("CARGO_PKG_VERSION"),
"client_version": crate::util::version::broker_version(),
}),
)
.await?;
Expand Down
2 changes: 1 addition & 1 deletion crates/broker/src/telemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ impl TelemetryClient {
// which component emitted the event. `agent_relay_version` is kept
// as a back-compat alias that mirrors `broker_version` here.
if let Some(obj) = props.as_object_mut() {
let broker_version = env!("CARGO_PKG_VERSION");
let broker_version = crate::util::version::broker_version();
obj.insert("agent_relay_version".to_string(), json!(broker_version));
obj.insert("broker_version".to_string(), json!(broker_version));
if let Some(ref v) = self.cli_version {
Expand Down
1 change: 1 addition & 0 deletions crates/broker/src/util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub(crate) mod ansi;
pub(crate) mod terminal;
pub(crate) mod version;
48 changes: 48 additions & 0 deletions crates/broker/src/util/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// The broker version reported in health/session/telemetry payloads and
/// by `agent-relay-broker --version`.
///
/// Released binaries are compiled with `AGENT_RELAY_VERSION` set to the
/// shipped `agent-relay` / `@agent-relay/sdk` product version so that
/// `broker_version` in telemetry, `/api/config`, and the health/session
/// responses matches the artifact users installed. Local `cargo build`
/// invocations have no such env var; in that case we fall back to the
/// Rust crate's `CARGO_PKG_VERSION`, which is a reasonable developer-build
/// label rather than a release-line identifier.
pub const BROKER_VERSION: &str = match option_env!("AGENT_RELAY_VERSION") {
// Treat an empty `AGENT_RELAY_VERSION` as unset — CI workflows that
// forward an unresolved expression (e.g. `${{ needs.build.outputs.new_version }}`
// before the upstream job ran) can leave the var defined but blank,
// which would otherwise surface as an empty broker version string.
Some(v) if !v.is_empty() => v,
_ => env!("CARGO_PKG_VERSION"),
};

/// Returns the broker version. Prefer this helper over `env!("CARGO_PKG_VERSION")`
/// so all components report the same release-line version.
pub fn broker_version() -> &'static str {
BROKER_VERSION
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn broker_version_is_non_empty() {
// Either AGENT_RELAY_VERSION (release builds) or CARGO_PKG_VERSION
// (developer builds) must produce a non-empty string.
assert!(!broker_version().is_empty());
assert_eq!(broker_version(), BROKER_VERSION);
}

#[test]
fn broker_version_matches_compile_time_env() {
// When AGENT_RELAY_VERSION is set to a non-empty string at build
// time, the helper surfaces that exact value; empty or unset
// falls back to the Cargo crate version.
match option_env!("AGENT_RELAY_VERSION") {
Some(v) if !v.is_empty() => assert_eq!(broker_version(), v),
_ => assert_eq!(broker_version(), env!("CARGO_PKG_VERSION")),
}
}
}
Loading