feat: implement Pull request + everything required + add tests

This commit is contained in:
aviac 2023-09-23 00:13:32 +02:00
parent 6c6f992ef9
commit 49e18362ea
No known key found for this signature in database
GPG key ID: 644781002BDEA982
14 changed files with 729 additions and 17 deletions

2
Cargo.lock generated
View file

@ -224,7 +224,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "forgejo-api-types"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"chrono",
"clap",

View file

@ -1,6 +1,6 @@
[package]
name = "forgejo-api-types"
version = "0.1.3"
version = "0.1.4"
edition = "2021"
license = "AGPL-3.0-or-later"
keywords = ["forgejo", "types", "codeberg", "api"]

View file

@ -6,7 +6,7 @@ use crate::types::misc::boolean_enums::is::template::IsTemplate;
use crate::types::misc::trust_model::TrustModel;
/// CreateRepoOption represents options when creating a repository.
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct CreateRepoOption {
/// Whether the repository should be auto-initialized.
pub auto_init: AutoInit,
@ -14,10 +14,11 @@ pub struct CreateRepoOption {
pub default_branch: String,
/// Description of the repository to create.
pub description: String,
// 🚧🚧 TODO 🚧🚧 : This can probably be enumerated
/// Gitignores to use.
pub gitignores: String,
/// Label-Set to use.
// 🚧🚧 TODO 🚧🚧 : Do better than comma separated list of names
/// Label-Set to use.
pub issue_labels: String,
/// License to use.
pub license: String,
@ -47,3 +48,28 @@ impl Default for CreateRepoOption {
}
}
}
#[test]
fn test_create_repo_option_serialization_deserialization() {
// Create a sample CreateRepoOption instance
let repo_option = CreateRepoOption {
auto_init: AutoInit::Yes,
default_branch: String::from("main"),
description: String::from("An empty repository."),
gitignores: String::from("rust"),
issue_labels: String::from("bug,feature"),
license: String::from("MIT"),
name: String::from("NewRepo"),
private: IsPrivate::Yes,
template: IsTemplate::No,
trust_model: TrustModel::Default,
};
let data = include_str!("../../../../test_data/example_create_repo_option.json");
// Deserialize the JSON string back to a CreateRepoOption instance
let deserialized: CreateRepoOption = serde_json::from_str(data).unwrap();
// Verify that the original and deserialized instances are equal
assert_eq!(repo_option, deserialized);
}

View file

@ -15,3 +15,59 @@
// title string
// updated_at string($date-time)
// }
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::types::misc::boolean_enums::state_type::StateType;
/// Milestone represents a collection of issues on one repository.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Milestone {
/// The timestamp when the milestone was closed.
pub closed_at: Option<DateTime<Utc>>,
/// The number of closed issues in the milestone.
pub closed_issues: usize,
/// The timestamp when the milestone was created.
pub created_at: DateTime<Utc>,
/// The description of the milestone.
pub description: String,
/// The due date for the milestone.
pub due_on: Option<DateTime<Utc>>,
/// The unique ID of the milestone.
pub id: usize,
/// The number of open issues in the milestone.
pub open_issues: usize,
/// The state of the milestone.
pub state: StateType,
/// The title of the milestone.
pub title: String,
/// The timestamp when the milestone was last updated.
pub updated_at: DateTime<Utc>,
}
#[test]
fn test_milestone_serialization_deserialization() {
use std::str::FromStr;
// Create a sample Milestone instance with predefined values for testing.
let milestone = Milestone {
closed_at: Some(DateTime::from_str("2023-09-22T22:04:43.456694702Z").unwrap()),
closed_issues: 10,
created_at: DateTime::from_str("2023-09-22T22:04:43.456699822Z").unwrap(),
description: String::from("Sample milestone description"),
due_on: Some(DateTime::from_str("2023-09-22T22:04:43.456705994Z").unwrap()),
id: 123,
open_issues: 5,
state: StateType::Open,
title: String::from("Sample Milestone"),
updated_at: DateTime::from_str("2023-09-22T22:04:43.456706164Z").unwrap(),
};
// Deserialize the JSON string back into a Milestone instance.
let deserialized: Milestone =
serde_json::from_str(include_str!("../../../test_data/example_milestone.json")).unwrap();
// Verify that the original and deserialized instances are equal.
assert_eq!(milestone, deserialized);
}

