Repository navigation
Releases: flipbit03/rustible
Releases · flipbit03/rustible
Release list
v0.9.3
Upgrading from 0.9.2
- No protocol change. Upgrade the CLI and bump the dependencies to
0.9.3together, as usual. - One new refusal: an apt step that would install, upgrade or remove a held package it names (
apt-mark hold) now fails, under--checktoo, namingapt-mark unhold <pkg>. apt-get already refused these in the real run; the failure now comes incheck, before the dry run sayswould change.
Fixes
apt::Absentno longer refuses a package that is already gone. dpkg keeps anot-installedrecord for any package another installed package names (Depends,Breaks, ...), so a playbook that purged such a package failed its next run withpackage ... is in dpkg state 'unknown ok not-installed'; fix it by hand (dpkg --configure -a). It now reports the package innot_presentand the step isok, with or without.purge(true). (#157, #158)- A held package that is installed is
okforapt::Present, and forapt::Latestwhen it is at its candidate, instead ofapt-get installrunning and reportingchangedon every run. - The apt ops now read a package's state from dpkg's state word, so a package selected for removal (
deinstall ok installed) still counts as installed. Real half-states (half-configured,unpacked, areinstreqflag, ...) are still refused byapt::Absent.
What's Changed
- apt: read dpkg's state word, and refuse to change a held package (#157) by @flipbit03 in #158
Full Changelog: v0.9.2...v0.9.3
v0.9.2
Upgrading from 0.9.1
- No protocol change, no API change. Upgrade the CLI and bump the dependencies to
0.9.2together, as usual.
Highlights
- No more
xcrunwarning when building for macOS without an Apple SDK. On a Linux controller (or a mac without the command line tools), every playbook build for anapple-darwintarget printed rustc'swarning: invoking "xcrun" ... failed. Rustible now gives rustc an empty stand-inSDKROOTin its cache so rustc stops looking, and removes it again before zig sees it; zig builds exactly as before. AnSDKROOTyou set yourself, or a real SDK fromxcrun, is left alone. (#155, #156)
v0.9.1
Upgrading from 0.9.0
- No protocol change, no API change, no behaviour change. Bump the dependencies to
0.9.1and rebuild.
Highlights
- Docs: take an account's home from Rustible, never hardcode
/home/<name>.USING_RUSTIBLE.mdnow shows getting it fromuser::Existing(.home), building paths withPath::joinand passing it into templates; its Syncthing example does exactly that.Account::home's rustdoc says it's taken verbatim (a trailing/is possible) and to join withPath::join. (#153, #154)
v0.9.0
Upgrading from 0.8.x
- No protocol change, no API change. Bump the dependencies to
0.9.0and rebuild. - Behaviour change on macOS targets:
ssh::authorized_keys'for_user_name(..)anduser::Existingused to refuse a mac. They now run there. A playbook that worked around the refusal withfor_account(home, uid, gid)keeps working.
Highlights
- Account lookups on macOS:
ssh::authorized_keys::{Present, Absent}::for_user_name(..)anduser::Existingfind the account in Open Directory. Local and directory-bound accounts both resolve, the way sshd finds them at login (getpwnam, through/usr/bin/id -P).- So
rustible_github::github_ssh_keys_to_user(ctx, "<gh user>", &ctx.facts().user)now works on a Mac too, and one playbook can keep a mixed Linux and macOS fleet's keys in sync (#151). user::Existingthenfor_user(&account)chains work on a mac.- On a mac,
user::Existing'sgroupsare the groups whoseGroupMembershiplists the account (/usr/bin/dscl), as on Linux they are the/etc/grouplines that list it. Groups held only through nesting or implicitly (everyone) are not listed, so there are fewer thanid -Gnprints. - A missing account is refused in both modes, as on Linux. So is a name
idwould read as a uid (501,-2), rather than resolving to whichever account has that uid. - Every other
userandgroupop still refuses a mac.
- So
What's Changed
- ssh::authorized_keys and user::Existing: look accounts up on macOS (Open Directory) by @flipbit03 in #152
Full Changelog: v0.8.1...v0.9.0
v0.8.1
Upgrading from 0.8.0
- No protocol change, no API change. Bump the dependencies to
0.8.1and rebuild.
Fixes
template!in rust-analyzer: no more false "cannot tell which file this call is in" error ontemplate!(include_str!(..)), with no editor setting needed.- rust-analyzer does not tell a proc macro which file a call is in.
template!now finds the files of the crate that hold the same call and checks from their directory. - The editor shows the build's errors when it can place the call, and stays silent when it cannot.
- After editing only a template file, the editor catches up at the next edit of the
.rsfile.
- rust-analyzer does not tell a proc macro which file a call is in.
- Clearer
template!errors:- Template file not found: the crate-relative path, the directory
include_str!resolves from, and a near miss when there is one. - Missing names: listed, with the
name = <value>to add. - A one-line literal with no Jinja in it: a hint that a file is written
include_str!(".."). - A failed
template!gives one error instead of a cascade.
- Template file not found: the crate-relative path, the directory
What's Changed
- template!: no false error in rust-analyzer, and errors that say what to do by @flipbit03 in #150
Full Changelog: v0.8.0...v0.8.1
v0.8.0
Upgrading from 0.7.x
- No protocol change. Rebuild as usual.
- New dependency:
rustible-sdkandrustible-macrosdepend onminijinjapinned to exactly=3.0.0(its syntax-tree API is unstable). A workspace that needs a different minijinja 3.x does not resolve. template!is in the prelude. A playbook that defines its own item namedtemplatemay need to rename it or import it explicitly.- More masking: a
Secretis now also masked in the HTML-safe JSON, percent-encoded and HTML-escaped spellings, from every op.
Highlights
rustible::template!: Jinja2 templates (minijinja) rendered to aStringon the target, for any op.- Sources: a literal,
include_str!("x.j2"), or text known at run time. - Variables:
name = value(anySerialize) and a..spread. - Compile-time checks for a literal or
include_str!template:- the syntax of every file in the tree;
- every
include/extends/importtarget exists, resolved relative to the file that names it, and is embedded, so cargo rebuilds when it changes; - every name passed is used, and every top-level name the template reads is passed.
- On the target: strict undefined,
trim_blocks, final newlines kept, no autoescape, every minijinja built-in. A template whose text arrives at run time can read no file. - See USING §13 and
template!'s rustdoc.
- Sources: a literal,
rustible::json!andrustible::serdeare re-exported, for ad hoc and typed template data.
What's Changed
- Templates: rustible::template! (Jinja2 rendering to a String), and vision §5.7 by @flipbit03 in #148
Full Changelog: v0.7.0...v0.8.0
v0.7.0
Upgrading from 0.6.x
- Protocol 6 → 8. Upgrade the
rustibleCLI and your workspace's crates together. A mismatched pair refuses at the handshake and tells you to rebuild. - Test API behind a
testingfeature.Fake,System::fake,testing::ctx/testing::dry,changed_then_okand#[integration_test]now need it.Ctx::newis no longer public; userustible_sdk::testing::ctx(sys). Collections add one line:[dev-dependencies] rustible-sdk = { version = "0.7.0", features = ["testing"] }
- Behaviour changes you may notice:
http::Downloadwrites only on a200. It refuses a body cut short by a reset or by TLS withoutclose_notify, and.timeout()also bounds silence in the body.ctx.fetchdoes nothing under--check.- Under
--check, a step run as an account that doesn't exist yet reports would change ("waits for account"). brewsteps never autoremove formulae.- Secrets are masked in every event the binary emits, and in panic messages. A secret under 4 characters is never masked.
Highlights
- File contents, listings and command I/O stream through the escalation helper, with no size limits.
http::Request(Ansible'suri).archive::Extractedhandles zstd, andgit archive/ GitHub source tarballs extract at strip 0.- A run-wide secret masker using Ansible's rules, plus
mask::apply_prefix. - A step failure the playbook catches counts as recovered, and
-vshows its command and stderr. - Output escapes control and invisible formatting characters, and a command killed by a signal shows
(killed by signal N).
What's Changed
- Host verdict: a step failure the playbook catches is recovered, not failed by @flipbit03 in #54
- Tier 4: a caught escalation failure under ssh_user names the override and counts as recovered by @flipbit03 in #65
- Testing tiers: three, numbered by environment (in-process, docker, VM); CI job names carry the tier by @flipbit03 in #67
- Testing tiers follow-up: correct what a container lacks, split the mac job by tier, widen T1 by @flipbit03 in #68
- --check contacts nothing outside the target: apt::Latest stops refreshing, UserKeys stops fetching, plus a sweep by @flipbit03 in #69
- Local::write sets setuid/setgid after its chown, so rewriting a setuid/setgid file keeps the bits by @flipbit03 in #74
- System::backup: never write through a planted symlink, never leave a setuid copy by @flipbit03 in #76
- archive::Extracted: a member whose stream ends early writes nothing under its name by @flipbit03 in #77
- http::Request: general HTTP API calls (Ansible's uri) by @flipbit03 in #81
- Diff::short is a summary's first line; http::Request shows its body at -v; -v prints a failed step's diff by @flipbit03 in #89
- A caught step failure shows its command's stderr at -v (StepFinished.cmd, protocol 8) by @flipbit03 in #94
- The helper refuses an answer larger than one frame instead of sending it (#84) by @flipbit03 in #97
- brew::Absent removes every installed version and refuses a pinned formula (#71) by @flipbit03 in #98
- brew: resolve an installed alias or old name through opt/ (#72) by @flipbit03 in #100
- apt: a refresh writes update-success-stamp, and the lists' age is the newer of it and the lists (#70) by @flipbit03 in #101
- archive: refuse pax sparse members, replace a symlink member through a renamed temporary link by @flipbit03 in #102
- Set the mode without setuid, then the owner, then the full mode by @flipbit03 in #105
- SDK: stream file contents, listings and command I/O across the escalation helper (#85) by @flipbit03 in #106
- Stream ctx.fetch and file::Copy (#86) by @flipbit03 in #108
- Stream http::Download; no default size caps on HTTP (#87) by @flipbit03 in #111
- Elevated: a helper that exits reports its whole stderr (#90) by @flipbit03 in #113
- Stream archive::Extracted, zstd included (#88) by @flipbit03 in #114
- PROGRESS: #82 merged with #114; backlog train 2 complete by @flipbit03 in #116
- Vision: back to a vision; the source is the authority on types by @flipbit03 in #120
- Docs: bring the user docs up to date with the week's changes by @flipbit03 in #121
- Vision 5.4: the binary never listens or connects back by @flipbit03 in #124
- Probe tests: join the in-process helper inside the watched window (#110) by @flipbit03 in #127
- Tests: make write-then-exec tests immune to the ETXTBSY fork race (#128) by @flipbit03 in #129
- SDK: test-only API behind a
testingfeature; Ctx::new leaves the public surface (#125) by @flipbit03 in #130 - ctx.fetch does nothing under --check (#117) by @flipbit03 in #131
- --check: steps as an account that does not exist yet wait for it (#118) by @flipbit03 in #132
- Run-wide secret masker with Ansible's rules, applied where events leave the binary (#126) by @flipbit03 in #133
- Renderers: a signal-killed command shows (killed by signal N) (#95) by @flipbit03 in #135
- Renderers escape control and invisible formatting characters (#91) by @flipbit03 in #136
- http::Download: verified close, idle body timeout, 200 only, apply executes the intent (#112) by @flipbit03 in #137
- archive::Extracted: a pax global header is metadata, so git archive tarballs extract at strip 0 (#103) by @flipbit03 in #139
- file::Symlink stages at a random sibling name, shared with archive (#104) by @flipbit03 in #140
- authorized_keys::Present gives mode and owner to the write (#119) by @flipbit03 in #141
- brew::Absent removes only what it names: HOMEBREW_NO_AUTOREMOVE (#99) by @flipbit03 in #142
- Inventory: the same-distance conflict message names fixes that work (#123) by @flipbit03 in #143
- mask::apply_prefix: mask before http cuts or reshapes text (#134) by @flipbit03 in #144
- ureq: minimum 3.4.1, and a scheduled check against the newest 3.x (#138) by @flipbit03 in #145
- CI: drop the weekly newest-ureq job; keep ureq's 3.4.1 minimum by @flipbit03 in #146
Full Changelog: v0.6.1...v0.7.0
v0.6.1
What's Changed
- as_user to an unprivileged account: stream the playbook binary to it (#62) by @flipbit03 in #63
Full Changelog: v0.6.0...v0.6.1
v0.6.0
What's Changed
- Vision: a dry run touches nothing outside the target; guide: upgrading Rustible and a workspace by @flipbit03 in #49
- SDK: check() returns a typed Intent that apply() executes; Diff becomes a write-only report by @flipbit03 in #50
- ctx.block: section becomes a grouping that returns its closure's value, with --check absorption by @flipbit03 in #53
- systemd: .user(true) reaches the user manager of a ctx.as_user(..) target by @flipbit03 in #57
- Playbook option ssh_user: override the inventory's login user per playbook by @flipbit03 in #59
- systemd: .user(true) waits for a user manager that linger is starting by @flipbit03 in #61
Full Changelog: v0.5.0...v0.6.0
v0.5.0
What's Changed
- Check mode without predictions: Ansible's rule, no registry by @flipbit03 in #42
Full Changelog: v0.3.2...v0.5.0