fix: apply messages.footer template in create_pull_request safe output#17098
fix: apply messages.footer template in create_pull_request safe output#17098
messages.footer template in create_pull_request safe output#17098Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
messages.footer template in create_pull_request safe output
There was a problem hiding this comment.
Pull request overview
This PR fixes inconsistent footer rendering for safe-outputs.create_pull_request by switching PR creation to the shared messages.footer templating system used by other safe-output flows, enabling org-level footer customization to apply uniformly.
Changes:
- Replaced the hardcoded PR footer/expiration helper with
generateFooterWithMessages+addExpirationToFootersomessages.footer/messages.footerInstall(and related sections) are respected. - Added extraction of workflow source metadata and triggering PR/discussion numbers from the GitHub Actions context for footer templating.
- Preserved existing XML markers behavior, including the PR expiration type marker and workflow-id marker.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const runUrl = context.payload.repository ? `${context.payload.repository.html_url}/actions/runs/${runId}` : `${githubServer}/${repoParts.owner}/${repoParts.repo}/actions/runs/${runId}`; | ||
| const workflowSource = process.env.GH_AW_WORKFLOW_SOURCE ?? ""; | ||
| const workflowSourceURL = process.env.GH_AW_WORKFLOW_SOURCE_URL ?? ""; | ||
| const triggeringPRNumber = context.payload.pull_request?.number; |
There was a problem hiding this comment.
triggeringPRNumber only reads context.payload.pull_request?.number. For events like issue_comment on a PR, GitHub only provides the PR number via context.payload.issue.number with issue.pull_request set, so the footer will miss the triggering PR reference. Other handlers handle this by falling back to context.payload.issue.number when issue.pull_request is present (e.g., create_issue.cjs:261). Consider aligning the extraction here to include that fallback.
| const triggeringPRNumber = context.payload.pull_request?.number; | |
| const triggeringPRNumber = | |
| context.payload.pull_request?.number ?? | |
| (context.payload.issue?.pull_request ? context.payload.issue.number : undefined); |
| let footer = generateFooterWithMessages(workflowName, runUrl, workflowSource, workflowSourceURL, triggeringIssueNumber, triggeringPRNumber, triggeringDiscussionNumber).trimEnd(); | ||
| footer = addExpirationToFooter(footer, expiresHours, "Pull Request"); | ||
| if (expiresHours > 0) { | ||
| footer += "\n\n<!-- gh-aw-expires-type: pull-request -->"; | ||
| } | ||
| bodyLines.push(``, ``, footer); |
There was a problem hiding this comment.
Footer generation logic was changed to use the messages.footer template system, but create_pull_request.test.cjs doesn’t appear to validate this integration (e.g., that a custom GH_AW_SAFE_OUTPUT_MESSAGES.footer is applied, and that the XML marker / expiration insertion stays in the expected place). Adding/adjusting tests around this block would help prevent regressions in the behavior this PR is fixing.
| let footer = generateFooterWithMessages(workflowName, runUrl, workflowSource, workflowSourceURL, triggeringIssueNumber, triggeringPRNumber, triggeringDiscussionNumber).trimEnd(); | |
| footer = addExpirationToFooter(footer, expiresHours, "Pull Request"); | |
| if (expiresHours > 0) { | |
| footer += "\n\n<!-- gh-aw-expires-type: pull-request -->"; | |
| } | |
| bodyLines.push(``, ``, footer); | |
| let footer = generateFooterWithMessages( | |
| workflowName, | |
| runUrl, | |
| workflowSource, | |
| workflowSourceURL, | |
| triggeringIssueNumber, | |
| triggeringPRNumber, | |
| triggeringDiscussionNumber | |
| ).trimEnd(); | |
| footer = addExpirationToFooter(footer, expiresHours, "Pull Request"); | |
| if (expiresHours > 0) { | |
| footer += "\n\n<!-- gh-aw-expires-type: pull-request -->"; | |
| } | |
| // Only add the footer (and its surrounding blank lines) if there is actual content | |
| if (footer.trim() !== "") { | |
| bodyLines.push("", "", footer); | |
| } |
safe-outputs.create_pull_requestused a hardcoded footer (> AI generated by [name](url)) instead of themessages.footertemplate system, making org-level footer customization incomplete —add_comment, PR review, and comment flows all respected the template but PR creation did not.Changes
create_pull_request.cjsgenerateFooterWithExpiration(hardcoded text) withgenerateFooterWithMessages— now respectsmessages.footer,messages.footerInstall, missing info sections, and blocked domains sectionscreateExpirationLineimport withaddExpirationToFooterto insert expiration inside the blockquote before the XML marker (consistent with other expiration flows)GH_AW_WORKFLOW_SOURCE,GH_AW_WORKFLOW_SOURCE_URL,triggeringPRNumber, andtriggeringDiscussionNumberfrom context — consistent withadd_comment.cjs<!-- gh-aw-expires-type: pull-request -->and<!-- gh-aw-workflow-id: ... -->markers are preservedBefore:
After:
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
https://api.github.com/graphql/usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw k/gh-aw/gh-aw/sclog 64/bin/go git rev-�� --show-toplevel /opt/hostedtoolc-buildtags /usr/bin/git /tmp/go-build898git -trimpath 64/bin/go git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v3/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha s "-s -w -X main.version=efd25e7@{u} GO111MODULE ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE ache/go/1.25.0/x64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha vaScript3654969011/001/test-complex-frontmatter-with-tools.md GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet -uns�� -unreachable=false cfg 918626/b349/vet.cfg GOSUMDB GOWORK 64/bin/go /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha 78 GO111MODULE /opt/hostedtoolcache/go/1.25.0/x-lang=go1.25 GOINSECURE GOMOD GOMODCACHE /opt/hostedtoolcache/go/1.25.0/x-dwarf=false -uns�� 5731-26748/test-3364448233 /tmp/go-build459918626/b044/vet.-c=4 918626/b330/vet.cfg l GOWORK 64/bin/go /opt/hostedtoolcache/go/1.25.0/x/tmp/go-build459918626/b430/_testmain.go(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git -json GO111MODULE x_amd64/vet git(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v5/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -json cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linu1(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -bool -buildtags /usr/bin/git -errorsas -ifaceassert -nilfunc git add runs/20260220-045731-26748/test-3364448233 /tmp/gh-aw-add-gitattributes-test1045689186/.github/workflows/test.lock.yml /usr/bin/git s/test.md GO111MODULE 64/bin/go git(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --git-dir go /opt/hostedtoolcache/node/24.13.0/x64/bin/node -json GO111MODULE x_amd64/vet node /tmp�� /home/REDACTED/work/gh-aw/gh-aw/.github/workflows/archie.md x_amd64/vet /opt/hostedtoolcache/node/24.13.0/x64/bin/node -json GO111MODULE x_amd64/vet /opt/hostedtoolcache/node/24.13.0/x64/bin/node(http block)https://api.github.com/repos/actions/github-script/git/ref/tags/v8/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha m-gk/QJ6LqapyehFGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE 510211/b380/impo/tmp/go-build459918626/b159/vet.cfg /hom�� che/go-build/9b/9b5c8b678de9f940GOINSECURE **/*.cjs 64/bin/go **/*.json --ignore-path ../../../.pretti-bool /opt/hostedtoolc-buildtags(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha che/go-build/bf/bf0813d7488cf446GOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go /opt/hostedtoolc/tmp/go-build459918626/b265/vet.cfg -o /tmp/go-build898510211/b395/_pkgGOINSECURE -trimpath 64/bin/go -p github.com/githu-atomic -lang=go1.25 go(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha che/go-build/f9/f9dd00c75c79c7baGOINSECURE GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go /opt/hostedtoolc-buildtags -o /tmp/go-build898-errorsas -trimpath 64/bin/go -p github.com/githu-test.testlogfile=/tmp/go-build459918626/b386/testlog.txt -lang=go1.25 go(http block)https://api.github.com/repos/actions/setup-go/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -json GO111MODULE /opt/hostedtoolcache/go/1.25.0/x/tmp/gh-aw-git-clone-3499450782 GOINSECURE GOMOD GOMODCACHE /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -uns�� -unreachable=false /tmp/go-build459918626/b046/vet.cfg 918626/b340/vet.cfg GOSUMDB GOWORK 64/bin/go /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/actions/setup-node/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha se 918626/b064/vet.cfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet -uns�� 5731-26748/test-3364448233 /tmp/go-build459918626/b038/vet.cfg cfg GOSUMDB GOWORK 64/bin/go /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts/usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env hub/workflows cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts/usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linutest@example.com env hub/workflows cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts/usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env y-test.md cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts/usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json cfg x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile(http block)/usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts/usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json cfg x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link(http block)/usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE x_amd64/cgo GOINSECURE GOMOD GOMODCACHE x_amd64/cgo env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts/usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link env -json cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE i8/wl1tDiMkVqxwJLLHK96I/vmtrAJLFtest@example.com(http block)/usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/workflows/usr/bin/gh gh workflow list --json name,state,path -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --che-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go go(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/github/gh-aw/contents/.github%2Fworkflows%2Faudit-workflows.md/opt/hostedtoolcache/node/24.13.0/x64/bin/node /opt/hostedtoolcache/node/24.13.0/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vitest/dist/workers/forks.js GOMOD GOMODCACHE go env elism GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha y-test.md GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 2888708846/.github/workflows cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999/usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha -json rty 64/pkg/tool/linu-nolocalimports GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User env 4030939882/.github/workflows cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/nonexistent/repo/actions/runs/12345/usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE JzA3LCk/icLmSHLMtest@example.com env _.a GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)/usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/owner/repo/actions/workflows/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --che-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go go(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go xterm-color x_amd64/vet /usr/bin/git sh -c "prettier" --wriGOINSECURE git 64/bin/go --show-toplevel x_amd64/vet /usr/bin/git node(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go - ^remote\..*\.gh-env /usr/bin/git sh -c "prettier" --wriGOINSECURE | tr '\n' ':')$GOMOD modules/@npmcli/run-script/lib/node-gyp-bin/sh --show-toplevel x_amd64/compile /usr/bin/git node(http block)https://api.github.com/repos/owner/repo/contents/file.md/tmp/go-build459918626/b380/cli.test /tmp/go-build459918626/b380/cli.test -test.testlogfile=/tmp/go-build459918626/b380/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE 510211/b407/impo-buildtags -c che/go-build/35/-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go /opt/hostedtoolc-buildtags(http block)/tmp/go-build908180246/b380/cli.test /tmp/go-build908180246/b380/cli.test -test.testlogfile=/tmp/go-build908180246/b380/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true OUTPUT -d 168.63.129.16 prettier --wr�� **/*.cjs **/*.ts 64/bin/go --ignore-path ../../../.pretti-c DROP sh(http block)https://api.github.com/repos/test-owner/test-repo/actions/secrets/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name data/action_pins.json..." GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh -c "prettier" --che-errorsas GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go go(http block)/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name --porcelain git 64/bin/go --show-toplevel x_amd64/vet /usr/bin/git sh -c "prettier" --wriGOINSECURE git 64/bin/go ettierignore x_amd64/vet /usr/bin/git node(http block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
create_pull_requestdoes not applymessages.footertemplate #17074✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.