Expose git-dir on push table for CI jobs
Thread the bare repo path through Runtime::new and set it as git-dir on
the push Lua table. ci.fnl uses GIT_DIR env var so git tag/push work
against the bare repo without a checkout.
Assisted-by: GLM-5.1 via pi
diff --git a/.quire/ci.fnl b/.quire/ci.fnl
index e60d38d..1b87cb7 100644
--- a/.quire/ci.fnl
+++ b/.quire/ci.fnl
@@ -3,7 +3,7 @@
(job :tag-and-mirror [:quire/push]
(fn [{: sh : secret : jobs}]
- (let [{: ref : sha} (jobs :quire/push)
+ (let [{: ref : sha : git-dir} (jobs :quire/push)
token (secret :github_token)]
(when (= ref "refs/heads/main")
(let [date (-> (sh "date --utc +%Y-%m-%d")
@@ -14,12 +14,13 @@
{:env {:T (.. "x-access-token:" token)}})
(. :stdout)
(: :gsub "\n$" ""))
- auth-header (.. "Authorization: Basic " encoded)]
- (sh [:git :tag tag sha])
+ auth-header (.. "Authorization: Basic " encoded)
+ git-opts {:env {:GIT_DIR git-dir}}]
+ (sh [:git :tag tag sha] git-opts)
(sh [:git
:-c
(.. :http.extraHeader= auth-header)
:push
:--porcelain
mirror-url
- (.. :refs/tags/ tag)]))))))
+ (.. :refs/tags/ tag)] git-opts))))))
diff --git a/src/bin/quire/commands/ci.rs b/src/bin/quire/commands/ci.rs
index 249dfcb..b1fac2e 100644
--- a/src/bin/quire/commands/ci.rs
+++ b/src/bin/quire/commands/ci.rs
@@ -44,7 +44,7 @@ pub async fn validate(maybe_sha: Option<&str>) -> Result<()> {
pub async fn run(quire: &Quire, maybe_sha: Option<&str>) -> Result<()> {
let repo_path = discover_repo()?;
let commit = resolve_commit(maybe_sha)?;
- let ci = Ci::new(repo_path);
+ let ci = Ci::new(repo_path.clone());
// Pull secrets from the global config; absence is fine for local
// testing. A broken-but-present config is a real error. Secrets
@@ -76,7 +76,7 @@ pub async fn run(quire: &Quire, maybe_sha: Option<&str>) -> Result<()> {
let run = runs.create(&meta)?;
println!("Run {}: executing at {}", run.id(), commit.display);
- let exec_result = run.execute(pipeline, secrets);
+ let exec_result = run.execute(pipeline, secrets, &repo_path);
match exec_result {
Ok(outputs) => {
diff --git a/src/ci/lua.rs b/src/ci/lua.rs
index c402096..5acba22 100644
--- a/src/ci/lua.rs
+++ b/src/ci/lua.rs
@@ -139,6 +139,7 @@ impl Runtime {
pipeline: super::pipeline::Pipeline,
secrets: HashMap<String, SecretString>,
meta: &super::run::RunMeta,
+ git_dir: &std::path::Path,
) -> Self {
let transitive = pipeline.transitive_inputs();
let lua = pipeline.fennel().lua();
@@ -149,6 +150,8 @@ impl Runtime {
push.set("ref", meta.r#ref.as_str()).expect("set ref");
push.set("pushed-at", meta.pushed_at.to_string().as_str())
.expect("set pushed-at");
+ push.set("git-dir", git_dir.to_string_lossy().as_ref())
+ .expect("set git-dir");
let push_value = push.into_lua(lua).expect("push table to value");
// Build per-job input views from transitive reachability.
diff --git a/src/ci/mod.rs b/src/ci/mod.rs
index 8c4931d..6faa8bc 100644
--- a/src/ci/mod.rs
+++ b/src/ci/mod.rs
@@ -170,7 +170,7 @@ fn trigger_ref(
}
};
- run.execute(pipeline, secrets.clone())?;
+ run.execute(pipeline, secrets.clone(), &repo.path())?;
Ok(())
}
diff --git a/src/ci/run.rs b/src/ci/run.rs
index 3d4453e..7167ed3 100644
--- a/src/ci/run.rs
+++ b/src/ci/run.rs
@@ -269,10 +269,11 @@ impl Run {
mut self,
pipeline: Pipeline,
secrets: HashMap<String, SecretString>,
+ git_dir: &std::path::Path,
) -> Result<HashMap<String, Vec<ShOutput>>> {
let meta = self.read_meta()?;
- let runtime = Rc::new(Runtime::new(pipeline, secrets, &meta));
+ let runtime = Rc::new(Runtime::new(pipeline, secrets, &meta, git_dir));
let lua = runtime.lua();
let rt_value = RuntimeHandle(runtime.clone())
@@ -760,7 +761,9 @@ mod tests {
);
let run_id = run.id().to_string();
- let outputs = run.execute(pipeline, HashMap::new()).expect("execute");
+ let outputs = run
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
+ .expect("execute");
// Verify the run landed in complete/ on disk.
let completed = runs.base.join(RunState::Complete.dir_name()).join(&run_id);
@@ -792,7 +795,8 @@ mod tests {
);
let pipeline = load(&source);
- run.execute(pipeline, HashMap::new()).expect("execute");
+ run.execute(pipeline, HashMap::new(), std::path::Path::new("."))
+ .expect("execute");
let contents = fs_err::read_to_string(&log).expect("read log");
assert_eq!(contents, "a\nb\n");
@@ -812,7 +816,7 @@ mod tests {
let run_id = run.id().to_string();
let err = run
- .execute(pipeline, HashMap::new())
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
.expect_err("expected failure");
assert!(matches!(err, Error::JobFailed { ref job, .. } if job == "a"));
@@ -835,7 +839,9 @@ mod tests {
(sh ["echo" push.sha push.ref]))))"#,
);
- let outputs = run.execute(pipeline, HashMap::new()).expect("execute");
+ let outputs = run
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
+ .expect("execute");
let grab = &outputs["grab"];
assert_eq!(grab.len(), 1);
@@ -859,7 +865,9 @@ mod tests {
(sh ["echo" push.sha]))))"#,
);
- let outputs = run.execute(pipeline, HashMap::new()).expect("execute");
+ let outputs = run
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
+ .expect("execute");
let b = &outputs["b"];
assert_eq!(b.len(), 1);
@@ -878,7 +886,7 @@ mod tests {
);
let err = run
- .execute(pipeline, HashMap::new())
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
.expect_err("expected failure");
let Error::JobFailed { job, source } = err else {
unreachable!()
@@ -905,7 +913,7 @@ mod tests {
);
let err = run
- .execute(pipeline, HashMap::new())
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
.expect_err("expected failure");
let Error::JobFailed { source, .. } = err else {
unreachable!()
@@ -929,7 +937,7 @@ mod tests {
);
let err = run
- .execute(pipeline, HashMap::new())
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
.expect_err("expected failure");
let Error::JobFailed { source, .. } = err else {
unreachable!()
@@ -957,7 +965,9 @@ mod tests {
(sh ["echo" (tostring a-outputs)]))))"#,
);
- let outputs = run.execute(pipeline, HashMap::new()).expect("execute");
+ let outputs = run
+ .execute(pipeline, HashMap::new(), std::path::Path::new("."))
+ .expect("execute");
let b = &outputs["b"];
assert_eq!(b.len(), 1);
assert_eq!(b[0].stdout, "nil\n");
@@ -975,7 +985,8 @@ mod tests {
);
let run_id = run.id().to_string();
- run.execute(pipeline, HashMap::new()).expect("execute");
+ run.execute(pipeline, HashMap::new(), std::path::Path::new("."))
+ .expect("execute");
let log_path = runs
.base
@@ -1010,7 +1021,7 @@ mod tests {
);
let run_id = run.id().to_string();
- let _ = run.execute(pipeline, HashMap::new());
+ let _ = run.execute(pipeline, HashMap::new(), std::path::Path::new("."));
let failed_dir = runs.base.join(RunState::Failed.dir_name()).join(&run_id);
assert!(failed_dir.exists(), "run should be in failed/");