View file

@ -116,7 +116,6 @@ pub mod access_token;
/* to-todo */ pub mod repository_settings;
/* to-todo */ pub mod review_state;
/* to-todo */ pub mod server_verion;
/* to-todo */ pub mod state_type;
/* to-todo */ pub mod stop_watch;
/* to-todo */ pub mod submit_pull_review;
/* to-todo */ pub mod tag;

View file

@ -36,3 +36,133 @@
// url string
// user User{...}
// }]
use crate::types::api::label::Label;
use crate::types::api::milestone::Milestone;
use crate::types::api::pull_request_branch_info::PRBranchInfo;
use crate::types::api::user::User;
use crate::types::misc::boolean_enums::allow::maintainer_edit::AllowMaintainerEdit;
use crate::types::misc::boolean_enums::is::locked::IsLocked;
use crate::types::misc::boolean_enums::is::mergeable::IsMergeable;
use crate::types::misc::boolean_enums::is::merged::IsMerged;
use crate::types::misc::boolean_enums::state_type::StateType;
use crate::types::misc::optional_url::OptionalUrl;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use url::Url;
/// PullRequest represents a pull request.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PullRequest {
/// Whether the pull request allows maintainer edits.
pub allow_maintainer_edit: AllowMaintainerEdit,
/// The assignee of the pull request.
pub assignee: User,
/// The list of assignees for the pull request.
pub assignees: Vec<User>,
/// Information about the base branch.
pub base: PRBranchInfo,
/// The body (description) of the pull request.
pub body: String,
/// The timestamp when the pull request was closed.
pub closed_at: DateTime<Utc>,
/// The number of comments on the pull request.
pub comments: usize,
/// The timestamp when the pull request was created.
pub created_at: DateTime<Utc>,
/// The URL to view the diff for the pull request.
pub diff_url: OptionalUrl,
/// The due date for the pull request.
pub due_date: DateTime<Utc>,
/// Information about the head branch.
pub head: PRBranchInfo,
/// The HTML URL for viewing the pull request.
pub html_url: OptionalUrl,
/// The unique ID of the pull request.
pub id: usize,
/// Whether the pull request is locked.
pub is_locked: IsLocked,
/// The labels associated with the pull request.
pub labels: Vec<Label>,
/// The merge base branch.
pub merge_base: String,
/// The SHA of the merge commit.
pub merge_commit_sha: String,
/// Whether the pull request is mergeable.
pub mergeable: IsMergeable,
/// Whether the pull request has been merged.
pub merged: IsMerged,
/// The timestamp when the pull request was merged.
pub merged_at: DateTime<Utc>,
/// The user who merged the pull request.
pub merged_by: User,
/// The milestone associated with the pull request.
pub milestone: Milestone,
/// The pull request number.
pub number: usize,
/// The URL to view the patch for the pull request.
pub patch_url: OptionalUrl,
/// The state of the pull request.
pub state: StateType,
/// The title of the pull request.
pub title: String,
/// The timestamp when the pull request was last updated.
pub updated_at: DateTime<Utc>,
/// The URL of the pull request.
pub url: Url,
/// The user who created the pull request.
pub user: User,
}
#[test]
fn test_pull_request_serialization_deserialization() {
let user: User =
serde_json::from_str(include_str!("../../../test_data/example_user.json")).unwrap();
let pr_info: PRBranchInfo = serde_json::from_str(include_str!(
"../../../test_data/example_pull_request_info.json"
))
.unwrap();
let label =
serde_json::from_str(include_str!("../../../test_data/example_label.json")).unwrap();
let milestone: Milestone =
serde_json::from_str(include_str!("../../../test_data/example_milestone.json")).unwrap();
// Create a sample PullRequest instance with some predefined values for testing.
let pr = PullRequest {
allow_maintainer_edit: AllowMaintainerEdit::Yes,
assignee: user.clone(),
assignees: vec![user.clone(); 2],
base: pr_info.clone(),
body: String::from("Sample pull request description"),
closed_at: DateTime::<Utc>::MIN_UTC,
comments: 5,
created_at: DateTime::<Utc>::MIN_UTC,
diff_url: OptionalUrl::Some(Url::parse("https://example.com/diff").unwrap()),
due_date: DateTime::<Utc>::MIN_UTC,
head: pr_info.clone(),
html_url: OptionalUrl::Some(Url::parse("https://example.com/pull_request").unwrap()),
id: 123,
is_locked: IsLocked::No,
labels: vec![label; 3],
merge_base: String::from("main"),
merge_commit_sha: String::from("abcdef123456"),
mergeable: IsMergeable::Yes,
merged: IsMerged::No,
merged_at: DateTime::<Utc>::MIN_UTC,
merged_by: user.clone(),
milestone,
number: 1,
patch_url: OptionalUrl::Some(Url::parse("https://example.com/patch").unwrap()),
state: StateType::Open,
title: String::from("Sample Pull Request"),
updated_at: DateTime::<Utc>::MIN_UTC,
url: Url::parse("https://example.com/pull_request/1").unwrap(),
user: user.clone(),
};
// Deserialize the JSON string back to a PullRequest instance.
let deserialized: PullRequest =
serde_json::from_str(include_str!("../../../test_data/example_pull_request.json")).unwrap();
// Verify that the original and deserialized instances are equal.
assert_eq!(pr, deserialized);
}

