WIP: catchup with F3 schema v1.0 #1

Draft
realaravinth wants to merge 3 commits from catchup into master
15 changed files with 1490 additions and 40 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "f3-schemas"]
path = f3-schemas
url = https://lab.forgefriends.org/friendlyforgeformat/f3-schemas

View file

@ -1,12 +1,18 @@
pipeline: steps:
backend: test:
image: rust image: rust
commands: commands:
- apt update && apt-get -y --no-install-recommends install tar gpg curl wget git
- rustup component add rustfmt - rustup component add rustfmt
- rustup component add clippy - rustup component add clippy
- make lint - make lint
- make test - make test
- make doc - make doc
publish:
image: python
when:
event: [push, tag, deployment]
branch: master
commands:
- apt update && apt-get -y --no-install-recommends install tar gpg curl wget git
- make ci-deploy - make ci-deploy
secrets: [ GITEA_WRITE_DEPLOY_KEY, LIBREPAGES_DEPLOY_SECRET ] secrets: [ GITEA_WRITE_DEPLOY_KEY, LIBREPAGES_DEPLOY_SECRET ]

1315
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -14,3 +14,6 @@ authors = ["realaravinth <realaravinth@batsense.net>"]
[dependencies] [dependencies]
serde = { version = "1.0.152", features = ["derive"] } serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.91" serde_json = "1.0.91"
[dev-dependencies]
jsonschema = "0.17.1"

1
f3-schemas Submodule

@ -0,0 +1 @@
Subproject commit 12240cef49703c2e62ba5a6b4a4f98b3053ba365

View file

