Skip to content

Commit c14bbec

Browse files
committed
ci: validate form
1 parent f75194b commit c14bbec

File tree

5 files changed

+477
-0
lines changed

5 files changed

+477
-0
lines changed

.github/workflows/validate-form.yml

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Validate Form
2+
3+
on:
4+
issues:
5+
types: [opened, edited]
6+
schedule:
7+
- cron: "20 * * * *"
8+
9+
jobs:
10+
check-version:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
issues: write
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Setup Node.js
18+
uses: actions/setup-node@v4
19+
with:
20+
node-js: 20
21+
22+
- name: Install Dependencies
23+
run: |
24+
cd scripts/validate-form
25+
npm ci
26+
27+
- name: Validate Form
28+
uses: actions/github-script@v7
29+
with:
30+
script: |
31+
const script = require('./scripts/validate-form/main.js')
32+
await script({github, context, core})
33+
env:
34+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
target/
22
yazi-*/completions
3+
node_modules/
34

45
.DS_Store
56

scripts/validate-form/main.js

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
const LABEL_NAME = "needs info"
2+
const RE_CHECKLIST = /#{3}\s+Checklist\s+(?:^-\s+\[x]\s+.+?\n){2}/gm
3+
4+
function bugReportBody(creator, content, hash) {
5+
if (content.includes(` (${hash} `) && RE_CHECKLIST.test(content)) {
6+
return null
7+
}
8+
9+
return `Hey @${creator}, I noticed that you did not correctly follow the bug report template. Please ensure that:
10+
11+
- The bug can still be reproduced on the [newest nightly build](https://yazi-rs.github.io/docs/installation/#binaries).
12+
- The debug information (\`yazi --debug\`) is updated for the newest nightly.
13+
- All required fields in the checklist have been checked.
14+
15+
Issues marked with \`${LABEL_NAME}\` will be closed if they have no activity within 2 days.
16+
`
17+
}
18+
19+
function featureRequestBody(creator, content, hash) {
20+
if (content.includes(` (${hash} `) && RE_CHECKLIST.test(content)) {
21+
return null
22+
}
23+
24+
return `Hey @${creator}, I noticed that you did not correctly follow the feature request template. Please ensure that:
25+
26+
- The requested feature does not exist in the [newest nightly build](https://yazi-rs.github.io/docs/installation/#binaries).
27+
- The debug information (\`yazi --debug\`) is updated for the newest nightly.
28+
- All required fields in the checklist have been checked.
29+
30+
Issues marked with \`${LABEL_NAME}\` will be closed if they have no activity within 2 days.
31+
`
32+
}
33+
34+
module.exports = async ({ github, context, core }) => {
35+
async function nightlyHash() {
36+
try {
37+
const { data: tagRef } = await github.rest.git.getRef({ owner: "sxyazi", repo: "yazi", ref: "tags/nightly" })
38+
return tagRef.object.sha.slice(0, 7)
39+
} catch (e) {
40+
if (e.status === 404) {
41+
core.error("Nightly tag not found")
42+
} else {
43+
core.error(`Error fetching nightly version: ${e.message}`)
44+
}
45+
return null
46+
}
47+
}
48+
49+
async function hasLabel(id, label) {
50+
try {
51+
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
52+
...context.repo,
53+
issue_number: id,
54+
})
55+
return labels.some(l => l.name === label)
56+
} catch (e) {
57+
core.error(`Error checking labels: ${e.message}`)
58+
return false
59+
}
60+
}
61+
62+
async function updateLabels(id, mark, body) {
63+
try {
64+
const marked = await hasLabel(id, LABEL_NAME)
65+
if (mark && !marked) {
66+
await github.rest.issues.addLabels({
67+
...context.repo,
68+
issue_number: id,
69+
labels: [LABEL_NAME],
70+
})
71+
await github.rest.issues.createComment({
72+
...context.repo,
73+
issue_number: id,
74+
body,
75+
})
76+
} else if (!mark && marked) {
77+
await github.rest.issues.removeLabel({
78+
...context.repo,
79+
issue_number: id,
80+
name: LABEL_NAME,
81+
})
82+
}
83+
} catch (e) {
84+
core.error(`Error updating labels: ${e.message}`)
85+
}
86+
}
87+
88+
async function closeOldIssues() {
89+
try {
90+
const { data: issues } = await github.rest.issues.listForRepo({
91+
...context.repo,
92+
state: "open",
93+
labels: LABEL_NAME,
94+
})
95+
96+
const now = new Date()
97+
const twoDaysAgo = new Date(now - 2 * 24 * 60 * 60 * 1000)
98+
99+
for (const issue of issues) {
100+
const markedAt = new Date(issue.labels_at || issue.created_at)
101+
if (markedAt < twoDaysAgo) {
102+
await github.rest.issues.update({
103+
...context.repo,
104+
issue_number: issue.number,
105+
state: "closed",
106+
state_reason: "not_planned",
107+
})
108+
await github.rest.issues.createComment({
109+
...context.repo,
110+
issue_number: issue.number,
111+
body: `This issue has been automatically closed because it was marked as \`${LABEL_NAME}\` for more than 2 days without updates.
112+
If the problem persists, please file a new issue and complete the issue template so we can capture all the details necessary to investigate further.`,
113+
})
114+
}
115+
}
116+
} catch (e) {
117+
core.error(`Error checking old issues: ${e.message}`)
118+
}
119+
}
120+
121+
async function main() {
122+
const hash = await nightlyHash()
123+
if (!hash) return
124+
125+
if (context.eventName === "schedule") {
126+
await closeOldIssues()
127+
return
128+
}
129+
130+
if (context.eventName === "issues") {
131+
const id = context.payload.issue.number
132+
const content = context.payload.issue.body || ""
133+
const creator = context.payload.issue.user.login
134+
135+
if (await hasLabel(id, "bug")) {
136+
const body = bugReportBody(creator, content, hash)
137+
await updateLabels(id, !!body, body)
138+
} else if (await hasLabel(id, "feature")) {
139+
const body = featureRequestBody(creator, content, hash)
140+
await updateLabels(id, !!body, body)
141+
}
142+
}
143+
}
144+
145+
await main()
146+
}

0 commit comments

Comments
 (0)