View file

@ -1,10 +1,37 @@
// PRBranchInfo{
// description:
// PRBranchInfo information about a branch
//
// label string
// ref string
// repo Repository{...}
// repo_id integer($int64)
// sha string
// }
use crate::types::api::repository::Repository;
use serde::{Deserialize, Serialize}; // Import the Repository type from your code
/// PRBranchInfo represents information about a branch.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PRBranchInfo {
/// The label of the branch.
pub label: String,
/// The reference (ref) of the branch.
pub ref_name: String,
/// The repository associated with the branch.
pub repo: Repository,
/// The unique ID of the repository.
pub repo_id: usize,
/// The SHA of the branch.
pub sha: String,
}
#[test]
fn test_pr_branch_info_serialization_deserialization() {
// Create a sample PRBranchInfo instance
let repo_info = PRBranchInfo {
label: String::from("feature-branch"),
ref_name: String::from("refs/heads/feature-branch"),
repo: serde_json::from_str(include_str!("../../../test_data/example_repo.json")).unwrap(),
repo_id: 12345,
sha: String::from("abcdef1234567890"),
};
let data = include_str!("../../../test_data/example_pull_request_info.json");
// Deserialize the JSON string back to a PRBranchInfo instance
let deserialized: PRBranchInfo = serde_json::from_str(data).unwrap();
// Verify that the original and deserialized instances are equal
assert_eq!(repo_info, deserialized);
}

View file

@ -1,2 +0,0 @@
// StateTypestring
// StateType issue state type

View file

@ -13,3 +13,6 @@ implement_boolean_enum!(restricted, IsRestricted);
implement_boolean_enum!(template, IsTemplate);
implement_boolean_enum!(owner, IsOwner);
implement_boolean_enum!(ok, IsOk);
implement_boolean_enum!(locked, IsLocked);
implement_boolean_enum!(mergeable, IsMergeable);
implement_boolean_enum!(merged, IsMerged);

View file

@ -11,3 +11,4 @@ implement_boolean_enum!(ignore_whitespace_conflicts, IgnoreWhitespaceConflicts);
implement_boolean_enum!(includes_all_repositories, IncludesAllRepositories);
implement_boolean_enum!(prohibit_login, ProhibitLogin);
implement_boolean_enum!(auto_init, AutoInit);
implement_boolean_enum!(state_type, StateType { Open, Closed });

View file

@ -0,0 +1,12 @@
{
"auto_init": true,
"default_branch": "main",
"description": "An empty repository.",
"gitignores": "rust",
"issue_labels": "bug,feature",
"license": "MIT",
"name": "NewRepo",
"private": true,
"template": false,
"trust_model": "default"
}

View file

