Skip to content

Commit 7a432f1

Browse files
feat: add info request for PET metadata including version and build ID (#470)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 89b2f53 commit 7a432f1

5 files changed

Lines changed: 99 additions & 0 deletions

File tree

crates/pet/build.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
// Licensed under the MIT License.
33

44
fn main() {
5+
println!("cargo:rerun-if-env-changed=PET_BUILD_ID");
6+
println!("cargo:rerun-if-env-changed=BUILD_BUILDID");
7+
8+
if let Some(build_id) = std::env::var("PET_BUILD_ID")
9+
.ok()
10+
.or_else(|| std::env::var("BUILD_BUILDID").ok())
11+
.filter(|value| !value.is_empty())
12+
{
13+
println!("cargo:rustc-env=PET_BUILD_ID={build_id}");
14+
}
15+
516
#[cfg(target_os = "windows")]
617
{
718
if std::env::var("CARGO_BIN_NAME").is_err() {

crates/pet/src/jsonrpc.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ pub fn start_jsonrpc_server() {
507507
};
508508

509509
let mut handlers = HandlersKeyedByMethodName::new(Arc::new(context));
510+
handlers.add_request_handler("info", handle_info);
510511
handlers.add_request_handler("configure", handle_configure);
511512
handlers.add_request_handler("refresh", handle_refresh);
512513
handlers.add_request_handler("resolve", handle_resolve);
@@ -516,6 +517,29 @@ pub fn start_jsonrpc_server() {
516517
start_server(&handlers)
517518
}
518519

520+
#[derive(Debug, Clone, Deserialize, Serialize)]
521+
#[serde(rename_all = "camelCase")]
522+
pub struct InfoResponse {
523+
pub pet_version: String,
524+
#[serde(skip_serializing_if = "Option::is_none")]
525+
pub build_id: Option<String>,
526+
}
527+
528+
impl InfoResponse {
529+
fn current() -> Self {
530+
Self {
531+
pet_version: env!("CARGO_PKG_VERSION").to_string(),
532+
build_id: option_env!("PET_BUILD_ID")
533+
.filter(|value| !value.is_empty())
534+
.map(ToString::to_string),
535+
}
536+
}
537+
}
538+
539+
pub fn handle_info(_context: Arc<Context>, id: u32, _params: Value) {
540+
send_reply(id, Some(InfoResponse::current()));
541+
}
542+
519543
#[derive(Debug, Clone, Deserialize, Serialize)]
520544
#[serde(rename_all = "camelCase")]
521545
pub struct ConfigureOptions {
@@ -1512,6 +1536,17 @@ mod tests {
15121536
);
15131537
}
15141538

1539+
#[test]
1540+
fn test_info_response_uses_package_version_and_optional_build_id() {
1541+
let info = InfoResponse::current();
1542+
1543+
assert_eq!(info.pet_version, env!("CARGO_PKG_VERSION"));
1544+
assert!(info
1545+
.build_id
1546+
.as_deref()
1547+
.is_none_or(|build_id| !build_id.is_empty()));
1548+
}
1549+
15151550
#[test]
15161551
fn test_parse_refresh_options_rejects_non_empty_array() {
15171552
assert!(parse_refresh_options(json!([{"searchKind": "Conda"}])).is_err());

crates/pet/tests/jsonrpc_client.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ pub struct RefreshResult {
2121
pub duration: u128,
2222
}
2323

24+
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
25+
#[serde(rename_all = "camelCase")]
26+
pub struct PetInfoResponse {
27+
pub pet_version: String,
28+
pub build_id: Option<String>,
29+
}
30+
2431
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
2532
#[serde(rename_all = "camelCase")]
2633
pub struct EnvironmentNotification {
@@ -156,6 +163,10 @@ impl PetJsonRpcClient {
156163
)
157164
}
158165

166+
pub fn info(&self) -> Result<PetInfoResponse, String> {
167+
self.send_request("info", json!({}), DEFAULT_REQUEST_TIMEOUT)
168+
}
169+
159170
#[allow(dead_code)]
160171
pub fn resolve(&self, executable: &str) -> Result<Value, String> {
161172
self.send_request_value(

crates/pet/tests/jsonrpc_server_test.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ fn assert_single_environment(
110110
assert_eq!(environment.error, None);
111111
}
112112

113+
#[test]
114+
fn info_reports_pet_version_and_optional_build_id() {
115+
let client = PetJsonRpcClient::spawn().expect("failed to spawn PET server");
116+
117+
let info = client.info().expect("info request failed");
118+
119+
assert_eq!(info.pet_version, env!("CARGO_PKG_VERSION"));
120+
assert!(info
121+
.build_id
122+
.as_deref()
123+
.is_none_or(|build_id| !build_id.is_empty()));
124+
}
125+
113126
#[test]
114127
fn configure_and_workspace_refresh_report_fake_venv() {
115128
let client = PetJsonRpcClient::spawn().expect("failed to spawn PET server");

docs/JSONRPC.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,35 @@ For samples using JSONRPC, please have a look at the [sample.js](./sample.js) fi
1111

1212
Any requests/notifications not documented here are not supported.
1313

14+
# Info Request
15+
16+
Returns metadata about the running PET binary. This request does not require a prior
17+
`configure` request. Clients can cache this response and attach it to PET-related
18+
telemetry such as `refresh` and `resolve` timings.
19+
20+
_Request_:
21+
22+
- method: `info`
23+
- params: `{}`
24+
25+
_Response_:
26+
27+
- result: `InfoResponse` defined as below.
28+
29+
```typescript
30+
interface InfoResponse {
31+
/**
32+
* PET package version baked into the binary at build time.
33+
* Pre-release builds may include a suffix such as `0.1.0-dev.12345`.
34+
*/
35+
petVersion: string;
36+
/**
37+
* Build identifier baked into the binary when built by CI.
38+
*/
39+
buildId?: string;
40+
}
41+
```
42+
1443
# Configuration Request
1544

1645
This should always be the first request sent to the tool.

0 commit comments

Comments
 (0)