Travis CI + Codecov + NoseでCIしてSlackに通知
きっかけ
これまでもTravis CIを使ってきていて、それ自体にはそんなに戸惑うことは無かったんですが、カバレッジも取得したくなったりしたので少し調べたら日本語情報があまりなかったのでここに残しておくことにしました。
環境
開発環境は以下
必要なPythonモジュールなど
- nose 1.3.7
- codecov 2.0.15
- coverage 4.5.1
各種サービスのセットアップ
Travis CI
Circle CIがどうにも複雑に見えてしまいずっとTravisを使っているため、今回もTravisです。
特に難しいところはなく、普通にサインアップしてCIしたいリポジトリを有効にするだけです。Build only if .travis.yml is present
にチェックを入れておくと良いと思います。
また、シークレットなトークンを暗号化するのに使うtravis
というコマンドをgem
でインストールします。
$ gem install travis $ travis login
.travis.ymlの文法エラーでCIをパスできないとめちゃくちゃ悲しくなるのでlint
コマンドを覚えると良いと思います。
$ cat .travis.yml language: python python: - "3.5" - "3.6" script: - nosetests -v $ travis lint Hooray, .travis.yml looks valid :)
Codecov
Codecovはカバレッジを表示してくれるWebサービスです。Pythonにはcodecov
というpipでインストールできるモジュールがあります*1。
同様のサービスとしてCoverallsなどがありますが、あまりデザインが好みで無かった上、Python用のパッケージが2種類あってうーんという感じだったのでこちらにしました*2。
上記リンクから、Githubアカウント、Gitlabアカウント、Bitbucketアカウントでサインアップできます。それぞれのオンプレ版にも対応しているみたいなので、かなり良さそうです。また、Teamでの使用もパブリックリポジトリなら無制限?のようです。プライベートリポジトリでの利用を検討している場合はリポジトリごと、またはユーザ数単位での課金になるようです*3。
有効にするリポジトリを選択するとトークンが表示され、カバレッジリポートのアップロードをしろみたいな画面になりますが、Travis CIから使うなら無視して良いです。
設定はもう終わりです(すごい)。
リポジトリのセットアップ
テストする
僕はずっとnoseを使っているので、今回もこれで行きます。フォルダ構成は以下の様にしました。student_portal_crawler
が今回テストするモジュールです。
$ tree -L 3 -I venv . ├── LICENSE ├── README.md ├── requirements.txt └── student_portal_crawler ├── __init__.py ├── browser.py ├── page ├── parser └── test ├── __init__.py └── test_script.py
noseのインストールおよびテスト実行は下記の様にします。テストの書き方についてはここでは解説しません。
$ pip install nose # テストの実行 $ nosetests ............................. ---------------------------------------------------------------------- Ran 20 tests in 0.680s OK # テストの実行とカバレッジの計算 $ pip install coverage $ nosetests --with-coverage
このままでは使用しているモジュール全てのカバレッジを取得してしまうので、--cover-package
オプションで取得するモジュールを指定してやります。今回の場合はstudent_portal_crawler
になります。
$ nosetests --with-coverage --cover-package=student_portal_crawler ............................. Name Stmts Miss Branch BrPart Cover --------------------------------------------------------------------------------------- student_portal_crawler/__init__.py 1 0 0 0 100% student_portal_crawler/browser.py 20 0 2 0 100% student_portal_crawler/page/__init__.py 1 0 0 0 100% student_portal_crawler/page/base.py 34 4 6 1 78% student_portal_crawler/parser/__init__.py 4 0 0 0 100% student_portal_crawler/parser/base.py 38 0 10 0 100% student_portal_crawler/parser/lec_info.py 18 0 6 0 100% student_portal_crawler/parser/static.py 5 0 0 0 100% student_portal_crawler/parser/utils.py 9 0 2 0 100% student_portal_crawler/shibboleth_login/__init__.py 1 0 0 0 100% student_portal_crawler/shibboleth_login/login.py 53 2 8 0 97% --------------------------------------------------------------------------------------- TOTAL 184 6 34 1 95% ---------------------------------------------------------------------- Ran 29 tests in 0.319s OK
.travis.ymlを書く
シンプルにPythonのバージョンいくつかでテストし、パスしたらCodecovにカバレッジを送信、Slackに結果を通知します。
まずは自分のSlackのIntegrationからTravis CI
を追加します。Hubotとかで節約している人も居るかとは思いますが、僕は面倒なので豪華に行きます。
追加したら投稿するチャンネルを決め、トークンを取得します。
Travis CIでの使い方についての説明の中に、トークンの暗号化についての項目があるのでコピペして実行します。事前に.travis.ymlがないとエラーが出るので作成しておきます。
$ touch .travis.yml $ travis encrypt "{{チーム名}}:{{トークン}}" --add notifications.slack $ cat .travis.yml notifications: slack: secure: npdNlesznnxrC7KsuB7....
Travis CIで利用可能なPythonバージョンは複数有り、最新は3.8-dev
やnightly
まで使える*4ようなのですが、
Recent Python development branches require OpenSSL 1.0.2+. As this library is not available for Trusty, 3.7-dev, 3.8-dev, and nightly do not work (or use outdated archive).
という記述があり、どうやったら使えるのか分からず3.6-dev
までしか使っていません…*5
最終的に下記の様にしました。
language: python python: - "3.5" - "3.5-dev" - "3.6" - "3.6-dev" install: - pip install -r requirements.txt - pip install codecov coverage script: - nosetests -v --with-coverage --cover-package=student_portal_crawler after_success: - codecov notifications: email: false slack: secure: npdNlesznnxrC7K...
after_success
でcodecov
コマンドを実行することで、Codecovにカバレッジリポートが送信されます。トークンなどを加える必要は有りません。
また、Slackへの通知のみで十分なのでメール通知はオフにしています。
.coveragercを書く
このままではテストコードまで含めたカバレッジがcodecovに表示されてしまったり、テストしないコード(デバッグ用のステートメントなど)まで含まれてしまうため、.coveragerc
という設定ファイルを置いて制御します。
[run] branch = True source = student_portal_crawler [report] exclude_lines = if TYPE_CHECKING: if __name__ == .__main__.: ignore_errors = True omit = student_portal_crawler/test/*
typing
モジュールを使用して型ヒントの定義をしているので、常にFalse
となり実行されないif TYPE_CHECKING:
という文が所々に現れるのでこれを排除しています。
また、実際の実行コード(if __name__ == '__main':
)も排除しています。
READMEへバッジを貼る
CI回してカバレッジ取得する最大の目的といっても過言ではない、READMEへのバッジを貼ります。
Travis CI
https://travis-ci.org/ユーザ名/リポジトリ名
にアクセスし、リポジトリ名の横に表示されているバッジをクリックすると、形式を選択してコピーできます。
Codecov
https://codecov.io/gh/ユーザ名/リポジトリ名/settings/badge
にアクセスすると形式を選択してコピーできます
後はpushすればCIが走ります。
結果を確認
Githubへpushしてしばらく待つとテストが完了します。
こんな風にSlackに通知が来ます。
Codecovに自動でカバレッジが送信され、以下の様に表示されます。
また、リンクを開いていくとどのモジュールのカバレッジが低いのか丸わかりな上、各ファイルのどの行がテストされていないのかも一発で分かります。
まとめ
取り扱いが面倒なことが多いトークン等の設定が必要ないため、Codecov + Travis CIはなかなかオススメの組み合わせかと思います。
どんどんunittestを書いて徳を積んでいきましょう!
macOSで任意のWi-Fiへ接続・切断時に任意のシェルスクリプトを実行させる
きっかけ
弊大学では学内ネットワークとして,学生が自分の持つアカウントで認証すれば使用できる認証付き無線LANが用意されています.ありがたいことに「自動プロキシ検出」さえオンにしていれば自動で設定されるため苦労はしませんが,自宅や研究室などプロキシの存在しない環境においてこの設定をしているとアプリケーションの通信に影響が出ることがあります(下記記事参照)
macOSには「ネットワーク環境」という設定があり,環境に応じて設定を一括で変更できるプロファイル変更機能が備わっているのですが,自動で切り替わるとかそいう頭の良いことをしてくれません.これをもっと簡単に,そして自動でやりたいなと思い最初は自作し始めたのですが良いツールを見つけたのでやめました.
Hammerspoonの紹介
Hammerspoonは上記ページにあるとおり,luaを用いて自分でロジックを書いて様々な動作を自動化するためのソフトウェアです.hs
というモジュールにhammerspoonによる独自の拡張が沢山含まれており,非常に幅広い動作を実現しています.
luaは簡単な言語ですが色々と癖があるので,慣れていないと引っかかるところがたまにあります.
環境
インストールは以下から可能です.
使用する機能
WiFi切り替え検知
実はこれは既に公式ページのGetting Startedに書いてあります.
しかしこのサンプルは一つのSSIDについて接続切断を見ているのみで,複数のSSIDについて接続・切断に対応させようと思うと割と面倒です.加えて言うと,新しいSSIDに対応させようとする度にこの~/.hammerspoon/init.lua
を編集して追加しないといけないとなると,やがて肥大化してパンクすることが目に見えています.
とはいえ基本は上記ページの hs.wifi.watcher
を使用します.
シェルスクリプト実行
hs.execute()
というメソッドによりシェルスクリプト実行が可能です.また,launchd
などを用いて実行させる場合などはパスが/usr/bin:/bin:/usr/sbin:/sbin
にしか通っていないのですが,先述のメソッドの第二引数にtrue
を渡すとどうも~/.bashrc
を読み込んでから実行してくれるようです*1.
ただしその場合はオーバーヘッドが大きいため,オプションにより制御できるようにしたいと思います.
実装
ちゃんと色々検証したわけではないので自己責任でお願いします.
構成
そこで下記のような構成にしたいと思います
~/.hammerspoon/config.json
を作成~/.hammerspoon/Scripts/
以下に実行するシェルスクリプトを格納init.lua
内で上記のjsonをロード(初回起動時および変更時のみ)- SSIDの変更を検知してネットワーク環境の変更およびシェルスクリプトの実行を行う
config.json
下記のようにし,~/.hammerspoon/
以下に配置します.
{ "base": { "notify": false, "shell": "/bin/bash", "with_user_env": true }, "networks": [ { "SSID": "ssid1", "profile": "proxy", "pre_hook": "hoge.sh", "post_hook": "fuga.sh" }, { "SSID": "ssid2", "pre_hook": "poyo.sh", "post_hook": "piyo.sh" } ] }
notify
: 通知を有効化するフラグ.今はconfig.iniを読み込むときに通知を出している.デフォルトはtrue
shell
: シェルスクリプトを実行するシェル.デフォルトは/bin/bash
with_user_env
:hs.execute()
の第二引数に渡す値.ユーザが定義したパスを読み込んだ状態で実行するかどうか.デフォルトはtrue
config.iniに変更があったときに自動で再読み込み
~/.hammerspoon/init.lua
に記述していきます.
-- init HOME = os.getenv("HOME") CONFIG_HOME = HOME .. "/.hammerspoon/" CONFIG_FILE = CONFIG_HOME .. "config.json" -- key NETWORKS_KEY = "networks" SHELL_KEY = "shell" BASE_CONFIG_KEY = "base" NOTIFY_KEY = "notify" USER_ENV_KEY = "with_user_env" SSID_KEY = "SSID" PROFILE_KEY = "profile" PRE_HOOK_KEY = "pre_hook" POST_HOOK_KEY = "post_hook" -- default settings NOTIFY = true SHELL = "/bin/bash" USER_ENV = true DEFAULT_NW_PROFILE = "Automatic" function hasKey(tbl, key) for k, v in pairs (tbl) do if k == key then return true end end return false end function readConfig(files) -- jsonファイルを開いて一行ずつ読み出し,decode local fp = io.open(files[1], "r") local json = fp:read("*a") fp:close() local config = hs.json.decode(json) if hasKey(config, BASE_CONFIG_KEY) then for k, v in pairs(config[BASE_CONFIG_KEY]) do hs.settings.set(k, v) end end -- Default valueをセット if not hasKey(config, NOTIFY_KEY) then hs.settings.set(NOTIFY_KEY, NOTIFY) end if not hasKey(config, SHELL_KEY) then hs.settings.set(SHELL_KEY, SHELL) end if not hasKey(config, USER_ENV_KEY) then hs.settings.set(USER_ENV_KEY, USER_ENV) end -- Networkプロファイルをロード if hasKey(config, NETWORKS_KEY) then hs.settings.set(NETWORKS_KEY, config[NETWORKS_KEY]) end if hs.settings.get(NOTIFY_KEY) then local notify_msg = string.format("display notification \"Reloaded\" with title \"WLAN Profiles\"") hs.osascript.applescript(notify_msg) end end -- exec readConfig({CONFIG_FILE}) hs.pathwatcher.new(CONFIG_FILE, readConfig):start()
Hammerspoonではhs.settings
というキーバリューストア的なものを提供していたのでこれを使えと言うことなのかと,動的なデータのほとんどはこれを介して出し入れしています*2.
ネットワーク環境切り替え
これはシェルスクリプト(nw_profile_changer.sh
)を置いておくことにします.
こちらからアイデアを頂きました.
currentlocation=`networksetup -getcurrentlocation` if test $currentlocation = $1; then return fi scselect `scselect | grep ${1} | cut -b 4-40`
これを~/.hammerspoon/Scripts
以下に置いておきます.
WiFi切り替え時に実行
SCRIPTS_PATH = CONFIG_HOME .. "Scripts/" PROFILE_CHANGE_SCRIPT = SCRIPTS_PATH .. "nw_profile_changer.sh" -- tmp prevSSID = hs.wifi.currentNetwork() -- シェルスクリプトを実行する関数 function execHook(path, profile) if path then local script = SCRIPTS_PATH .. path local shell = hs.settings.get(SHELL_KEY) local with_user_env = hs.settings.get(USER_ENV_KEY) hs.execute(shell .. " " .. script, with_user_env) end end -- ネットワーク環境を切り替える関数 function loadNwProfile(profile_name) local command = nil local shell = hs.settings.get(SHELL_KEY) local with_user_env = hs.settings.get(USER_ENV_KEY) if profile_name then command = shell .. " " .. PROFILE_CHANGE_SCRIPT .. " " .. profile_name else command = shell .. " " .. PROFILE_CHANGE_SCRIPT .. " " .. DEFAULT_NW_PROFILE end hs.execute(command, with_user_env) end function nwProfileChanger(ssid, profile, connection) if connection then -- 接続時にプロファイルを変更 loadNwProfile(profile[PROFILE_KEY]) if hasKey(profile, PRE_HOOK_KEY) then execHook(profile[PRE_HOOK_KEY]) end else if hasKey(profile, POST_HOOK_KEY) then execHook(profile[POST_HOOK_KEY]) end end end function ssidChangedCallback(watcher, msg, interface) local newSSID = hs.wifi.currentNetwork() if prevSSID ~= newSSID then for i, nw in ipairs(hs.settings.get(NETWORKS_KEY)) do if not prevSSID and newSSID and nw[SSID_KEY] == newSSID then -- 接続時 nwProfileChanger(newSSID, nw, true) break elseif prevSSID and not newSSID and nw[SSID_KEY] == prevSSID then -- 切断時 nwProfileChanger(prevSSID, nw, false) break end end end prevSSID = newSSID end -- SSID変更を監視 hs.wifi.watcher.new(ssidChangedCallback):start()
解説は省きますが,SSID変更を検知してそのSSIDに合致する設定が書かれていた場合,ネットワーク環境変更およびシェルスクリプト実行を行います.
全体は下記にあります.
任意のWiFi接続・切断時に任意のシェルスクリプトを実行するHammerspoonの設定 · GitHub
Hammerspoonをリロード
メニューバーまたはコンソールからReload Config
します.
これで準備は完了です!
応用
研究室のWiFiに接続する度に論文提出までの期限を通知
このためだけにGoで超簡単に書きました.
下記のようなシェルスクリプトを用意し,~/.hammerspoon/when_connect_lab.sh
として配置します.
limit=`go-sotsuron-counter` osascript -e 'display notification "'"${limit}です"'" with title "Welcome to Laboratory"'
config.json
に記述
{ "base": { "notify": false, "shell": "/bin/bash", "with_user_env": true }, "networks": [ { "SSID": "ラボのSSID", "pre_hook": "when_connect_lab.sh" } ] }
はい!こうなります!
思わず画面をたたき割らないように注意しましょう.
gitのプロキシ設定を行う
こういう用途が本命です. プロキシのオンオフスクリプトをそれぞれ書きます.
~/.hammerspoon/proxy_on.sh
# git git config --global http.proxy http://hoge.com:8080 git config --global https.proxy https://hoge.com:8080 # その他 launchctl setenv HTTP_PROXY http://hoge.com:8080 launchctl setenv http_proxy http://hoge.com:8080 launchctl setenv HTTPS_PROXY https://hoge.com:8080 launchctl setenv https_proxy https://hoge.com:8080 launchctl setenv ALL_PROXY http://hoge.com:8080 launchctl setenv all_proxy http://hoge.com:8080
~/.hammerspoon/proxy_off.sh
[2018/1/30 追記]
[http]
と[https]
セクションが.gitconfigに大量に追記されてしまう問題を修正しました
# git git config --global --unset http.proxy git config --global --unset https.proxy git config --global --remove-section http git config --global --remove-section https # その他 launchctl unsetenv HTTP_PROXY launchctl unsetenv http_proxy launchctl unsetenv HTTPS_PROXY launchctl unsetenv https_proxy launchctl unsetenv ALL_PROXY launchctl unsetenv all_proxy
config.json
に記述
{ "base": { "notify": false, "shell": "/bin/bash", "with_user_env": true }, "networks": [ { "SSID": "ProxyありのSSID", "profile": "プロキシ設定したネットワーク環境名", "pre_hook": "proxy_on.sh", "post_hook": "proxy_off.sh" } ] }
export
ではなくlaunchctl setenv
するのがミソです.
適当なWiFiで設定してみて実際に動くか確かめると良いと思います.
デバッグ目的だけならosascript -e 'display notification "hoge" with title "test"'
とか書くと実行された場合に通知が出て良いです.
課題
- 突貫で書いたので雑
- たまにjson読み込みでエラーを吐く(
init.lua
再読込で直る).原因不明.
2018-01-16 16:53:19: ******** 2018-01-16 16:53:19: 16:53:19 ERROR: LuaSkin: hs.pathwatcher callback error: The data couldn窶冲 be read because it isn窶冲 in the correct format. stack traceback: [C]: in function 'hs.json.internal.decode' /Users/pudding/.hammerspoon/init.lua:42: in function 'readConfig' 2018-01-16 16:53:19: ********
まとめ
自動で設定できるとはいえ,例えばシェルは開き直さないと環境変数が反映されないとかそういうのがあるので,移動時にちゃんと後始末しない(ウィンドウ開けたら開けっぱなし)な人は気をつけないとつらくなります.
…卒論書きます.
Octopassで簡単ユーザ管理
きっかけ
ちょっとした技術コミュニティを作りたくなって友人と学内で一つ非公式サークルを立ち上げました.
当然のようにVPSを借り,Webサーバを立ち上げ,Wikiを建て…なんていうのを考えているとき,ふと「ユーザ管理面倒だな.LDAPほど大げさじゃない何か良いものはないだろうか」と考えてググったら出てきました.
Githubをバックエンドとして使用してユーザ認証できるなんてステキ!と飛びついてみたら簡単にできて最高だったという話です.
環境
メンバーもまだ少なく,ほとんど創立メンバーの友人と二人で折半するので費用は抑えたい…ということでさくらのVPSのメモリ1GBプランを契約.年額一括1万円程度で固定IPのあるサーバが使えるのはありがたいです.
OSには使い慣れているUbuntuを選択しました.
導入
基本は下記ページ及びgithubのREADMEに従うだけです.
下記操作は全てさくらのVPSのコントロールパネルからアクセスできるシリアルコンソールから行っています.
Octopassのインストール
UbuntuやCentOSならソースからコンパイルしなくてもpackagecloudに既に用意されています.ありがたい.
$ sudo apt-get update $ sudo apt-get upgrade $ curl -s https://packagecloud.io/install/repositories/linyows/octopass/script.deb.sh | sudo bash $ sudo apt-get install octopass
Personal Access Tokenの取得
https://github.com/settings/tokens/newからログインして新しいトークンを作成します.
このとき,必要な権限はadmin:org
の中のread:org
のみで良いようです.
設定ファイルの作成
設定ファイルのテンプレートが用意されているのでmv
します.
$ sudo mv /etc/octopass.conf.example /etc/octopass.conf $ sudo vim /etc/octopass.conf
設定ファイルの必要な項目を埋めます.僕は下記のコメントを外しているところのみを埋めています.
# O C T O P A S S # Required Token = "{Your token}" ## Use team Organization = "{Your org}" Team = "{Your team}" ## Use collaborators #Owner = "yourname" #Repository = "yourrepository" # Default #Endpoint = "https://api.github.com/" #Group = "" Home = "/home/%s" Shell = "/bin/bash" #UidStarts = 2000 #Gid = 2000 #Cache = 300 Syslog = true # Advanced #SharedUsers = [ "admin", "deploy" ]
情報が取れるか確認してみます.
$ sudo octopass passwd hoge:x:120000:2000:managed by octopass:/home/hoge:/bin/bash fuga:x:130000:2000:managed by octopass:/home/fuga:/bin/bash
こんな感じでチームに所属しているメンバーが一覧で表示できるはずです.
sshdやpamの設定
これらをsshdやpamから叩けるようにします.とはいってもgithubとかにあるコードをそのままコピペすれば動きます.ステキ.
/etc/ssh/sshd_config
デフォルトではパスワードによるsshなどが可能なので制限します.
# rootログイン禁止 PermitRootLogin no # 鍵認証にoctopassをrootから叩いて使用 AuthorizedKeysCommand /usr/bin/octopass AuthorizedKeysCommandUser root # 公開鍵認証を有効に RSAAuthentication yes PubkeyAuthentication yes # パスワード認証を無効 PasswordAuthentication no # PAMを使用 UsePAM yes
/etc/pam.d/sshd
@include common-auth
は元から記述されているのでコメントアウトします.
#@include common-auth
auth requisite pam_exec.so quiet expose_authtok /usr/bin/octopass pam
auth optional pam_unix.so not_set_pass use_first_pass nodelay
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
/etc/nsswitch.conf
これを触ったのは初めてだったのですが,名前解決の順序を決定するための設定のようです*1.
passwd
, shadow
, group
の3項目を下記のように変更.
passwd: files octopass sss shadow: files octopass sss group: files octopass sss
Githubへの鍵の登録
既にやってるひとは飛ばして構わないです.
ここの操作はMacBook Pro上で行っていますが,やることとしてはWindowsやLinuxでも同じで
の2つだけです.
鍵ペアの作成
ssh-keygen
コマンドを使用します.-C
はコメントで,末尾に付加されるユーザ名@ホスト名
を上書きします(オプション).
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/{key name} -C "youremail@hoge.com"
公開鍵の中身をクリップボードにコピーします.
$ pbcopy < ~/.ssh/{key name}.pub
登録
- https://github.com/settings/keys からログイン
- 右上の
New SSH key
をクリック - わかりやすいTitleを入力して
Key
セクションに先ほどコピーした公開鍵をペースト Add SSH key
をクリック
SSHしてみる
クライアントPCからアクセスしてみます.今後のためにまず~/.ssh/config
に設定を追記しておきます.sshするポートを変更している人などは適宜読み替えてください.
ServerAliveInterval 60 Host hoge HostName {address of your server} User {your github name} Port 22 IdentityFile ~/.ssh/{key name}
いざログイン(初回はAre you sure you want to continue connecting (yes/no)?
みたいなメッセージが出ます)
$ ssh hoge Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-62-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage SAKURA Internet [Virtual Private Server SERVICE] Last login: Sun Dec 10 00:00:00 2017 from 000.00.00.0 {your github name}@{your host}:
わーいやったー!
sudoしたい
ここまででsshはできましたが,実はこのままではsudo
できません./etc/octopass.conf
のGroups
がユーザの所属するグループを決定するのですが,これをsudo
とかにしてもsudo
はできません.どうやるんだーーーーとなってissueで質問させていただきました.
まさかその日中にレスポンスを頂けるとは…ありがたい.
というわけで,/etc/sudoers.d/
以下に設定を追記します.
sudoerへのグループの追加
/etc/octopass.conf
のGroups
を設定しなかった場合,初期値はGithub Teamのチーム名が使用されます(ここではhoge
とします).
このhoge
グループに対してパスワードを要求せずsudo
する権限を与える必要があるようです.(ここからはサーバ上での作業です.さくらのVPSのシリアルコンソールから作業しました*2)
$ sudo visudo -f /etc/sudoers.d/hoge
立ち上がるのがvimじゃなくていつも戸惑うのですが,下記のように記述します.
%hoge ALL=(ALL) NOPASSWD: ALL
これで保存するとhoge
グループのユーザはパスワード無しでsudo
できるようになります*3.
まとめ
Team単位で認証できるため,例えば新しく鯖管を育成したいとなったときもユーザ作って〜鍵登録して〜とかせず,Teamにメンバーを追加するだけで済みます.また,複数サーバを建てた際にも最初にこれを導入さえしてしまえば他のメンバがログインして作業できるため効率的です.
サーバ数台程度の規模ならばGithubのAPI制限にかかる可能性は低いですし,速度面も特に気になりませんでした.Githubが落ちてるときはどうせまともに作業できないのでゆっくりコーヒーでも飲んで待ちます.
あとは複数ロールへの対応が欲しい…sudo
不可のTeamを追加して運用できれば小規模チームにとってはかなり最高なソリューションなのでは.
以上,導入してみた所感でした.