Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: PUEUE_CONFIG env variable support #468

Merged
merged 1 commit into from
Oct 14, 2023
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
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
Loading