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