-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support private repositories and private submodules #287
Comments
This worked for me: |
Thanks @marcofranssen, For anyone else looking, deploy keys are a partial fix. The problem with deploy keys and a separate clone submodules step is that you need to keep the submodule ref and the ref in github actions the same, editing the setting in two places. Personal access tokens as suggested by @beroso work, but either involve giving access to all your repos, or creating a new machine user and adding them as a collaborator, big faff. It would be great if github could provide a proper and simple way to clone private submodules. |
For anyone else having trouble with this, I have a solution that doesn't require personal access tokens but keeps the reference to the child repo commit in one place (using git submodules) - name: clone submodule
uses: actions/checkout@v2
with:
repository: <org name>/<repo name>
path: path
ssh-key: ${{ secrets.SSH_KEY }}
persist-credentials: true
- name: checkout submodule
run: |
git submodule init
git submodule update although the action checks out master, the |
See, this is what I really want... just the persist-credentials part. then I could have
and all it does is make it so the next git command or ssh command can use that key. |
Instead of using an SSH key (:scream: ) you can simply use a personal access token:
Here the |
Correct me if I'm wrong, but this wont work for multiple private submodules, because each needs their own deploy key. |
I ended up building a rudimentary private package manager for python to get round this problem. I think the reason github aren't fixing it is that they think the long term solution should be their package manager(s). |
I ended up just embedding the private keys for read-only deploy keys in the yml workflow files directly as ENV variables then following this advice with the hard coded strings instead of secrets (which aren't available for free in GitHub Org private repos): https://rgoswami.me/posts/priv-gh-actions/ Hacky and gross, but it works. |
diff --git a/.cache/kvs-node-localstorage/proofdict-lastUpdated b/.cache/kvs-node-localstorage/proofdict-lastUpdated index eff9476..cefbfec 100644 --- a/.cache/kvs-node-localstorage/proofdict-lastUpdated +++ b/.cache/kvs-node-localstorage/proofdict-lastUpdated @@ -1 +1 @@ -1619384079626 \ No newline at end of file +1619692984086 \ No newline at end of file diff --git a/articles/improve-dependabot-pr.md b/articles/improve-dependabot-pr.md index 1187eb3..8ebb47a 100644 --- a/articles/improve-dependabot-pr.md +++ b/articles/improve-dependabot-pr.md @@ -1,86 +1,22 @@ --- -title: "GitHub Actions で Dependabot プルリクエストの滞留を防ぐ仕組みづくり" +title: "GitHub Actions で Dependabot のプルリクエストの滞留を防ぐ仕組みづくり" emoji: "🛤" type: "tech" topics: ["githubactions", "github", "dependabot"] -published: false +published: true --- 自動的にライブラリのアップデートのプルリクエストを作ってくれる[Dependabot](https://dependabot.com/)はとても便利です。ただ、何かと通常の開発タスクに追われライブラリアップデートのプルリクエストは滞留しがちです。それを解決するための仕組みはないかなと思い、試行錯誤してみたので書きます。 - -# Dependabotのプルリクエスト作成時にランダムにレビュアーをアサイン - -私のチームのプルリクエスト作成からマージまでの流れは以下です。 - -1. プルリクエスト作成時に任意のチームメンバーを 1 人選びレビュアーにアサイン -2. レビュアーがレビュー後マージ - -基本的には、レビュアーにアサインされたものをレビューするという運用なので、レビュアーのアサインがない Dependabot のプルリクエストは後回しになりがちです。 - -それを改善するために、Dependabot のプルリクエストのみ自動的にレビュアーをアサインする仕組みを GitHub Actions を使って作りました。 -以下がコードです。 - -```yml -name: Reviewer assign action - -on: - pull_request_target: - types: [opened] - -jobs: - reviewer-assign: - timeout-minutes: 10 - runs-on: ubuntu-18.04 - if: contains(github.head_ref, 'dependabot/npm_and_yarn') || contains(github.head_ref, 'dependabot/pip') - steps: - # ランダムでレビュアーをアサイン - - name: Assign reviewer - uses: hkusu/[email protected] - with: - reviewers: taro, jiro, masaki, ichiro - max-num-of-reviewers: 1 - # ライブラリアップデートロールをアサイン - - if: contains(github.head_ref, 'npm_and_yarn') - run: echo ROLL_USER=kawamataryo >> $GITHUB_ENV - - if: contains(github.head_ref, 'pip') - run: echo ROLL_USER=shiro >> $GITHUB_ENV - - name: Assign roll user - uses: hkusu/[email protected] - with: - reviewers: ${{ env.ROLL_USER }} - assignees: ${{ env.ROLL_USER }} -``` - -プルリクエストの自動レビュアーアサインには、[Review Assign Action](https://github.com/hkusu/review-assign-action) を利用しています。 - -https://github.com/marketplace/actions/review-assign-action - -上記のコードだと、最初の `name: Assign reviewer` のステップで `reviewers` に指定されているユーザーから、ランダムに 1 人がレビュアーにアサインされます。 -そして、その後の `name: Assign roll user` の方で、ライブラリの種類(ここでは npm か pip)によって専任の担当者を決めています。これはライブラリアップデートという役割を持つメンバーがチームにいて、その者をランダムなレビュアーとは別に必ずアサインするためです。このように GitHub Actions の `if` 構文を使うことで条件によって動的にアサイン対象を変えることも可能です。 - - -また、Dependabot のプルリクエストのみを対象にするために、`jobs.xxx.if`で dependabot の作成ブランチのみ true を返すように指定しています。これで、通常のプルリクエストは対象にならず、Dependabot のプルリクエストのみこの GitHub Actions が実行されます。 - - -:::message -Dependabot の標準の設定でも、レビュアーやアサイナーの設定はできるのですが、複数人の候補からランダムに 1 人を選ぶというのはできないので GitHub Actions で対応しています。 -もし必ず固定メンバーをアサインということなら、[こちら](https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates#reviewers)で設定可能です。 -::: - -:::message -Dependabot と同様の機能を持つ[Renovate](https://github.com/renovatebot/renovate) の場合は、指定メンバーの中からのランダムアサインも可能なようです。 -::: - # 静的アセットのビルド差分からレビューの必要性を判断 -今のチームではバックエンドは Python、フロントエンドが Vue.js という構成なので、Node.js はランタイムで利用せず、あくまで静的アセット(JS, CSS, Image)のビルドのみです。 -そのため、npm モジュールのライブラリアップデートは**プルリクエストブランチでビルドされた静的アセットが、master ブランチでビルドされた静的アセットと差分がなければプロダクトの動きは変わららないはず**です。 -なので、差分をみれば詳細なレビューが必要かどうか判断できます。差分もなく CI も通っていればほぼノールックでマージしてよいはず。 +今のチームのプロダクトでは静的アセット(JS, CSS, Image)のビルドにのみ Node.js を利用しています。 +そのため、npm モジュールのライブラリアップデート時に**プルリクエストのブランチでビルドされた静的アセットが、master ブランチでビルドされた静的アセットと差分がなければプロダクトの動きは変わららないはず**です。 +なので、そのビルド差分の有無をみれば詳細なレビューが必要かどうか判断できます。差分もなく CI も通っていればほぼ動作確認�は不要で、Change log の確認だけでマージしてもよいでしょう。 -※ 差分が出ない場合の例: Test 系、Lint 系、ビルド系のライブラリ、Tree Shaking で除去される部分のコードの変更 +※ 差分が出ない場合の例: Test 系、Lint 系、ビルド系のライブラリ、Tree Shaking で除去される部分のコードの変更など :::message -この考え・仕組みは前職の開発チームで[@mugi_uno](https://twitter.com/mugi_uno)が作ってくれたスクリプトをそのまま参考にしています。ありがとうございます🙏 +この考え・仕組みは前職の開発チームで[@mugi_uno](https://twitter.com/mugi_uno)が作ってくた仕組みを参考にしています。感謝🙏 ::: その差分比較を毎回手動で行うのは面倒なので、GitHub Actions で自動実行できるようにしました。 @@ -190,15 +126,78 @@ jobs: ![](https://storage.googleapis.com/zenn-user-upload/1ft5n4j30866cze0ddak9wo3kxs8) **差分がある場合** -![](https://storage.googleapis.com/zenn-user-upload/496c6u9lw58mjgz4drgj7vancfnz) +![](https://storage.googleapis.com/zenn-user-upload/co3e550t6fzpaym7belne7s3q60r) 差分がないとコメントされた場合は、気軽にマージできます。 +# Dependabotのプルリクエスト作成時にランダムにレビュアーをアサイン + +私のチームのプルリクエスト作成からマージまでの流れは以下です。 + +1. プルリクエスト作成時に任意のチームメンバーを 1 人選びレビュアーにアサイン +2. レビュアーがレビュー後マージ + +基本的には、レビュアーにアサインされたものをレビューするという運用なので、レビュアーのアサインがない Dependabot のプルリクエストは後回しになりがちです。 + +それを改善するために、Dependabot のプルリクエストのみ自動的にレビュアーをアサインする仕組みを GitHub Actions を使って作りました。 +以下がコードです。 + +```yml +name: Reviewer assign action + +on: + pull_request_target: + types: [opened] + +jobs: + reviewer-assign: + timeout-minutes: 10 + runs-on: ubuntu-18.04 + if: contains(github.head_ref, 'dependabot/npm_and_yarn') || contains(github.head_ref, 'dependabot/pip') + steps: + # ランダムでレビュアーをアサイン + - name: Assign reviewer + uses: hkusu/[email protected] + with: + reviewers: taro, jiro, masaki, ichiro + max-num-of-reviewers: 1 + # ライブラリアップデートロールをアサイン + - if: contains(github.head_ref, 'npm_and_yarn') + run: echo ROLL_USER=kawamataryo >> $GITHUB_ENV + - if: contains(github.head_ref, 'pip') + run: echo ROLL_USER=shiro >> $GITHUB_ENV + - name: Assign roll user + uses: hkusu/[email protected] + with: + reviewers: ${{ env.ROLL_USER }} + assignees: ${{ env.ROLL_USER }} +``` + +プルリクエストの自動レビュアーアサインには、[Review Assign Action](https://github.com/hkusu/review-assign-action) を利用しています。 + +https://github.com/marketplace/actions/review-assign-action + +上記のコードだと、最初の `name: Assign reviewer` のステップで `reviewers` に指定されているユーザーから、ランダムに 1 人がレビュアーにアサインされます。 +そして、その後の `name: Assign roll user` の方で、ライブラリの種類(ここでは npm か pip)によって専任の担当者を決めています。これはライブラリアップデートという役割を持つメンバーがチームにいて、その者をランダムなレビュアーとは別に必ずアサインするためです。このように GitHub Actions の `if` 構文を使うことで条件によって動的にアサイン対象を変えることも可能です。 + + +また、Dependabot のプルリクエストのみを対象にするために、`jobs.xxx.if`で dependabot の作成ブランチのみ true を返すように指定しています。これで、通常のプルリクエストは対象にならず、Dependabot のプルリクエストのみこの GitHub Actions が実行されます。 + + +:::message +Dependabot の標準の設定でも、レビュアーやアサイナーの設定はできるのですが、複数人の候補からランダムに 1 人を選ぶというのはできないので GitHub Actions で対応しています。 +もし必ず固定メンバーをアサインということなら、[こちら](https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates#reviewers)で設定可能です。 +::: + +:::message +Dependabot と同様の機能を持つ[Renovate](https://github.com/renovatebot/renovate) の場合は、指定メンバーの中からのランダムアサインも可能なようです。 +::: + # 詰まったところ -実装上で色々踏み抜いたので書きます。 +実装上で色々詰まった部分があったのでまとめます。 -## 対象ブランチで動作しない・・ +### 対象ブランチで動作しない・・ 当初対象ブランチの指定方法を間違え、以下のように`pull_request.branches`でブランチ名を指定していました。 @@ -216,7 +215,7 @@ on: https://zenn.dev/ryo_kawamata/articles/github-actions-specific-branch -## Dependabot作成のPRだけ、403でコメント・レビュアーアサインが落ちる・・ +### Dependabot作成のPRだけ、403でコメント・レビュアーアサインが落ちる・・ 「もう完璧に動くやろ!」とメインブランチにマージした後に気がついたのですが、Dependabot の作ったプルリクエストの場合のみ、同じ GitHub Actions でも書き込み系の操作で 403 エラーが発生しました。これは、Dependabot のみ`GITHUB_TOKEN`で取れるトークンが読み取り専ようになるため起こるようです。 @@ -225,13 +224,13 @@ https://zenn.dev/ryo_kawamata/articles/github-actions-specific-branch dependabot/dependabot-core#3253 :::message -こういう面倒な点を考慮すると、Renovate を使ったほうが良いのかもしれない・・ +こういう面倒な点を考慮すると、Renovate を使ったほうが良いのかもしれないです。 ::: -## Runの中でエラーでもないのになぜか毎回終了する・・ +### Runの中でエラーでもないのになぜか毎回終了する・・ 差分を取るために GitHub Actions の run でコマンドを実行しているのですが、なぜか`git diff`で差分がある場合のみ、コマンドがそこで終了するという現象に悩まされました。 -原因は、`git diff`で差分がある場合、終了コードが`1`になるためでした。GitHub Actions の run は終了コードが`1`となるコマンドが実行されるとそこで処理を停止するようです。 +原因は、Git 管理対象外のファイルに`git diff`を行った際に差分がある場合、終了コードが`1`になるためでした。GitHub Actions の run は終了コードが`1`となるコマンドが実行されるとそこで処理を停止するようです。 今回はコマンドでは、最後に`|| true`をつけることで回避しています。 @@ -241,9 +240,22 @@ git diff --compact-summary /tmp/current /tmp/master > $RESULT_FILE || true #... ``` +### プロジェクト内のSubmoduleのcloneに失敗・・ +今回この仕組を導入したプロジェクトが、プライベートリポジトリの Git Submodule を含むプロジェクトだったため `actions/checkout@v2` の通常の submodule の設定だけではうまく行かず詰まりました。結局、以下 Issue を参考に、Personal Access Token を設定することで回避しました。 + +actions/checkout#287 + +```yaml + - name: Checkout current branch + uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + token: ${{ secrets.PAT }} + submodules: 'recursive' +``` # おわりに -以上、「GitHub Actions で Dependabot のプルリクエスト滞留問題を解決する仕組み作り」でした。まだ、運用を始めたばかりで道半ばというところですが、この仕組を使って良い感じにバージョンアップを進められればと思っています。 +以上、「GitHub Actions で Dependabot のプルリクエスト滞留問題を解決する仕組み作り」でした。まだ、運用を始めたばかりで道半ばというところですが、この仕組を使って良い感じにバージョンアップを進められればなと思っています。 # 参考
Less hacky and gross variant, using
|
It's a travesty really that this doesn't work out of the box. It forces behaviors that should be discouraged - people fret about submodules (they shouldn't), people have to pay for dummy GitHub accounts just to make this work, people have to bend backwards to get something that is well within the minimally viable product spec for any CI environment. /smh |
I tend to use deployment keys for this. Add the set -Eeuo pipefail
mkdir -p ~/.ssh
ssh-keyscan -t rsa -H github.com >> ~/.ssh/known_hosts
echo $GH_ACTION_DKEY > ~/.ssh/id_rsa.b64
base64 -d -i ~/.ssh/id_rsa.b64 > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
exit 0 |
something like this worked for multiple private submodules. steps:
- uses: actions/checkout@v2
with:
ssh-key: ${{secrets.SSH_KEY}}
- name: Checkout submodules
env:
GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=no"
run: |
eval `ssh-agent -s`
echo "${{secrets.SSH_KEY_SUBMODULE1}}" | ssh-add -
git submodule update --init -- src/submodule1
ssh-add -D
echo "${{secrets.SSH_KEY_SUBMODULE2}}" | ssh-add -
git submodule update --init -- src/submodule2
ssh-add -D
eval `ssh-agent -k` |
This is insecure and not recommended. The secure alternative is |
@fearphage true, although ssh-keyscan will accept incorrect key in case of the spoofed server. I don't like the ssh-keyscan solution because on self hosted servers this appends to the same file on each trigger. One solution to this problem is to use From the security perspective it may be better to tmpdir=$(mktemp -d)
echo "${{ secrets.GITHUB_PUBLIC }}" >> $tmpdir/known_hosts
ssh -o UserKnownHostsFile=$tmpdir/known_hosts Then can remove temporary directory to clean things up. |
That sounds pretty bad in general. I have no experience using self-hosted runners, but the whole point of GitHub Actions (in my mind) is that every run is from a clean room environment. Reusing a dirty machine/image sounds like a security hole in and of itself. |
my repository and its submodules don't support SSH ( only HTTPS ). Is there a solution for this protocol to retrieve submodules in GitHub Actions ? |
@fairmonk – the trick here is to specify the submodule via a relative path when initially configuring it, that way it works when the parent module is checked out via either scheme. See https://stackoverflow.com/a/44630028/31629 for more info. |
Using relative URL didn't help here. |
Using a PAT or SSH key means that it needs to be generated for a specific user's account. This is not a viable solution, because if that person leaves the project, and we remove their access to the project, then we need to regenerate the PAT and SSH key for another user. This is the problem we have been having, or am I misunderstanding this and there is a better way? |
I've checked that solution first, unfortunately these ssh keys needs to be added as deployment keys to repository that contains submodules and for some reason multiple keys failed to work :( You approach with ssh-agent config worked! |
Is this really required? Are there security reasons why a much better UX can't be provided to developers? The workflow runs with the identity of the user who triggered it, if this person has checkout privileges on submodules can't his token be authorized to checkout submodules? |
I can confirm that this method no longer works reliably - it returned the following error in my case:
I agree with @edmondop, utilizing user's (or even organization's) access permissions automatically should be a way to go. Ideally, there could be an option to set action permissions within the GH's UI. As an avid user GH actions, I really appreciate how they simplify repository management. But I believe that simplifying those kind of low-level configurations/processes would be of a great benefit. |
After an hour of wasting my time on this, I can confirm this does not work, at least not for self-hosted GitHub Enterprise. |
Right now we do not use Github actions because the configuration for private submodules is just too cumbersome. We would also like this to see this working 'out of the box'. We already setup repo access with Github Teams, and then we want to stop thinking about it. |
This is really sad story. I want to generate access token just in-memory for GitHub Action, because I'm in the same organisation for got sake! 🤦 https://docs.github.com/en/actions/security-guides/automatic-token-authentication Please GitHub do something with this. |
@ScottTylerHall349 You can create repo-specific SSH keys using deploy keys. |
@king-of-poppk yeah, but why do you even have to do it? It's in your organisation... |
You can also create a dedicated service account if you prefer a PAT or in general managing SSH keys there. Sure it's really bad because it means one more seat to pay for on enterprise.
Access might be more fine-grained than all-or-nothing within an org. |
I endorse @matthijskooijman's solution. Also: now there's an official action to handle GH App tokens. jobs:
test-submodules:
runs-on: ubuntu-latest
steps:
- name: Get token from Github App
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
# owner is required, otherwise the creds will fail the checkout step
owner: ${{ github.repository_owner }}
- name: Checkout from GitHub
uses: actions/checkout@v4
with:
submodules: true
token: ${{ steps.app_token.outputs.token }}
- name: Print .gitmodules
run: cat .gitmodules In the GH app side:
|
Thank you for the provided workaround, @magmanu! 🙏🏼 GitHub needs to do something to make this easier, though. The below discussions are related and point to a solution where the issued |
Deploy key solution: jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Clone main repository
uses: actions/checkout@v4
- name: Add SSH private keys for submodule repositories
uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.READ_ONLY_DEPLOY_KEY }}
- name: Clone submodules
run: git submodule update --init --recursive --remote Read ssh-agent Usage section to learn how to:
Also, in
|
Doing this via ssh-agent is just overkill. It should be possible to do this via token. GitHub please introduce this feature. |
Thanks @doutv, using ssh-agent is unfortunate but worked for me. Simply defining +1 for this feature. I'm coming from GitLab where this type of this was easy to achieve. |
After aggregating solutions here and reading some documentation I've came up with a clean solution. My use case is the following, in an action in Repo A I need to clone Repo B that has a submodule Repo C. All three are private in my organization.
IMPORTANTThis works because For example: If you generate the key with puttygen export the private key with |
I would love to see official solution from GitHub. It's should be based on Action permissions, org config of tmp token. |
Second this but I think "my" solution is not really hacky or sketchy and also scalable. I can now really fine tune permissions by the use of some ssh keys. |
AFAICS the ssh-keys approach does have limitations, in particular you can either use:
Did I get that right? For completeness, one alternative is to use github app tokens as I previously proposed (original #287 (comment) and followup #287 (comment) showing there is now an official GH action to support this flow). Possibly a bit more hassle to set up, but possibly a bit easier to manage than per-repository deploy SSH-keys (or maybe not - haven't tried that solution). |
@matthijskooijman What I've done is I created a deploy key for each of the two repositories in my scenario and added the private keys for that to the secrets in the repo that the action runs in. After that I can simply use I guess if you have a ton of repositories this gets pretty cumbersome. I haven't tried the GH App approach, I guess this one could be useful if you have many repositories where you need to do this. |
I too ran into this, one way to balance security concerns would be if github could detect you have submodules and install keys onto your agent which only allow the clone of that specific commit and can only be redeemed once / expire after an hour |
How would it check that you have the permission to read from that submodule? That also needs to be automated somehow. And it is complex: The permission is not necessarily tied to a "committer" or "pusher", there are many different triggers. Also you cannot just assume a "commiter" or a "pusher" gives consent to cloning from a repo that was potentially added as a submodule by someone else (who does not necessarily have access to that repo). |
How I imagine it would be like this:
|
@nebuk89 can you please look on this as well? I believe that's a similar case as this one https://github.com/orgs/community/discussions/46566#discussioncomment-10889835. Is it? Current ways are such a overkill, UX unfriendly for company like GitHub. |
Repository Settings -> Security -> Allow the following repositories to clone this repository -> [ No, this sadly doesn't exist. But GitHub, this is the way it should work. Just because I'm a programmer doesn't mean I love to spend days configuring a basic build system. We don't jump out of bed looking to continue the 4 year long discussion (I'm serious, scroll up) about the pros and cons of asymmetric cryptographic approaches compared to user-specific access tokens and what mystical arcane incantation should be invoked to perform either. You wouldn't buy a car where you had to spend days writing an algorithm to configure the geometric shape of the tyres before you could get it to move off your drive. Implement a checkbox and bring an end to this Lovecraftian dark age of hackery. You're not a startup any more. Behave like a mature company in your UX design. |
We have multiple orgs under one enterprise.
While I can easily check this out w/ submodules using my PAT, there's not a way to do this with app tokens as those aren't a thing at the enterprise level, so an app token could only checkout half using a given token because it'd be scoped to either |
Currently the checkout action doesn't work with private repositories using a private submodule.
As a work-around we use the following in our workflow.
It would be good if the checkout action would support some option to provide a different SSH_KEY for private submodules. E.g.
SUBMODULE_SSH_KEY
could be an organisation level SSH Key that allows pulling the repos.The text was updated successfully, but these errors were encountered: