feat: with gitea

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-07-31 11:28:56 +02:00
parent 8c3a0c699c
commit 0e876a25a6
Signed by: kjuulh
GPG Key ID: 9AA7BC13CE474394
2 changed files with 212 additions and 0 deletions

View File

@ -219,6 +219,24 @@ impl Command {
self.ui.write_str_ln(&format!("- {}", commit.get_title()))
}
}
GiteaCommand::CheckPr {} => {
let pr = client.get_pull_request(
self.global.owner.unwrap(),
self.global.repo.unwrap(),
)?;
match pr {
Some(index) => {
self.ui.write_str_ln(&format!(
"found cuddle-please (index={}) pr from gitea",
index
));
}
None => {
self.ui.write_str_ln("found no cuddle-please pr from gitea");
}
}
}
}
}
Some(Commands::Doctor {}) => {
@ -315,6 +333,7 @@ enum GiteaCommand {
#[arg(long)]
branch: String,
},
CheckPr {},
}
#[derive(Subcommand, Debug, Clone)]

View File

@ -191,6 +191,199 @@ impl GiteaClient {
Ok(commits)
}
pub fn get_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
) -> anyhow::Result<Option<usize>> {
let request_pull_request =
|owner: &str, repo: &str, page: usize| -> anyhow::Result<(Vec<PullRequest>, bool)> {
let client = self.create_client()?;
tracing::trace!(owner = owner, repo = repo, "fetching pull-requests");
let request = client
.get(format!(
"{}/api/v1/repos/{}/{}/pulls?state=open&sort=recentupdate&page={}&limit={}",
&self.url.trim_end_matches("/"),
owner,
repo,
page,
50,
))
.build()?;
let resp = client.execute(request)?;
let mut has_more = false;
if let Some(gitea_has_more) = resp.headers().get("X-HasMore") {
let gitea_has_more = gitea_has_more.to_str()?;
if gitea_has_more == "true" || gitea_has_more == "True" {
has_more = true;
}
}
if !resp.status().is_success() {
return Err(anyhow::anyhow!(resp.error_for_status().unwrap_err()));
}
let commits: Vec<PullRequest> = resp.json()?;
Ok((commits, has_more))
};
self.get_pull_request_inner(owner, repo, request_pull_request)
}
fn get_pull_request_inner<F>(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
request_pull_request: F,
) -> anyhow::Result<Option<usize>>
where
F: Fn(&str, &str, usize) -> anyhow::Result<(Vec<PullRequest>, bool)>,
{
let mut page = 1;
let owner: String = owner.into();
let repo: String = repo.into();
loop {
let (pull_requests, has_more) = request_pull_request(&owner, &repo, page)?;
for pull_request in pull_requests {
if pull_request.head.r#ref.contains("cuddle-please/release") {
return Ok(Some(pull_request.number));
}
}
if !has_more {
break;
}
page += 1;
}
Ok(None)
}
pub fn create_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
version: impl Into<String>,
body: impl Into<String>,
base: impl Into<String>,
) -> anyhow::Result<usize> {
#[derive(Clone, Debug, Serialize, Deserialize)]
struct CreatePullRequestOption {
base: String,
body: String,
head: String,
title: String,
}
let client = self.create_client()?;
let owner = owner.into();
let repo = repo.into();
let version = version.into();
let body = body.into();
let base = base.into();
let request = CreatePullRequestOption {
base: base.clone(),
body: body.clone(),
head: "cuddle-please/release".into(),
title: format!("chore(release): {}", version),
};
tracing::trace!(
owner = owner,
repo = repo,
version = version,
base = base,
"create pull_request"
);
let request = client
.post(format!(
"{}/api/v1/repos/{}/{}/pulls",
&self.url.trim_end_matches("/"),
owner,
repo,
))
.json(&request)
.build()?;
let resp = client.execute(request)?;
if !resp.status().is_success() {
return Err(anyhow::anyhow!(resp.error_for_status().unwrap_err()));
}
let commits: PullRequest = resp.json()?;
Ok(commits.number)
}
pub fn update_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
version: impl Into<String>,
body: impl Into<String>,
index: usize,
) -> anyhow::Result<usize> {
#[derive(Clone, Debug, Serialize, Deserialize)]
struct CreatePullRequestOption {
body: String,
title: String,
}
let client = self.create_client()?;
let owner = owner.into();
let repo = repo.into();
let version = version.into();
let body = body.into();
let request = CreatePullRequestOption {
body: body.clone(),
title: format!("chore(release): {}", version),
};
tracing::trace!(
owner = owner,
repo = repo,
version = version,
"update pull_request"
);
let request = client
.patch(format!(
"{}/api/v1/repos/{}/{}/pulls",
&self.url.trim_end_matches("/"),
owner,
repo,
))
.json(&request)
.build()?;
let resp = client.execute(request)?;
if !resp.status().is_success() {
return Err(anyhow::anyhow!(resp.error_for_status().unwrap_err()));
}
let commits: PullRequest = resp.json()?;
Ok(commits.number)
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct PullRequest {
number: usize,
head: PRBranchInfo,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct PRBranchInfo {
#[serde(alias = "ref")]
r#ref: String,
label: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]