feat(notstrap): migrate to notsecrets age-native API, remove sops shell-out
Replace AgeKeySource/resolve_age_key/install_age_key with IdentitySource/resolve_identities. Update integration tests to use a valid age bech32 key fixture. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,8 @@ use anyhow::{Context, Result};
|
|||||||
use notcore::{HookPhase, Report, StepStatus};
|
use notcore::{HookPhase, Report, StepStatus};
|
||||||
use notfiles::{LinkOptions, link};
|
use notfiles::{LinkOptions, link};
|
||||||
use nothooks::{HookRunner, run_phase};
|
use nothooks::{HookRunner, run_phase};
|
||||||
use notsecrets::{BitwardenSource, FileSource, PromptSource, install_age_key, resolve_age_key};
|
use notsecrets::{BitwardenSource, FileSource, PromptSource, resolve_identities};
|
||||||
|
use notsecrets::sources::IdentitySource;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@@ -88,8 +89,8 @@ pub fn run(opts: BootstrapOptions) -> Result<Report> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Retrieve age key and install
|
// 4. Resolve age identities
|
||||||
let sources: Vec<Box<dyn notsecrets::AgeKeySource>> = if let Some(kf) = opts.key_file {
|
let sources: Vec<Box<dyn IdentitySource>> = if let Some(kf) = opts.key_file {
|
||||||
vec![Box::new(FileSource::new(kf))]
|
vec![Box::new(FileSource::new(kf))]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
@@ -98,9 +99,8 @@ pub fn run(opts: BootstrapOptions) -> Result<Report> {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
match resolve_age_key(sources) {
|
match resolve_identities(sources) {
|
||||||
Ok(key) => {
|
Ok(_identities) => {
|
||||||
install_age_key(&key)?;
|
|
||||||
report.add("age key", StepStatus::Ok);
|
report.add("age key", StepStatus::Ok);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ fn main() -> Result<()> {
|
|||||||
key_file,
|
key_file,
|
||||||
dotfiles,
|
dotfiles,
|
||||||
check_prereqs: Some(Box::new(prereqs::check_prerequisites)),
|
check_prereqs: Some(Box::new(prereqs::check_prerequisites)),
|
||||||
env_injector: Some(Box::new(notsecrets::decrypt_sops)),
|
env_injector: None,
|
||||||
};
|
};
|
||||||
let report = run(opts)?;
|
let report = run(opts)?;
|
||||||
report.print();
|
report.print();
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ fn make_test_env() -> TestEnv {
|
|||||||
|
|
||||||
// age key file (content doesn't matter — FileSource reads it verbatim)
|
// age key file (content doesn't matter — FileSource reads it verbatim)
|
||||||
let key_file = d.join("age.key");
|
let key_file = d.join("age.key");
|
||||||
fs::write(&key_file, "AGE-SECRET-KEY-1TESTKEY\n").unwrap();
|
fs::write(
|
||||||
|
&key_file,
|
||||||
|
"AGE-SECRET-KEY-1X3QKFQ4MZQM7LTJ3AX0N3EM63RGRV4J6N5ZDWPVKCEUCZKJWJSUSU6GYN6\n",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// notfiles.toml — one package "shell" targeting home tempdir
|
// notfiles.toml — one package "shell" targeting home tempdir
|
||||||
fs::write(
|
fs::write(
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ use tempfile::TempDir;
|
|||||||
use notcore::{HookPhase, HookSpec};
|
use notcore::{HookPhase, HookSpec};
|
||||||
use notfiles::{LinkOptions, link};
|
use notfiles::{LinkOptions, link};
|
||||||
use nothooks::{HookResult, HookRunner};
|
use nothooks::{HookResult, HookRunner};
|
||||||
use notsecrets::{AgeKeySource, FileSource, resolve_age_key};
|
use notsecrets::{FileSource, resolve_identities};
|
||||||
|
use notsecrets::sources::IdentitySource;
|
||||||
|
|
||||||
/// Test that notsecrets and nothooks can each be used independently
|
/// Test that notsecrets and nothooks can each be used independently
|
||||||
/// in the same integration boundary — resolving an age key from a file
|
/// in the same integration boundary — resolving an age key from a file
|
||||||
@@ -16,14 +17,15 @@ fn test_nothooks_notsecrets_independent() {
|
|||||||
|
|
||||||
// Write a fake age key via FileSource
|
// Write a fake age key via FileSource
|
||||||
let key_path = dir.path().join("age.key");
|
let key_path = dir.path().join("age.key");
|
||||||
fs::write(&key_path, "AGE-SECRET-KEY-1CROSSCRATE\n").unwrap();
|
fs::write(
|
||||||
|
&key_path,
|
||||||
|
"AGE-SECRET-KEY-1X3QKFQ4MZQM7LTJ3AX0N3EM63RGRV4J6N5ZDWPVKCEUCZKJWJSUSU6GYN6\n",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let sources: Vec<Box<dyn AgeKeySource>> = vec![Box::new(FileSource::new(key_path))];
|
let sources: Vec<Box<dyn IdentitySource>> = vec![Box::new(FileSource::new(key_path))];
|
||||||
let key = resolve_age_key(sources).expect("resolve_age_key failed");
|
let identities = resolve_identities(sources).expect("resolve_identities failed");
|
||||||
assert!(
|
assert!(!identities.is_empty(), "expected at least one identity");
|
||||||
key.trim().starts_with("AGE-SECRET-KEY-"),
|
|
||||||
"expected age key prefix, got: {key:?}"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write a hook that just prints
|
// Write a hook that just prints
|
||||||
let script = dir.path().join("chain.nu");
|
let script = dir.path().join("chain.nu");
|
||||||
|
|||||||
Reference in New Issue
Block a user