review #432501 #74
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
name: review | |
run-name: "review #${{ inputs.pr }}${{ inputs.extra-args && format(' ({0})', inputs.extra-args) || '' }}" | |
permissions: {} | |
env: | |
PR_NUMBER: ${{ inputs.pr }} | |
on: | |
workflow_dispatch: | |
inputs: | |
pr: | |
description: "Pull Request Number" | |
required: true | |
type: string | |
x86_64-linux: | |
description: "Run on x86_64-linux" | |
required: true | |
type: boolean | |
default: true | |
aarch64-linux: | |
description: "Run on aarch64-linux" | |
required: true | |
type: boolean | |
default: true | |
x86_64-darwin: | |
description: "Run on x86_64-darwin" | |
required: true | |
type: choice | |
default: yes_sandbox_true | |
options: | |
- 'no' | |
- yes_sandbox_false | |
- yes_sandbox_relaxed | |
- yes_sandbox_true | |
aarch64-darwin: | |
description: "Run on aarch64-darwin" | |
required: true | |
type: choice | |
default: yes_sandbox_true | |
options: | |
- 'no' | |
- yes_sandbox_false | |
- yes_sandbox_relaxed | |
- yes_sandbox_true | |
extra-args: | |
description: "nixpkgs-review extra args" | |
required: false | |
type: string | |
push-to-cache: | |
description: "Push to cache" | |
required: true | |
type: boolean | |
default: true | |
upterm: | |
description: "Start upterm session after nixpkgs-review" | |
required: true | |
type: boolean | |
default: false | |
post-result: | |
description: "Post Result" | |
required: true | |
type: boolean | |
default: true | |
on-success: | |
description: "What to do on review success" | |
required: true | |
type: choice | |
default: nothing | |
options: | |
- nothing | |
- mark_as_ready | |
- approve | |
- merge | |
jobs: | |
prepare: | |
runs-on: ubuntu-latest | |
outputs: | |
pr: ${{ steps.pr.outputs.pr }} | |
head: ${{ steps.pr.outputs.head }} | |
merge: ${{ steps.pr.outputs.merge }} | |
author_id: ${{ steps.pr.outputs.author_id }} | |
steps: | |
- name: get pr | |
id: pr | |
run: | | |
while true; do | |
pr="$(gh api "/repos/NixOS/nixpkgs/pulls/$PR_NUMBER")" | |
jq -e '.mergeable_state == "unknown" and (.merged | not)' <<< "$pr" > /dev/null || break | |
echo "mergeable state not known yet, retrying..." | |
sleep 2 | |
done | |
jq <<< "$pr" | |
if [[ "$(jq '.merged or .mergeable' <<< "$pr")" != "true" ]]; then | |
echo "::error::PR is not mergeable" | |
exit 1 | |
fi | |
echo "pr=$pr" >> "$GITHUB_OUTPUT" | |
echo "head=$(jq -r '.head.sha' <<< "$pr")" >> "$GITHUB_OUTPUT" | |
echo "merge=$(jq -r '.merge_commit_sha' <<< "$pr")" >> "$GITHUB_OUTPUT" | |
echo "author_id=$(jq -r '.user.id' <<< "$pr")" >> "$GITHUB_OUTPUT" | |
env: | |
GH_TOKEN: ${{ github.token }} | |
review: | |
needs: [prepare] | |
strategy: | |
fail-fast: false | |
matrix: | |
system: | |
- x86_64-linux | |
- aarch64-linux | |
- x86_64-darwin | |
- aarch64-darwin | |
exclude: | |
- system: ${{ !inputs.x86_64-linux && 'x86_64-linux' || '' }} | |
- system: ${{ !inputs.aarch64-linux && 'aarch64-linux' || '' }} | |
- system: ${{ inputs.x86_64-darwin == 'no' && 'x86_64-darwin' || '' }} | |
- system: ${{ inputs.aarch64-darwin == 'no' && 'aarch64-darwin' || '' }} | |
runs-on: >- | |
${{ (matrix.system == 'x86_64-linux' && 'ubuntu-latest') | |
|| (matrix.system == 'aarch64-linux' && 'ubuntu-24.04-arm') | |
|| (matrix.system == 'x86_64-darwin' && 'macos-latest') | |
|| (matrix.system == 'aarch64-darwin' && 'macos-latest') }} | |
outputs: | |
report_x86_64-linux: ${{ steps.report.outputs.report_x86_64-linux }} | |
report_aarch64-linux: ${{ steps.report.outputs.report_aarch64-linux }} | |
report_x86_64-darwin: ${{ steps.report.outputs.report_x86_64-darwin }} | |
report_aarch64-darwin: ${{ steps.report.outputs.report_aarch64-darwin }} | |
fetch_cmd_x86_64-linux: ${{ steps.report.outputs.fetch_cmd_x86_64-linux }} | |
fetch_cmd_aarch64-linux: ${{ steps.report.outputs.fetch_cmd_aarch64-linux }} | |
fetch_cmd_x86_64-darwin: ${{ steps.report.outputs.fetch_cmd_x86_64-darwin }} | |
fetch_cmd_aarch64-darwin: ${{ steps.report.outputs.fetch_cmd_aarch64-darwin }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
sparse-checkout: | | |
.github/actions | |
packages.nix | |
- name: setup nix | |
uses: ./.github/actions/setup-nix | |
with: | |
system: ${{ matrix.system }} | |
sandbox: ${{ | |
(matrix.system == 'x86_64-darwin' && inputs.x86_64-darwin == 'yes_sandbox_false' | |
|| matrix.system == 'aarch64-darwin' && inputs.aarch64-darwin == 'yes_sandbox_false') && 'false' | |
|| (matrix.system == 'x86_64-darwin' && inputs.x86_64-darwin == 'yes_sandbox_relaxed' | |
|| matrix.system == 'aarch64-darwin' && inputs.aarch64-darwin == 'yes_sandbox_relaxed') && 'relaxed' | |
|| 'true' }} | |
- name: install packages | |
run: | | |
pkgs=(coreutils nixpkgs-review jq gnused) | |
if [[ ${{ inputs.push-to-cache && vars.ATTIC_SERVER != '' && vars.ATTIC_CACHE != '' }} = true ]]; then | |
pkgs+=(attic-client) | |
elif [[ ${{ inputs.push-to-cache && vars.CACHIX_CACHE != '' }} = true ]]; then | |
pkgs+=(cachix) | |
fi | |
nix profile add -f packages.nix ${pkgs[@]} | |
- name: clone nixpkgs | |
uses: actions/checkout@v4 | |
with: | |
repository: NixOS/nixpkgs | |
path: nixpkgs | |
persist-credentials: false | |
- name: run nixpkgs-review ${{ inputs.extra-args }} | |
run: | | |
nixpkgs-review -- \ | |
pr ${PR_NUMBER} \ | |
--no-shell \ | |
--no-headers \ | |
--print-result \ | |
--build-args="-L" \ | |
--pr-json="$PR_JSON" \ | |
$EXTRA_ARGS \ | |
|| true | |
working-directory: nixpkgs | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
EXTRA_ARGS: ${{ inputs.extra-args }} | |
PR_JSON: ${{ needs.prepare.outputs.pr }} | |
- name: push results to cache | |
if: ${{ inputs.push-to-cache && ((vars.ATTIC_SERVER != '' && vars.ATTIC_CACHE != '') || vars.CACHIX_CACHE != '') }} | |
run: | | |
set -ex | |
(realpath -qe ~/.cache/nixpkgs-review/pr-${PR_NUMBER}/results/* || true) > paths | |
[[ -s paths ]] || exit 0 | |
if [[ ${{ vars.ATTIC_SERVER != '' && vars.ATTIC_CACHE != '' }} = true ]]; then | |
attic login default "$ATTIC_SERVER" "$ATTIC_TOKEN" | |
if ! attic cache info "$ATTIC_CACHE"; then | |
echo "::error::attic returned an error" | |
exit 0 | |
fi | |
attic push --stdin "$ATTIC_CACHE" < paths | |
info=$(curl -f -H "Authorization: Bearer ${ATTIC_TOKEN}" "${ATTIC_SERVER}_api/v1/cache-config/${ATTIC_CACHE}") | |
substituter_endpoint=$(jq -r .substituter_endpoint <<< "$info") | |
public_key=$(jq -r .public_key <<< "$info") | |
is_public=$(jq -r .is_public <<< "$info") | |
elif [[ ${{ vars.CACHIX_CACHE != '' }} = true ]]; then | |
[[ -n "$CACHIX_SIGNING_KEY" ]] || unset CACHIX_SIGNING_KEY | |
cachix push "$CACHIX_CACHE" < paths | |
info=$(curl -f -H "Authorization: Bearer ${CACHIX_AUTH_TOKEN}" "https://app.cachix.org/api/v1/cache/${CACHIX_CACHE}") | |
substituter_endpoint=$(jq -r .uri <<< "$info") | |
public_key=$(jq -r '.publicSigningKeys[]' <<< "$info") | |
is_public=$(jq -r .isPublic <<< "$info") | |
fi | |
[[ "$is_public" = true ]] || exit 0 | |
echo "nix-store -r --add-root nixpkgs-pr-${PR_NUMBER}-${{ matrix.system }} \\" >> fetch_cmd | |
echo " --option binary-caches 'https://cache.nixos.org/ $substituter_endpoint' \\" >> fetch_cmd | |
echo " --option trusted-public-keys '" >> fetch_cmd | |
echo " cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" >> fetch_cmd | |
echo " $public_key" >> fetch_cmd | |
echo -n " '" >> fetch_cmd | |
for p in $(cat paths); do | |
echo -e " \\" >> fetch_cmd | |
echo -n " $p" >> fetch_cmd | |
done | |
env: | |
ATTIC_SERVER: ${{ vars.ATTIC_SERVER }} | |
ATTIC_CACHE: ${{ vars.ATTIC_CACHE }} | |
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }} | |
CACHIX_CACHE: ${{ vars.CACHIX_CACHE }} | |
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} | |
CACHIX_SIGNING_KEY: ${{ secrets.CACHIX_SIGNING_KEY }} | |
- name: start upterm session | |
if: ${{ inputs.upterm }} | |
uses: owenthereal/action-upterm@v1 | |
with: | |
limit-access-to-actor: true | |
- name: generate report | |
id: report | |
run: | | |
if [[ -s fetch_cmd ]]; then | |
cat fetch_cmd | |
echo fetch_cmd_${{ matrix.system }}=$(base64 -w0 fetch_cmd) >> "$GITHUB_OUTPUT" | |
fi | |
dir=~/.cache/nixpkgs-review/pr-${PR_NUMBER} | |
if [[ "$OS" != "Linux" ]]; then | |
sandbox=$(nix config show sandbox) | |
sed -i '/^###/s/$/ (sandbox = '"$sandbox"')/' "$dir/report.md" | |
fi | |
if ! [[ -s "$dir/report.md" ]]; then | |
echo -e "\n---" >> "$dir/report.md" | |
echo "### \`${{ matrix.system }}\`" >> "$dir/report.md" | |
echo ":white_check_mark: *No rebuilds*" >> "$dir/report.md" | |
fi | |
cat $dir/report.md | |
report=$(jq -c '.+{$md}' $dir/report.json --rawfile md $dir/report.md | base64 -w0) | |
echo report_${{ matrix.system }}=$report >> "$GITHUB_OUTPUT" | |
env: | |
OS: ${{ runner.os }} | |
report: | |
runs-on: ubuntu-latest | |
needs: [prepare, review] | |
outputs: | |
report: ${{ steps.report.outputs.report }} | |
success: ${{ steps.report.outputs.success }} | |
steps: | |
- name: generate report | |
id: report | |
run: | | |
echo -e "## \`nixpkgs-review\` result\n" >> report.md | |
echo -e "Generated using [\`nixpkgs-review-gha\`](https://github.com/Defelo/nixpkgs-review-gha)\n" >> report.md | |
echo -e "Command: \`nixpkgs-review pr ${PR_NUMBER}${EXTRA_ARGS:+ $EXTRA_ARGS}\`" >> report.md | |
echo -e "Commit: [\`$HEAD\`](https://github.com/NixOS/nixpkgs/commit/$HEAD) ([subsequent changes](https://github.com/NixOS/nixpkgs/compare/$HEAD..pull/$PR_NUMBER/head))" >> report.md | |
echo -e "Merge: [\`$MERGE\`](https://github.com/NixOS/nixpkgs/commit/$MERGE)\n" >> report.md | |
echo -e "Logs: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n" >> report.md | |
mkdir .tmp | |
cd .tmp | |
echo ${FETCH_CMD_X86_64_LINUX} | base64 -d > x86_64-linux | |
echo ${FETCH_CMD_AARCH64_LINUX} | base64 -d > aarch64-linux | |
echo ${FETCH_CMD_X86_64_DARWIN} | base64 -d > x86_64-darwin | |
echo ${FETCH_CMD_AARCH64_DARWIN} | base64 -d > aarch64-darwin | |
for system in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do | |
[[ -s $system ]] || continue | |
echo -e "<li><details><summary><code>$system</code></summary>\n\n\`\`\`shell" >> ../cache.md | |
cat $system >> ../cache.md | |
echo -e "\n\`\`\`\n</details></li>" >> ../cache.md | |
done | |
cd .. | |
if [[ -s cache.md ]]; then | |
echo -e "<details><summary>Download packages from cache:</summary><ul>" >> report.md | |
cat cache.md >> report.md | |
echo -e "</ul></details>\n" >> report.md | |
fi | |
mkdir reports | |
echo ${REPORT_X86_64_LINUX} | base64 -d > reports/x86_64-linux.json | |
echo ${REPORT_AARCH64_LINUX} | base64 -d > reports/aarch64-linux.json | |
echo ${REPORT_X86_64_DARWIN} | base64 -d > reports/x86_64-darwin.json | |
echo ${REPORT_AARCH64_DARWIN} | base64 -d > reports/aarch64-darwin.json | |
for system in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do | |
if [[ -s reports/$system.json ]]; then | |
jq -r '.md' reports/$system.json >> report.md | |
fi | |
done | |
cat report.md | |
echo report=$(base64 -w0 report.md) >> "$GITHUB_OUTPUT" | |
echo success=$(jq -s 'all(.[].result[]; .failed==[])' reports/*.json) >> "$GITHUB_OUTPUT" | |
sed '1s|$| for [#'"$PR_NUMBER"'](https://github.com/NixOS/nixpkgs/pull/'"$PR_NUMBER"')|' report.md >> $GITHUB_STEP_SUMMARY | |
env: | |
HEAD: ${{ needs.prepare.outputs.head }} | |
MERGE: ${{ needs.prepare.outputs.merge }} | |
EXTRA_ARGS: ${{ inputs.extra-args }} | |
FETCH_CMD_X86_64_LINUX: ${{ needs.review.outputs.fetch_cmd_x86_64-linux }} | |
FETCH_CMD_AARCH64_LINUX: ${{ needs.review.outputs.fetch_cmd_aarch64-linux }} | |
FETCH_CMD_X86_64_DARWIN: ${{ needs.review.outputs.fetch_cmd_x86_64-darwin }} | |
FETCH_CMD_AARCH64_DARWIN: ${{ needs.review.outputs.fetch_cmd_aarch64-darwin }} | |
REPORT_X86_64_LINUX: ${{ needs.review.outputs.report_x86_64-linux }} | |
REPORT_AARCH64_LINUX: ${{ needs.review.outputs.report_aarch64-linux }} | |
REPORT_X86_64_DARWIN: ${{ needs.review.outputs.report_x86_64-darwin }} | |
REPORT_AARCH64_DARWIN: ${{ needs.review.outputs.report_aarch64-darwin }} | |
post-result: | |
runs-on: ubuntu-latest | |
needs: [prepare, report] | |
if: ${{ inputs.post-result || inputs.on-success != 'nothing' }} | |
steps: | |
- name: fetch report | |
run: echo ${REPORT} | base64 -d > report.md | |
env: | |
REPORT: ${{ needs.report.outputs.report }} | |
- name: post comment | |
if: ${{ inputs.post-result }} | |
run: | | |
if [[ -n "$GH_TOKEN" ]]; then | |
gh pr -R NixOS/nixpkgs comment ${PR_NUMBER} -F report.md | |
fi | |
env: | |
GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
- name: mark pull request as ready for review | |
if: ${{ needs.report.outputs.success == 'true' && inputs.on-success == 'mark_as_ready' }} | |
run: | | |
if [[ -z "$GH_TOKEN" ]]; then | |
echo "::error::Cannot mark the PR as ready for review because no GH_TOKEN has been configured." | |
exit 1 | |
fi | |
gh pr -R NixOS/nixpkgs ready ${PR_NUMBER} | |
env: | |
GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
- name: approve pull request | |
if: ${{ needs.report.outputs.success == 'true' && (inputs.on-success == 'approve' || inputs.on-success == 'merge') }} | |
run: | | |
if [[ -z "$GH_TOKEN" ]]; then | |
echo "::error::Cannot approve the PR because no GH_TOKEN has been configured." | |
exit 1 | |
fi | |
user_id="$(gh api /user --jq .id)" | |
if [[ "$user_id" != "$PR_AUTHOR_ID" ]]; then | |
gh pr -R NixOS/nixpkgs review ${PR_NUMBER} --approve -b "Approved automatically following the successful run of \`nixpkgs-review\`." | |
elif [[ "${{ inputs.on-success }}" = "approve" ]]; then | |
echo "::error::You cannot approve your own pull request." | |
exit 1 | |
fi | |
env: | |
GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
PR_AUTHOR_ID: ${{ needs.prepare.outputs.author_id }} | |
- name: merge pull request | |
if: ${{ needs.report.outputs.success == 'true' && inputs.on-success == 'merge' }} | |
run: | | |
if [[ -z "$GH_TOKEN" ]]; then | |
echo "::error::Cannot merge the PR because no GH_TOKEN has been configured." | |
exit 1 | |
fi | |
is_committer="$(gh api /repos/NixOS/nixpkgs --jq .permissions.push)" | |
if [[ "$is_committer" = true ]]; then | |
gh pr -R NixOS/nixpkgs merge ${PR_NUMBER} --merge --match-head-commit "$HEAD" | |
else | |
current_head="$(gh api "/repos/NixOS/nixpkgs/pulls/$PR_NUMBER" --jq .head.sha)" | |
if [[ "$current_head" != "$HEAD" ]]; then | |
echo "::error::Refusing to merge because the head branch was modified (expected $HEAD, got $current_head instead)" | |
exit 1 | |
fi | |
gh pr -R NixOS/nixpkgs comment ${PR_NUMBER} -b "@NixOS/nixpkgs-merge-bot merge" | |
fi | |
env: | |
GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
HEAD: ${{ needs.prepare.outputs.head }} |