FUNDING.ymlを置いてもSponsorボタンは出ない: 42リポジトリを棚卸しした
昨日、OSSのリポジトリを3つ公開しました。支援導線も整えたつもりでした。アカウント共通のFUNDING.ymlは継承されているし、APIを叩けばfundingLinksも返ってくる。ところがリポジトリのページを開くと、Sponsorボタンがどこにもありません。
APIは「ある」と言い、ページは「ない」と言う。原因を追ったらGitHubの仕様が二層構造になっていて、しかも片方の層はCLIでリポジトリを作る人だけが踏む作りでした。勢いで自分のpublicリポジトリ42個を全部棚卸ししたので、その記録を残します。
Sponsorボタンは二層構造
ボタンの表示には、独立した2つの設定が両方揃っている必要があります。
| 層 | 役割 | 設定場所 |
|---|---|---|
| FUNDING.yml | 何を表示するか(リンク先のリスト) | .github/FUNDING.yml |
| Sponsorshipsフラグ | 表示するかどうか | repo Settings → Features のチェックボックス |
FUNDING.ymlは、.githubという名前のリポジトリを作ってそこに1枚置くと、アカウント内の全publicリポジトリのデフォルトになります。私はここに GitHub Sponsors と Ko-fi を書いていて、これは新しいリポジトリにも自動で効いていました。
問題はもう1つの層です。Web UIからFUNDING.ymlを作ると、フラグも一緒にオンになります。しかしgh repo createやgit pushでリポジトリを作ると、フラグはfalseのままです。つまりブラウザで設定した人は存在にすら気づかず、CLIで量産する人だけが静かに踏みます。
さらにこのフラグ、REST APIには存在しません。GraphQLのhasSponsorshipsEnabledだけです。gh repo editのオプションを探しても出てこないのはこのためで、有効化はこう書きます。
id=$(gh api graphql -f query='{ repository(owner: "you", name: "repo") { id } }' \
--jq '.data.repository.id')
gh api graphql -f query='
mutation($id: ID!) {
updateRepository(input: {repositoryId: $id, hasSponsorshipsEnabled: true}) {
repository { name hasSponsorshipsEnabled }
}
}' -f id="$id"
「APIが返す」と「表示されている」は別物
冒頭の誤認はこれでした。GraphQLでfundingLinksを引くとSponsorsとKo-fiの2件がきれいに返ってきたので、表示されていると判断した。実際にはそれはFUNDING.ymlが継承されている証明であって、ボタンが出ている証明ではありません。
検証は実ページに聞くのが確実です。
curl -s "https://github.com/you/repo" | grep -c "Sponsor this project"
# 1 なら右サイドバーに表示されている
42リポジトリを棚卸しした結果
同じ漏れが他にもあるはずだと思い、publicリポジトリ42個を全部調べました。
| 状態 | repo数 | 対応 |
|---|---|---|
| ボタンが出ていた | 12 | (うち3つは同日の朝に直したばかり) |
| 現役の自作repoでフラグ漏れ | 9 | GraphQLで有効化 |
| archived | 18 | 対象外 |
| fork | 3 | 対象外 |
ボタンが出ていた12個は、3つが当日の朝、9つが前日に、どちらも手作業で直した分でした。つまり自然にボタンが出ていたリポジトリは、42個中0個です。棚卸しにはもう1つ収穫があって、過去に個別設置したFUNDING.ymlが9リポジトリに残っており、そのうち8つは古い内容(Sponsorsのみ)でした。個別ファイルはアカウントデフォルトを上書きするので、この8リポジトリではKo-fiリンクが欠けたままだった。個別ファイルは全部削除して、.githubの1枚に寄せました。
FUNDING.ymlをリポジトリごとにコピーして回るのは、二重管理の始まりです。後からデフォルトを更新しても、古い個別ファイルが勝ち続けます。
自分のアカウントを監査するスクリプトはこれだけです。
OWNER=you
gh repo list "$OWNER" --visibility public --limit 200 --json name --jq '.[].name' |
while read -r name; do
flag=$(gh api graphql -f query="{ repository(owner: \"$OWNER\", name: \"$name\") \
{ hasSponsorshipsEnabled } }" --jq '.data.repository.hasSponsorshipsEnabled')
echo "$flag $name"
done | sort
falseの行が、ボタンの出ていないリポジトリです。
触らないと決めたもの
全部trueにすれば終わり、とはしませんでした。
archivedの18個は、そもそもread-onlyなのでmutationが通りません。unarchiveすれば変えられますが、10年前のAndroidサンプルにまで支援を募る執念は私にはありませんでした。
forkの3個は意図的に見送りました。調べてみると、fork由来のFUNDING.ymlにはfork元作者の支援設定が入っています。手元の例では、あるターミナルアプリのforkにconnectbot作者のGitHub Sponsorsが設定されていました。これを消して自分のボタンを立てると、他人の作品で自分への支援を募る形になります。fork元の設定はそのまま温存が筋だと思います。
受け皿は無料、機会損失は静かに積もる
収益の話を正直に書くと、私のSponsorsにはまだ語れる数字がありません。ただ、受け皿が無ければゼロが確定します。GitHub Sponsorsは個人からの支援にプラットフォーム手数料がかからず、併記しているKo-fiも寄付のプラットフォーム手数料は0%なので、置いておくコストは設定の5分だけです。個人開発でOSSを出すなら、リポジトリを作った瞬間に済ませておく類いの作業です。
最後に白状すると、私はこの罠を前日にも別のリポジトリで踏んでいて、対処法のメモまで残していました。それでも翌日、新しい3リポジトリで同じ漏れをやった。記憶は当てにならないので、リポジトリ公開手順のチェックリストにフラグ有効化と実ページ検証を組み込みました。この記事も、そのチェックリストの延長です。
この記事は役に立ちましたか?