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

feat: ✨ codefair v1 #30

Merged
merged 101 commits into from
Jul 11, 2024
Merged

feat: ✨ codefair v1 #30

merged 101 commits into from
Jul 11, 2024

Conversation

slugb0t
Copy link
Member

@slugb0t slugb0t commented Jul 11, 2024

No description provided.

slugb0t and others added 30 commits April 25, 2024 17:44
* 🐛 fix: update env var name

* 🐛 fix: update folder name

* 🐛 fix: update probot to esm

* ✨ feat: add basic license get page

---------

Co-authored-by: Dorian Portillo <wheresdorian@gmail.com>
* 🐛 fix: update env var name

* 🐛 fix: update folder name

* 🐛 fix: update probot to esm

* ✨ feat: add basic license get page

* 🚧 wip: add base ui

* ✨ feat: add license ui

---------

Co-authored-by: Dorian Portillo <wheresdorian@gmail.com>
* 🚧 wip: protected page

* 🚧 fix: auth
* 🚧 wip: add mongoose

* fix: 🐛 mongoose adapter/callback

* refactor: ♻️ use mongoose on client end

* chore: 🔨 remove unused code

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* ✨ feat: add error sections

* 🧑‍💻 chore: remove console.logs

---------

Co-authored-by: slugb0t <wheresdorian@gmail.com>
* dev: 👷 yml file for creating probot app

* wip: 🚧 dashboard issue

* dev: 👷 nodemon for probot

* refactor: ♻️ provide context for renderissue fn + nodemon file watch

* wip: 🚧 provide localhost list depending on production

* feat: ✨ provide link to PR for dashboard

* feat: ✨ update dashboard on push

* wip: 🚧 abstracting code

* wip: 🚧 abstract functions of probot

* feat: ✨ dashboard workflow for LICENSE

* wip: 🚧 clean license UI

* feat: ✨ help text for license UI

* feat: ✨ renderer file has documentation + db update

* feat: ✨ documentation for tools

* feat: ✨ documentation for probot event listeners

* refactor: ♻️ file name instead of just name on UI/add license page

* wip: 🚧 styling for license UI

Co-authored-by: Dorian Portillo <wheresdorian@gmail.com>
@slugb0t slugb0t requested a review from megasanjay July 11, 2024 20:46
Copy link

Thank you for submitting this pull request! We appreciate your contribution to the project. Before we can merge it, we need to review the changes you've made to ensure they align with our code standards and meet the requirements of the project. We'll get back to you as soon as we can with feedback. Thanks again!

Copy link

vercel bot commented Jul 11, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
codefair ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2024 8:53pm
codefair-bot ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2024 8:53pm

Copy link

sourcery-ai bot commented Jul 11, 2024

🧙 Sourcery has finished reviewing your pull request!


Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • Continue your discussion with Sourcery by replying directly to review comments.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine. If you would also like our AI-powered code review then let us know.

Comment on lines 268 to 278
if (
context.payload.issue.title === "No citation file found [codefair-app]" &&
context.payload.issue.title ===
`No citation file found [${GITHUB_APP_NAME}]` &&
["MEMBER", "OWNER"].includes(authorAssociation) &&
userComment.includes("codefair-app")
userComment.includes(GITHUB_APP_NAME)
) {
if (userComment.includes("Yes")) {
// Gather the information for the CITATION.cff file
await gatherCitationInfo(context, owner, repo);
await gatherCitationInfo(context, owner, repoName);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Merge nested if conditions (merge-nested-ifs)

Suggested change
if (
context.payload.issue.title === "No citation file found [codefair-app]" &&
context.payload.issue.title ===
`No citation file found [${GITHUB_APP_NAME}]` &&
["MEMBER", "OWNER"].includes(authorAssociation) &&
userComment.includes("codefair-app")
userComment.includes(GITHUB_APP_NAME)
) {
if (userComment.includes("Yes")) {
// Gather the information for the CITATION.cff file
await gatherCitationInfo(context, owner, repo);
await gatherCitationInfo(context, owner, repoName);
}
}
if (context.payload.issue.title ===
`No citation file found [${GITHUB_APP_NAME}]` &&
["MEMBER", "OWNER"].includes(authorAssociation) &&
userComment.includes(GITHUB_APP_NAME) && userComment.includes("Yes")) {
await gatherCitationInfo(context, owner, repoName);
}


ExplanationReading deeply nested conditional code is confusing, since you have to keep track of which
conditions relate to which levels. We therefore strive to reduce nesting where
possible, and the situation where two if conditions can be combined using
and is an easy win.

Comment on lines 280 to 290
}
}

