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

Custom Projects List Feature #14

Open
wants to merge 57 commits into
base: master
Choose a base branch
from

Conversation

mrthankyou
Copy link
Contributor

@mrthankyou mrthankyou commented Feb 17, 2021

Issues Resolved

#11
#15

What Does This PR Do

This PR adds an optional choice for users to add projects they follow to custom lists. The way this works is as follows:

# This command finds repositories based on a search term. The projects are then followed. Please note that the custom list name will be the name of the custom list you want these projects to eventually go to.
python3 follow_repos_by_search_term.py javascript <keyword_search> <custom_list_name>

# This command actually moves the projects to your custom list and then unfollows the projects.
python3 move_repos_to_lgtm_lists.py

One neat feature is that if a project is still being built and we can't move it to the custom list, the move_repos_to_lgtm_lists.py script will stop and report that the project is still being built. This informs the user that they must wait at a later time to re-run the script

Besides this major new feature, there are numerous under-the-hood/misc changes:

  • The SimpleProject class was updated to handle processing LGTM projects for our new feature. It could use some refactoring down the road but for now it works.
  • Code in lgtm.py was refactored to allow this new feature to take advantage of some of the baked-in logic in dealing with proto vs. real projects.
  • A new utils/cacher.py was added to handle caching projects in a txt file. This txt file can then later be used in the move_repos_to_lgtm_lists.py script.
  • A unfollow_all_followed_projects.py script was added. I mostly used this for testing purposes but since I wrote it felt like I should keep it in the PR.
  • Added Python documentation to several methods.
  • All cached files are now placed in the cache folder.

Anything Else We Should Know

This took way longer than expected. As I wrap up this PR I want to note that so far I've experienced no errors in testing this new functionality. If possible, I encourage others to test this as well. Although I think all the kinks are out I've grown weary of LGTM and their internal workings.

I also have to admit that this code can be better. But I've spent more than two weeks on this and am a bit exhausted and would like to go back to writing CodeQL queries. If you decide to shelve this for some time as you want to let this feature "bake" so to speak, that's fine with me. I'll be using this script on a daily basis so if there are more bugs I'll find them.

@mrthankyou
Copy link
Contributor Author

@JLLeitschuh,

If you want to, you can start taking a look at the work I've done. It would be appreciated. That way, I can catch any errors early on before I invest more time in polishing/testing code.

@@ -104,14 +108,15 @@ def force_rebuild_project(self, simple_project: 'SimpleProject'):
except LGTMRequestException:
print('Failed rebuilding project. This may be because it is already being built. `%s`' % simple_project)

def follow_repository(self, repository_url: str):
def follow_repository(self, repository_url: str) -> dict:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I checked and can't find any case where returning data in the function breaks the code.

test.py Outdated
@@ -0,0 +1,36 @@
from typing import List
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will remove this file once the code is more polished.

README.md Outdated
Comment on lines 76 to 81
To resolve this, we decided to create a feature users can opt-in. This feature called "Custom Projects Lists" does the
following:

- Follows all repos (aka project) in your LGTM account.
- Stores every project you follow in a txt file.
- At a later date (we suggest 24 hours), the user may run a follow-up command that will take the repos followed, add them to a LGTM custom list, and finally unfollow the projects in the user's LGTM account.
Copy link
Owner

Choose a reason for hiding this comment

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

Big fan of this!

@lgtm-com
Copy link

lgtm-com bot commented Feb 17, 2021

This pull request introduces 4 alerts when merging e69003a into 00273ac - view on LGTM.com

new alerts:

  • 2 for Unused import
  • 1 for Unused local variable
  • 1 for Wrong number of arguments in a call

lgtm.py Outdated
@@ -35,6 +35,7 @@ def _make_lgtm_get(self, url: str) -> dict:
)
return r.json()

# Retrieves a user's projects
Copy link
Owner

Choose a reason for hiding this comment

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

Can you use the python standard for API doc comments?

Copy link
Contributor Author

@mrthankyou mrthankyou Feb 17, 2021

Choose a reason for hiding this comment

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

Can you point me in that direction? I can google it but want to make sure we are on the same page. I'm not native to python :/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JLLeitschuh

Can you send that link to me? I tried looking online but can't find any defacto API doc comment rules.

Copy link
Owner

Choose a reason for hiding this comment

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

test.py Outdated Show resolved Hide resolved
@JLLeitschuh
Copy link
Owner

I'm a fan of this! Nice work!

@lgtm-com
Copy link

lgtm-com bot commented Feb 17, 2021

This pull request introduces 2 alerts when merging 69543fb into 00273ac - view on LGTM.com

new alerts:

  • 2 for Unused import

@lgtm-com
Copy link

lgtm-com bot commented Mar 3, 2021

This pull request introduces 2 alerts when merging f44b959 into 4cbdb21 - view on LGTM.com

new alerts:

  • 2 for Unused import

@mrthankyou mrthankyou marked this pull request as ready for review March 4, 2021 15:23
@mrthankyou
Copy link
Contributor Author

@JLLeitschuh This is now ready for review. I've updated the PR description with details on this PR request. Thank you.

Comment on lines +298 to +300
def is_protoproject(self):
# The values for project_type should be hardcoded in one central location
return self.project_type == "protoproject"
Copy link
Owner

Choose a reason for hiding this comment

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

Are there other project types other than protoprojects and non-protoprojects?

Copy link
Contributor Author

@mrthankyou mrthankyou Mar 10, 2021

Choose a reason for hiding this comment

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

As far as I know, no. But I will take a deeper look and get back to you on this.

utils/cacher.py Outdated
Comment on lines 159 to 183
file = open(cached_file, "r")

project_data = file.read().split("\n")
cached_projects = file.read().split("\n")

while("" in project_data):
project_data.remove("")
while("" in cached_projects):
cached_projects.remove("")

for i, project in enumerate(cached_projects):
cached_projects[i] = ProjectBuild(
display_name=project.split(",")[0],
key=project.split(",")[1],
project_type=project.split(",")[2],
is_valid_project=True,
org="",
state=""
)

for i, project in enumerate(project_data):
project_data[i] = ProjectBuild({
"name": project.split(",")[0],
"id": project.split(",")[1],
"type": project.split(",")[2],
})
# display_name: str
# key: str
# project_type: str
# is_valid_project: bool
# org: str
# state: str

file.close()
Copy link
Owner

Choose a reason for hiding this comment

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

Consider refactoring to with open(cached_file, "r") as file: so that close is automatically called even if an exception is thrown.

Comment on lines +151 to +156
file = open("cache/" + file_name + ".txt", "a")

for project_key in project_keys:
file.write(project_key + "\n")

file.close()
Copy link
Owner

Choose a reason for hiding this comment

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

This should use the with open style so that you don't need to call close

@mrthankyou
Copy link
Contributor Author

I'm holding off on fixing these changes. I've been exploring other code options and would like to field-test this code a bit more before I commit a thumps-up from me for this PR. I hope that's ok with you.

@mrthankyou
Copy link
Contributor Author

Short update: I'm actively using these scripts and have squashed most potential bugs that come from it. I think I want to spend a little more time working out these scripts. Interestingly enough I'm using a script that utilizes ghtopdep to collect repos based on a libraries dependencies and have found great results from that. Almost every query I'm running produces hits. Obviously this only works if you have a dependency library you're query identifies vulnerabilities in.

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