@ -22,16 +22,16 @@ use crate::Reaction;
/// Comments associated to an issue or a pull/merge request within the repository of a forge /// Comments associated to an issue or a pull/merge request within the repository of a forge
/// (Gitea, GitLab, etc.) /// (Gitea, GitLab, etc.)
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
pub struct Comment { pub struct Comment {
/// Unique identifier of the issue or pull/merge request containing the comment /// Unique identifier of the issue or pull/merge request containing the comment
pub issue_index: usize, pub issue_index: usize,
/// Unique identifier of the comment /// Unique identifier of the comment
pub index: usize, pub index: String,
/// Unique identifier of the user who authored the comment /// Unique identifier of the user who authored the comment
pub poster_id: usize, pub poster_id: String,
// TODO: add validation for format "date-time" // TODO: add validation for format "date-time"
/// Creating time /// Creating time

View file

@ -23,10 +23,10 @@ use crate::{OpenCloseState, Reaction};
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct Issue { pub struct Issue {
/// Unique identifier, relative to the repository /// Unique identifier, relative to the repository
pub index: usize, pub index: String,
/// Unique identifier of the user who authored the issue. /// Unique identifier of the user who authored the issue.
pub poster_id: usize, pub poster_id: String,
/// Short description displayed as the title. /// Short description displayed as the title.
pub title: String, pub title: String,
@ -40,10 +40,10 @@ pub struct Issue {
/// "reference". However, "reference" will automatically be renamed to "ref" while serializing /// "reference". However, "reference" will automatically be renamed to "ref" while serializing
/// and vice versa /// and vice versa
#[serde(rename(serialize = "ref", deserialize = "ref"))] #[serde(rename(serialize = "ref", deserialize = "ref"))]
pub reference: Option<String>, pub reference: String,
/// Name of the milestone /// Name of the milestone
pub milestone: Option<String>, pub milestone: String,
/// state of the issue /// state of the issue
pub state: OpenCloseState, pub state: OpenCloseState,

View file

@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct Label { pub struct Label {
/// Unique identifier of the label /// Unique identifier of the label
pub index: usize, pub index: String,
/// Name of the label, unique within the repository /// Name of the label, unique within the repository
pub name: String, pub name: String,
@ -31,5 +31,5 @@ pub struct Label {
pub color: String, pub color: String,
/// Long, multi-line description /// Long, multi-line description
pub description: Option<String>, pub description: String,
} }

View file

@ -25,6 +25,8 @@ pub mod identities;
pub mod issue; pub mod issue;
pub mod label; pub mod label;
pub mod milestone; pub mod milestone;
pub mod object;
pub mod organization;
pub mod project; pub mod project;
pub mod pullrequest; pub mod pullrequest;
pub mod reaction; pub mod reaction;
@ -39,6 +41,8 @@ pub use identities::Identities;
pub use issue::Issue; pub use issue::Issue;
pub use label::Label; pub use label::Label;
pub use milestone::Milestone; pub use milestone::Milestone;
pub use object::Object;
pub use organization::Organization;
pub use project::Project; pub use project::Project;
pub use pullrequest::PullRequest; pub use pullrequest::PullRequest;
pub use reaction::Reaction; pub use reaction::Reaction;

34
src/object.rs Normal file
View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//! Meta information and reference to an opaque content such as an image. The unique identifier is the SHA-256 of the content of the object.
use serde::{Deserialize, Serialize};
/// Meta information and reference to an opaque content such as an image. The unique identifier is the SHA-256 of the content of the object.
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct Object {
/// Unique identifier
pub index: String,
/// Human readable file name.
pub name: String,
/// Mime type of the object.
pub mime: String,
/// Description
pub description: String,
}

28
src/organization.rs Normal file
View file

@ -0,0 +1,28 @@
/*
* Copyright (C) 2023 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//! An organization that contains projects.
use serde::{Deserialize, Serialize};
/// An organization that contains projects.
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct Organization {
/// Unique identifier of the organization
pub index: String,
/// User readable name of the organization."
pub name: String,
}

View file

@ -23,7 +23,7 @@ use crate::Repository;
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct Project { pub struct Project {
/// Unique identifier of the project /// Unique identifier of the project
pub index: usize, pub index: String,
/// Name of the project, relative to the owner /// Name of the project, relative to the owner
pub name: String, pub name: String,

View file

@ -23,10 +23,10 @@ use crate::{OpenCloseState, Reaction};
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct PullRequest { pub struct PullRequest {
/// Unique identifier, relative to the repository /// Unique identifier, relative to the repository
pub index: usize, pub index: String,
/// Unique identifier of the user who authored the pull request. /// Unique identifier of the user who authored the pull request.
pub poster_id: usize, pub poster_id: String,
/// Short description displayed as the title. /// Short description displayed as the title.
pub title: String, pub title: String,
@ -35,7 +35,7 @@ pub struct PullRequest {
pub content: String, pub content: String,
/// Name of the milestone /// Name of the milestone
pub milestone: Option<String>, pub milestone: String,
/// state of the pull request /// state of the pull request
pub state: OpenCloseState, pub state: OpenCloseState,

View file

@ -21,7 +21,7 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct User { pub struct User {
/// Unique identifier of the user /// Unique identifier of the user
pub index: usize, pub index: String,
/// User readable name of the user /// User readable name of the user
pub name: String, pub name: String,
@ -30,7 +30,7 @@ pub struct User {
pub username: String, pub username: String,
/// Mail of the user /// Mail of the user
pub email: Option<String>, pub email: String,
/// Password of the user /// Password of the user
pub password: String, pub password: String,

100
tests/basic.rs Normal file
View file

@ -0,0 +1,100 @@
use std::fs;
use std::path::Path;
use jsonschema::JSONSchema;
use serde::Serialize;
use serde_json::json;
fn util<T: Serialize>(instance: &T, schema_path: &Path) {
let instance = json!(instance);
let schema_str = fs::read_to_string(schema_path).unwrap();
let schema = serde_json::from_str(&schema_str).unwrap();
let compiled = JSONSchema::compile(&schema).expect("A valid schema");
let result = compiled.validate(&instance);
if let Err(errors) = result {
for error in errors {
println!("Validation error: {}", error);
println!("Instance path: {}", error.instance_path);
}
}
assert!(compiled.is_valid(&instance));
}
#[test]
fn test_comment() {
let schema_path = Path::new("./f3-schemas/comment.json");
let instance = f3_rs::Comment {
created: "1963-06-19T08:30:06.283185Z".into(),
updated: "1963-06-19T08:30:06.283185Z".into(),
..Default::default()
};
util(&instance, schema_path);
}
#[test]
fn test_issue() {
let schema_path = Path::new("./f3-schemas/issue.json");
let instance = f3_rs::Issue {
created: "1963-06-19T08:30:06.283185Z".into(),
updated: "1963-06-19T08:30:06.283185Z".into(),
..Default::default()
};
util(&instance, schema_path);
}
#[test]
fn test_user() {
let schema_path = Path::new("./f3-schemas/user.json");
let instance = f3_rs::User {
..Default::default()
};
util(&instance, schema_path);
}
#[test]
fn test_pr() {
let schema_path = Path::new("./f3-schemas/pullrequest.json");
let instance = f3_rs::PullRequest {
created: "1963-06-19T08:30:06.283185Z".into(),
updated: "1963-06-19T08:30:06.283185Z".into(),
..Default::default()
};
util(&instance, schema_path);
}
#[test]
fn test_identities() {
let schema_path = Path::new("./f3-schemas/identities.json");
let instance = f3_rs::Identities::default();
util(&instance, schema_path);
}
#[test]
fn test_label() {
let schema_path = Path::new("./f3-schemas/label.json");
let instance = f3_rs::Label::default();
util(&instance, schema_path);
}
#[test]
fn test_object() {
let schema_path = Path::new("./f3-schemas/object.json");
let instance = f3_rs::Object::default();
util(&instance, schema_path);
}
#[test]
fn test_organization() {
let schema_path = Path::new("./f3-schemas/organization.json");
let instance = f3_rs::Organization::default();
util(&instance, schema_path);
}
#[test]
fn test_project() {
let schema_path = Path::new("./f3-schemas/project.json");
let instance = f3_rs::Project {
..Default::default()
};
util(&instance, schema_path);
}