スクリーンショットはDroidKaigi/conference-app-2020のものをお借りしています。
なぜするか
自社サービスのアプリ開発をしています。アプリアップデータリリース時の速報として、新しく作られたり変更があった画面のスクリーンショット一覧を、企画、運用部門と共有することを一部自動化したいです。また、あとで文章にまとめるときにも、すでに収集されたスクリーンショット集があるので効率的に作れます。
私が所属する開発チームではプルリクのレビュー依頼時にプルリクの本文にスクリーンショットやGifアニメーションを貼る習慣あるので、その画像を企画、運用部門と共有します。
Pythonを使って一括ダウンロードする
事前準備
mkdir Downloads
pip install PyGithub BeautifulSoup4 requests
実行Pythonソースコード
import os
from datetime import datetime, timedelta
# マークダウンからHTMLに変換
import markdown
# Github API クライアント
from github import Github
# HTMLパーサー
from bs4 import BeautifulSoup
# HTTPクライアント
import requests
# MIMEタイプから拡張子を取得
import mimetypes
# 保存先ディレクトリ
save_dir = "Downloads"
# マークダウンをHTMLに変換する担当オブジェクト作成
md = markdown.Markdown()
# アクセストークンはこちらで作る
# https://github.com/settings/tokens
access_token = os.environ['GITHUB_API_ACCESS_TOKEN']
# アクセストークンを持ってGithubオブジェクトを作成
g = Github(access_token)
# リポジトリを取得
gr = g.get_organization('DroidKaigi').get_repo('conference-app-2020')
# 個人のリポジトリの場合は
# gr = g.get_user().get_repo('repository_name')
# ダウンロードする範囲(プルリク作成日基準)
start_datetime = datetime(2020, 1, 1)
end_datetime = datetime(2020, 1, 13)
# 閉じられたプルリクエスト一覧を取得
prs = gr.get_pulls(state='close', base='master')
for pr in prs:
# 順番は作成日降順
if pr.created_at < start_datetime:
# これ以上は遡らなくて良い
break
if pr.created_at < end_datetime:
# ダウンロードする範囲に入った
# マージされたPRに限定する
if pr.merged != True:
continue
print("#%d %s" % (pr.number, pr.title))
# プルリク本文のマークダウンをHTMLに変換する
html = md.convert(pr.body)
# HTMLをパースする
soup = BeautifulSoup(html, features='html.parser')
# すべてのimgタグに対して
for img_index, img in enumerate(soup.find_all('img')):
# src属性の値を画像urlとして取得して
url = img.get('src')
# src属性が空のケース対応
if len(url) == 0:
continue
# URLをダウンロードする
r = requests.get(url)
if r.ok:
# ダウンロード成功
# ファイルのmimeタイプを取得する
content_type = r.headers['Content-Type']
# mimeタイプから拡張子を取得する
ext = mimetypes.guess_extension(content_type)
# ファイル名にプルリクタイトルを含めたいが
# スラッシュがファイル名に含まれているとファイルを作れないので
# 全角に変換する
title = pr.title.replace('/', '/')
# 保存先パスを作成
path = "%s/%04d_%s_%02d.%s" % (save_dir,
pr.number, title, img_index, ext)
# 画像を保存する
with open(path, 'wb') as f:
f.write(r.content)
else:
# ダウンロード失敗
message = "Image download error\n%s\n%d %s" % (
url, r.status_code, r.reason)
raise RuntimeError(message)
状況に応じてカスタマイズ
上記ソースコードはとりあえずローカルPCで動かしてローカルフォルダに一括ダウンロードしています。組織やプロジェクトの状況に応じて例えばこのようなカスタマイズを行うと良いと思います。
- 継続的デリバリーのワークフローで実行する
- SlackBotにする
- 画像はGoogle Driveにアップロードする
バージョンアップの差分だけ画像をダウンロードする
自作アプリのリリースワークフローでは前バージョンリリース以後にマージされたPR一覧を取得してリリースノートを自動で作るPythonスクリプトを動かしています。そのPR一覧から本文を取得して上記と同じような処理を行えばバージョンアップの差分だけ画像をダウンロードできます。
注意点
他部門と共有するスクリーンショットにAWSアクセスキーにような秘密の情報が含まれていないかご注意ください。