Repository navigation
ci: add review-gate, OpenSSF Scorecard and Dependabot cooldown #16
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
Open
ricardofrantz
wants to merge
5
commits into
main
Choose a base branch
from
ci/review-gate-scorecard
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
a73e60e
ci: review-gate, Scorecard, Dependabot cooldown and CodeRabbit inheri…
ricardofrantz 75988ef
ci: review-gate pages the PR commits, polls once more at the end, and…
ricardofrantz 33d585b
ci: review-gate treats a failed history lookup as no earlier review
ricardofrantz 145d241
ci: review-gate and Scorecard fixes from the bot reviews (copy of pi-…
ricardofrantz 7ec0fc2
ci: review-gate and Scorecard fixes, round 2 (copy of pi-effort 73f514f)
ricardofrantz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| # Fails when cubic did not complete a review, or when CodeRabbit was off or errored. | ||
| # Passes with a warning when CodeRabbit is only rate limited. | ||
| # Reads check runs only. Check titles are matched as text: update them here | ||
| # when a vendor renames one. | ||
| name: review-gate | ||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened, ready_for_review] | ||
| permissions: | ||
| checks: read | ||
| pull-requests: read # list the PR commits | ||
| # A newer push to the same PR cancels the run that still polls the older commit. | ||
| concurrency: | ||
| group: review-gate-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
| jobs: | ||
| review-gate: | ||
| # Bot-authored dependency PRs and draft PRs: the job is skipped, which passes a required check. | ||
| if: >- | ||
| github.event.pull_request.user.login != 'dependabot[bot]' && | ||
| github.event.pull_request.user.login != 'renovate[bot]' && | ||
| github.event.pull_request.draft == false | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - name: Wait for both bots, then decide | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| REPO: ${{ github.repository }} | ||
| SHA: ${{ github.event.pull_request.head.sha }} | ||
| PR: ${{ github.event.pull_request.number }} | ||
| run: | | ||
| set -euo pipefail | ||
| # Latest check run of one app on this commit, as JSON; "null" when none or on an API error. | ||
| # gh prints an HTTP error body to stdout, so on failure the value is replaced, not appended to; | ||
| # the error text on stderr stays in the log. $2 (optional) is the exact check name: | ||
| # CodeRabbit publishes other checks under the same app, for example CodeRabbit Security. | ||
| latest() { | ||
| local out | ||
| out=$(gh api "repos/$REPO/commits/$SHA/check-runs?app_id=$1${2:+&check_name=$2}&filter=latest&per_page=100" \ | ||
| --jq '[.check_runs[] | {id, status, conclusion, title: .output.title}] | max_by(.id)') || out=null | ||
| echo "$out" | ||
| } | ||
| # True when CodeRabbit finished a review on any commit of this PR | ||
| # (the commits endpoint returns at most 250 commits). | ||
| cr_reviewed_before() { | ||
| local shas c n | ||
| shas=$(gh api --paginate "repos/$REPO/pulls/$PR/commits?per_page=100" --jq '.[].sha') \ | ||
| || { echo "::error::could not list the PR commits"; exit 1; } | ||
| for c in $shas; do | ||
| # filter=all: a later failed attempt on a commit does not hide its finished review | ||
| n=$(gh api "repos/$REPO/commits/$c/check-runs?app_id=347564&check_name=CodeRabbit&filter=all&per_page=100" \ | ||
| --jq '[.check_runs[] | select(.output.title=="Finished" and .conclusion=="success")] | length') || n=0 | ||
|
ricardofrantz marked this conversation as resolved.
Resolved
|
||
| [ "$n" != 0 ] && return 0 | ||
| done | ||
| return 1 | ||
| } | ||
| cr=null; cu=null | ||
| for i in $(seq 1 36); do # 36 polls, 30 s apart, the last at 17.5 min | ||
| cr=$(latest 347564 CodeRabbit) # CodeRabbit app, review check | ||
| cu=$(latest 1082092) # cubic app | ||
| [ "$(jq -r '.status' <<<"$cr")" = completed ] && [ "$(jq -r '.status' <<<"$cu")" = completed ] && break | ||
| if [ "$i" -lt 36 ]; then sleep 30; fi | ||
| done | ||
| echo "CodeRabbit: $cr"; echo "cubic: $cu" | ||
| cr_title=$(jq -r 'if .status=="completed" then .title else "missing" end' <<<"$cr") | ||
| cr_concl=$(jq -r '.conclusion // "none"' <<<"$cr") | ||
| cu_title=$(jq -r 'if .status=="completed" then .title else "missing" end' <<<"$cu") | ||
| cu_concl=$(jq -r '.conclusion // "none"' <<<"$cu") | ||
| if [ "$cu_title" != "AI review completed" ] || [ "$cu_concl" != success ]; then | ||
| echo "::error::cubic did not complete a review: $cu_title ($cu_concl)"; exit 1 | ||
| fi | ||
| case "$cr_concl" in | ||
| failure|cancelled|timed_out|action_required|stale|none) echo "::error::CodeRabbit check did not pass: $cr_title ($cr_concl)"; exit 1 ;; | ||
| esac | ||
| case "$cr_title" in | ||
| "Finished") | ||
| [ "$cr_concl" = success ] || { echo "::error::CodeRabbit finished without success ($cr_concl)"; exit 1; } ;; | ||
| "Review rate limited") echo "::warning::CodeRabbit rate limited; cubic reviewed." ;; | ||
| "Path filters excluded"*|"No files to review") echo "::notice::CodeRabbit: $cr_title" ;; | ||
| # CodeRabbit reviews the opening push only (auto_incremental_review false); cubic reviews every push. | ||
| # Accept the skip only when CodeRabbit finished a review on an earlier commit of this PR. | ||
| "Review skipped: incremental reviews are disabled"|"Incremental review skipped") | ||
| if cr_reviewed_before; then | ||
| echo "::warning::CodeRabbit reviews the opening push only; comment '@coderabbitai review' for this commit." | ||
| else | ||
| echo "::error::CodeRabbit never finished a review on this PR; comment '@coderabbitai full review', then re-run this job once that review has finished."; exit 1 | ||
| fi ;; | ||
| *) echo "::error::CodeRabbit did not review: $cr_title ($cr_concl)"; exit 1 ;; | ||
| esac | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # OpenSSF Scorecard: supply-chain checks, weekly and on branch-protection changes. | ||
| # Based on the template in https://github.com/ossf/scorecard-action | ||
| name: Scorecard supply-chain security | ||
| on: | ||
| branch_protection_rule: | ||
| schedule: | ||
| - cron: '17 4 * * 1' | ||
| push: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| analysis: | ||
| name: Scorecard analysis | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| # Scorecard rejects a manual run on a non-default branch | ||
| if: github.event_name != 'workflow_dispatch' || github.ref_name == github.event.repository.default_branch | ||
| permissions: | ||
| security-events: write # upload SARIF to code scanning | ||
| id-token: write # publish results to the OpenSSF API | ||
| contents: read | ||
| actions: read | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Run analysis | ||
| uses: ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e # v2.5.0 | ||
| with: | ||
| results_file: results.sarif | ||
| results_format: sarif | ||
| publish_results: true | ||
| - name: Upload artifact | ||
| uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 | ||
| with: | ||
| name: SARIF file | ||
| path: results.sarif | ||
| retention-days: 5 | ||
| - name: Upload to code scanning | ||
| uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1 | ||
| with: | ||
| sarif_file: results.sarif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.