@ -0,0 +1,12 @@
{
"closed_at": "2023-09-22T22:04:43.456694702Z",
"closed_issues": 10,
"created_at": "2023-09-22T22:04:43.456699822Z",
"description": "Sample milestone description",
"due_on": "2023-09-22T22:04:43.456705994Z",
"id": 123,
"open_issues": 5,
"state": true,
"title": "Sample Milestone",
"updated_at": "2023-09-22T22:04:43.456706164Z"
}

View file

@ -0,0 +1,358 @@
{
"allow_maintainer_edit": true,
"assignee": {
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
},
"assignees": [
{
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
},
{
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
}
],
"base": {
"label": "feature-branch",
"ref_name": "refs/heads/feature-branch",
"repo": {
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_rebase_update": true,
"allow_squash_merge": true,
"archived": false,
"avatar_url": "",
"clone_url": "https://codeberg.org/VoiDD/tmp.git",
"created_at": "2023-07-27T18:59:48Z",
"default_allow_maintainer_edit": false,
"default_branch": "main",
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"description": "",
"empty": true,
"external_tracker": null,
"external_wiki": null,
"fork": false,
"forks_count": 0,
"full_name": "VoiDD/tmp",
"has_issues": true,
"has_projects": true,
"has_pull_requests": true,
"has_wiki": true,
"html_url": "https://codeberg.org/VoiDD/tmp",
"id": 128746,
"ignore_whitespace_conflicts": false,
"internal": false,
"internal_tracker": {
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": false,
"enable_time_tracker": true
},
"language": "",
"languages_url": "https://codeberg.org/api/v1/repos/VoiDD/tmp/languages",
"link": "",
"mirror": false,
"mirror_interval": "",
"mirror_updated": "0001-01-01T00:00:00Z",
"name": "tmp",
"open_issues_count": 0,
"open_pr_counter": 0,
"original_url": "",
"owner": {
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
},
"parent": null,
"permissions": {
"admin": true,
"pull": false,
"push": true
},
"private": false,
"release_counter": 0,
"repo_transfer": null,
"size": 24,
"ssh_url": "git@codeberg.org:VoiDD/tmp.git",
"stars_count": 0,
"template": false,
"updated_at": "2023-07-27T18:59:48Z",
"watchers_count": 1,
"website": ""
},
"repo_id": 12345,
"sha": "abcdef1234567890"
},
"body": "Sample pull request description",
"closed_at": "-262144-01-01T00:00:00Z",
"comments": 5,
"created_at": "-262144-01-01T00:00:00Z",
"diff_url": "https://example.com/diff",
"due_date": "-262144-01-01T00:00:00Z",
"head": {
"label": "feature-branch",
"ref_name": "refs/heads/feature-branch",
"repo": {
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_rebase_update": true,
"allow_squash_merge": true,
"archived": false,
"avatar_url": "",
"clone_url": "https://codeberg.org/VoiDD/tmp.git",
"created_at": "2023-07-27T18:59:48Z",
"default_allow_maintainer_edit": false,
"default_branch": "main",
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"description": "",
"empty": true,
"external_tracker": null,
"external_wiki": null,
"fork": false,
"forks_count": 0,
"full_name": "VoiDD/tmp",
"has_issues": true,
"has_projects": true,
"has_pull_requests": true,
"has_wiki": true,
"html_url": "https://codeberg.org/VoiDD/tmp",
"id": 128746,
"ignore_whitespace_conflicts": false,
"internal": false,
"internal_tracker": {
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": false,
"enable_time_tracker": true
},
"language": "",
"languages_url": "https://codeberg.org/api/v1/repos/VoiDD/tmp/languages",
"link": "",
"mirror": false,
"mirror_interval": "",
"mirror_updated": "0001-01-01T00:00:00Z",
"name": "tmp",
"open_issues_count": 0,
"open_pr_counter": 0,
"original_url": "",
"owner": {
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
},
"parent": null,
"permissions": {
"admin": true,
"pull": false,
"push": true
},
"private": false,
"release_counter": 0,
"repo_transfer": null,
"size": 24,
"ssh_url": "git@codeberg.org:VoiDD/tmp.git",
"stars_count": 0,
"template": false,
"updated_at": "2023-07-27T18:59:48Z",
"watchers_count": 1,
"website": ""
},
"repo_id": 12345,
"sha": "abcdef1234567890"
},
"html_url": "https://example.com/pull_request",
"id": 123,
"is_locked": false,
"labels": [
{
"color": "#00aabb",
"description": "Label a label to an issue or a pr",
"exclusive": false,
"id": 42,
"name": "bug",
"url": "https://example.com/labels/bug"
},
{
"color": "#00aabb",
"description": "Label a label to an issue or a pr",
"exclusive": false,
"id": 42,
"name": "bug",
"url": "https://example.com/labels/bug"
},
{
"color": "#00aabb",
"description": "Label a label to an issue or a pr",
"exclusive": false,
"id": 42,
"name": "bug",
"url": "https://example.com/labels/bug"
}
],
"merge_base": "main",
"merge_commit_sha": "abcdef123456",
"mergeable": true,
"merged": false,
"merged_at": "-262144-01-01T00:00:00Z",
"merged_by": {
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
},
"milestone": {
"closed_at": "2023-09-22T22:04:43.456694702Z",
"closed_issues": 10,
"created_at": "2023-09-22T22:04:43.456699822Z",
"description": "Sample milestone description",
"due_on": "2023-09-22T22:04:43.456705994Z",
"id": 123,
"open_issues": 5,
"state": true,
"title": "Sample Milestone",
"updated_at": "2023-09-22T22:04:43.456706164Z"
},
"number": 1,
"patch_url": "https://example.com/patch",
"state": true,
"title": "Sample Pull Request",
"updated_at": "-262144-01-01T00:00:00Z",
"url": "https://example.com/pull_request/1",
"user": {
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
}
}

