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

Initial code commit #1

Merged
merged 5 commits into from
Feb 11, 2020
Merged

Initial code commit #1

merged 5 commits into from
Feb 11, 2020

Conversation

gregeinfrank
Copy link
Contributor

This is a WIP PR while I work through tests and TODOs



def _task_name_from_pull_request(pull_request: PullRequest) -> str:
return "#{} - {}".format(pull_request.number(), pull_request.title())
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use f-strings everywhere we need to do string formatting?

Copy link
Contributor

Choose a reason for hiding this comment

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

If we use temporary variables instead of expressions in f-strings, then I would agree. Embedding code in f-string {} blocks is generally bad for readability/maintainability, IMO :)

e.g.

def _task_name_from_pull_request(pull_request: PullRequest) -> str:
    pr_number = pull_request.number()
    pr_title = pull_request.title()
    return f"#{pr_number} - {pr_title}"

rather than

def _task_name_from_pull_request(pull_request: PullRequest) -> str:
    return f"#{pull_request.number()} - {pull_request.title()}"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I think I agree with this ^^ and that it's not worth splitting into 3 lines for that reason

Comment on lines +136 to +145
return _wrap_in_tag("body")(
_wrap_in_tag("em")(
"This is a one-way sync from GitHub to Asana. Do not edit this task or comment on it!"
)
+ f"\n\n\uD83D\uDD17 {url}"
+ "\n✍️ "
+ asana_author_url
+ _wrap_in_tag("strong")("\n\nDescription:\n")
+ escape(pull_request.body())
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Somewhere in here we would need the task status text right? Task is closed/not closed because...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, maybe I'll just add a task for tracking that - I took it out explicitly because it just seemed like noise but maybe it's useful for some people

@@ -0,0 +1,47 @@
from typing import Tuple
from sgqlc.endpoint.http import HTTPEndpoint
Copy link
Contributor

Choose a reason for hiding this comment

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

I was looking into this GraphQL client - and I think we should be able to do something along the lines of this to ensure that we can do away with our schema file, and be able to write this

query {
  repository(owner: "profusion", name: "sgqlc") {
    issues(first: 100) {
      nodes {
        number
        title
      }
    }
  }
}

as

op = Operation(Query)
issues = op.repository(owner=owner, name=name).issues(first=100)

They have an example of how to use their code generator that can output a schema file which we can directly query against in python code. (We would merge this in its current form and then I could work on changing how we use GraphQL)

if len(maybe_multi_assignees) == 1:
return maybe_multi_assignees[0]
elif len(maybe_multi_assignees) == 0:
logger.info("GitHub PR has no assignees. Choosing author as assignee")
Copy link
Contributor

Choose a reason for hiding this comment

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

This text is also currently something that is part of the task description

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 didn't feel the need - but can add a task for it

Comment on lines +44 to +48
logger.info(
"GitHub PR has multiple assignees: {} Choosing first one in alphabetical order as as assignee: {}".format(
maybe_multi_assignees, assignee
)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same with this text - we would need some way to make sure the _task_description_from_pull_request method gets this message - the current Clojure code returns an object of the form

{
    assignee: ...
    warning: ...
}

and displays these warnings if present

@@ -0,0 +1,7 @@
from datetime import datetime
Copy link
Contributor

Choose a reason for hiding this comment

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

This file isn't related to github, so we could move it to the top level directory.

client.tasks.add_followers(task_id, {"followers": followers})


def add_comment(task_id: str, comment_body: str):
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: str return type

"completed": _task_completion_from_pull_request(pull_request),
"followers": _task_followers_from_pull_request(pull_request),
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm open to working on splitting out some of the functions in this file into a couple different files (one for creating asana comment from git comment, another for task from pr, etc.) and doing some general cleanup! I feel like not all of this logic should be just in a helpers file.

Copy link
Contributor

@padresmurfa padresmurfa left a comment

Choose a reason for hiding this comment

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

LGTM!

I believe there might be a major piece of functionality missing, i.e. adding newly created SGTM tasks to a pre-configured / pre-created project. This should probably be addressed prior to using SGTM in Asana, but does not need to be addressed in this PR. I added an Asana task for this.

None of my other review comments need immediate action, and I am happy to do them all myself in subsequent PRs, assuming that you agree with them.

Comment on lines +1 to +5
provider "aws" {
region = "us-east-1"
shared_credentials_file = "/Users/gregeinfrank/.aws/credentials"
profile = "sgtm"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that this information should be specified via Terraform variables, rather than hardcoded in the script

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah - this was for my testing because I wanted to override the profile to sgtm (pointing to my personal AWS account) -- I'll leave out of this PR

# The filebase64sha256() function is available in Terraform 0.11.12 and later
# For Terraform 0.11.11 and earlier, use the base64sha256() function and the file() function:
# source_code_hash = "${base64sha256(file("lambda_function_payload.zip"))}"
source_code_hash = "${filebase64sha256("../function.zip")}"
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel that this should not require the user to edit the source code to achieve the correct result. A few possible solutions to this could include:

  • only supporting Terraform 0.11.12 and later

  • using the interpolation syntax, possibly along with templates, to achieve the desired version specific results.

  • providing different versions of the .tf files for different versions of Terraform, and using a shell script to determine the Terraform version and use the appropriate files

  • using the approach we use in Asana with .yaml.py files, e.g. main.tf.py is a python script that outputs main.tf, using whatever means it finds appropriate to create the file, such as using the Python template system, or python string-replace on well-known-strings. A runner script of some sort would handle this transformation phase.

For example:

`
template = """
...
handler = "src.handler.handler"
source_code_hash = "@@SOURCE_CODE_HASH@@"
...
"""

if terraform_11_12_or_later:
output = template.replace("@@SOURCE_CODE_HASH@@", "${filebase64sha256("../function.zip")}")
else:
output = template.replace("@@SOURCE_CODE_HASH@@", """${base64sha256(file("lambda_function_payload.zip"))}""")

print(output)
`

}

resource "aws_lambda_function" "sgtm" {
filename = "../function.zip"
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm assume at this point that I will see later in the review that this zip file is the output of some command executed on the command line. This command should be documented somewhere, e.g. in a README.md file. An alternative would be to use a scripts directory, as mentioned elsewhere in this review.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I don't see anything in the project that makes it obvious what the functions.zip file should contain precisely, and how it should be created. I'd guess that zipping the src directory, with path info included, would do the trick, but this should be documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah - on the TODO list for deployment strategy. I've done this manually so far in testing but will add a script and deployment instructions


runtime = "python3.7"

timeout = 30
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that this should be a Terraform variable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sur

}
}

resource "aws_api_gateway_resource" "sgtm_resource" {
Copy link
Contributor

Choose a reason for hiding this comment

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

A single-line(or so) comment for each resource, explaining what it is in plain english, would be great for readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool - i'll add a task for that

Comment on lines 54 to 62
reviews = [
review
for review in pull_request.reviews()
if review.is_approval_or_changes_requested()
and review.submitted_at() < merged_at
]
if reviews:
latest_review = sorted(reviews, key=lambda r: r.submitted_at())[-1]
return latest_review.is_approval()
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel that reviews would be better named premerge_reviews for clarity.

Comment on lines 77 to 82
comments = [
comment
for comment in pull_request.comments()
if comment.published_at() > merged_at
]
reviews = [
Copy link
Contributor

Choose a reason for hiding this comment

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

likewise, I'd suggest using the terms postmerge_comments and postmerge_reviews here for increased clarity.

@@ -0,0 +1,132 @@
from uuid import uuid4
Copy link
Contributor

Choose a reason for hiding this comment

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

it seems to me from the contents of this file that it could be named request_builders.py, which would be an improvement over the generic "helpers" name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm request_builders doesn't seem right because I don't think it's really building "requests" - how about github/stub_builders.py?

@@ -0,0 +1,45 @@
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

this file should probably be renamed something like mock_dynamobdb_test_case



@mock_dynamodb2
class MockTestCase(TestCase):
Copy link
Contributor

Choose a reason for hiding this comment

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

and likewise, the test case should be named something like MockDynamoDbTestCase, as the name implies that this is more generic than it actually is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I think my original plan was to build on this and add more default mocks, but since that didn't happen - that sounds reasonable

@gregeinfrank
Copy link
Contributor Author

Thanks for the comments - I tried to address everything or open a task for it. I'm going to merge so people can start opening up branches

@gregeinfrank gregeinfrank merged commit cf7024b into master Feb 11, 2020
@gregeinfrank gregeinfrank deleted the gregeinfrank-initital-commit branch February 11, 2020 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants