Skip to content

Commit

Permalink
getting Code Scanning (#669)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrienpessu authored Jul 30, 2024
1 parent c8910fe commit 870b74a
Show file tree
Hide file tree
Showing 14 changed files with 796 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Currently, the following modules are available as of version `0.17`.
- [`teams`] Teams.
- [`gists`] GitHub's gists API
- [`users`] Users.
- [`code_scannings`] Code scannings

[`models`]: https://docs.rs/octocrab/latest/octocrab/models/index.html
[`auth`]: https://docs.rs/octocrab/latest/octocrab/auth/index.html
Expand Down
1 change: 1 addition & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod actions;
pub mod activity;
pub mod apps;
pub mod checks;
pub mod code_scannings;
pub mod commits;
pub mod current;
pub mod events;
Expand Down
43 changes: 43 additions & 0 deletions src/api/code_scannings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! The code scanning API.
use crate::{models, params, Octocrab, Result};

mod list;

/// Handler for GitHub's code scanning API.
///
/// Created with [`Octocrab::code_scannings`].
pub struct CodeScanningHandler<'octo> {
crab: &'octo Octocrab,
owner: String,
repo: Option<String>,
}

impl<'octo> CodeScanningHandler<'octo> {
pub(crate) fn new(crab: &'octo Octocrab, owner: String, repo: Option<String>) -> Self {
Self { crab, owner, repo }
}

/// Gets an code scanning from the repository.
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// # let octocrab = octocrab::Octocrab::default();
/// let code_scanning = octocrab.code_scannings("owner", "repo").get(3).await?;
/// # Ok(())
/// # }
/// ```
pub async fn get(&mut self, number: u64) -> Result<models::code_scannings::CodeScanningAlert> {
let route = format!(
"/repos/{owner}/{repo}/code-scanning/alerts/{number}",
owner = self.owner,
repo = self.repo.as_mut().expect("Repository must be specified"),
number = number,
);

self.crab.get(route, None::<&()>).await
}

/// List code scannings in the repository.
pub fn list(&self) -> list::ListCodeScanningsBuilder<'_, '_> {
list::ListCodeScanningsBuilder::new(self)
}
}
100 changes: 100 additions & 0 deletions src/api/code_scannings/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use super::*;
use crate::params::Direction;

#[derive(crate::Serialize)]
pub struct ListCodeScanningsBuilder<'octo, 'b> {
#[serde(skip)]
handler: &'b CodeScanningHandler<'octo>,
#[serde(skip_serializing_if = "Option::is_none")]
tool_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
tool_guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
per_page: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
reference: Option<params::code_scannings::Reference>,
#[serde(skip_serializing_if = "Option::is_none")]
direction: Option<Direction>,
#[serde(skip_serializing_if = "Option::is_none")]
sort: Option<params::code_scannings::Sort>,
#[serde(skip_serializing_if = "Option::is_none")]
state: Option<params::State>,
#[serde(skip_serializing_if = "Option::is_none")]
severity: Option<params::code_scannings::Severity>,
}

impl<'octo, 'b, 'c, 'd> ListCodeScanningsBuilder<'octo, 'b> {
pub(crate) fn new(handler: &'b CodeScanningHandler<'octo>) -> Self {
Self {
handler,
tool_name: None,
tool_guid: None,
per_page: None,
page: None,
reference: None,
direction: None,
sort: None,
state: None,
severity: None,
}
}

/// Filter pull requests by `state`.
pub fn state(mut self, state: params::State) -> Self {
self.state = Some(state);
self
}

/// What to sort results by. Can be either `created`, `updated`,
/// `popularity` (comment count) or `long-running` (age, filtering by pulls
/// updated in the last month).
pub fn sort(mut self, sort: impl Into<params::code_scannings::Sort>) -> Self {
self.sort = Some(sort.into());
self
}

/// The direction of the sort. Can be either ascending or descending.
/// Default: descending when sort is `created` or sort is not specified,
/// otherwise ascending sort.
pub fn direction(mut self, direction: impl Into<params::Direction>) -> Self {
self.direction = Some(direction.into());
self
}

/// Results per page (max 100).
pub fn per_page(mut self, per_page: impl Into<u8>) -> Self {
self.per_page = Some(per_page.into());
self
}

/// Page number of the results to fetch.
pub fn page(mut self, page: impl Into<u32>) -> Self {
self.page = Some(page.into());
self
}

/// Sends the actual request.
pub async fn send(
self,
) -> crate::Result<crate::Page<models::code_scannings::CodeScanningAlert>> {
let route = self
.handler
.repo
.as_ref()
.map(|r| {
format!(
"/repos/{owner}/{repo}/code-scanning/alerts",
owner = self.handler.owner,
repo = r,
)
})
.unwrap_or(format!(
"/orgs/{owner}/code-scanning/alerts",
owner = self.handler.owner,
));

self.handler.crab.get(route, Some(&self)).await
}
}
21 changes: 20 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ use crate::service::middleware::extra_headers::ExtraHeadersLayer;
#[cfg(feature = "retry")]
use crate::service::middleware::retry::RetryConfig;

