mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-04 16:00:59 +00:00
provide custom webhook secret to all resources which take webhooks
This commit is contained in:
@@ -216,6 +216,12 @@ impl Resolve<CreateBuildWebhook, User> for State {
|
||||
..
|
||||
} = core_config();
|
||||
|
||||
let webhook_secret = if build.config.webhook_secret.is_empty() {
|
||||
webhook_secret
|
||||
} else {
|
||||
&build.config.webhook_secret
|
||||
};
|
||||
|
||||
let host = webhook_base_url.as_ref().unwrap_or(host);
|
||||
let url = format!("{host}/listener/github/build/{}", build.id);
|
||||
|
||||
|
||||
@@ -217,6 +217,12 @@ impl Resolve<CreateRepoWebhook, User> for State {
|
||||
..
|
||||
} = core_config();
|
||||
|
||||
let webhook_secret = if repo.config.webhook_secret.is_empty() {
|
||||
webhook_secret
|
||||
} else {
|
||||
&repo.config.webhook_secret
|
||||
};
|
||||
|
||||
let host = webhook_base_url.as_ref().unwrap_or(host);
|
||||
let url = match action {
|
||||
RepoWebhookAction::Clone => {
|
||||
|
||||
@@ -348,6 +348,12 @@ impl Resolve<CreateStackWebhook, User> for State {
|
||||
..
|
||||
} = core_config();
|
||||
|
||||
let webhook_secret = if stack.config.webhook_secret.is_empty() {
|
||||
webhook_secret
|
||||
} else {
|
||||
&stack.config.webhook_secret
|
||||
};
|
||||
|
||||
let host = webhook_base_url.as_ref().unwrap_or(host);
|
||||
let url = match action {
|
||||
StackWebhookAction::Refresh => {
|
||||
|
||||
@@ -105,7 +105,11 @@ impl Resolve<UpdateResourceSync, User> for State {
|
||||
}
|
||||
|
||||
impl Resolve<RefreshResourceSyncPending, User> for State {
|
||||
#[instrument(name = "RefreshResourceSyncPending", level = "debug", skip(self, user))]
|
||||
#[instrument(
|
||||
name = "RefreshResourceSyncPending",
|
||||
level = "debug",
|
||||
skip(self, user)
|
||||
)]
|
||||
async fn resolve(
|
||||
&self,
|
||||
RefreshResourceSyncPending { sync }: RefreshResourceSyncPending,
|
||||
@@ -420,6 +424,12 @@ impl Resolve<CreateSyncWebhook, User> for State {
|
||||
..
|
||||
} = core_config();
|
||||
|
||||
let webhook_secret = if sync.config.webhook_secret.is_empty() {
|
||||
webhook_secret
|
||||
} else {
|
||||
&sync.config.webhook_secret
|
||||
};
|
||||
|
||||
let host = webhook_base_url.as_ref().unwrap_or(host);
|
||||
let url = match action {
|
||||
SyncWebhookAction::Refresh => {
|
||||
|
||||
@@ -31,15 +31,20 @@ pub async fn handle_build_webhook(
|
||||
let lock = build_locks().get_or_insert_default(&build_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let build = resource::get::<Build>(&build_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &build.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !build.config.webhook_enabled {
|
||||
return Err(anyhow!("build does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != build.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = ExecuteRequest::RunBuild(RunBuild { build: build_id });
|
||||
let update = init_execution_update(&req, &user).await?;
|
||||
|
||||
@@ -216,6 +216,7 @@ pub fn router() -> Router {
|
||||
async fn verify_gh_signature(
|
||||
headers: HeaderMap,
|
||||
body: &str,
|
||||
custom_secret: &str,
|
||||
) -> anyhow::Result<()> {
|
||||
// wait random amount of time
|
||||
tokio::time::sleep(random_duration(0, 500)).await;
|
||||
@@ -229,10 +230,13 @@ async fn verify_gh_signature(
|
||||
return Err(anyhow!("failed to unwrap signature"));
|
||||
}
|
||||
let signature = signature.unwrap().replace("sha256=", "");
|
||||
let mut mac = HmacSha256::new_from_slice(
|
||||
core_config().webhook_secret.as_bytes(),
|
||||
)
|
||||
.expect("github webhook | failed to create hmac sha256");
|
||||
let secret_bytes = if custom_secret.is_empty() {
|
||||
core_config().webhook_secret.as_bytes()
|
||||
} else {
|
||||
custom_secret.as_bytes()
|
||||
};
|
||||
let mut mac = HmacSha256::new_from_slice(secret_bytes)
|
||||
.expect("github webhook | failed to create hmac sha256");
|
||||
mac.update(body.as_bytes());
|
||||
let expected = mac.finalize().into_bytes().encode_hex::<String>();
|
||||
if signature == expected {
|
||||
|
||||
@@ -33,15 +33,24 @@ pub async fn handle_procedure_webhook(
|
||||
procedure_locks().get_or_insert_default(&procedure_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let procedure = resource::get::<Procedure>(&procedure_id).await?;
|
||||
|
||||
verify_gh_signature(
|
||||
headers,
|
||||
&body,
|
||||
&procedure.config.webhook_secret,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if !procedure.config.webhook_enabled {
|
||||
return Err(anyhow!("procedure does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != target_branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
let procedure = resource::get::<Procedure>(&procedure_id).await?;
|
||||
if !procedure.config.webhook_enabled {
|
||||
return Err(anyhow!("procedure does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = ExecuteRequest::RunProcedure(RunProcedure {
|
||||
procedure: procedure_id,
|
||||
|
||||
@@ -30,15 +30,20 @@ pub async fn handle_repo_clone_webhook(
|
||||
let lock = repo_locks().get_or_insert_default(&repo_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let repo = resource::get::<Repo>(&repo_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &repo.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !repo.config.webhook_enabled {
|
||||
return Err(anyhow!("repo does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != repo.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req =
|
||||
crate::api::execute::ExecuteRequest::CloneRepo(CloneRepo {
|
||||
@@ -64,15 +69,20 @@ pub async fn handle_repo_pull_webhook(
|
||||
let lock = repo_locks().get_or_insert_default(&repo_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let repo = resource::get::<Repo>(&repo_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &repo.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !repo.config.webhook_enabled {
|
||||
return Err(anyhow!("repo does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != repo.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = crate::api::execute::ExecuteRequest::PullRepo(PullRepo {
|
||||
repo: repo_id,
|
||||
@@ -96,23 +106,30 @@ pub async fn handle_repo_build_webhook(
|
||||
let lock = repo_locks().get_or_insert_default(&repo_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let repo = resource::get::<Repo>(&repo_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &repo.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !repo.config.webhook_enabled {
|
||||
return Err(anyhow!("repo does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != repo.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = crate::api::execute::ExecuteRequest::BuildRepo(BuildRepo {
|
||||
repo: repo_id,
|
||||
});
|
||||
let req =
|
||||
crate::api::execute::ExecuteRequest::BuildRepo(BuildRepo {
|
||||
repo: repo_id,
|
||||
});
|
||||
let update = init_execution_update(&req, &user).await?;
|
||||
let crate::api::execute::ExecuteRequest::BuildRepo(req) = req else {
|
||||
let crate::api::execute::ExecuteRequest::BuildRepo(req) = req
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
State.resolve(req, (user, update)).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,15 +31,20 @@ pub async fn handle_stack_refresh_webhook(
|
||||
let lock = stack_locks().get_or_insert_default(&stack_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let stack = resource::get::<Stack>(&stack_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &stack.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !stack.config.webhook_enabled {
|
||||
return Err(anyhow!("stack does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != stack.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
State
|
||||
.resolve(RefreshStackCache { stack: stack.id }, user)
|
||||
@@ -58,15 +63,20 @@ pub async fn handle_stack_deploy_webhook(
|
||||
let lock = stack_locks().get_or_insert_default(&stack_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let stack = resource::get::<Stack>(&stack_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &stack.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !stack.config.webhook_enabled {
|
||||
return Err(anyhow!("stack does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != stack.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = ExecuteRequest::DeployStack(DeployStack {
|
||||
stack: stack_id,
|
||||
|
||||
@@ -31,15 +31,20 @@ pub async fn handle_sync_refresh_webhook(
|
||||
let lock = sync_locks().get_or_insert_default(&sync_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let sync = resource::get::<ResourceSync>(&sync_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &sync.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !sync.config.webhook_enabled {
|
||||
return Err(anyhow!("sync does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != sync.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
State
|
||||
.resolve(RefreshResourceSyncPending { sync: sync_id }, user)
|
||||
@@ -58,15 +63,20 @@ pub async fn handle_sync_execute_webhook(
|
||||
let lock = sync_locks().get_or_insert_default(&sync_id).await;
|
||||
let _lock = lock.lock().await;
|
||||
|
||||
verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let sync = resource::get::<ResourceSync>(&sync_id).await?;
|
||||
|
||||
verify_gh_signature(headers, &body, &sync.config.webhook_secret)
|
||||
.await?;
|
||||
|
||||
if !sync.config.webhook_enabled {
|
||||
return Err(anyhow!("sync does not have webhook enabled"));
|
||||
}
|
||||
|
||||
let request_branch = extract_branch(&body)?;
|
||||
if request_branch != sync.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
|
||||
let user = git_webhook_user().to_owned();
|
||||
let req = ExecuteRequest::RunSync(RunSync { sync: sync_id });
|
||||
let update = init_execution_update(&req, &user).await?;
|
||||
|
||||
@@ -243,6 +243,7 @@ impl TryFrom<Build> for monitor_client::entities::build::Build {
|
||||
use_buildx,
|
||||
labels: Default::default(),
|
||||
webhook_enabled: true,
|
||||
webhook_secret: Default::default(),
|
||||
commit: Default::default(),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -163,6 +163,7 @@ impl From<BuildConfig>
|
||||
extra_args: value.extra_args,
|
||||
use_buildx: value.use_buildx,
|
||||
webhook_enabled: value.webhook_enabled,
|
||||
webhook_secret: Default::default(),
|
||||
image_registry: value.image_registry.into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +157,7 @@ impl From<BuildConfig>
|
||||
})
|
||||
},
|
||||
webhook_enabled: value.webhook_enabled,
|
||||
webhook_secret: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ Users will have to manage their own versioning though.
|
||||
- **Sync**: Sync resources declared in toml files in Github repos.
|
||||
- Manage resources declaratively, with git history for configuration rollbacks.
|
||||
- See the actions which will be performed in the UI, and execute them upon manual confirmation.
|
||||
- Use a Github webhook to automatically execute syncs on git push.
|
||||
- Use a Git webhook to automatically execute syncs on git push.
|
||||
|
||||
- **Resource Tagging**
|
||||
- Attach multiple *tags* to resources, which can be used to group related resources together. These can be used to filter resources in the UI.
|
||||
|
||||
@@ -127,6 +127,15 @@ pub struct BuildConfig {
|
||||
#[partial_default(default_git_https())]
|
||||
pub git_https: bool,
|
||||
|
||||
/// The git account used to access private repos.
|
||||
/// Passing empty string can only clone public repos.
|
||||
///
|
||||
/// Note. A token for the account must be available in the core config or the builder server's periphery config
|
||||
/// for the configured git provider.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub git_account: String,
|
||||
|
||||
/// The repo used as the source of the build.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
@@ -143,14 +152,17 @@ pub struct BuildConfig {
|
||||
#[builder(default)]
|
||||
pub commit: String,
|
||||
|
||||
/// The git account used to access private repos.
|
||||
/// Passing empty string can only clone public repos.
|
||||
///
|
||||
/// Note. A token for the account must be available in the core config or the builder server's periphery config
|
||||
/// for the configured git provider.
|
||||
/// Whether incoming webhooks actually trigger action.
|
||||
#[serde(default = "default_webhook_enabled")]
|
||||
#[builder(default = "default_webhook_enabled()")]
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
|
||||
/// Optionally provide an alternate webhook secret for this build.
|
||||
/// If its an empty string, use the default secret from the config.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub git_account: String,
|
||||
pub webhook_secret: String,
|
||||
|
||||
/// The optional command run after repo clone and before docker build.
|
||||
#[serde(default)]
|
||||
@@ -185,12 +197,6 @@ pub struct BuildConfig {
|
||||
#[builder(default)]
|
||||
pub use_buildx: bool,
|
||||
|
||||
/// Whether incoming webhooks actually trigger action.
|
||||
#[serde(default = "default_webhook_enabled")]
|
||||
#[builder(default = "default_webhook_enabled()")]
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
|
||||
/// Any extra docker cli arguments to be included in the build command
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
@@ -298,6 +304,7 @@ impl Default for BuildConfig {
|
||||
use_buildx: Default::default(),
|
||||
image_registry: Default::default(),
|
||||
webhook_enabled: default_webhook_enabled(),
|
||||
webhook_secret: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,12 @@ pub struct ProcedureConfig {
|
||||
#[builder(default = "default_webhook_enabled()")]
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
|
||||
/// Optionally provide an alternate webhook secret for this procedure.
|
||||
/// If its an empty string, use the default secret from the config.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub webhook_secret: String,
|
||||
}
|
||||
|
||||
impl ProcedureConfig {
|
||||
@@ -83,6 +89,7 @@ impl Default for ProcedureConfig {
|
||||
Self {
|
||||
stages: Default::default(),
|
||||
webhook_enabled: default_webhook_enabled(),
|
||||
webhook_secret: Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,23 @@ pub struct RepoConfig {
|
||||
#[partial_default(default_git_provider())]
|
||||
pub git_provider: String,
|
||||
|
||||
/// Whether to use https to clone the repo (versus http). Default: true
|
||||
///
|
||||
/// Note. Monitor does not currently support cloning repos via ssh.
|
||||
#[serde(default = "default_git_https")]
|
||||
#[builder(default = "default_git_https()")]
|
||||
#[partial_default(default_git_https())]
|
||||
pub git_https: bool,
|
||||
|
||||
/// The git account used to access private repos.
|
||||
/// Passing empty string can only clone public repos.
|
||||
///
|
||||
/// Note. A token for the account must be available in the core config or the builder server's periphery config
|
||||
/// for the configured git provider.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub git_account: String,
|
||||
|
||||
/// The github repo to clone.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
@@ -127,28 +144,23 @@ pub struct RepoConfig {
|
||||
#[builder(default)]
|
||||
pub commit: String,
|
||||
|
||||
/// The git account used to access private repos.
|
||||
/// Passing empty string can only clone public repos.
|
||||
///
|
||||
/// Note. A token for the account must be available in the core config or the builder server's periphery config
|
||||
/// for the configured git provider.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub git_account: String,
|
||||
|
||||
/// Whether to use https to clone the repo (versus http). Default: true
|
||||
///
|
||||
/// Note. Monitor does not currently support cloning repos via ssh.
|
||||
#[serde(default = "default_git_https")]
|
||||
#[builder(default = "default_git_https()")]
|
||||
#[partial_default(default_git_https())]
|
||||
pub git_https: bool,
|
||||
|
||||
/// Explicitly specify the folder to clone the repo in.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub path: String,
|
||||
|
||||
/// Whether incoming webhooks actually trigger action.
|
||||
#[serde(default = "default_webhook_enabled")]
|
||||
#[builder(default = "default_webhook_enabled()")]
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
|
||||
/// Optionally provide an alternate webhook secret for this repo.
|
||||
/// If its an empty string, use the default secret from the config.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub webhook_secret: String,
|
||||
|
||||
/// Command to be run after the repo is cloned.
|
||||
/// The path is relative to the root of the repo.
|
||||
#[serde(default)]
|
||||
@@ -189,12 +201,6 @@ pub struct RepoConfig {
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub skip_secret_interp: bool,
|
||||
|
||||
/// Whether incoming webhooks actually trigger action.
|
||||
#[serde(default = "default_webhook_enabled")]
|
||||
#[builder(default = "default_webhook_enabled()")]
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
}
|
||||
|
||||
impl RepoConfig {
|
||||
@@ -241,6 +247,7 @@ impl Default for RepoConfig {
|
||||
env_file_path: default_env_file_path(),
|
||||
skip_secret_interp: Default::default(),
|
||||
webhook_enabled: default_webhook_enabled(),
|
||||
webhook_secret: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +358,12 @@ pub struct StackConfig {
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
|
||||
/// Optionally provide an alternate webhook secret for this stack.
|
||||
/// If its an empty string, use the default secret from the config.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub webhook_secret: String,
|
||||
|
||||
/// Whether to send StackStateChange alerts for this stack.
|
||||
#[serde(default = "default_send_alerts")]
|
||||
#[builder(default = "default_send_alerts()")]
|
||||
@@ -421,6 +427,7 @@ impl Default for StackConfig {
|
||||
commit: Default::default(),
|
||||
git_account: Default::default(),
|
||||
webhook_enabled: default_webhook_enabled(),
|
||||
webhook_secret: Default::default(),
|
||||
send_alerts: default_send_alerts(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,12 @@ pub struct ResourceSyncConfig {
|
||||
#[builder(default = "default_webhook_enabled()")]
|
||||
#[partial_default(default_webhook_enabled())]
|
||||
pub webhook_enabled: bool,
|
||||
|
||||
/// Optionally provide an alternate webhook secret for this sync.
|
||||
/// If its an empty string, use the default secret from the config.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub webhook_secret: String,
|
||||
}
|
||||
|
||||
impl ResourceSyncConfig {
|
||||
@@ -280,6 +286,7 @@ impl Default for ResourceSyncConfig {
|
||||
resource_path: default_resource_path(),
|
||||
delete: Default::default(),
|
||||
webhook_enabled: default_webhook_enabled(),
|
||||
webhook_secret: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
-22
@@ -401,12 +401,6 @@ export interface BuildConfig {
|
||||
* Note. Monitor does not currently support cloning repos via ssh.
|
||||
*/
|
||||
git_https: boolean;
|
||||
/** The repo used as the source of the build. */
|
||||
repo?: string;
|
||||
/** The branch of the repo. */
|
||||
branch: string;
|
||||
/** Optionally set a specific commit hash. */
|
||||
commit?: string;
|
||||
/**
|
||||
* The git account used to access private repos.
|
||||
* Passing empty string can only clone public repos.
|
||||
@@ -415,6 +409,19 @@ export interface BuildConfig {
|
||||
* for the configured git provider.
|
||||
*/
|
||||
git_account?: string;
|
||||
/** The repo used as the source of the build. */
|
||||
repo?: string;
|
||||
/** The branch of the repo. */
|
||||
branch: string;
|
||||
/** Optionally set a specific commit hash. */
|
||||
commit?: string;
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
/**
|
||||
* Optionally provide an alternate webhook secret for this build.
|
||||
* If its an empty string, use the default secret from the config.
|
||||
*/
|
||||
webhook_secret?: string;
|
||||
/** The optional command run after repo clone and before docker build. */
|
||||
pre_build?: SystemCommand;
|
||||
/** Configuration for the registry to push the built image to. */
|
||||
@@ -430,8 +437,6 @@ export interface BuildConfig {
|
||||
skip_secret_interp?: boolean;
|
||||
/** Whether to use buildx to build (eg `docker buildx build ...`) */
|
||||
use_buildx?: boolean;
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
/** Any extra docker cli arguments to be included in the build command */
|
||||
extra_args?: string[];
|
||||
/**
|
||||
@@ -871,6 +876,11 @@ export interface ProcedureConfig {
|
||||
stages?: ProcedureStage[];
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
/**
|
||||
* Optionally provide an alternate webhook secret for this procedure.
|
||||
* If its an empty string, use the default secret from the config.
|
||||
*/
|
||||
webhook_secret?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -980,12 +990,12 @@ export interface RepoConfig {
|
||||
builder_id?: string;
|
||||
/** The git provider domain. Default: github.com */
|
||||
git_provider: string;
|
||||
/** The github repo to clone. */
|
||||
repo?: string;
|
||||
/** The repo branch. */
|
||||
branch: string;
|
||||
/** Optionally set a specific commit hash. */
|
||||
commit?: string;
|
||||
/**
|
||||
* Whether to use https to clone the repo (versus http). Default: true
|
||||
*
|
||||
* Note. Monitor does not currently support cloning repos via ssh.
|
||||
*/
|
||||
git_https: boolean;
|
||||
/**
|
||||
* The git account used to access private repos.
|
||||
* Passing empty string can only clone public repos.
|
||||
@@ -994,14 +1004,21 @@ export interface RepoConfig {
|
||||
* for the configured git provider.
|
||||
*/
|
||||
git_account?: string;
|
||||
/**
|
||||
* Whether to use https to clone the repo (versus http). Default: true
|
||||
*
|
||||
* Note. Monitor does not currently support cloning repos via ssh.
|
||||
*/
|
||||
git_https: boolean;
|
||||
/** The github repo to clone. */
|
||||
repo?: string;
|
||||
/** The repo branch. */
|
||||
branch: string;
|
||||
/** Optionally set a specific commit hash. */
|
||||
commit?: string;
|
||||
/** Explicitly specify the folder to clone the repo in. */
|
||||
path?: string;
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
/**
|
||||
* Optionally provide an alternate webhook secret for this repo.
|
||||
* If its an empty string, use the default secret from the config.
|
||||
*/
|
||||
webhook_secret?: string;
|
||||
/**
|
||||
* Command to be run after the repo is cloned.
|
||||
* The path is relative to the root of the repo.
|
||||
@@ -1028,8 +1045,6 @@ export interface RepoConfig {
|
||||
env_file_path: string;
|
||||
/** Whether to skip secret interpolation into the repo environment variable file. */
|
||||
skip_secret_interp?: boolean;
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
}
|
||||
|
||||
export interface RepoInfo {
|
||||
@@ -1522,6 +1537,11 @@ export interface StackConfig {
|
||||
commit?: string;
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
/**
|
||||
* Optionally provide an alternate webhook secret for this stack.
|
||||
* If its an empty string, use the default secret from the config.
|
||||
*/
|
||||
webhook_secret?: string;
|
||||
/** Whether to send StackStateChange alerts for this stack. */
|
||||
send_alerts: boolean;
|
||||
}
|
||||
@@ -1732,6 +1752,11 @@ export interface ResourceSyncConfig {
|
||||
delete?: boolean;
|
||||
/** Whether incoming webhooks actually trigger action. */
|
||||
webhook_enabled: boolean;
|
||||
/**
|
||||
* Optionally provide an alternate webhook secret for this sync.
|
||||
* If its an empty string, use the default secret from the config.
|
||||
*/
|
||||
webhook_secret?: string;
|
||||
}
|
||||
|
||||
export type PendingSyncUpdatesData =
|
||||
|
||||
@@ -287,16 +287,31 @@ export const BuildConfig = ({
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Github Webhook",
|
||||
label: "Git Webhook",
|
||||
description:
|
||||
"Configure your repo provider to send webhooks to Monitor",
|
||||
components: {
|
||||
["Guard" as any]: () => {
|
||||
if (update.branch ?? config.branch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ConfigItem label="Configure Branch">
|
||||
<div>Must configure Branch before webhooks will work.</div>
|
||||
</ConfigItem>
|
||||
);
|
||||
},
|
||||
["build" as any]: () => (
|
||||
<ConfigItem label="Webhook Url">
|
||||
<CopyGithubWebhook path={`/build/${id}`} />
|
||||
</ConfigItem>
|
||||
),
|
||||
webhook_enabled: webhook !== undefined && !webhook.managed,
|
||||
webhook_secret: {
|
||||
description:
|
||||
"Provide a custom webhook secret for this resource, or use the global default.",
|
||||
placeholder: "Input custom secret",
|
||||
},
|
||||
["managed" as any]: () => {
|
||||
const inv = useInvalidate();
|
||||
const { toast } = useToast();
|
||||
|
||||
@@ -192,7 +192,7 @@ const ProcedureConfigInner = ({
|
||||
<Section>
|
||||
<Card>
|
||||
<CardHeader className="p-4">
|
||||
<ConfigItem label="Github Webhook" className="items-start">
|
||||
<ConfigItem label="Git Webhook" className="items-start">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -223,6 +223,19 @@ const ProcedureConfigInner = ({
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-4 w-full">
|
||||
<div className="text-muted-foreground">Custom Secret:</div>
|
||||
<Input
|
||||
value={
|
||||
config.webhook_secret ?? procedure.config?.webhook_secret
|
||||
}
|
||||
onChange={(e) =>
|
||||
setConfig({ ...config, webhook_secret: e.target.value })
|
||||
}
|
||||
disabled={disabled}
|
||||
className="w-[400px] max-w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ConfigItem>
|
||||
</CardHeader>
|
||||
|
||||
@@ -150,10 +150,20 @@ export const RepoConfig = ({ id }: { id: string }) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Github Webhooks",
|
||||
label: "Git Webhooks",
|
||||
description:
|
||||
"Configure your repo provider to send webhooks to Monitor",
|
||||
components: {
|
||||
["Guard" as any]: () => {
|
||||
if (update.branch ?? config.branch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ConfigItem label="Configure Branch">
|
||||
<div>Must configure Branch before webhooks will work.</div>
|
||||
</ConfigItem>
|
||||
);
|
||||
},
|
||||
["pull" as any]: () => (
|
||||
<ConfigItem label="Pull">
|
||||
<CopyGithubWebhook path={`/repo/${id}/pull`} />
|
||||
@@ -170,6 +180,11 @@ export const RepoConfig = ({ id }: { id: string }) => {
|
||||
</ConfigItem>
|
||||
),
|
||||
webhook_enabled: webhooks !== undefined && !webhooks.managed,
|
||||
webhook_secret: {
|
||||
description:
|
||||
"Provide a custom webhook secret for this resource, or use the global default.",
|
||||
placeholder: "Input custom secret",
|
||||
},
|
||||
["managed" as any]: () => {
|
||||
const inv = useInvalidate();
|
||||
const { toast } = useToast();
|
||||
|
||||
@@ -101,10 +101,20 @@ export const ResourceSyncConfig = ({
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Github Webhooks",
|
||||
label: "Git Webhooks",
|
||||
description:
|
||||
"Configure your repo provider to send webhooks to Monitor",
|
||||
components: {
|
||||
["Guard" as any]: () => {
|
||||
if (update.branch ?? config.branch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ConfigItem label="Configure Branch">
|
||||
<div>Must configure Branch before webhooks will work.</div>
|
||||
</ConfigItem>
|
||||
);
|
||||
},
|
||||
["refresh" as any]: () => (
|
||||
<ConfigItem
|
||||
label="Refresh Pending"
|
||||
@@ -122,6 +132,11 @@ export const ResourceSyncConfig = ({
|
||||
</ConfigItem>
|
||||
),
|
||||
webhook_enabled: webhooks !== undefined && !webhooks.managed,
|
||||
webhook_secret: {
|
||||
description:
|
||||
"Provide a custom webhook secret for this resource, or use the global default.",
|
||||
placeholder: "Input custom secret",
|
||||
},
|
||||
["managed" as any]: () => {
|
||||
const inv = useInvalidate();
|
||||
const { toast } = useToast();
|
||||
|
||||
@@ -380,6 +380,11 @@ export const StackConfig = ({
|
||||
!!(update.branch ?? config.branch) &&
|
||||
webhooks !== undefined &&
|
||||
!webhooks.managed,
|
||||
webhook_secret: {
|
||||
description:
|
||||
"Provide a custom webhook secret for this resource, or use the global default.",
|
||||
placeholder: "Input custom secret",
|
||||
},
|
||||
["managed" as any]: () => {
|
||||
const inv = useInvalidate();
|
||||
const { toast } = useToast();
|
||||
|
||||
Reference in New Issue
Block a user