Skip to content

review #432501

review #432501 #74

Workflow file for this run

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 }}