async function verifyFirstIssue(context, owner, repo, title) {
// If there is an issue that has been created by the bot, (either opened or closed) don't create another issue
const issues = await context.octokit.issues.listForRepo({
owner,
repo,
creator: "codefair-app[bot]",
state: "all",
});

if (issues.data.length > 0) {
// iterate through issues to see if there is an issue with the same title
let no_issue = false;
for (let i = 0; i < issues.data.length; i++) {
if (issues.data[i].title === title) {
console.log("Issue already exists, will not recreate");
no_issue = true;
break;
}
}

if (!no_issue) {
return false;
} else {
return true;
}
}
}

async function checkForLicense(context, owner, repo) {
console.log("checking for license");
try {
await context.octokit.rest.licenses.getForRepo({
owner,
repo,
});

console.log("license found!");
return true;
} catch (error) {
console.log("no license found");
// Errors when no License is found in the repo
return false;
}
}

async function checkForCitation(context, owner, repo) {
try {
await context.octokit.rest.repos.getContent({
owner,
repo,
path: "CITATION.cff",
});

return true;
} catch (error) {
return false;
}
}

async function checkForCodeMeta(context, owner, repo) {
try {
await context.octokit.rest.repos.getContent({
owner,
repo,
path: "codemeta.json",
});

return true;
} catch (error) {
return false;
}
}

