Replace repo_config() with mirror_url() directly on Repo
The RepoConfig/RepoGithubConfig intermediate structs only ever served
one consumer (mirror.rs) and one field (github.mirror). Replace them
with Repo::mirror_url(sha) -> AppResult<Option<String>> that reads the
config inline with private structs, keeping the public API minimal.
https://claude.ai/code/session_01MtUMXi7Z3GCDWQFY8puWpu
diff --git a/quire-server/src/mirror.rs b/quire-server/src/mirror.rs
index e1b52f7..35302d7 100644
--- a/quire-server/src/mirror.rs
+++ b/quire-server/src/mirror.rs
@@ -31,8 +31,9 @@ pub fn trigger(quire: &Quire, event: &PushEvent) -> crate::Result<()> {
.transpose()?;
for push_ref in event.updated_refs() {
- let repo_config = match repo.repo_config(&push_ref.new_sha) {
- Ok(c) => c,
+ let mirror_url = match repo.mirror_url(&push_ref.new_sha) {
+ Ok(Some(url)) => url,
+ Ok(None) => continue,
Err(e) => {
tracing::warn!(
ref_name = %push_ref.ref_name,
@@ -44,10 +45,6 @@ pub fn trigger(quire: &Quire, event: &PushEvent) -> crate::Result<()> {
}
};
- let Some(mirror_url) = repo_config.github.mirror else {
- continue;
- };
-
let Some(token) = mirror_token.as_deref() else {
tracing::warn!(
ref_name = %push_ref.ref_name,
diff --git a/quire-server/src/quire/mod.rs b/quire-server/src/quire/mod.rs
index 0907f56..8aaba98 100644
--- a/quire-server/src/quire/mod.rs
+++ b/quire-server/src/quire/mod.rs
@@ -156,10 +156,21 @@ impl Repo {
Ci::new(self.path())
}
- /// Read and parse `.quire/config.fnl` at the given commit SHA.
+ /// Read `github.mirror` URL from `.quire/config.fnl` at the given commit SHA.
///
- /// Returns defaults if the file does not exist at that commit.
- pub fn repo_config(&self, sha: &str) -> AppResult<RepoConfig> {
+ /// Returns `None` if unconfigured or the file does not exist at that commit.
+ pub fn mirror_url(&self, sha: &str) -> AppResult<Option<String>> {
+ #[derive(serde::Deserialize, Default)]
+ #[serde(default, rename_all = "kebab-case")]
+ struct Config {
+ github: Github,
+ }
+ #[derive(serde::Deserialize, Default)]
+ #[serde(default, rename_all = "kebab-case")]
+ struct Github {
+ mirror: Option<String>,
+ }
+
let output = self
.git(&["show", &format!("{sha}:.quire/config.fnl")])
.stdout(std::process::Stdio::piped())
@@ -169,7 +180,7 @@ impl Repo {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("does not exist") || stderr.contains("not found") {
- return Ok(RepoConfig::default());
+ return Ok(None);
}
return Err(Error::Io(std::io::Error::other(format!(
"failed to read .quire/config.fnl at {sha}: {stderr}"
@@ -177,7 +188,8 @@ impl Repo {
}
let source = String::from_utf8(output.stdout)?;
- Ok(Fennel::new()?.load_string(&source, ".quire/config.fnl")?)
+ let cfg: Config = Fennel::new()?.load_string(&source, ".quire/config.fnl")?;
+ Ok(cfg.github.mirror)
}
/// The base directory for CI runs (`runs/<repo>/`).
@@ -195,22 +207,6 @@ impl Repo {
}
}
-/// Per-repo CI configuration parsed from `.quire/config.fnl`.
-#[derive(serde::Deserialize, Debug, Default, Clone)]
-#[serde(default, rename_all = "kebab-case")]
-pub struct RepoConfig {
- pub github: RepoGithubConfig,
-}
-
-/// Per-repo GitHub configuration.
-#[derive(serde::Deserialize, Debug, Default, Clone)]
-#[serde(default, rename_all = "kebab-case")]
-pub struct RepoGithubConfig {
- /// Remote URL to mirror every pushed ref to.
- /// E.g. `"https://github.com/user/repo.git"`.
- pub mirror: Option<String>,
-}
-
/// Application runtime context.
///
/// Carries configuration and provides resolved paths to repositories.