diff --git a/clomonitor-core/src/linter/patterns.rs b/clomonitor-core/src/linter/patterns.rs index 6bade9b7..a61f7bc3 100644 --- a/clomonitor-core/src/linter/patterns.rs +++ b/clomonitor-core/src/linter/patterns.rs @@ -21,6 +21,7 @@ pub(crate) static LICENSE: [&str; 2] = ["LICENSE*", "COPYING*"]; pub(crate) static FOSSA_BADGE: [&str; 1] = [r"https://app.fossa.*/api/projects/.*"]; // Best practices +pub(crate) static ARTIFACTHUB_BADGE: [&str; 1] = [r"https://artifacthub.io/badge/repository/.*"]; pub(crate) static COMMUNITY_MEETING: [&str; 3] = [ r"(?i)(community|developer|development) (call|event|meeting|session)", r"(?i)(weekly|biweekly|monthly) meeting", diff --git a/clomonitor-core/src/linter/primary.rs b/clomonitor-core/src/linter/primary.rs index d97a0652..8b566f45 100644 --- a/clomonitor-core/src/linter/primary.rs +++ b/clomonitor-core/src/linter/primary.rs @@ -39,6 +39,7 @@ pub struct License { /// BestPractices section of the report. #[derive(Debug, Serialize, Deserialize)] pub struct BestPractices { + pub artifacthub_badge: bool, pub community_meeting: bool, pub openssf_badge: bool, } @@ -135,6 +136,14 @@ fn lint_license(root: &Path) -> Result { /// Run best practices checks and prepare the report's best practices section. fn lint_best_practices(root: &Path) -> Result { Ok(BestPractices { + artifacthub_badge: check::content_matches( + Globs { + root, + patterns: README, + case_sensitive: true, + }, + ARTIFACTHUB_BADGE, + )?, community_meeting: check::content_matches( Globs { root, diff --git a/clomonitor-core/src/score/primary.rs b/clomonitor-core/src/score/primary.rs index 76124989..a573f32d 100644 --- a/clomonitor-core/src/score/primary.rs +++ b/clomonitor-core/src/score/primary.rs @@ -70,11 +70,14 @@ pub(crate) fn calculate_score(report: &Report) -> Score { } // Best practices + if report.best_practices.artifacthub_badge { + score.best_practices += 5; + } if report.best_practices.community_meeting { score.best_practices += 25; } if report.best_practices.openssf_badge { - score.best_practices += 75; + score.best_practices += 70; } // Security diff --git a/clomonitor-linter/src/display.rs b/clomonitor-linter/src/display.rs index 37fd7183..baf4ca45 100644 --- a/clomonitor-linter/src/display.rs +++ b/clomonitor-linter/src/display.rs @@ -104,6 +104,10 @@ pub(crate) fn display_primary(report: &linter::primary::Report, score: &score::p cell_entry("License / FOSSA badge"), cell_check(report.license.fossa_badge), ]) + .add_row(vec![ + cell_entry("Best practices / Artifact Hub badge"), + cell_check(report.best_practices.artifacthub_badge), + ]) .add_row(vec![ cell_entry("Best practices / Community meeting"), cell_check(report.best_practices.community_meeting), diff --git a/web/src/data.tsx b/web/src/data.tsx index 9049551e..8e4dce87 100644 --- a/web/src/data.tsx +++ b/web/src/data.tsx @@ -1,6 +1,7 @@ import { BiLock, BiMedal, BiShieldQuarter, BiTrophy } from 'react-icons/bi'; import { CgFileDocument, CgReadme } from 'react-icons/cg'; import { FaBalanceScale, FaCheckDouble, FaTools } from 'react-icons/fa'; +import { FiHexagon } from 'react-icons/fi'; import { GiFountainPen, GiStamper, GiTiedScroll } from 'react-icons/gi'; import { GoLaw } from 'react-icons/go'; import { HiOutlinePencilAlt, HiTerminal } from 'react-icons/hi'; @@ -8,6 +9,7 @@ import { ImOffice } from 'react-icons/im'; import { IoIosPeople, IoMdRibbon } from 'react-icons/io'; import { RiRoadMapLine } from 'react-icons/ri'; +import ExternalLink from './layout/common/ExternalLink'; import RoundedBadge from './layout/common/RoundedBadge'; import { Category, @@ -103,7 +105,11 @@ export const REPORT_OPTIONS_BY_CATEGORY: ReportOptsByCategory = { ReportOption.Roadmap, ], [ScoreType.License]: [ReportOption.ApprovedLicense, ReportOption.SPDX, ReportOption.FossaBadge], - [ScoreType.BestPractices]: [ReportOption.OpenSSFBadge, ReportOption.CommunityMeeting], + [ScoreType.BestPractices]: [ + ReportOption.OpenSSFBadge, + ReportOption.CommunityMeeting, + ReportOption.ArtifactHubBadge, + ], [ScoreType.Security]: [ReportOption.SecurityPolicy], }, [RepositoryKind.Secondary]: { @@ -333,7 +339,7 @@ export const REPORT_OPTIONS: ReportOptionInfo = { ), weight: { - [RepositoryKind.Primary]: 75, + [RepositoryKind.Primary]: 70, }, }, [ReportOption.SecurityPolicy]: { @@ -373,4 +379,25 @@ export const REPORT_OPTIONS: ReportOptionInfo = { [RepositoryKind.Primary]: 25, }, }, + [ReportOption.ArtifactHubBadge]: { + icon: , + name: 'Artifact Hub badge', + legend: ( + + Projects can list their content on{' '} + + Artifact Hub + {' '} + to improve their discoverability. + + ), + description: ( + + We check that the README file contains an Artifact Hub badge + + ), + weight: { + [RepositoryKind.Primary]: 5, + }, + }, }; diff --git a/web/src/types.ts b/web/src/types.ts index a56e90a6..66fab358 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -173,6 +173,7 @@ export enum ReportOption { OpenSSFBadge = 'openssfBadge', SecurityPolicy = 'securityPolicy', CommunityMeeting = 'communityMeeting', + ArtifactHubBadge = 'artifacthubBadge', } export interface SearchFiltersURL extends BasicQuery {