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 building better tools for ourselves
Search
Alex Gaynor
May 30, 2016
Programming
1
220
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
67
Learning from Failure: Post-mortems
alex
2
260
Techniques for Debugging Hard Problems
alex
1
450
Building Communities with Code Review
alex
4
220
Documenting Domain Specific Knowledge
alex
1
250
Pickles are for Delis, not for Software
alex
0
270
Code Review in Open Source Software
alex
4
700
Why Ruby isn't slow
alex
10
3.6k
PyPy + Swift
alex
2
490
Other Decks in Programming
See All in Programming
GitHub Actionsで泣かないためにやっておきたい設定 / Recommended GHA settings to avoid crying
pinkumohikan
3
500
今の SmartHR にエンジニアで入社するとどうなるの?
daisukeshinoku
5
4.6k
雑に思考を整理する技術と効能
konifar
57
26k
DMMプラットフォームがTiDB Cloudを採用した背景
pospome
8
3.7k
Front-end application development, Symfony-style(s)
dunglas
2
1.9k
Ruby GitHub Packages
bkuhlmann
0
620
Micro Frontends for Java Microservices - Devnexus 2024
mraible
PRO
0
440
データアナリストが行うDatabricksを活用したETLの自動化事例
shinoa
0
260
Git Rebase
bkuhlmann
11
1.6k
try!Swift Tokyo 2024 参加報告 LT
akidon0000
1
200
try! Swift Tokyo 初参加報告LT
hinakko2
0
200
今、知っておきたい! 生成AIエージェントの世界
elith
3
340
Featured
See All Featured
Navigating Team Friction
lara
177
13k
The Straight Up "How To Draw Better" Workshop
denniskardys
227
130k
Teambox: Starting and Learning
jrom
128
8.4k
Into the Great Unknown - MozCon
thekraken
10
980
Statistics for Hackers
jakevdp
789
220k
How To Stay Up To Date on Web Technology
chriscoyier
782
250k
Optimizing for Happiness
mojombo
370
69k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
154
14k
What's new in Ruby 2.0
geeforr
337
31k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
220
21k
Bootstrapping a Software Product
garrettdimon
PRO
301
110k
5 minutes of I Can Smell Your CMS
philhawksworth
199
19k
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