View file

@ -0,0 +1,90 @@
{
"label": "feature-branch",
"ref_name": "refs/heads/feature-branch",
"repo": {
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_rebase_update": true,
"allow_squash_merge": true,
"archived": false,
"avatar_url": "",
"clone_url": "https://codeberg.org/VoiDD/tmp.git",
"created_at": "2023-07-27T18:59:48Z",
"default_allow_maintainer_edit": false,
"default_branch": "main",
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"description": "",
"empty": true,
"external_tracker": null,
"external_wiki": null,
"fork": false,
"forks_count": 0,
"full_name": "VoiDD/tmp",
"has_issues": true,
"has_projects": true,
"has_pull_requests": true,
"has_wiki": true,
"html_url": "https://codeberg.org/VoiDD/tmp",
"id": 128746,
"ignore_whitespace_conflicts": false,
"internal": false,
"internal_tracker": {
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": false,
"enable_time_tracker": true
},
"language": "",
"languages_url": "https://codeberg.org/api/v1/repos/VoiDD/tmp/languages",
"link": "",
"mirror": false,
"mirror_interval": "",
"mirror_updated": "0001-01-01T00:00:00Z",
"name": "tmp",
"open_issues_count": 0,
"open_pr_counter": 0,
"original_url": "",
"owner": {
"active": true,
"avatar_url": "https://codeberg.org/avatars/foo-bar",
"created": "2022-11-04T14:41:29Z",
"description": "",
"email": "example@mail.com",
"followers_count": 2,
"following_count": 1,
"full_name": "",
"id": 12345,
"is_admin": false,
"language": "en-US",
"last_login": "2023-07-26T19:38:27Z",
"location": "",
"login": "ExampleUser",
"login_name": "",
"prohibit_login": false,
"restricted": false,
"starred_repos_count": 0,
"username": "ExampleUser",
"visibility": "public",
"website": "https://example.com/"
},
"parent": null,
"permissions": {
"admin": true,
"pull": false,
"push": true
},
"private": false,
"release_counter": 0,
"repo_transfer": null,
"size": 24,
"ssh_url": "git@codeberg.org:VoiDD/tmp.git",
"stars_count": 0,
"template": false,
"updated_at": "2023-07-27T18:59:48Z",
"watchers_count": 1,
"website": ""
},
"repo_id": 12345,
"sha": "abcdef1234567890"
}