※この記事の読了目安時間は6分です。
はじめに
個人開発をしていて、私はこのようなジレンマを感じました。
「せっかく作ったアプリ、みんなに使ってほしい!」
「バグ報告やIssueもオープンに受け付けたい!」
「でも...ソースコードを見せるのは、ちょっと恥ずかしい🫣」(というか、戦略的、セキュリティ的に隠しておきたい)
そこで、ソースコードが書いてあるPrivateリポジトリと、Issueを立てるためだけのPublicリポジトリを作成して紐付ければ、ソースコードを公開せずともユーザーとのやり取りやバグ報告などを受けることができるわけです!!
構成図
実際に構築することができたので今回は紹介したいと思います。 全部で3ステップです!
全体像
その前にまずは、全体像で、どういうデータの流れになるのかをサクッと解説します。
本システムは、2つのリポジトリを GitHub Actions で繋いでいます。
- Publicリポジトリ: ユーザーがIssueを立てる場所。
- Privateリポジトリ: 実際の開発拠点。
Publicで記載したIssueは自動でPrivateに転送され、Privateでタスクを完了(Close)させると、Public側も連動して「完了(Close)になる仕組みです!(逆もまた然り)
Step 1:2つのリポジトリを繋ぐ「合鍵」を作る
- GitHubのSettings から
Fine-grained tokensでトークンを発行。

- 権限の設定
-
Only select repositories で任意の二つのリポジトリを選択します。
-
Permissionsでは検索窓から
Issuesを選択してください。
- Permissions の
IssuesをRead and writeに設定するのを忘れないでください!
- Permissions の
3. 各リポジトリの Secrets に、発行したトークンを登録します。
- Publicリポジトリのページを開く
Settings > Secrets and variables > ActionsをクリックNew repository secretボタンを押す
Nameに任意の値を入れ、Secretに先ほどコピーしたトークンを入力して保存

これで準備完了。いよいよ自動化のコードを書いていきます!
リポジトリの Settings > Secrets and variables > Actions で 登録する名前(PRIVATE_REPO_TOKEN など)は、YAMLに書く名前と一字一句合わせてください
Step 2:PublicからPrivateへ自動転送(YAML)
Publicリポジトリ側に .github/workflows/sync-to-private.yml を作成します。
そして以下を記述します
name: Sync Issue to Private
on:
issues:
types: [opened, reopened]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Create Issue in Private Repo
uses: actions/github-script@v7
with:
# 事前に設定した「合鍵(PAT)」をここで使います
github-token: ${{ secrets.PRIVATE_REPO_TOKEN }}
script: |
await github.rest.issues.create({
owner: '【ここにユーザー名】',
repo: '【ここにPrivateリポジトリ名】',
title: `${context.payload.issue.title}`,
// 元のIssueへのリンクを本文の先頭に自動挿入するのがポイント!
body: `Original Issue: ${context.payload.issue.html_url}\n\n${context.payload.issue.body || 'No description provided.'}`
});
Step 3:Privateでのcloseをpublicに反映させる(逆同期)
今回のこだわりポイント、双方向同期の話です。
最後に、プライベート側で作業が終わった時、公開側のIssueも自動で閉じてくれるように設定します。
本文内のリンクから元IssueのIDを特定し、状態を同期させています。
closed だけでなく reopened にも対応させたのが、個人的なこだわりポイントです💪
name: Sync Status to Public
on:
issues:
# 閉じた時(closed)と、再開した時(reopened)の両方を検知
types: [closed, reopened]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Sync Status with Public Repo
uses: actions/github-script@v7
with:
github-token: ${{ secrets.PUBLIC_REPO_TOKEN }}
script: |
const body = context.payload.issue.body || '';
const match = body.match(/【ここにユーザー名】\/【ここに公開リポジトリ名】\/issues\/(\d+)/);
if (match) {
const issueNumber = parseInt(match[1]);
// 現在のアクションが 'closed' なら 'closed' に、それ以外(reopened)なら 'open' に設定
const newState = context.payload.action === 'closed' ? 'closed' : 'open';
await github.rest.issues.update({
owner: '【ここにユーザー名】',
repo: '【ここに公開リポジトリ名】',
issue_number: issueNumber,
state: newState
});
}
これで構築は完了です!
挙動の確認
ではPublicリポジトリでIssueを立ててみましょう!(友人にIssueを立ててもらいました。)
次にPrivateリポジトリでも同様のIssueが立っているか確認します。(10秒ほど待つと反映されていました!)
うまくいきました!!!!
これで完了です。
※上記コードでは運用上、Privateリポジトリで立てたIssueに関してはPublicには反映されないような仕組みとなっております。
おわりに
実際にこのリポジトリを運用することでユーザーからの意見を受け入れやすくなりました!
バグ報告もIssueを通じて知ることができるので、私が持っていない視点で意見をもらうことが何より嬉しいです!
最後に
宣伝のようになっていまい、恐縮ですが今回作成したPublicリポジトリ(開発フィードバックリポジトリ)と
私が運営しているテックブログを紹介させてください!
改善点等ありましたら、お気軽にIssueを立てていただけますと嬉しいです!!
- 個人テックブログ : tully-blog
- 開発フィードバックリポジトリ
本記事における「OSS運用」の定義
厳密にはプロダクト本体(アプリケーション)のソースコードは非公開ですが、
「Issue管理に必要な設定を公開リポジトリとしてオープンにし、
開発プロセスを全開放する運用スタイル」を、便宜上「OSS運用」と呼称しています。
コメント
コメントを読み込み中...



