Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
The cobbler's children have no shoes, or buildi...
Search
Alex Gaynor
May 30, 2016
Programming
1
250
The cobbler's children have no shoes, or building better tools for ourselves
As delivered at PyCon 2016 in Portland, OR.
Alex Gaynor
May 30, 2016
Tweet
Share
More Decks by Alex Gaynor
See All by Alex Gaynor
Quantifying Memory Unsafety and Reactions to It
alex
0
89
Learning from Failure: Post-mortems
alex
2
290
Techniques for Debugging Hard Problems
alex
1
560
Building Communities with Code Review
alex
4
270
Documenting Domain Specific Knowledge
alex
1
360
Pickles are for Delis, not for Software
alex
0
340
Code Review in Open Source Software
alex
4
750
Why Ruby isn't slow
alex
10
3.8k
PyPy + Swift
alex
2
520
Other Decks in Programming
See All in Programming
抽象データ型について学んだ
ryounasso
0
210
『Python → TypeScript』オンボーディング奮闘記
takumi_tatsuno
1
140
Agent Rules as Domain Parser
yodakeisuke
1
350
事業戦略を理解してソフトウェアを設計する
masuda220
PRO
7
1.3k
JVM の仕組みを理解して PHP で実装してみよう
m3m0r7
PRO
1
250
TypeScript LSP の今までとこれから
quramy
0
110
〜可視化からアクセス制御まで〜 BigQuery×Looker Studioで コスト管理とデータソース認証制御する方法
cuebic9bic
2
270
REST API設計の実践 – ベストプラクティスとその落とし穴
kentaroutakeda
2
320
Efficiency and Rock 'n’ Roll (Really!)
hollycummins
0
600
Rails産でないDBを Railsに引っ越すHACK - Omotesando.rb #110
lnit
1
100
Building an Application with TDD, DDD and Hexagonal Architecture - Isn't it a bit too much?
mufrid
0
370
TypeScriptのmoduleオプションを改めて整理する
bicstone
4
430
Featured
See All Featured
How GitHub (no longer) Works
holman
314
140k
The World Runs on Bad Software
bkeepers
PRO
68
11k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
12k
Stop Working from a Prison Cell
hatefulcrawdad
269
20k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
47
2.8k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
3k
Art, The Web, and Tiny UX
lynnandtonic
298
21k
Site-Speed That Sticks
csswizardry
7
590
Testing 201, or: Great Expectations
jmmastey
42
7.5k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
357
30k
4 Signs Your Business is Dying
shpigford
183
22k
Transcript
The cobbler's children have no shoes, or building better tools
for ourselves Alex Gaynor - PyCon 2016
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
A short history of tools
$ git init
None
Code review
Deployment automation
Emerging trends
CI for PRs
Linting (flake8, bandit, flake8-import-order, etc.)
Coverage Tracking
livegrep.com
github.com/facebook/mention-bot
Workflow
Build more tailored tools
Automation > Process
APIs!
Issues • Create an issue • Add/remove labels • Add
a comment • Assign to someone
Pull requests • Send a PR • Assign a PR
• Add/remove labels • Leave a code review • Add a commit status
Examples
$ pip install github3.py
import github3 gh_client = github3.login( os.environ["GITHUB_USERNAME"], os.environ["GITHUB_PASSWORD"], )
repo = gh_client.repository("django", "django")
HTTPS certificate expiration
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)
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)
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"] )
Auto-labeling
Web hooks
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)
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")
Other ideas
requirements.txt bumper
UI change reviewer
Github Web hook UI Reviewer Comment Screenshots
Approval process commit status
Thanks! Questions? https://github.com/alex https://speakerdeck.com/alex