async function createIssue(context, owner, repo, title, body) {
// If issue has been created, create one
console.log("gathering issues");
const issue = await context.octokit.issues.listForRepo({
owner,
repo: repo,
state: "open",
creator: "codefair-app[bot]",
title: title,
});

console.log("ISSUE DATA");
console.log(issue.data);

if (issue.data.length > 0) {
// iterate through issues to see if there is an issue with the same title
let no_issue = false;
for (let i = 0; i < issue.data.length; i++) {
if (issue.data[i].title === title) {
no_issue = true;
break;
await gatherCodeMetaInfo(context, owner, repoName);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Merge nested if conditions (merge-nested-ifs)

Suggested change
if (
context.payload.issue.title ===
"No codemeta.json file found [codefair-app]" &&
`No codemeta.json file found [${GITHUB_APP_NAME}]` &&
["MEMBER", "OWNER"].includes(authorAssociation) &&
userComment.includes("codefair-app")
userComment.includes(GITHUB_APP_NAME)
) {
if (userComment.includes("Yes")) {
// Gather the information for the codemeta.json file
await gatherCodeMetaInfo(context, owner, repo);
}
}
});
};
async function getDefaultBranch(context, owner, repo) {
let default_branch;
try {
default_branch = await context.octokit.repos.getBranch({
owner,
repo,
branch: context.payload.repository.default_branch,
});
return default_branch;
} catch (error) {
console.log("Error getting the default branch");
console.log(error);
return;
}
}
async function closeOpenIssue(context, owner, repo, title) {
// Check if issue is open and close it
// TODO: UPDATE THE CREATOR WHEN MOVING TO PROD
const issue = await context.octokit.issues.listForRepo({
owner,
repo: repo,
state: "open",
creator: "codefair-app[bot]",
title: title,
});
if (issue.data.length > 0) {
// If title if issue is found, close the issue
for (let i = 0; i < issue.data.length; i++) {
if (issue.data[i].title === title) {
await context.octokit.issues.update({
repo,
owner,
issue_number: issue.data[i].number,
state: "closed",
});
}
}
}
}
async function verifyFirstIssue(context, owner, repo, title) {
// If there is an issue that has been created by the bot, (either opened or closed) don't create another issue
const issues = await context.octokit.issues.listForRepo({
owner,
repo,
creator: "codefair-app[bot]",
state: "all",
});
if (issues.data.length > 0) {
// iterate through issues to see if there is an issue with the same title
let no_issue = false;
for (let i = 0; i < issues.data.length; i++) {
if (issues.data[i].title === title) {
console.log("Issue already exists, will not recreate");
no_issue = true;
break;
}
}
if (!no_issue) {
return false;
} else {
return true;
}
}
}
async function checkForLicense(context, owner, repo) {
console.log("checking for license");
try {
await context.octokit.rest.licenses.getForRepo({
owner,
repo,
});
console.log("license found!");
return true;
} catch (error) {
console.log("no license found");
// Errors when no License is found in the repo
return false;
}
}
async function checkForCitation(context, owner, repo) {
try {
await context.octokit.rest.repos.getContent({
owner,
repo,
path: "CITATION.cff",
});
return true;
} catch (error) {
return false;
}
}
async function checkForCodeMeta(context, owner, repo) {
try {
await context.octokit.rest.repos.getContent({
owner,
repo,
path: "codemeta.json",
});
return true;
} catch (error) {
return false;
}
}
async function createIssue(context, owner, repo, title, body) {
// If issue has been created, create one
console.log("gathering issues");
const issue = await context.octokit.issues.listForRepo({
owner,
repo: repo,
state: "open",
creator: "codefair-app[bot]",
title: title,
});
console.log("ISSUE DATA");
console.log(issue.data);
if (issue.data.length > 0) {
// iterate through issues to see if there is an issue with the same title
let no_issue = false;
for (let i = 0; i < issue.data.length; i++) {
if (issue.data[i].title === title) {
no_issue = true;
break;
await gatherCodeMetaInfo(context, owner, repoName);
}
}
if (context.payload.issue.title ===
`No codemeta.json file found [${GITHUB_APP_NAME}]` &&
["MEMBER", "OWNER"].includes(authorAssociation) &&
userComment.includes(GITHUB_APP_NAME) && userComment.includes("Yes")) {
await gatherCodeMetaInfo(context, owner, repoName);
}


ExplanationReading deeply nested conditional code is confusing, since you have to keep track of which
conditions relate to which levels. We therefore strive to reduce nesting where
possible, and the situation where two if conditions can be combined using
and is an easy win.

Comment on lines +208 to +245
const codeMeta = {
name: repoData.data.name,
applicationCategory: null,
authors: citationAuthors || [],
codeRepository: repoData.data.html_url,
continuousIntegration: "",
contributors: [],
creationDate: Date.parse(repoData.data.created_at) || null,
currentVersion: releases.data[0]?.tag_name || "",
currentVersionDownloadURL: releases.data[0]?.html_url || "",
currentVersionReleaseDate:
Date.parse(releases.data[0]?.published_at) || null,
currentVersionReleaseNotes: releases.data[0]?.body || "",
description: repoData.data.description,
developmentStatus: null,
firstReleaseDate: Date.parse(releases.data[0]?.published_at) || null,
fundingCode: "",
fundingOrganization: "",
isPartOf: "",
isSourceCodeOf: "",
issueTracker: `https://github.com/${owner}/${repo.name}/issues`,
keywords: repoData.data.topics || [],
license:
repoData.data.license?.spdx_id === "NOASSERTION"
? null
: repoData.data.license?.spdx_id || null,
operatingSystem: [],
otherSoftwareRequirements: [],
programmingLanguages: languagesUsed || [],
referencePublication: doi[1] || "",
relatedLinks: [],
reviewAspect: "",
reviewBody: "",
runtimePlatform: [],
uniqueIdentifier: "",
};

return codeMeta;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Inline variable that is immediately returned (inline-immediately-returned-variable)

Suggested change
const codeMeta = {
name: repoData.data.name,
applicationCategory: null,
authors: citationAuthors || [],
codeRepository: repoData.data.html_url,
continuousIntegration: "",
contributors: [],
creationDate: Date.parse(repoData.data.created_at) || null,
currentVersion: releases.data[0]?.tag_name || "",
currentVersionDownloadURL: releases.data[0]?.html_url || "",
currentVersionReleaseDate:
Date.parse(releases.data[0]?.published_at) || null,
currentVersionReleaseNotes: releases.data[0]?.body || "",
description: repoData.data.description,
developmentStatus: null,
firstReleaseDate: Date.parse(releases.data[0]?.published_at) || null,
fundingCode: "",
fundingOrganization: "",
isPartOf: "",
isSourceCodeOf: "",
issueTracker: `https://github.com/${owner}/${repo.name}/issues`,
keywords: repoData.data.topics || [],
license:
repoData.data.license?.spdx_id === "NOASSERTION"
? null
: repoData.data.license?.spdx_id || null,
operatingSystem: [],
otherSoftwareRequirements: [],
programmingLanguages: languagesUsed || [],
referencePublication: doi[1] || "",
relatedLinks: [],
reviewAspect: "",
reviewBody: "",
runtimePlatform: [],
uniqueIdentifier: "",
};
return codeMeta;
return {
name: repoData.data.name,
applicationCategory: null,
authors: citationAuthors || [],
codeRepository: repoData.data.html_url,
continuousIntegration: "",
contributors: [],
creationDate: Date.parse(repoData.data.created_at) || null,
currentVersion: releases.data[0]?.tag_name || "",
currentVersionDownloadURL: releases.data[0]?.html_url || "",
currentVersionReleaseDate:
Date.parse(releases.data[0]?.published_at) || null,
currentVersionReleaseNotes: releases.data[0]?.body || "",
description: repoData.data.description,
developmentStatus: null,
firstReleaseDate: Date.parse(releases.data[0]?.published_at) || null,
fundingCode: "",
fundingOrganization: "",
isPartOf: "",
isSourceCodeOf: "",
issueTracker: `https://github.com/${owner}/${repo.name}/issues`,
keywords: repoData.data.topics || [],
license:
repoData.data.license?.spdx_id === "NOASSERTION"
? null
: repoData.data.license?.spdx_id || null,
operatingSystem: [],
otherSoftwareRequirements: [],
programmingLanguages: languagesUsed || [],
referencePublication: doi[1] || "",
relatedLinks: [],
reviewAspect: "",
reviewBody: "",
runtimePlatform: [],
uniqueIdentifier: "",
};


ExplanationSomething that we often see in people's code is assigning to a result variable
and then immediately returning it.

Returning the result directly shortens the code and removes an unnecessary
variable, reducing the mental load of reading the function.

Where intermediate variables can be useful is if they then get used as a
parameter or a condition, and the name can act like a comment on what the
variable represents. In the case where you're returning it from a function, the
function name is there to tell you what the result is, so the variable name
is unnecessary.

import { checkForLicense } from "../license/index.js";
import { gatherMetadata, convertMetadataForDB } from "../metadata/index.js";

const GITHUB_APP_NAME = process.env.GITHUB_APP_NAME;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)

Suggested change
const GITHUB_APP_NAME = process.env.GITHUB_APP_NAME;
const {GITHUB_APP_NAME} = process.env;


ExplanationObject destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the Airbnb Javascript Style Guide

Comment on lines +4 to +6
const user = useState<User | null>("user", () => null);

return user;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Inline variable that is immediately returned (inline-immediately-returned-variable)

Suggested change
const user = useState<User | null>("user", () => null);
return user;
return useState<User | null>("user", () => null);


ExplanationSomething that we often see in people's code is assigning to a result variable
and then immediately returning it.

Returning the result directly shortens the code and removes an unnecessary
variable, reducing the mental load of reading the function.

Where intermediate variables can be useful is if they then get used as a
parameter or a condition, and the name can act like a comment on what the
variable represents. In the case where you're returning it from a function, the
function name is there to tell you what the result is, so the variable name
is unnecessary.

@vercel vercel bot temporarily deployed to Preview – codefair July 11, 2024 20:53 Inactive
@vercel vercel bot temporarily deployed to Preview – codefair-bot July 11, 2024 20:53 Inactive
@slugb0t slugb0t merged commit 9262c64 into main Jul 11, 2024
4 checks passed
Copy link

Thanks for closing this pull request! If you have any further questions, please feel free to open a new issue. We are always happy to help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants