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
230
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
72
Learning from Failure: Post-mortems
alex
2
270
Techniques for Debugging Hard Problems
alex
1
520
Building Communities with Code Review
alex
4
250
Documenting Domain Specific Knowledge
alex
1
310
Pickles are for Delis, not for Software
alex
0
300
Code Review in Open Source Software
alex
4
730
Why Ruby isn't slow
alex
10
3.7k
PyPy + Swift
alex
2
500
Other Decks in Programming
See All in Programming
今年のアップデートで振り返るCDKセキュリティのシフトレフト/2024-cdk-security-shift-left
tomoki10
0
200
ゆるやかにgolangci-lintのルールを強くする / Kyoto.go #56
utgwkk
2
390
fs2-io を試してたらバグを見つけて直した話
chencmd
0
240
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
190
The Efficiency Paradox and How to Save Yourself and the World
hollycummins
1
450
見えないメモリを観測する: PHP 8.4 `pg_result_memory_size()` とSQL結果のメモリ管理
kentaroutakeda
0
370
Haze - Real time background blurring
chrisbanes
1
510
[JAWS-UG横浜 #76] イケてるアップデートを宇宙いち早く紹介するよ!
maroon1st
0
460
Symfony Mapper Component
soyuka
2
730
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
4
590
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
5
910
PHPUnitしか使ってこなかった 一般PHPerがPestに乗り換えた実録
mashirou1234
0
200
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
229
18k
How to Ace a Technical Interview
jacobian
276
23k
Designing for Performance
lara
604
68k
Unsuck your backbone
ammeep
669
57k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Navigating Team Friction
lara
183
15k
Docker and Python
trallard
42
3.1k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
810
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
How to train your dragon (web standard)
notwaldorf
88
5.7k
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