cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
158 lines
5.9 KiB
YAML
158 lines
5.9 KiB
YAML
name: Comment on an issue
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows:
|
|
- "Check code formatting"
|
|
- "Check for private emails used in PRs"
|
|
- "PR Request Release Note"
|
|
types:
|
|
- completed
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
pr-comment:
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
pull-requests: write
|
|
if: >
|
|
github.event.workflow_run.event == 'pull_request' &&
|
|
(
|
|
github.event.workflow_run.conclusion == 'success' ||
|
|
github.event.workflow_run.conclusion == 'failure'
|
|
)
|
|
steps:
|
|
- name: Fetch Sources
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
with:
|
|
sparse-checkout: |
|
|
.github/workflows/unprivileged-download-artifact/action.yml
|
|
sparse-checkout-cone-mode: false
|
|
- name: 'Download artifact'
|
|
uses: ./.github/workflows/unprivileged-download-artifact
|
|
id: download-artifact
|
|
with:
|
|
run-id: ${{ github.event.workflow_run.id }}
|
|
artifact-name: workflow-args
|
|
|
|
- name: 'Comment on PR'
|
|
if: steps.download-artifact.outputs.artifact-id != ''
|
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
script: |
|
|
var fs = require('fs');
|
|
const comments = JSON.parse(fs.readFileSync('./comments'));
|
|
if (!comments || comments.length == 0) {
|
|
return;
|
|
}
|
|
|
|
let runInfo = await github.rest.actions.getWorkflowRun({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
run_id: context.payload.workflow_run.id
|
|
});
|
|
|
|
console.log(runInfo);
|
|
|
|
|
|
// Query to find the number of the pull request that triggered this job.
|
|
// The associated pull requests are based off of the branch name, so if
|
|
// you create a pull request for a branch, close it, and then create
|
|
// another pull request with the same branch, then this query will return
|
|
// two associated pull requests. This is why we have to fetch all the
|
|
// associated pull requests and then iterate through them to find the
|
|
// one that is open.
|
|
const gql_query = `
|
|
query($repo_owner : String!, $repo_name : String!, $branch: String!) {
|
|
repository(owner: $repo_owner, name: $repo_name) {
|
|
ref (qualifiedName: $branch) {
|
|
associatedPullRequests(first: 100) {
|
|
nodes {
|
|
baseRepository {
|
|
owner {
|
|
login
|
|
}
|
|
}
|
|
number
|
|
state
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`
|
|
const gql_variables = {
|
|
repo_owner: runInfo.data.head_repository.owner.login,
|
|
repo_name: runInfo.data.head_repository.name,
|
|
branch: runInfo.data.head_branch
|
|
}
|
|
const gql_result = await github.graphql(gql_query, gql_variables);
|
|
console.log(gql_result);
|
|
// If the branch for the PR was deleted before this job has a chance
|
|
// to run, then the ref will be null. This can happen if someone:
|
|
// 1. Rebase the PR, which triggers some workflow.
|
|
// 2. Immediately merges the PR and deletes the branch.
|
|
// 3. The workflow finishes and triggers this job.
|
|
if (!gql_result.repository.ref) {
|
|
console.log("Ref has been deleted");
|
|
return;
|
|
}
|
|
console.log(gql_result.repository.ref.associatedPullRequests.nodes);
|
|
|
|
var pr_number = 0;
|
|
gql_result.repository.ref.associatedPullRequests.nodes.forEach((pr) => {
|
|
|
|
// The largest PR number is the one we care about. The only way
|
|
// to have more than one associated pull requests is if all the
|
|
// old pull requests are in the closed state.
|
|
if (pr.baseRepository.owner.login = context.repo.owner && pr.number > pr_number) {
|
|
pr_number = pr.number;
|
|
}
|
|
});
|
|
if (pr_number == 0) {
|
|
console.log("Error retrieving pull request number");
|
|
return;
|
|
}
|
|
|
|
await comments.forEach(function (comment) {
|
|
if (comment.id) {
|
|
// Security check: Ensure that this comment was created by
|
|
// the github-actions bot, so a malicious input won't overwrite
|
|
// a user's comment.
|
|
github.rest.issues.getComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: comment.id
|
|
}).then((old_comment) => {
|
|
console.log(old_comment);
|
|
if (old_comment.data.user.login != "github-actions[bot]") {
|
|
console.log("Invalid comment id: " + comment.id);
|
|
return;
|
|
}
|
|
github.rest.issues.updateComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr_number,
|
|
comment_id: comment.id,
|
|
body: comment.body
|
|
});
|
|
});
|
|
} else {
|
|
github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: pr_number,
|
|
body: comment.body
|
|
});
|
|
}
|
|
});
|
|
|
|
- name: Dump comments file
|
|
if: >-
|
|
always() &&
|
|
steps.download-artifact.outputs.artifact-id != ''
|
|
run: cat comments
|