Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trademark footer check #112

Merged
merged 1 commit into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
*.snap linguist-generated
*.sql linguist-detectable=true
*.sql linguist-language=sql
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions clomonitor-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ glob = "0.3.0"
lazy_static = "1.4.0"
octocrab = "0.15.4"
regex = "1.5.4"
reqwest = "0.11.9"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8.23"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
Expand Down
13 changes: 13 additions & 0 deletions clomonitor-core/src/linter/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use askalono::*;
use glob::{glob_with, MatchOptions, PatternError};
use lazy_static::lazy_static;
use regex::{Regex, RegexSet};
use reqwest;
use std::fs;
use std::path::{Path, PathBuf};

Expand Down Expand Up @@ -81,6 +82,18 @@ where
}))
}

/// Check if the content of the url provided matches any of the regular
/// expressions given.
pub(crate) async fn content_url_matches<R>(url: &str, regexps: R) -> Result<bool, Error>
where
R: IntoIterator,
R::Item: AsRef<str>,
{
let content = reqwest::get(url).await?.text().await?;
let re = RegexSet::new(regexps)?;
Ok(re.is_match(&content))
}

/// Check if the license provided is an approved one.
pub(crate) fn is_approved_license(spdx_id: &str) -> bool {
APPROVED_LICENSES.contains(&spdx_id)
Expand Down
2 changes: 2 additions & 0 deletions clomonitor-core/src/linter/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub(crate) static COMMUNITY_MEETING_TEXT: [&str; 3] = [
];
pub(crate) static OPENSSF_BADGE_URL: [&str; 1] =
[r"https://bestpractices.coreinfrastructure.org/projects/\d+"];
pub(crate) static TRADEMARK_FOOTER: [&str; 1] =
[r"https://www.linuxfoundation.org/trademark-usage"];

// Security
pub(crate) static SECURITY_POLICY_FILE: [&str; 3] =
Expand Down
31 changes: 23 additions & 8 deletions clomonitor-core/src/linter/primary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct BestPractices {
pub community_meeting: bool,
pub openssf_badge: bool,
pub recent_release: bool,
pub trademark_footer: bool,
}

/// Security section of the report.
Expand All @@ -66,11 +67,12 @@ pub async fn lint(options: LintOptions<'_>) -> Result<Report, Error> {
// Get CLOMonitor metadata
let md = Metadata::from(options.root.join(METADATA_FILE))?;

// Run some async expressions and wait for them to complete
let (gh_md, best_practices) = tokio::try_join!(
github::get_metadata(options.url),
lint_best_practices(options.root, options.url)
)?;
// Get Github metadata
let gh_md = github::get_metadata(options.url).await?;

// Async checks: best_practices
let (best_practices,) =
tokio::try_join!(lint_best_practices(options.root, options.url, &gh_md))?;

Ok(Report {
documentation: lint_documentation(options.root, &gh_md)?,
Expand Down Expand Up @@ -235,7 +237,11 @@ fn lint_license(root: &Path, md: &Option<Metadata>) -> Result<License, Error> {
}

/// Run best practices checks and prepare the report's best practices section.
async fn lint_best_practices(root: &Path, repo_url: &str) -> Result<BestPractices, Error> {
async fn lint_best_practices(
root: &Path,
repo_url: &str,
gh_md: &Repository,
) -> Result<BestPractices, Error> {
// Artifact Hub badge
let artifacthub_badge = check::content_matches(
Globs {
Expand Down Expand Up @@ -266,14 +272,23 @@ async fn lint_best_practices(root: &Path, repo_url: &str) -> Result<BestPractice
OPENSSF_BADGE_URL,
)?;

// Async checks: recent_release
let (recent_release,) = tokio::try_join!(github::has_recent_release(repo_url))?;
// Recent release
let recent_release = github::has_recent_release(repo_url).await?;

// Trademark footer
let mut trademark_footer: bool = false;
if let Some(url) = &gh_md.homepage {
if !url.is_empty() {
trademark_footer = check::content_url_matches(url, TRADEMARK_FOOTER).await?;
}
}

Ok(BestPractices {
artifacthub_badge,
community_meeting,
openssf_badge,
recent_release,
trademark_footer,
})
}

Expand Down
7 changes: 6 additions & 1 deletion clomonitor-core/src/score/primary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,14 @@ pub(crate) fn calculate_score(report: &Report) -> Score {
score.best_practices += 25;
}
if report.best_practices.openssf_badge {
score.best_practices += 60;
score.best_practices += 50;
}
if report.best_practices.recent_release {
score.best_practices += 10;
}
if report.best_practices.trademark_footer {
score.best_practices += 10;
}

// Security
if report.security.security_policy {
Expand Down Expand Up @@ -146,6 +149,7 @@ mod tests {
community_meeting: true,
openssf_badge: true,
recent_release: true,
trademark_footer: true,
},
security: Security {
security_policy: true,
Expand Down Expand Up @@ -186,6 +190,7 @@ mod tests {
community_meeting: false,
openssf_badge: false,
recent_release: false,
trademark_footer: false,
},
security: Security {
security_policy: false,
Expand Down
4 changes: 4 additions & 0 deletions clomonitor-linter/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ pub(crate) fn display_primary(report: &linter::primary::Report, score: &score::p
cell_entry("Best practices / Recent release"),
cell_check(report.best_practices.recent_release),
])
.add_row(vec![
cell_entry("Best practices / Trademark footer"),
cell_check(report.best_practices.trademark_footer),
])
.add_row(vec![
cell_entry("Security / Security policy"),
cell_check(report.security.security_policy),
Expand Down
8 changes: 7 additions & 1 deletion web/src/data.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BiLock, BiMedal, BiShieldQuarter, BiTrophy, BiWorld } from 'react-icons/bi';
import { BsCalendar3 } from 'react-icons/bs';
import { CgFileDocument, CgReadme } from 'react-icons/cg';
import { FaBalanceScale, FaCheckDouble, FaTools } from 'react-icons/fa';
import { FaBalanceScale, FaCheckDouble, FaTools, FaTrademark } from 'react-icons/fa';
import { FiHexagon } from 'react-icons/fi';
import { GiFountainPen, GiStamper, GiTiedScroll } from 'react-icons/gi';
import { GoLaw } from 'react-icons/go';
Expand Down Expand Up @@ -314,6 +314,12 @@ export const REPORT_OPTIONS: ReportOptionInfo = {
</span>
),
},
[ReportOption.TrademarkFooter]: {
icon: <FaTrademark />,
name: 'Trademark footer',
legend: <span>Projects sites should have Linux Foundation trademark footer</span>,
description: <span>We check that the website defined in Github has the trademark footer</span>,
},
[ReportOption.Website]: {
icon: <BiWorld />,
name: 'Website',
Expand Down
1 change: 1 addition & 0 deletions web/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export enum ReportOption {
Roadmap = 'roadmap',
SecurityPolicy = 'security_policy',
SPDX = 'spdx_id',
TrademarkFooter = 'trademark_footer',
Website = 'website',
}

Expand Down