use crate::api::users;
use crate::api::{code_scannings, users};
use auth::{AppAuth, Auth};
use models::{AppId, InstallationId, InstallationToken};

Expand Down Expand Up @@ -1080,6 +1080,25 @@ impl Octocrab {
issues::IssueHandler::new(self, owner.into(), repo.into())
}

/// Creates a [`code_scanning::CodeSCanningHandler`] for the repo specified at `owner/repo`,
/// that allows you to access GitHub's Code scanning API.
pub fn code_scannings(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
) -> code_scannings::CodeScanningHandler {
code_scannings::CodeScanningHandler::new(self, owner.into(), Option::from(repo.into()))
}

/// Creates a [`code_scanning::CodeSCanningHandler`] for the org specified at `owner`,
/// that allows you to access GitHub's Code scanning API.
pub fn code_scannings_organisation(
&self,
owner: impl Into<String>,
) -> code_scannings::CodeScanningHandler {
code_scannings::CodeScanningHandler::new(self, owner.into(), None)
}

/// Creates a [`commits::CommitHandler`] for the repo specified at `owner/repo`,
pub fn commits(
&self,
Expand Down
2 changes: 2 additions & 0 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod actions;
pub mod activity;
pub mod apps;
pub mod checks;
pub mod code_scannings;
pub mod commits;
pub mod events;
pub mod gists;
Expand Down Expand Up @@ -105,6 +106,7 @@ id_type!(
CardId,
CheckSuiteId,
CheckRunId,
CodeScanningId,
CommentId,
InstallationId,
IssueEventId,
Expand Down
107 changes: 107 additions & 0 deletions src/models/code_scannings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use super::*;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CodeScanningAlert {
pub number: i64,
pub created_at: String,
pub updated_at: Option<String>,
pub url: String,
pub html_url: String,
pub state: String,
pub fixed_at: Option<String>,
pub dismissed_by: Dismisser,
pub dismissed_at: String,
pub dismissed_reason: String,
pub dismissed_comment: String,
pub rule: Rule,
pub tool: Tool,
pub most_recent_instance: MostRecentInstance,
pub instances_url: String,
}

#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Dismisser {
pub login: String,
pub id: UserId,
pub node_id: String,
pub avatar_url: Url,
pub gravatar_id: String,
pub url: Url,
pub html_url: Url,
pub followers_url: Url,
pub following_url: Url,
pub gists_url: Url,
pub starred_url: Url,
pub subscriptions_url: Url,
pub organizations_url: Url,
pub repos_url: Url,
pub events_url: Url,
pub received_events_url: Url,
pub r#type: String,
pub site_admin: bool,
pub patch_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Rule {
pub id: String,
pub severity: String,
pub description: String,
pub name: String,
pub tags: Vec<String>,
pub security_severity_level: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Tool {
pub name: String,
pub guid: Option<String>,
pub version: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct MostRecentInstance {
#[serde(rename = "ref")]
pub ref_field: String,
pub analysis_key: String,
pub environment: Environment,
pub category: String,
pub state: String,
pub commit_sha: String,
pub message: Message,
pub location: Location,
pub classifications: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Environment {
#[serde(rename = "build-mode")]
pub build_mode: Option<String>,
pub category: Option<String>,
pub language: Option<String>,
pub runner: Option<Vec<String>>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Message {
pub text: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Location {
pub path: String,
pub start_line: i64,
pub end_line: i64,
pub start_column: i64,
pub end_column: i64,
}
Loading

0 comments on commit 870b74a

Please sign in to comment.