mirror of
https://github.com/moghtech/komodo.git
synced 2026-07-10 19:48:09 -05:00
build webhook cancel build before triggering another - better behavior for back-to-back pushes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::{str::FromStr, sync::OnceLock};
|
||||
use std::{str::FromStr, sync::OnceLock, time::Duration};
|
||||
|
||||
use anyhow::{Context, anyhow};
|
||||
use komodo_client::{
|
||||
@@ -23,6 +23,7 @@ use crate::{
|
||||
},
|
||||
helpers::update::init_execution_update,
|
||||
resource,
|
||||
state::action_states,
|
||||
};
|
||||
|
||||
use super::{ANY_BRANCH, ListenerLockCache};
|
||||
@@ -37,11 +38,6 @@ impl super::CustomSecret for Build {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_locks() -> &'static ListenerLockCache {
|
||||
static BUILD_LOCKS: OnceLock<ListenerLockCache> = OnceLock::new();
|
||||
BUILD_LOCKS.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
pub async fn handle_build_webhook<B: super::ExtractBranch>(
|
||||
build: Build,
|
||||
body: String,
|
||||
@@ -50,12 +46,6 @@ pub async fn handle_build_webhook<B: super::ExtractBranch>(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Acquire and hold lock to make a task queue for
|
||||
// subsequent listener calls on same resource.
|
||||
// It would fail if we let it go through from action state busy.
|
||||
let lock = build_locks().get_or_insert_default(&build.id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
// Use the correct target branch when using linked repo.
|
||||
let branch = if build.config.linked_repo.is_empty() {
|
||||
build.config.branch
|
||||
@@ -69,13 +59,45 @@ pub async fn handle_build_webhook<B: super::ExtractBranch>(
|
||||
|
||||
B::verify_branch(&body, &branch)?;
|
||||
|
||||
// Cancel if currently building
|
||||
if action_states()
|
||||
.build
|
||||
.get(&build.id)
|
||||
.await
|
||||
.and_then(|states| {
|
||||
states.get().ok().map(|states| states.building)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
{
|
||||
let user = git_webhook_user().to_owned();
|
||||
let cancel = ExecuteRequest::CancelBuild(CancelBuild {
|
||||
build: build.id.clone(),
|
||||
});
|
||||
let update = init_execution_update(&cancel, &user).await?;
|
||||
let ExecuteRequest::CancelBuild(cancel) = cancel else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
cancel
|
||||
.resolve(&ExecuteArgs {
|
||||
user,
|
||||
update,
|
||||
task_id: Uuid::new_v4(),
|
||||
})
|
||||
.await
|
||||
.ok();
|
||||
|
||||
poll_build_until_cancelled(&build.id).await?;
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = ExecuteRequest::RunBuild(RunBuild { build: build.id });
|
||||
let update = init_execution_update(&req, &user).await?;
|
||||
let ExecuteRequest::RunBuild(req) = req else {
|
||||
let run = ExecuteRequest::RunBuild(RunBuild { build: build.id });
|
||||
let update = init_execution_update(&run, &user).await?;
|
||||
let ExecuteRequest::RunBuild(run) = run else {
|
||||
unreachable!()
|
||||
};
|
||||
req
|
||||
|
||||
run
|
||||
.resolve(&ExecuteArgs {
|
||||
user,
|
||||
update,
|
||||
@@ -83,9 +105,32 @@ pub async fn handle_build_webhook<B: super::ExtractBranch>(
|
||||
})
|
||||
.await
|
||||
.map_err(|e| e.error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn poll_build_until_cancelled(
|
||||
build_id: &String,
|
||||
) -> anyhow::Result<()> {
|
||||
let action_states = action_states();
|
||||
// Poll to ensure cancelled
|
||||
for _ in 0..10 {
|
||||
if !action_states
|
||||
.build
|
||||
.get(build_id)
|
||||
.await
|
||||
.and_then(|states| {
|
||||
states.get().ok().map(|states| states.building)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
Err(anyhow!("Build still running after cancel"))
|
||||
}
|
||||
|
||||
// ======
|
||||
// REPO
|
||||
// ======
|
||||
|
||||
Reference in New Issue
Block a user