Skip to content

Commit

Permalink
Merge pull request #468 from Nukesor/pueue_config_env
Browse files Browse the repository at this point in the history
add: PUEUE_CONFIG env variable support
  • Loading branch information
Nukesor authored Oct 14, 2023
2 parents 61fcfce + 52c6881 commit 7acc4f9
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [3.3.0] - unreleased

### Added

- Support the `PUEUE_CONFIG_PATH` environment variable in addition to the `--config` option. [#464](https://github.com/Nukesor/pueue/issues/464)

### Fixed

- Support parameter parsing for signal names with capslock (`SIGINT`) and short name (`INT`|`int`). [#455](https://github.com/Nukesor/pueue/issues/455)
Expand Down
4 changes: 4 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ ensure_installed *args:
echo "error: cargo-{{ args }} is not installed"
exit 1
fi

lint:
cargo fmt
cargo clippy --all --tests
5 changes: 3 additions & 2 deletions pueue/src/client/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,8 +537,9 @@ pub struct CliArguments {
#[arg(long, value_enum, default_value = "auto")]
pub color: ColorChoice,

/// Path to a specific pueue config file to use.
/// This ignores all other config files.
/// If provided, Pueue only uses this config file.
/// This path can also be set via the "PUEUE_CONFIG_PATH" environment variable.
/// The commandline option overwrites the environment variable!
#[arg(short, long, value_hint = ValueHint::FilePath)]
pub config: Option<PathBuf>,

Expand Down
5 changes: 3 additions & 2 deletions pueue/src/daemon/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ pub struct CliArguments {
#[arg(short, long)]
pub daemonize: bool,

/// Path to a specific pueue config file to use.
/// This ignores all other config files.
/// If provided, Pueue only uses this config file.
/// This path can also be set via the "PUEUE_CONFIG_PATH" environment variable.
/// The commandline option overwrites the environment variable!
#[arg(short, long, value_hint = ValueHint::FilePath)]
pub config: Option<PathBuf>,

Expand Down
91 changes: 91 additions & 0 deletions pueue/tests/client/integration/configuration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use std::{
collections::HashMap,
process::{Child, Command, Stdio},
};

use anyhow::{bail, Context, Result};

use assert_cmd::prelude::CommandCargoExt;
use pueue_lib::{
settings::{Shared, PUEUE_CONFIG_PATH_ENV},
state::State,
};

use crate::helper::*;

/// Spawn the daemon by calling the actual pueued binary.
/// This is basically the same as the `standalone_daemon` logic, but it uses the
/// `PUEUE_CONFIG_PATH` environment variable instead of the `--config` flag.
pub async fn standalone_daemon_with_env_config(shared: &Shared) -> Result<Child> {
// Inject an environment variable into the daemon.
// This is used to test that the spawned subprocesses won't inherit the daemon's environment.
let mut envs = HashMap::new();
envs.insert("PUEUED_TEST_ENV_VARIABLE", "Test".to_owned());
envs.insert(
PUEUE_CONFIG_PATH_ENV,
shared
.pueue_directory()
.join("pueue.yml")
.to_string_lossy()
.to_string(),
);

let child = Command::cargo_bin("pueued")?
.arg("-vvv")
.envs(envs)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;

let tries = 20;
let mut current_try = 0;

// Wait up to 1s for the unix socket to pop up.
let socket_path = shared.unix_socket_path();
while current_try < tries {
sleep_ms(50).await;
if socket_path.exists() {
return Ok(child);
}

current_try += 1;
}

bail!("Daemon didn't boot in stand-alone mode after 1sec")
}

/// Test that editing a task without any flags only updates the command.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn run_with_env_config_path() -> Result<()> {
let (settings, _tempdir) = daemon_base_setup()?;
let mut child = standalone_daemon_with_env_config(&settings.shared).await?;
let shared = &settings.shared;

// Check if the client can connect to the daemon.
let mut envs = HashMap::new();
envs.insert(
PUEUE_CONFIG_PATH_ENV,
shared
.pueue_directory()
.join("pueue.yml")
.to_string_lossy()
.to_string(),
);
let output = Command::cargo_bin("pueue")?
.args(["status", "--json"])
.envs(envs)
.current_dir(shared.pueue_directory())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.context("Failed to execute pueue with env config variable".to_string())?;

// Deserialize the message and make sure it's a status response.
let response = String::from_utf8_lossy(&output.stdout);
let state: State = serde_json::from_str(&response)?;

assert!(state.tasks.is_empty(), "State must have no tasks");

child.kill()?;
Ok(())
}
1 change: 1 addition & 0 deletions pueue/tests/client/integration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod completions;
mod configuration;
mod edit;
mod follow;
mod group;
Expand Down
12 changes: 11 additions & 1 deletion pueue_lib/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use shellexpand::tilde;
use crate::error::Error;
use crate::setting_defaults::*;

/// The environment variable that can be set to overwrite pueue's config path.
pub const PUEUE_CONFIG_PATH_ENV: &str = "PUEUE_CONFIG_PATH";

/// All settings which are used by both, the client and the daemon
#[derive(PartialEq, Eq, Clone, Debug, Deserialize, Serialize)]
pub struct Shared {
Expand Down Expand Up @@ -315,8 +318,13 @@ impl Settings {
///
/// The default local config locations depends on the current target.
pub fn read(from_file: &Option<PathBuf>) -> Result<(Settings, bool), Error> {
// If no explicit path is provided, we look for the PUEUE_CONFIG_PATH env variable.
let from_file = from_file
.clone()
.or_else(|| std::env::var(PUEUE_CONFIG_PATH_ENV).map(PathBuf::from).ok());

// Load the config from a very specific file path
if let Some(path) = from_file {
if let Some(path) = &from_file {
// Open the file in read-only mode with buffer.
let file = File::open(path)
.map_err(|err| Error::IoPathError(path.clone(), "opening config file", err))?;
Expand Down Expand Up @@ -360,6 +368,8 @@ impl Settings {
pub fn save(&self, path: &Option<PathBuf>) -> Result<(), Error> {
let config_path = if let Some(path) = path {
path.clone()
} else if let Ok(path) = std::env::var(PUEUE_CONFIG_PATH_ENV) {
PathBuf::from(path)
} else if let Some(path) = dirs::config_dir() {
let path = path.join("pueue");
path.join("pueue.yml")
Expand Down

0 comments on commit 7acc4f9

Please sign in to comment.