Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
http: Change `/api/v1/node` version to node user agent
Open did:key:z6MkkfM3...sVz5 opened 1 year ago

We used the RADICLE_VERSION env variable to display the node version, which as of recently matched always the radicle-httpd version. Since the separation this isn’t the case anymore, and the user agent seems a more reliable metric.

check check-visual check-unit-test check-http-client-unit-test check-radicle-httpd check-e2e check-build check-http

πŸ‘‰ Preview πŸ‘‰ Workflow runs πŸ‘‰ Branch on GitHub

9 files changed +29 -14 b0f3c631 β†’ f21a8016
modified config/default.json
@@ -1,7 +1,7 @@
{
  "nodes": {
    "fallbackPublicExplorer": "https://app.radicle.xyz/nodes/$host/$rid$path",
-
    "apiVersion": "1.1.0",
+
    "apiVersion": "1.2.0",
    "defaultHttpdPort": 443,
    "defaultLocalHttpdPort": 8080,
    "defaultHttpdHostname": "seed.radicle.garden",
modified http-client/index.ts
@@ -94,7 +94,7 @@ export type Node = z.infer<typeof nodeSchema>;

const nodeSchema = object({
  id: string(),
-
  version: string(),
+
  agent: string(),
  config: nodeConfigSchema.nullable(),
  state: union([literal("running"), literal("stopped")]),
});
modified radicle-httpd/src/api.rs
@@ -36,7 +36,7 @@ use crate::Options;

pub const RADICLE_VERSION: &str = env!("RADICLE_VERSION");
// This version has to be updated on every breaking change to the radicle-httpd API.
-
pub const API_VERSION: &str = "1.1.0";
+
pub const API_VERSION: &str = "1.2.0";

/// Identifier for sessions
type SessionId = String;
modified radicle-httpd/src/api/v1/node.rs
@@ -7,12 +7,13 @@ use hyper::StatusCode;
use serde_json::json;

use radicle::identity::RepoId;
+
use radicle::node::address::Store as AddressStore;
use radicle::node::routing::Store;
use radicle::node::{AliasStore, Handle, NodeId, DEFAULT_TIMEOUT};
use radicle::Node;

use crate::api::error::Error;
-
use crate::api::{self, Context, PoliciesQuery, RADICLE_VERSION};
+
use crate::api::{self, Context, PoliciesQuery};
use crate::axum_extra::{Path, Query};

pub fn router(ctx: Context) -> Router {
@@ -35,6 +36,10 @@ pub fn router(ctx: Context) -> Router {
async fn node_handler(State(ctx): State<Context>) -> impl IntoResponse {
    let node = Node::new(ctx.profile.socket());
    let node_id = ctx.profile.public_key;
+
    let home = ctx.profile.home.database()?;
+
    let agent = AddressStore::get(&home, &node_id)
+
        .unwrap_or_default()
+
        .map(|node| node.agent);
    let node_state = if node.is_running() {
        "running"
    } else {
@@ -49,7 +54,7 @@ async fn node_handler(State(ctx): State<Context>) -> impl IntoResponse {
    };
    let response = json!({
        "id": node_id.to_string(),
-
        "version": format!("{}-{}", RADICLE_VERSION, env!("GIT_HEAD")),
+
        "agent": agent,
        "config": config,
        "state": node_state,
    });
modified src/lib/utils.ts
@@ -21,6 +21,11 @@ export function formatShortSeedingPolicy(
    : "restrictive";
}

+
// Removes the first and last character which are always `/`.
+
export function formatUserAgent(agent: string): string {
+
  return agent.slice(1, -1);
+
}
+

export function parseNodeId(
  nid: string,
): { prefix: string; pubkey: string } | undefined {
modified src/views/nodes/View.svelte
@@ -8,6 +8,7 @@
  import {
    baseUrlToString,
    formatShortSeedingPolicy,
+
    formatUserAgent,
    isLocal,
    truncateId,
  } from "@app/lib/utils";
@@ -28,8 +29,8 @@
  export let nid: string;
  export let stats: NodeStats;
  export let externalAddresses: string[];
-
  export let version: string;
  export let seedingPolicy: DefaultSeedingPolicy | undefined = undefined;
+
  export let agent: string;

  $: shortScope = formatShortSeedingPolicy(seedingPolicy);
  $: hostname = isLocal(baseUrl.hostname) ? "Local Node" : baseUrl.hostname;
@@ -73,7 +74,7 @@
    display: flex;
    justify-content: space-between;
  }
-
  .version {
+
  .agent {
    color: var(--color-fill-gray);
    font-family: var(--font-family-monospace);
    font-size: var(--font-size-small);
@@ -147,9 +148,13 @@
              </div>
            {/each}
          </div>
-
          <Id ariaLabel="version" id={version} shorten={false} style="none">
-
            <div class="version">
-
              {version}
+
          <Id
+
            ariaLabel="agent"
+
            id={formatUserAgent(agent)}
+
            shorten={false}
+
            style="none">
+
            <div class="agent">
+
              {formatUserAgent(agent)}
            </div>
          </Id>
        </div>
modified src/views/nodes/router.ts
@@ -22,7 +22,7 @@ export interface NodesLoadedRoute {
  resource: "nodes";
  params: {
    baseUrl: BaseUrl;
-
    version: string;
+
    agent: string;
    externalAddresses: string[];
    nid: string;
    stats: NodeStats;
@@ -54,8 +54,8 @@ export async function loadNodeRoute(
        nid: node.id,
        stats,
        externalAddresses: node.config?.externalAddresses ?? [],
-
        version: node.version,
        seedingPolicy: node.config?.seedingPolicy,
+
        agent: node.agent,
      },
    };
  } catch (error) {
modified tests/e2e/landingPage.spec.ts
@@ -94,7 +94,7 @@ test("stored custom preferred seeds in local storage", async ({ page }) => {

const nodeInfo = {
  id: "z6MkkGfMNQmjrp66Po2n4snzcSyTFRFw1m1fbYhCURxLxZpD",
-
  version: "1.0.0-rc.9-d56d619f",
+
  agent: "/radicle:1.0.0-rc.11/",
  config: {
    alias: "rhizoma",
    listen: [],
modified tests/e2e/node.spec.ts
@@ -17,7 +17,7 @@ test("node metadata", async ({ page, peerManager }) => {
  await expect(
    page.getByText(`${shortNodeRemote}@seed.radicle.test:8123`),
  ).toBeVisible();
-
  await expect(page.getByText("pre-release")).toBeVisible();
+
  await expect(page.getByText("radicle:1.0.0-rc.11")).toBeVisible();
});

test("node projects", async ({ page }) => {