1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Common trait interface for Git forge platforms (GitHub, GitLab, Gitea).
use async_trait::async_trait;
use std::any::Any;
use url::Url;
#[cfg(test)]
use mockall::automock;
use crate::{
analyzer::release::Tag,
config::Config,
error::Result,
forge::request::{
Commit, CreateCommitRequest, CreatePrRequest,
CreateReleaseBranchRequest, ForgeCommit, GetFileContentRequest,
GetPrRequest, PrLabelsRequest, PullRequest, ReleaseByTagResponse,
UpdatePrRequest,
},
};
/// Common interface for Git forge platform operations including repository
/// access, PR management, tagging, and release publishing.
#[cfg_attr(test, automock)]
#[async_trait]
pub trait Forge: Any + Send + Sync {
/// Get repository name from configuration.
fn repo_name(&self) -> String;
/// Get the base URL for release links (e.g., GitHub web URL for commits).
fn release_link_base_url(&self) -> Url;
/// Get the base URL for comparing releases and showing diffs
fn compare_link_base_url(&self) -> Url;
/// Fetch the default branch name (e.g., "main" or "master").
fn default_branch(&self) -> String;
/// Load releasaurus.toml configuration from repository root.
async fn load_config(&self, branch: Option<String>) -> Result<Config>;
/// Fetch file content from repository by path, returning None if file
/// doesn't exist.
async fn get_file_content(
&self,
req: GetFileContentRequest,
) -> Result<Option<String>>;
/// Retrieves the release notes for a specified tag
async fn get_release_by_tag(
&self,
tag: &str,
) -> Result<ReleaseByTagResponse>;
/// Create a new branch with file changes and return the commit SHA.
async fn create_release_branch(
&self,
req: CreateReleaseBranchRequest,
) -> Result<Commit>;
/// Creates a commit on a target branch
async fn create_commit(&self, req: CreateCommitRequest) -> Result<Commit>;
/// Create a git tag pointing to a specific commit SHA.
async fn tag_commit(&self, tag_name: &str, sha: &str) -> Result<()>;
/// Find all tags matching the given prefix (e.g., "v" or "api-v") that
/// are ancestors of the given branch, returned as normalized Tag structs
/// in no guaranteed order.
async fn get_latest_tags_for_prefix(
&self,
prefix: &str,
branch: &str,
) -> Result<Vec<Tag>>;
/// Fetch commits for a package path, optionally starting from a specific
/// SHA.
async fn get_commits(
&self,
branch: Option<String>,
sha: Option<String>,
) -> Result<Vec<ForgeCommit>>;
/// Find an open release PR matching the given branch criteria.
async fn get_open_release_pr(
&self,
req: GetPrRequest,
) -> Result<Option<PullRequest>>;
/// Find the most recently merged release PR with pending label.
async fn get_merged_release_pr(
&self,
req: GetPrRequest,
) -> Result<Option<PullRequest>>;
/// Create a new pull request and return its details.
async fn create_pr(&self, req: CreatePrRequest) -> Result<PullRequest>;
/// Update an existing pull request's title and body.
async fn update_pr(&self, req: UpdatePrRequest) -> Result<()>;
/// Replace all labels on a pull request with the provided set.
async fn replace_pr_labels(&self, req: PrLabelsRequest) -> Result<()>;
/// Publish a release on the forge platform with notes and tag reference.
async fn create_release(
&self,
tag: &str,
sha: &str,
notes: &str,
) -> Result<()>;
}