dashboard: diff against applied/proposal/<id>, prefer fetched_sha

approval_diff now runs git diff refs/heads/main..refs/tags/
proposal/<id> against the applied repo instead of cobbling a
single-file diff from proposed. consequences: multi-file
proposals show every change, manager amendments in proposed
cannot lie about what'll be deployed, no-op proposals render
an explicit '(proposal matches currently-deployed tree)'.
displayed sha prefers fetched_sha (hive-c0re-vouched) and
falls back to commit_ref only for the brief pre-fetch window.
unified_diff helper + similar dep dropped — git diff is the
source of truth now. dead-code allows on the lifecycle git
helpers + approvals.set_fetched_sha come off since all are
wired up. readme picks up the tag flow + /applied RO mount.
This commit is contained in:
müde 2026-05-15 23:18:17 +02:00
parent fc61cb9310
commit e26143a412
6 changed files with 42 additions and 55 deletions

View file

@ -475,7 +475,6 @@ async fn git(dir: &Path, args: &[&str]) -> Result<()> {
/// amendments / force-pushes in `src` no longer affect what gets
/// built. Returns the resolved sha (which equals `sha` on success
/// but normalised — short shas get expanded).
#[allow(dead_code)] // wired up by manager_server in a later commit
pub async fn git_fetch_to_tag(dst: &Path, src: &Path, sha: &str, tag: &str) -> Result<String> {
let src_str = src.display().to_string();
let refspec = format!("{sha}:refs/tags/{tag}");
@ -484,7 +483,6 @@ pub async fn git_fetch_to_tag(dst: &Path, src: &Path, sha: &str, tag: &str) -> R
}
/// Resolve `refname` (a tag, branch, or sha) in `dir` to its full sha.
#[allow(dead_code)]
pub async fn git_rev_parse(dir: &Path, refname: &str) -> Result<String> {
let out = git_command()
.current_dir(dir)
@ -505,7 +503,6 @@ pub async fn git_rev_parse(dir: &Path, refname: &str) -> Result<String> {
/// Plant a lightweight tag at `target`. Errors if the tag already
/// exists — we want loud failures on id reuse, not silent
/// overwrites.
#[allow(dead_code)]
pub async fn git_tag(dir: &Path, name: &str, target: &str) -> Result<()> {
git(dir, &["tag", name, target]).await
}
@ -514,7 +511,6 @@ pub async fn git_tag(dir: &Path, name: &str, target: &str) -> Result<()> {
/// `failed/<id>` (body = build error) and `denied/<id>` (body =
/// operator note). Multi-line bodies handled via stdin so we don't
/// have to escape anything.
#[allow(dead_code)]
pub async fn git_tag_annotated(dir: &Path, name: &str, target: &str, body: &str) -> Result<()> {
use tokio::io::AsyncWriteExt;
let mut child = git_command()
@ -549,7 +545,6 @@ pub async fn git_tag_annotated(dir: &Path, name: &str, target: &str, body: &str)
/// `deployed/*` while we let `nixos-container update` evaluate the
/// candidate. On build failure callers reset back to HEAD; on
/// success they fast-forward main to `target`.
#[allow(dead_code)]
pub async fn git_read_tree_reset(dir: &Path, target: &str) -> Result<()> {
git(dir, &["read-tree", "--reset", "-u", target]).await
}
@ -557,7 +552,6 @@ pub async fn git_read_tree_reset(dir: &Path, target: &str) -> Result<()> {
/// Hard-set a ref to `target`. Used to fast-forward `refs/heads/main`
/// to the just-deployed proposal commit. Uses `update-ref`, not
/// `branch -f`, so it works regardless of where HEAD currently sits.
#[allow(dead_code)]
pub async fn git_update_ref(dir: &Path, refname: &str, target: &str) -> Result<()> {
git(dir, &["update-ref", refname, target]).await
}