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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ members = [
]

[workspace.package]
version = "3.8.0"
version = "3.8.1"
edition = "2024"
license = "MIT"
repository = "https://github.com/pragmatrix/context-switch"
Expand Down
23 changes: 23 additions & 0 deletions VERSIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Versioning

The workspace uses a single shared version (`[workspace.package] version` in the
root `Cargo.toml`); all member crates inherit it via `version.workspace = true`.

## When to bump

- **Every behavioral change** bumps the version by at least a patch increment,
in the commit that introduces the change. Behavioral changes include new or
altered runtime behavior, protocol changes, new configuration, and new
warnings or log outcomes that affect operation.
- **Non-behavioral changes** (comment updates, doc rewording, formatting,
refactors without observable behavior change) do not require a bump.
- Bump the minor version for new features or compatible protocol extensions,
and the major version for breaking protocol or interface changes, following
Semantic Versioning.

## Release history

| Version | Change |
|---------|--------|
| 3.8.0 | google-transcribe: numerals support via digit-sequence class token (#99) |
| 3.8.1 | audio-knife: startup self-test warning for `GOOGLE_APPLICATION_CREDENTIALS` (#100) |
3 changes: 3 additions & 0 deletions audio-knife/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod app_error;
mod event_scheduler;
mod mod_audio_fork;
mod selftest;
mod server_event_router;

use std::env;
Expand Down Expand Up @@ -65,6 +66,8 @@ async fn main() -> Result<()> {
info!("Environment variables loaded from {env_path:?}");
}

selftest::run();

let addr = {
match env::var("AUDIO_KNIFE_ADDRESS") {
Ok(addr) => addr.parse().expect("Failed to parse AUDIO_KNIFE_ADDRESS"),
Expand Down
33 changes: 33 additions & 0 deletions audio-knife/src/selftest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//! Startup self-test: verifies deployment configuration that the server itself does not
//! depend on, so problems are surfaced early without preventing startup.

use std::env;
use std::fs;
use std::path::Path;

use anyhow::{Context, Result};
use tracing::warn;

/// Runs the startup self-tests. Failures are logged as warnings with context about what will
/// not work, but never prevent startup.
pub fn run() {
if let Err(err) = google_credentials() {
warn!("The `google-transcribe` service will not work: {err:#}");
}
}

/// Checks `GOOGLE_APPLICATION_CREDENTIALS`: the variable must be set and point to a file
/// containing valid JSON. Returns the first problem found as an error.
fn google_credentials() -> Result<()> {
const VAR: &str = "GOOGLE_APPLICATION_CREDENTIALS";

let path = env::var(VAR).context(format!("{VAR} is not set"))?;

let json = fs::read_to_string(Path::new(&path))
.with_context(|| format!("{VAR}={path}: cannot read file"))?;

serde_json::from_str::<serde_json::Value>(&json)
.with_context(|| format!("{VAR}={path}: not valid JSON"))?;

Ok(())
}
Loading