add diff comment to help reviewers #2
Workflow file for this run
This file contains 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: Generate Diff | |
on: | |
pull_request_target: | |
permissions: | |
contents: read | |
pull-requests: write | |
defaults: | |
run: | |
shell: 'bash -Eeuo pipefail -x {0}' | |
env: | |
# https://github.com/docker-library/bashbrew/issues/10 | |
GIT_LFS_SKIP_SMUDGE: 1 | |
jobs: | |
gather: | |
name: Gather Metadata | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 | |
with: | |
# ideally this would be "github.event.pull_request.merge_commit_sha" but according to https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls#get-a-pull-request if "mergeable" is null (meaning there's a background job in-progress to check mergeability), that value is undefined... | |
ref: ${{ github.event.pull_request.head.sha }} | |
fetch-depth: 0 | |
- id: gather | |
name: Affected Images | |
run: | | |
(set +x; echo "::stop-commands::$(echo -n ${{ github.token }} | sha256sum | head -c 64)") | |
git fetch --quiet https://github.com/docker-library/official-images.git master | |
externalPins="$(git diff --no-renames --name-only FETCH_HEAD...HEAD -- '.external-pins/*/**')" | |
externalPinTags="$( | |
if [ -n "$externalPins" ]; then | |
# doing backflips to run "tag.sh" from master instead of from the PR | |
git show FETCH_HEAD:.external-pins/tag.sh > ~/master-external-pins-tag.sh | |
chmod +x ~/master-external-pins-tag.sh | |
~/master-external-pins-tag.sh $externalPins | |
fi | |
)" | |
images="$(git diff --no-renames --name-only FETCH_HEAD...HEAD -- library/)" | |
if [ -n "$images" ]; then | |
new="$(git diff --no-renames --name-only --diff-filter=A FETCH_HEAD...HEAD -- $images)" | |
deleted="$(git diff --no-renames --name-only --diff-filter=D FETCH_HEAD...HEAD -- $images)" | |
else | |
new= | |
deleted= | |
fi | |
export images new deleted externalPins externalPinTags | |
images="$(jq -cn ' | |
(env.images | rtrimstr("\n") | split("\n")) as $images | |
| (env.new | rtrimstr("\n") | split("\n")) as $new | |
| (env.deleted | rtrimstr("\n") | split("\n")) as $deleted | |
| (env.externalPins | rtrimstr("\n") | split("\n")) as $externalPins | |
| (env.externalPinTags | rtrimstr("\n") | split("\n")) as $externalPinTags | |
| { | |
images: $images, | |
count: ($images | length), | |
new: $new, | |
deleted: $deleted, | |
externalPins: $externalPins, | |
externalPinTags: $externalPinTags, | |
externalPinsCount: ($externalPins | length), | |
} | |
| .imagesAndExternalPinsCount = (.count + .externalPinsCount) # man, I *really* do not love GitHub Actions expressions... | |
')" | |
jq . <<<"$images" | |
set +x | |
echo "::$(echo -n ${{ github.token }} | sha256sum | head -c 64)::" | |
echo "images=$images" >> "$GITHUB_OUTPUT" | |
outputs: | |
images: '${{ steps.gather.outputs.images }}' | |
diff: | |
name: Diff Comment | |
runs-on: ubuntu-latest | |
needs: gather | |
if: fromJSON(needs.gather.outputs.images).imagesAndExternalPinsCount > 0 | |
steps: | |
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 | |
with: | |
# again, this would ideally be "github.event.pull_request.merge_commit_sha" but we might not have that yet when this runs, so we compromise by checkout out the latest code from the target branch (so we get the latest "diff-pr.sh" script to run) | |
ref: ${{ github.event.pull_request.base.ref }} | |
fetch-depth: 0 | |
- uses: docker-library/official-images/.github/workflows/.bashbrew@master | |
with: | |
build: 'docker' | |
- name: Prepare Environment | |
run: | | |
# this avoids running repo-local scripts (to avoid CVE-2020-15228 via the scripts being updated to write nasty things to $GITHUB_ENV) | |
docker build --tag oisupport/bashbrew:diff-pr . | |
- name: Gather Maintainers | |
env: | |
IMAGES: ${{ needs.gather.outputs.images }} | |
run: | | |
files="$(jq <<<"$IMAGES" -r '.images | map(@sh) | join(" ")')" | |
eval "set -- $files" | |
for f; do | |
if [ -s "$f" ]; then | |
docker run --rm --read-only --tmpfs /tmp oisupport/bashbrew:diff-pr \ | |
bashbrew cat --format ' - `{{ $.RepoName }}`:{{ range .Manifest.Global.Maintainers }} @{{ .Handle }}{{ end }}' "$f" | |
fi | |
done | tee "$GITHUB_WORKSPACE/oi-pr.maint" | |
- name: Generate Diff | |
env: | |
GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} | |
run: | | |
docker run --rm --read-only --tmpfs /tmp oisupport/bashbrew:diff-pr ./diff-pr.sh "$GITHUB_PR_NUMBER" | tee "$GITHUB_WORKSPACE/oi-pr.diff" | |
- name: Comment | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
script: | | |
const commentText = 'Diff for ' + context.payload.pull_request.head.sha + ':'; | |
const fs = require('fs'); | |
const diff = fs.readFileSync(process.env.GITHUB_WORKSPACE + '/oi-pr.diff').toString().trimEnd(); | |
var body = "<details>\n<summary>" + commentText + "</summary>\n\n```diff\n" + diff + "\n```\n\n</details>"; | |
fs.writeFileSync(process.env.GITHUB_STEP_SUMMARY, body); | |
// https://docs.github.com/en/graphql/reference/mutations#minimizecomment | |
const minimizeql = ` | |
mutation($comment: ID!) { | |
minimizeComment(input: { classifier: OUTDATED, clientMutationId: "doi-munge-pr", subjectId: $comment }) { | |
clientMutationId | |
minimizedComment { | |
isMinimized | |
minimizedReason | |
} | |
} | |
} | |
`; | |
// https://docs.github.com/en/graphql/reference/mutations#unminimizecomment | |
const unminimizeql = ` | |
mutation($comment: ID!) { | |
unminimizeComment(input: { clientMutationId: "doi-munge-pr", subjectId: $comment }) { | |
clientMutationId | |
unminimizedComment { | |
isMinimized | |
minimizedReason | |
} | |
} | |
} | |
`; | |
needNewComment = true; | |
console.log('Reviewing existing comments...'); | |
for await (const { data: comments } of github.paginate.iterator( | |
github.rest.issues.listComments, | |
{ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.payload.pull_request.number, | |
} | |
)) { | |
for (const comment of comments) { | |
if (comment.user.login === 'github-actions[bot]') { | |
if (needNewComment && comment.body.includes(commentText)) { | |
needNewComment = false; | |
console.log('Unhiding comment: ' + comment.id + ' (' + comment.node_id + ')'); | |
const result = await github.graphql(unminimizeql, { comment: comment.node_id }); | |
console.log('- result: ' + JSON.stringify(result)); | |
} else { | |
console.log('Hiding comment: ' + comment.id + ' (' + comment.node_id + ')'); | |
const result = await github.graphql(minimizeql, { comment: comment.node_id }); | |
console.log('- result: ' + JSON.stringify(result)); | |
} | |
} | |
} | |
} | |
if (needNewComment) { | |
console.log('Creating new comment...'); | |
await github.rest.issues.createComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.payload.pull_request.number, | |
body: body, | |
}); | |
} |