xref: /freebsd/.github/workflows/checklist.yml (revision a9a6a51edac13aaff5517dd602272152efa6d7bd)
1name: Checklist
2
3# Produce a list of things that need to be changed
4# for the submission to align with CONTRIBUTING.md
5
6on:
7  pull_request:
8    types: [ opened, reopened, edited, synchronize ]
9
10permissions:
11  pull-requests: write
12
13jobs:
14  checklist:
15    name: commit
16    runs-on: ubuntu-latest
17    steps:
18      - uses: actions/github-script@v7
19        with:
20          # An asynchronous javascript function
21          script: |
22            /*
23             * Github's API returns the results in pages of 30, so
24             * pass the function we want, along with it's arguments,
25             * to paginate() which will handle gathering all the results.
26             */
27            const comments = await github.paginate(github.rest.issues.listComments, {
28              owner: context.repo.owner,
29              repo: context.repo.repo,
30              issue_number: context.issue.number
31            });
32
33            const commits = await github.paginate(github.rest.pulls.listCommits, {
34              owner: context.repo.owner,
35              repo: context.repo.repo,
36              pull_number: context.issue.number
37            });
38
39            let checklist = {};
40            let checklist_len = 0;
41            let comment_id = -1;
42
43            const msg_prefix = "Thank you for taking the time to contribute to FreeBSD!\n";
44            const addToChecklist = (msg, sha) => {
45              if (!checklist[msg]) {
46                checklist[msg] = [];
47                checklist_len++;
48              }
49              checklist[msg].push(sha);
50            }
51
52            for (const commit of commits) {
53              const sob_lines = commit.commit.message.match(/^[^\S\r\n]*signed-off-by:.*/gim);
54
55              if (sob_lines == null && !commit.commit.author.email.toLowerCase().endsWith("freebsd.org"))
56                addToChecklist("Missing Signed-off-by lines", commit.sha);
57              else if (sob_lines != null) {
58                let author_signed = false;
59                for (const line of sob_lines) {
60                  if (!line.includes("Signed-off-by: "))
61                    /* Only display the part we care about. */
62                    addToChecklist("Expected `Signed-off-by: `, got `" + line.match(/^[^\S\r\n]*signed-off-by:./i) + "`", commit.sha);
63                  if (line.includes(commit.commit.author.email))
64                    author_signed = true;
65                }
66
67                if (!author_signed)
68                  console.log("::warning title=Missing-Author-Signature::Missing Signed-off-by from author");
69              }
70
71              if (commit.commit.author.email.toLowerCase().includes("noreply"))
72                addToChecklist("Real email address is needed", commit.sha);
73            }
74
75            /* Check if we've commented before. */
76            for (const comment of comments) {
77              if (comment.user.login == "github-actions[bot]") {
78                comment_id = comment.id;
79                break;
80              }
81            }
82
83            if (checklist_len != 0) {
84              let msg = msg_prefix +
85                "There " + (checklist_len > 1 ? "are a few issues that need " : "is an issue that needs ") +
86                "to be fixed:\n";
87              let comment_func = comment_id == -1 ? github.rest.issues.createComment : github.rest.issues.updateComment;
88
89              /* Loop for each key in "checklist". */
90              for (const c in checklist)
91                msg += "- " + c + "<sup>" + checklist[c].join(", ") + "</sup>\n";
92
93              comment_func({
94                owner: context.repo.owner,
95                repo: context.repo.repo,
96                body: msg,
97                ...(comment_id == -1 ? {issue_number: context.issue.number} : {comment_id: comment_id})
98              });
99            } else if (comment_id != -1) {
100              github.rest.issues.updateComment({
101                owner: context.repo.owner,
102                repo: context.repo.repo,
103                comment_id: comment_id,
104                body: msg_prefix + "All issues resolved."
105              });
106            }
107