From a363f2032c97483ebfe228464833506ef3b49d02 Mon Sep 17 00:00:00 2001 From: Maurizio Pillitu Date: Fri, 5 Jul 2024 00:41:03 +0200 Subject: [PATCH] aligned docs with project reporting structure in code still some TODOs in the code --- .gitignore | 1 + .project | 11 ++++ README.md | 8 +-- .../org/finos/ls/queries/BasicQueries.java | 12 ++-- .../ls/queries/ProjectScanCSVSummarizer.java | 65 +++++++++++-------- src/test/java/org/finos/ls/BasicTest.java | 20 +++--- 6 files changed, 69 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index 917c5371c..a8081f0f5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ application-local.yml /bin env lib +.project \ No newline at end of file diff --git a/.project b/.project index 813649cb7..2af67ca8d 100644 --- a/.project +++ b/.project @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1720132041193 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/README.md b/README.md index 2637cef23..174c119df 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ The PAT must have the following scopes enabled: | Column name | description | | ----------- | ----------- | -| Total Score | Issue Activity + Commit Activity | +| Score | Issue Activity + Commit Activity | | Pass | TO BE REMOVED | | Organisation | Name of the GitHub organisation | | Repo Name | Name of the GitHub repository | @@ -55,17 +55,17 @@ The PAT must have the following scopes enabled: | Project Type | Software Project or Special Interest Group, parsed from https://github.com/finos/finos-landscape/blob/master/landscape.yml | | Project Stage | FINOS Lifecycle Stage, parsed from https://github.com/finos/finos-landscape/blob/master/landscape.yml | | Stage | Finos Lifecycle Stage, parsed from README.md badges - https://community.finos.org/docs/governance/Software-Projects/project-lifecycle | +| Github Archived | Check if the GitHub repository is marked as archived, using GitHub API | | License | Repo license, pulled from GitHub Api - https://community.finos.org/docs/governance/Software-Projects/license-categories | | Meeting attendance | All comments to issues labeled as `meeting` in the last X days | | Issue/PR Activity | All issue creations and comments in the last X days (except for those with label `meeting`) | | Issue/PR lifespan | Average issue lifespan in the last X days | | Commit Activity | Count number of commits in last 6 months, maxed at 100 (TODO - remove the 100 max) | -| OpenSSF Best Practices Badge | The OpenSSF Best Practices score, parsed from README.md badges - https://www.bestpractices.dev/en | -| Github Archived | Check if the GitHub repository is marked as archived, using GitHub API | +| OpenSSF Best Practices | The OpenSSF Best Practices score, parsed from README.md badges - https://www.bestpractices.dev/en | | Branch Protection | Check branch rules: returns the number of approvers, 0 if no approvers are set, -1 if the is no branch protection enabled on the main branch | | SemGrep | Checks existance of .github/workflows/semgrep.yml file - (TODO - would be better to check GitHub Actions execution) | | CVE Scanning | Checks existance of .github/workflows/cve-scanning.yml file - (TODO - would be better to check GitHub Actions execution) | -| Main Branch Name | Checks if default branch name is `main` | +| Default Branch Name | Checks if default branch name is `main` | | Admins | List of users that have admin rights on the repository (expected to be 0, since only finos-admin should have Admin rights on FINOS repositories) | | Issue Participants | List of all participants for issues loaded in Issue Activity column | | Committers | List of all repository committers | diff --git a/src/main/java/org/finos/ls/queries/BasicQueries.java b/src/main/java/org/finos/ls/queries/BasicQueries.java index f69b204ed..411de4131 100644 --- a/src/main/java/org/finos/ls/queries/BasicQueries.java +++ b/src/main/java/org/finos/ls/queries/BasicQueries.java @@ -40,7 +40,7 @@ public class BasicQueries { + " }\n" + " }"; - public enum FinosStatus { NO_README, INCUBATING, ACTIVE, NONE } + public enum FinosStage { NO_README, INCUBATING, ACTIVE, NONE } public enum OpenSSFStatus { NO_README, OK, NONE } @@ -91,20 +91,20 @@ public enum OpenSSFStatus { NO_README, OK, NONE } + " }", 20, (r, qe) -> wrongAdmins(r)); - public static QueryType FINOS_STATUS = new AbstractQueryType( + public static QueryType FINOS_STAGE = new AbstractQueryType( FILE_LIST, 10, (r, qe) -> { String text = getReadme(r, qe); if (text == null) { - return FinosStatus.NO_README; + return FinosStage.NO_README; } else if (text.contains("https://finosfoundation.atlassian.net/wiki/display/FINOS/Incubating") || text.contains("https://cdn.jsdelivr.net/gh/finos/contrib-toolbox@master/images/badge-incubating.svg")) { - return FinosStatus.INCUBATING; + return FinosStage.INCUBATING; } else if (text.contains("https://finosfoundation.atlassian.net/wiki/display/FINOS/Active") || text.contains("https://cdn.jsdelivr.net/gh/finos/contrib-toolbox@master/images/badge-released.svg")) { - return FinosStatus.ACTIVE; + return FinosStage.ACTIVE; } else { - return FinosStatus.NONE; + return FinosStage.NONE; } }); diff --git a/src/main/java/org/finos/ls/queries/ProjectScanCSVSummarizer.java b/src/main/java/org/finos/ls/queries/ProjectScanCSVSummarizer.java index 3e19d0523..e3ac2f9a5 100644 --- a/src/main/java/org/finos/ls/queries/ProjectScanCSVSummarizer.java +++ b/src/main/java/org/finos/ls/queries/ProjectScanCSVSummarizer.java @@ -5,7 +5,7 @@ import org.finos.ls.landscape.ProjectInfo; import org.finos.ls.landscape.ProjectInfo.ProjectType; -import org.finos.ls.queries.BasicQueries.FinosStatus; +import org.finos.ls.queries.BasicQueries.FinosStage; import org.finos.ls.queries.BasicQueries.OpenSSFStatus; import org.finos.scan.github.client.Repository; import org.finos.scan.github.client.util.QueryExecutor; @@ -22,26 +22,26 @@ public ProjectScanCSVSummarizer(List projects) { public static final String[] FIELDS = { "Score", - "Pass", "Organisation", "Repo Name", - "Finos Lifecycle State (from the README badge)", - "License (from GitHub Api)", - "Issue Activity (for most recent 50 issues, count most recent 30 comments in last 6 months)", - "Commit Activity (count of commits in last 6 months, maxed at 100)", - "OpenSSF Status (from the README badge)", - "Github Archived (has the Archive tag in GitHub API)", - "Branch Rules/Private (number of approvers or 0 if no approvers, -1 no branch rules", - "SemGrep (checks .github/workflows/semgrep.yml file exists)", - "CVE Scanning (checks .github/workflows/cve-scanning.yml file exists)", - "Default Branch Name", - "Excess Admins", - "Main Issue Participants (list of all participants for issues loaded in Issue Activity column)", - "Main Committers (list of all participants for commits loaded in Commit Activity column)", - "Length of Readme", "Project Name", - "Type", - "Stage" + "Project Type", + "Project Stage", + "Stage", + "Github Archived", + "License", + "Meeting Attendance", + "Issue/PR Activity", + "Commit Activity", + "OpenSSF Best Practices", + "Branch Protection", + "SemGrep", + "CVE Scanning", + "Default Branch Name", + "Admins", + "Issue Participants", + "Committers", + "Readme Length", }; @Override @@ -58,31 +58,43 @@ public String getFields() { @Override public List convert(Repository r, QueryExecutor qe) { + + // TODO - make sure PRs are included Activity issue = BasicQueries.ISSUE_ACTIVITY.convert(r, qe); + + // TODO - remove 100 items cap Activity commit = BasicQueries.MAIN_RECENT_COMMITTERS.convert(r, qe); - FinosStatus finosStatus = BasicQueries.FINOS_STATUS.convert(r, qe); + + // TODO - build query + Activity meetingAttendance = null; + FinosStage finosStage = BasicQueries.FINOS_STAGE.convert(r, qe); OpenSSFStatus openSSF = BasicQueries.OPENSSF_STATUS.convert(r, qe); String license = BasicQueries.LICENSE_INFO.convert(r, qe); + Boolean semGrep = BasicQueries.SEMGREP_ACTION.convert(r, qe); Boolean cveScan = BasicQueries.CVE_SCANNING_ACTION.convert(r, qe); String defaultBranchName = BasicQueries.DEFAULT_BRANCH_NAME.convert(r, qe); String wrongAdmins = BasicQueries.WRONG_ADMINS.convert(r, qe); int branchReviewers = BasicQueries.BRANCH_RULES.convert(r, qe); long score = calculateScore(issue, commit, r.getName(), r.getIsPrivate() | r.getIsArchived()); - String pass = passes(finosStatus, openSSF, wrongAdmins, branchReviewers, license, semGrep, cveScan, score == -1); + // TODO - this may be useful for documenting health criteria + // String pass = passes(finosStatus, openSSF, wrongAdmins, branchReviewers, license, semGrep, cveScan, score == -1); long readmeLength = BasicQueries.README_LENGTH.convert(r, qe); List out = new ArrayList<>(); out.add(score); - out.add(pass); out.add(r.getOwner().getLogin()); out.add(r.getName()); - out.add(finosStatus.name()); + out.add(projectName(r)); + out.add(projectType(r)); + out.add(projectStage(r)); + out.add(finosStage.name()); + out.add(r.getIsArchived()); out.add(license); + out.add(meetingAttendance); out.add(issue.getScore()); out.add(commit.getScore()); out.add(openSSF.name()); - out.add(r.getIsArchived()); out.add(r.getIsPrivate() ? "PRIVATE" : ""+branchReviewers); out.add(semGrep); out.add(cveScan); @@ -91,9 +103,6 @@ public List convert(Repository r, QueryExecutor qe) { out.add(convertToSpaceList(issue)); out.add(convertToSpaceList(commit)); out.add(readmeLength); - out.add(projectName(r)); - out.add(projectType(r)); - out.add(projectStage(r)); return out; } @@ -134,14 +143,14 @@ private ProjectInfo getMatchingProject(String name, String owner) { return null; } - private String passes(FinosStatus finosStatus, OpenSSFStatus openSSFStatus, String wrongAdmins, int branchReviewers, String license, boolean semGrep, Boolean cveScan, boolean ignore) { + private String passes(FinosStage finosStatus, OpenSSFStatus openSSFStatus, String wrongAdmins, int branchReviewers, String license, boolean semGrep, Boolean cveScan, boolean ignore) { StringBuilder sb = new StringBuilder(); if (ignore) { return ""; } - if ((finosStatus == FinosStatus.NONE) || (finosStatus == FinosStatus.NO_README)) { + if ((finosStatus == FinosStage.NONE) || (finosStatus == FinosStage.NO_README)) { sb.append(" (Finos Lifecycle)"); } diff --git a/src/test/java/org/finos/ls/BasicTest.java b/src/test/java/org/finos/ls/BasicTest.java index 8a1ff4c67..36a1a409c 100644 --- a/src/test/java/org/finos/ls/BasicTest.java +++ b/src/test/java/org/finos/ls/BasicTest.java @@ -9,7 +9,7 @@ import org.finos.ls.outputs.PullRequestService; import org.finos.ls.queries.Activity; import org.finos.ls.queries.BasicQueries; -import org.finos.ls.queries.BasicQueries.FinosStatus; +import org.finos.ls.queries.BasicQueries.FinosStage; import org.finos.ls.queries.BasicQueries.OpenSSFStatus; import org.finos.ls.queries.MarkdownSummarizer; import org.finos.ls.queries.MarkdownSummarizer.SummaryLevel; @@ -83,20 +83,20 @@ public long countStatus(Map input, X expected) { @Test public void testListOfReposWithStatusInfo() throws GraphQLRequestExecutionException, GraphQLRequestPreparationException { - FinosStatus status = qs.getSingleRepository(BasicQueries.FINOS_STATUS, ORG, "FDC3"); - Assertions.assertEquals(FinosStatus.ACTIVE, status); + FinosStage status = qs.getSingleRepository(BasicQueries.FINOS_STAGE, ORG, "FDC3"); + Assertions.assertEquals(FinosStage.ACTIVE, status); - status = qs.getSingleRepository(BasicQueries.FINOS_STATUS, ORG, "spring-bot"); - Assertions.assertEquals(FinosStatus.INCUBATING, status); + status = qs.getSingleRepository(BasicQueries.FINOS_STAGE, ORG, "spring-bot"); + Assertions.assertEquals(FinosStage.INCUBATING, status); - status = qs.getSingleRepository(BasicQueries.FINOS_STATUS, ORG, "datahub"); - Assertions.assertEquals(FinosStatus.NONE, status); + status = qs.getSingleRepository(BasicQueries.FINOS_STAGE, ORG, "datahub"); + Assertions.assertEquals(FinosStage.NONE, status); - Map statuses = qs.getAllRepositoriesInOrg(BasicQueries.FINOS_STATUS, ORG); + Map statuses = qs.getAllRepositoriesInOrg(BasicQueries.FINOS_STAGE, ORG); outputMap(statuses); - Assertions.assertTrue(countStatus(statuses, FinosStatus.ACTIVE)>5); - Assertions.assertTrue(countStatus(statuses, FinosStatus.INCUBATING)>5); + Assertions.assertTrue(countStatus(statuses, FinosStage.ACTIVE)>5); + Assertions.assertTrue(countStatus(statuses, FinosStage.INCUBATING)>5); }