mirror of
https://codeberg.org/Toasterson/solstice-ci.git
synced 2026-04-10 13:20:41 +00:00
Add repository owner/name parsing and integrate with commit status updates
This commit introduces: - A utility function to parse repository owner and name from URLs, supporting HTTPS, SSH, and Git formats. - Enhancements to job messages and results with optional `repo_owner` and `repo_name` fields for downstream integrations. - Updated orchestrator and forge-integration workflows to leverage parsed repository details for status updates and accurate routing.
This commit is contained in:
parent
c00ce54112
commit
06ae079b14
4 changed files with 87 additions and 14 deletions
4
TODO.txt
4
TODO.txt
|
|
@ -1,6 +1,6 @@
|
|||
- Return status to codeberg: Extract repo from Webhook and keep in messages
|
||||
- Make RabbitMQ Messages Print nicely
|
||||
- move runner logs to debug level so they can be logged in the CI job but don't spam the deployed version
|
||||
- Make Orchestrator serve the runner binaries so no external server is needed
|
||||
- Make orchestrator detect the address it will be reachable by checking the libvirt config or on illumos use it's external IP
|
||||
- Make VM reachable IP of the orchestrator configurable in case the setup on illumos gets more complicated (via config file)
|
||||
- Make VM reachable IP of the orchestrator configurable in case the setup on illumos gets more complicated (via config file)
|
||||
- Make the forge-integration task use fnox secrets
|
||||
|
|
@ -15,6 +15,12 @@ pub struct JobRequest {
|
|||
pub source: SourceSystem,
|
||||
/// Repository clone URL (SSH or HTTPS).
|
||||
pub repo_url: String,
|
||||
/// Repository owner (parsed from webhook or URL); optional for backward-compat.
|
||||
#[serde(default)]
|
||||
pub repo_owner: Option<String>,
|
||||
/// Repository name (parsed from webhook or URL); optional for backward-compat.
|
||||
#[serde(default)]
|
||||
pub repo_name: Option<String>,
|
||||
/// Commit SHA to check out.
|
||||
pub commit_sha: String,
|
||||
/// Optional path to the workflow file within the repo (KDL).
|
||||
|
|
@ -50,6 +56,8 @@ impl JobRequest {
|
|||
request_id: Uuid::new_v4(),
|
||||
source,
|
||||
repo_url: repo_url.into(),
|
||||
repo_owner: None,
|
||||
repo_name: None,
|
||||
commit_sha: commit_sha.into(),
|
||||
workflow_path: None,
|
||||
workflow_job_id: None,
|
||||
|
|
@ -69,6 +77,12 @@ pub struct JobResult {
|
|||
pub request_id: Uuid,
|
||||
/// Repository and commit info (for convenience in consumers)
|
||||
pub repo_url: String,
|
||||
/// Repository owner (when known). Optional for backward-compat.
|
||||
#[serde(default)]
|
||||
pub repo_owner: Option<String>,
|
||||
/// Repository name (when known). Optional for backward-compat.
|
||||
#[serde(default)]
|
||||
pub repo_name: Option<String>,
|
||||
pub commit_sha: String,
|
||||
/// Outcome info
|
||||
pub success: bool,
|
||||
|
|
@ -96,6 +110,8 @@ impl JobResult {
|
|||
schema_version: default_jobresult_schema(),
|
||||
request_id,
|
||||
repo_url,
|
||||
repo_owner: None,
|
||||
repo_name: None,
|
||||
commit_sha,
|
||||
success,
|
||||
exit_code,
|
||||
|
|
|
|||
|
|
@ -221,6 +221,20 @@ async fn post_commit_status(
|
|||
) -> Result<()> {
|
||||
// Extract owner/repo from repo_url (supports https://.../owner/repo.git and ssh://git@host/owner/repo.git)
|
||||
let (owner, repo) = parse_owner_repo(repo_url).ok_or_else(|| miette::miette!("cannot parse owner/repo from repo_url: {repo_url}"))?;
|
||||
post_commit_status_owner(base, token, &owner, &repo, sha, context, state, target_url, description).await
|
||||
}
|
||||
|
||||
async fn post_commit_status_owner(
|
||||
base: &str,
|
||||
token: &str,
|
||||
owner: &str,
|
||||
repo: &str,
|
||||
sha: &str,
|
||||
context: &str,
|
||||
state: &str,
|
||||
target_url: Option<&str>,
|
||||
description: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let api = format!("{}/repos/{}/{}/statuses/{}", base.trim_end_matches('/'), owner, repo, sha);
|
||||
let mut body = serde_json::json!({
|
||||
"state": state,
|
||||
|
|
@ -377,17 +391,31 @@ async fn handle_job_result(state: &AppState, jobres: &common::messages::JobResul
|
|||
let state_str = if jobres.success { "success" } else { "failure" };
|
||||
if let (Some(base), Some(token)) = (state.forgejo_base.as_ref(), state.forgejo_token.as_ref()) {
|
||||
let desc = if jobres.success { Some("Job succeeded") } else { Some("Job failed") };
|
||||
let _ = post_commit_status(
|
||||
base,
|
||||
token,
|
||||
&jobres.repo_url,
|
||||
&jobres.commit_sha,
|
||||
&state.forge_context,
|
||||
state_str,
|
||||
target_url.as_deref(),
|
||||
desc,
|
||||
)
|
||||
.await;
|
||||
// Prefer explicit owner/repo from JobResult when available
|
||||
if let (Some(owner), Some(repo)) = (jobres.repo_owner.as_ref(), jobres.repo_name.as_ref()) {
|
||||
let _ = post_commit_status_owner(
|
||||
base,
|
||||
token,
|
||||
owner,
|
||||
repo,
|
||||
&jobres.commit_sha,
|
||||
&state.forge_context,
|
||||
state_str,
|
||||
target_url.as_deref(),
|
||||
desc,
|
||||
).await;
|
||||
} else {
|
||||
let _ = post_commit_status(
|
||||
base,
|
||||
token,
|
||||
&jobres.repo_url,
|
||||
&jobres.commit_sha,
|
||||
&state.forge_context,
|
||||
state_str,
|
||||
target_url.as_deref(),
|
||||
desc,
|
||||
).await;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -679,6 +707,11 @@ async fn enqueue_job(state: &Arc<AppState>, repo_url: String, commit_sha: String
|
|||
miette::bail!("missing repo_url in webhook payload");
|
||||
}
|
||||
let mut jr = common::JobRequest::new(common::SourceSystem::Forgejo, repo_url, commit_sha);
|
||||
// Try to populate repo_owner/repo_name from URL for accurate status routing
|
||||
if let Some((owner, name)) = parse_owner_repo(&jr.repo_url) {
|
||||
jr.repo_owner = Some(owner);
|
||||
jr.repo_name = Some(name);
|
||||
}
|
||||
// Infer runs_on from repo map, labels, or default
|
||||
jr.runs_on = infer_runs_on(state, &jr.repo_url, labels.as_ref().map(|v| v.as_slice()));
|
||||
common::publish_job(&state.mq_cfg, &jr).await?;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,25 @@ use std::sync::Arc;
|
|||
|
||||
use crate::persist::Persist;
|
||||
|
||||
fn parse_owner_repo(repo_url: &str) -> Option<(String, String)> {
|
||||
let url = repo_url.trim_end_matches(".git");
|
||||
if let Some(rest) = url.strip_prefix("https://").or_else(|| url.strip_prefix("http://")) {
|
||||
let parts: Vec<&str> = rest.split('/').collect();
|
||||
if parts.len() >= 3 { return Some((parts[1].to_string(), parts[2].to_string())); }
|
||||
} else if let Some(rest) = url.strip_prefix("ssh://") {
|
||||
// ssh://git@host/owner/repo
|
||||
let after_host = rest.splitn(2, '/').nth(1)?;
|
||||
let parts: Vec<&str> = after_host.split('/').collect();
|
||||
if parts.len() >= 2 { return Some((parts[0].to_string(), parts[1].to_string())); }
|
||||
} else if let Some(idx) = url.find(':') {
|
||||
// git@host:owner/repo
|
||||
let after = &url[idx+1..];
|
||||
let parts: Vec<&str> = after.split('/').collect();
|
||||
if parts.len() >= 2 { return Some((parts[0].to_string(), parts[1].to_string())); }
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub struct RunnerSvc {
|
||||
mq_cfg: MqConfig,
|
||||
persist: Arc<Persist>,
|
||||
|
|
@ -95,7 +114,7 @@ impl Runner for RunnerSvc {
|
|||
if let (Some(id), Some(repo), Some(sha)) =
|
||||
(req_id.as_ref(), repo_url.as_ref(), commit_sha.as_ref())
|
||||
{
|
||||
let result = common::messages::JobResult::new(
|
||||
let mut result = common::messages::JobResult::new(
|
||||
id.clone(),
|
||||
repo.clone(),
|
||||
sha.clone(),
|
||||
|
|
@ -103,6 +122,11 @@ impl Runner for RunnerSvc {
|
|||
exit_code,
|
||||
None,
|
||||
);
|
||||
// Try to parse owner/repo for downstream integrations to avoid reparsing URLs
|
||||
if let Some((owner, name)) = parse_owner_repo(&repo) {
|
||||
result.repo_owner = Some(owner);
|
||||
result.repo_name = Some(name);
|
||||
}
|
||||
if let Err(e) = publish_job_result(&self.mq_cfg, &result).await {
|
||||
error!(error = %e, request_id = %id, "failed to publish JobResult");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue