mirror of
https://github.com/bahdotsh/wrkflw.git
synced 2026-08-29 10:09:25 +02:00
* feat(evaluator): make toJSON(needs) return nested needs object Same bug that toJSON(steps) had before #97, and toJSON(env) had before #96: resolve() had no match arm for the bare "needs" identifier, so it fell through to Null. Anyone trying to dump the cross-job outputs context got "null" back. Useful. Build the shape GHA actually provides: each job ID maps to an object with "outputs" (sub-object) and "result". Merge the key sets of needs_context and needs_results so a job appears even if only one of the two has recorded something for it — same union-of-keys trick as the steps arm. Omit "result" when no result was recorded, mirroring how steps omits outcome/conclusion in that case. The only real shape difference vs. steps is the single "result" string instead of the (outcome, conclusion) pair. Tests mirror the toJSON(steps) suite: populated context, empty, sorted keys, one-sided populations, and special-character escaping. Also drops "needs" from the lingering TODO comment — github, secrets, matrix still to go. * chore(secrets): silence clippy::unnecessary_sort_by in masker Clippy 1.95 decided that `sort_by(|a, b| b.0.len().cmp(&a.0.len()))` is an unnecessary dance when `sort_by_key` with `Reverse` says the same thing in fewer tokens. CI is now `-D warnings`, so this was the difference between a green build and a red one. Swap to `sort_by_key(|pair| std::cmp::Reverse(pair.0.len()))`. Same descending-by-length order, same behavior, clippy goes quiet. Not a change anyone will miss.
wrkflw-secrets
Secrets management for wrkflw workflow execution. Provides secure handling of secrets with multiple providers, encryption, masking, and GitHub Actions-compatible ${{ secrets.* }} substitution.
Features
- Providers: environment variables, files (JSON/YAML/.env), HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager
- Encryption: AES-256-GCM encrypted storage for secrets at rest
- Masking: automatic masking of secrets in logs (GitHub tokens, AWS keys, JWTs, etc.)
- Substitution: GitHub Actions-compatible
${{ secrets.* }}and${{ secrets.provider:name }}syntax - Caching: optional TTL-based cache for frequently accessed secrets
- Rate limiting: built-in protection against secret access abuse
- Validation: comprehensive input validation for secret names and values
Quick Start
use wrkflw_secrets::prelude::*;
#[tokio::main]
async fn main() -> SecretResult<()> {
let manager = SecretManager::default().await?;
std::env::set_var("GITHUB_TOKEN", "ghp_your_token_here");
let secret = manager.get_secret("GITHUB_TOKEN").await?;
// Substitute in templates
let mut sub = SecretSubstitution::new(&manager);
let resolved = sub.substitute("Bearer ${{ secrets.GITHUB_TOKEN }}").await?;
// Mask secrets in logs
let mut masker = SecretMasker::new();
masker.add_secret(secret.value());
println!("{}", masker.mask(&resolved));
Ok(())
}
Configuration
Create ~/.wrkflw/secrets.yml:
default_provider: env
enable_masking: true
timeout_seconds: 30
enable_caching: true
cache_ttl_seconds: 300
providers:
env:
type: environment
prefix: "WRKFLW_SECRET_"
file:
type: file
path: "~/.wrkflw/secrets.json"
vault:
type: vault
url: "https://vault.example.com"
auth:
method: token
token: "${VAULT_TOKEN}"
mount_path: "secret"
Feature Flags
[dependencies]
wrkflw-secrets = { version = "0.7", features = ["vault-provider", "aws-provider"] }
Available: env-provider (default), file-provider (default), vault-provider, aws-provider, azure-provider, gcp-provider, all-providers.
See the secrets demo for end-to-end usage examples.