Skip to content
Open
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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ Confirm the install with a command that needs no API token:
brainpod describe
```

### Staying current

Interactive runs report a newer release once it exists, after the command's own output:

```
Update Available
New version 0.0.6 is available, you are on 0.0.5. Download: https://github.com/brainpodnl/cli/releases/latest
```

The check reads where the `latest` alias redirects, which costs one request carrying no body, at most once a day; the answer is cached in `version-check.json` beside the configuration file and every other run that day reads it from there. An attempt that never came back — an unreachable GitHub, or a link slower than the moment the CLI is willing to wait — is retried an hour later rather than a day later, and a configuration directory that cannot be written to disables the check rather than turning it into a request per command. It never delays a command by more than a moment: the request runs alongside the command and anything still in flight when the command ends is left for the next run to read. Runs that a program reads stay silent and make no request at all — `--json`, anything whose standard error is not a terminal, and anything with `CI` set. Set `BRAINPOD_NO_UPDATE_CHECK=1` to turn it off entirely. Unstamped builds report `0.0.0-dev` (see [Versioning](#versioning)) and are never compared against a release, so a checkout build stays quiet.

Building from source needs Nix; this is the same build the release workflow runs:

```sh
Expand Down
14 changes: 11 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod image;
mod openapi;
mod output;
mod tunnel;
mod update;

use client::{ApiError, Client};
use cmd::Command;
Expand Down Expand Up @@ -76,7 +77,11 @@ async fn main() -> ExitCode {
}
agent::configure(opts.session.clone());

match run(opts).await {
// Started before the command so the two run side by side: whatever the
// command spends talking to the API is time this costs nobody.
let update = update::start(json_output);

let code = match run(opts).await {
Ok(value) => match output::write(value, json_output).await {
Ok(()) => ExitCode::SUCCESS,
Err(error) if is_broken_pipe(&error) => ExitCode::SUCCESS,
Expand All @@ -90,7 +95,10 @@ async fn main() -> ExitCode {
write_error(&error, json_output);
ExitCode::FAILURE
}
}
};

update.notify().await;
code
}

async fn run(opts: Opts) -> Result<output::CommandOutput> {
Expand Down Expand Up @@ -220,7 +228,7 @@ pub(crate) fn http_client_builder() -> Result<reqwest::ClientBuilder> {
Ok(reqwest::Client::builder())
}

fn environment(name: &str) -> Option<String> {
pub(crate) fn environment(name: &str) -> Option<String> {
std::env::var(name)
.ok()
.filter(|value| !value.trim().is_empty())
Expand Down
2 changes: 1 addition & 1 deletion src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,7 @@ fn render_event(event: &Value, color: bool) -> String {
}
}

fn style(value: &str, code: &str, enabled: bool) -> String {
pub(crate) fn style(value: &str, code: &str, enabled: bool) -> String {
if enabled && !code.is_empty() {
format!("\u{1b}[{code}m{value}\u{1b}[0m")
} else {
Expand Down
Loading
Loading