Skip to content

Commit

Permalink
feat: Add a route to get the current API version information
Browse files Browse the repository at this point in the history
Fixes #112.
  • Loading branch information
RemiBardon committed Jan 17, 2025
1 parent ba066d4 commit c54443a
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,6 @@ jobs:
cache-to: type=gha,mode=max
build-args: |
CARGO_PROFILE=${{ startsWith(github.ref, 'refs/tags/') && 'release' || 'staging' }}
VERSION=${{ fromJSON(steps.metadata.outputs.json).labels['org.opencontainers.image.version'] }}
COMMIT=${{ fromJSON(steps.metadata.outputs.json).labels['org.opencontainers.image.revision'] }}
BUILD_TIMESTAMP=${{ fromJSON(steps.metadata.outputs.json).labels['org.opencontainers.image.created'] }}
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ RUN cargo chef cook --profile="${CARGO_PROFILE}" --recipe-path recipe.json ${CAR
# Build the application.
COPY --exclude=crates/*/static/ . .
ARG CARGO_INSTALL_EXTRA_ARGS=''
ARG VERSION
ARG COMMIT
ARG BUILD_TIMESTAMP=''
RUN API_VERSION_DIR=./crates/rest-api/static/api-version && \
mkdir -p "${API_VERSION_DIR:?}" && \
echo "${VERSION:?}" > "${API_VERSION_DIR:?}"/VERSION && \
echo "${COMMIT:?}" > "${API_VERSION_DIR:?}"/COMMIT && \
if [ -z "${BUILD_TIMESTAMP}" ]; then BUILD_TIMESTAMP="$(date -u -Iseconds)" && BUILD_TIMESTAMP="${BUILD_TIMESTAMP//+00:00/Z}"; fi && \
echo "${BUILD_TIMESTAMP:?}" > "${API_VERSION_DIR:?}"/BUILD_TIMESTAMP
RUN cargo install --path crates/rest-api --bin prose-pod-api --profile="${CARGO_PROFILE}" ${CARGO_INSTALL_EXTRA_ARGS}


Expand Down
2 changes: 2 additions & 0 deletions crates/rest-api/src/features/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub mod pod_config;
pub mod profile;
pub mod roles;
pub mod server_config;
pub mod version;
pub mod workspace_details;

const NETWORK_ROUTE: &'static str = "/v1/network";
Expand All @@ -36,5 +37,6 @@ pub(super) fn router(app_state: AppState) -> axum::Router {
.merge(roles::router(app_state.clone()))
.merge(server_config::router(app_state.clone()))
.merge(workspace_details::router(app_state.clone()))
.merge(version::router())
.layer(tower::ServiceBuilder::new().map_request(rename_bracketed_query_param_names))
}
82 changes: 82 additions & 0 deletions crates/rest-api/src/features/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// prose-pod-api
//
// Copyright: 2025, Rémi Bardon <[email protected]>
// License: Mozilla Public License v2.0 (MPL v2.0)

use axum::{routing::get, Json};
use iso8601_timestamp::Timestamp;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};

lazy_static! {
static ref API_VERSION: VersionInfo = VersionInfo::new(
non_empty(include_str!("../../static/api-version/VERSION").trim())
.unwrap_or("unknown")
.to_string(),
non_empty(include_str!("../../static/api-version/COMMIT").trim()).map(|s| s.to_string()),
non_empty(include_str!("../../static/api-version/BUILD_TIMESTAMP").trim())
.and_then(|s| Timestamp::parse(s)),
);
}

pub(super) fn router() -> axum::Router {
axum::Router::new().route("/version", get(version_route))
}

async fn version_route() -> Json<Versions> {
Json(Versions {
api: API_VERSION.clone(),
})
}

#[derive(Serialize, Deserialize)]
struct Versions {
#[serde(rename = "self")]
api: VersionInfo,
}

#[derive(Clone, Serialize, Deserialize)]
struct VersionInfo {
/// E.g. `"v0.4.0 (2025-01-01)"`
version: String,
/// E.g. `"v0.4.0"`
tag: String,
/// E.g. `"2025-01-01"`
build_date: Option<String>,
/// E.g. `"2025-01-01T22:12:00Z"`
build_timestamp: Option<String>,
/// E.g. `"e3e6bbb"`
commit_short: Option<String>,
/// E.g. `"e3e6bbba82fa0d1934990f878c1db376fc35f7d8"`
commit_long: Option<String>,
}

impl VersionInfo {
fn new(tag: String, commit_hash: Option<String>, build_timestamp: Option<Timestamp>) -> Self {
let build_date = build_timestamp.map(|timestamp| timestamp.date().to_string());
let commit_short = commit_hash.as_ref().map(|hash| hash[..7].to_string());
let version = if let Some(ref date) = build_date {
format!("{tag} ({date})")
} else {
format!("{tag}")
};
Self {
version,
tag,
build_date,
build_timestamp: build_timestamp.as_ref().map(Timestamp::to_string),
commit_short,
commit_long: commit_hash,
}
}
}

// UTILITIES

fn non_empty(s: &'static str) -> Option<&'static str> {
if s.is_empty() {
None
} else {
Some(s)
}
}
Empty file.
Empty file.
1 change: 1 addition & 0 deletions crates/rest-api/static/api-version/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unknown
8 changes: 8 additions & 0 deletions scripts/build-image
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,19 @@ fi

# ===== MAIN LOGIC =====

if [ -z "$(git status -s)" ]; then
COMMIT="$(git rev-parse HEAD)"
else
warn 'You have uncommitted changes, the API version will have no commit hash information.'
fi

edo docker buildx build \
${DOCKER_TARGET_PLATFORM:+--platform "${DOCKER_TARGET_PLATFORM:?}"} \
-t "${PROSE_POD_API_IMAGE:?}" \
${CARGO_PROFILE:+--build-arg CARGO_PROFILE="${CARGO_PROFILE}"} \
${CARGO_CHEF_EXTRA_ARGS:+--build-arg CARGO_CHEF_EXTRA_ARGS="${CARGO_CHEF_EXTRA_ARGS[*]}"} \
${CARGO_INSTALL_EXTRA_ARGS:+--build-arg CARGO_INSTALL_EXTRA_ARGS="${CARGO_INSTALL_EXTRA_ARGS[*]}"} \
--build-arg VERSION="${PROSE_POD_API_IMAGE_TAG:?}" \
--build-arg COMMIT="${COMMIT:?}" \
${NO_PULL:+--pull=false} \
"${PROSE_POD_API_DIR:?}"

0 comments on commit c54443a

Please sign in to comment.