The cobbler's children have no shoes, or building better tools for ourselves

The cobbler's children have no shoes, or building better tools for ourselves

As delivered at PyCon 2016 in Portland, OR.

Edcdfd5affb524e0f88ec1a00ed3fe5d?s=128

Alex Gaynor

May 30, 2016
Tweet

Transcript

  1. The cobbler's children have no shoes, or building better tools

    for ourselves Alex Gaynor - PyCon 2016
  2. About me • Director of the Python Software Foundation •

    Open source contributor • Django, PyPy, CPython, pyca/cryptography, etc. • Washington, D.C. resident • Bagel and deli enthusiast • US Digital Service employee
  3. A short history of tools

  4. $ git init

  5. None
  6. Code review

  7. Deployment automation

  8. Emerging trends

  9. CI for PRs

  10. Linting (flake8, bandit, flake8-import-order, etc.)

  11. Coverage Tracking

  12. livegrep.com

  13. github.com/facebook/mention-bot

  14. Workflow

  15. Build more tailored tools

  16. Automation > Process

  17. APIs!

  18. Issues • Create an issue • Add/remove labels • Add

    a comment • Assign to someone
  19. Pull requests • Send a PR • Assign a PR

    • Add/remove labels • Leave a code review • Add a commit status
  20. Examples

  21. $ pip install github3.py

  22. import github3 gh_client = github3.login( os.environ["GITHUB_USERNAME"], os.environ["GITHUB_PASSWORD"], )

  23. repo = gh_client.repository("django", "django")

  24. HTTPS certificate expiration

  25. def get_expiration_date(host): ssl_context = ssl.create_default_context() with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:

    sock = ssl_context.wrap_socket(sock, server_hostname=host) sock.connect((host, 443)) expiration = ssl.cert_time_to_seconds(sock.getpeercert()["notAfter"]) return datetime.datetime.fromtimestamp(expiration)
  26. while True: for host in MY_DOMAINS: expiration = get_expiration_date(host) if

    expiration - datetime.datetime.now() < CUTOFF: file_an_issue(gh_client, host, expiration) time.sleep(3600)
  27. def file_an_issue(gh_client, host, expiration): gh_client.create_issue( "django", "django", "Cert expiring soon:

    {}".format(host), "The cert for `{}` expires on {}, get a new one!".format( host, expiration ), "alex", labels=["ssl-cert"] )
  28. Auto-labeling

  29. Web hooks

  30. def github_webhook(request): event = request.headers.get("X-Github-Event") if event != "pull_request": return

    Response(status=200) body = json.load(request.stream) if body.get("action") not in {"opened", "reopened", "synchronize"}: return Response(status=200)
  31. issue = repo.issue(body["number"]) pr = repo.pull_request(issue.number) changed_files = (f.filename for

    f in pr.iter_files()) if "django/utils/crypto.py" in changed_files: issue.add_labels("security")
  32. Other ideas

  33. requirements.txt bumper

  34. UI change reviewer

  35. Github Web hook UI Reviewer Comment Screenshots

  36. Approval process commit status

  37. Thanks! Questions? https://github.com/alex https://speakerdeck.com/alex