mirror of
https://codeberg.org/Toasterson/solstice-ci.git
synced 2026-04-10 21:30:41 +00:00
Atomically upload runner via SFTP to ensure safe file replacement; bump version to 0.1.11
- Refactor runner upload logic to use temporary files and atomic renaming for safer updates. - Improve file permission handling during temporary file creation. - Increment orchestrator version to 0.1.11. Signed-off-by: Till Wegmueller <toasterson@gmail.com>
This commit is contained in:
parent
b36e5c70a8
commit
20a0efd116
2 changed files with 17 additions and 6 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "orchestrator"
|
name = "orchestrator"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -599,22 +599,33 @@ async fn run_job_via_ssh_owned(
|
||||||
if !sess.authenticated() {
|
if !sess.authenticated() {
|
||||||
return Err(miette::miette!("ssh not authenticated"));
|
return Err(miette::miette!("ssh not authenticated"));
|
||||||
}
|
}
|
||||||
// Upload runner via SFTP
|
// Upload runner via SFTP atomically: write to temp, close, then rename over final path
|
||||||
let sftp = sess.sftp().map_err(OrchestratorError::SftpInit).into_diagnostic()?;
|
let sftp = sess.sftp().map_err(OrchestratorError::SftpInit).into_diagnostic()?;
|
||||||
let mut local = StdFile::open(&local_runner)
|
let mut local = StdFile::open(&local_runner)
|
||||||
.map_err(OrchestratorError::OpenLocalRunner)
|
.map_err(OrchestratorError::OpenLocalRunner)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
local.read_to_end(&mut buf).map_err(OrchestratorError::ReadRunner).into_diagnostic()?;
|
local.read_to_end(&mut buf).map_err(OrchestratorError::ReadRunner).into_diagnostic()?;
|
||||||
let mut remote = sftp.create(&remote_path)
|
// Temp remote path
|
||||||
|
let tmp_remote = {
|
||||||
|
let mut p = remote_path.clone();
|
||||||
|
let tmp_name = format!("{}.tmp", p.file_name().and_then(|s| s.to_str()).unwrap_or("solstice-runner"));
|
||||||
|
p.set_file_name(tmp_name);
|
||||||
|
p
|
||||||
|
};
|
||||||
|
let mut remote_tmp = sftp.create(&tmp_remote)
|
||||||
.map_err(OrchestratorError::SftpCreate)
|
.map_err(OrchestratorError::SftpCreate)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
remote.write_all(&buf)
|
remote_tmp.write_all(&buf)
|
||||||
.map_err(OrchestratorError::SftpWrite)
|
.map_err(OrchestratorError::SftpWrite)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
let remote_file_stat = ssh2::FileStat { size: None, uid: None, gid: None, perm: Some(0o755), atime: None, mtime: None };
|
let tmp_file_stat = ssh2::FileStat { size: None, uid: None, gid: None, perm: Some(0o755), atime: None, mtime: None };
|
||||||
let _ = sftp.setstat(&remote_path, remote_file_stat);
|
let _ = sftp.setstat(&tmp_remote, tmp_file_stat);
|
||||||
|
// Ensure remote file handle is closed before attempting exec/rename
|
||||||
|
drop(remote_tmp);
|
||||||
|
// Rename temp to final atomically; overwrite if exists
|
||||||
|
let _ = sftp.rename(&tmp_remote, &remote_path, Some(ssh2::RenameFlags::OVERWRITE));
|
||||||
|
|
||||||
// Build command
|
// Build command
|
||||||
let cmd = format!(
|
let cmd = format!(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue