Skip to content

Commit 97fd412

Browse files
[25.05] ci/treefmt: add biome (#435283)
2 parents 1a71504 + 1304c54 commit 97fd412

File tree

13 files changed

+532
-486
lines changed

13 files changed

+532
-486
lines changed

.editorconfig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ insert_final_newline = false
2323

2424
# see https://nixos.org/nixpkgs/manual/#chap-conventions
2525

26-
# Match json/lockfiles/markdown/nix/perl/python/ruby/shell/docbook files, set indent to spaces
27-
[*.{bash,json,lock,md,nix,pl,pm,py,rb,sh,xml}]
26+
[*.{bash,css,js,json,lock,md,nix,pl,pm,py,rb,sh,xml}]
2827
indent_style = space
2928

3029
# Match docbook files, set indent width of one
3130
[*.xml]
3231
indent_size = 1
3332

3433
# Match json/lockfiles/markdown/nix/ruby files, set indent width of two
35-
[*.{json,lock,md,nix,rb}]
34+
[*.{js,json,lock,md,nix,rb}]
3635
indent_size = 2
3736

3837
# Match all the Bash code in Nix files, set indent width of two

ci/.editorconfig

Lines changed: 0 additions & 4 deletions
This file was deleted.

ci/default.nix

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ let
4242

4343
programs.actionlint.enable = true;
4444

45+
programs.biome = {
46+
enable = true;
47+
settings.formatter = {
48+
useEditorconfig = true;
49+
};
50+
settings.javascript.formatter = {
51+
quoteStyle = "single";
52+
semicolons = "asNeeded";
53+
};
54+
settings.json.formatter.enabled = false;
55+
};
56+
settings.formatter.biome.excludes = [
57+
"*.min.js"
58+
"pkgs/*"
59+
];
60+
4561
programs.keep-sorted.enable = true;
4662

4763
# This uses nixfmt underneath,

ci/github-script/commits.js

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
module.exports = async function ({ github, context, core, dry }) {
1+
module.exports = async ({ github, context, core, dry }) => {
22
const { execFileSync } = require('node:child_process')
3-
const { readFile } = require('node:fs/promises')
4-
const { join } = require('node:path')
53
const { classify } = require('../supportedBranches.js')
64
const withRateLimit = require('./withRateLimit.js')
75

@@ -18,13 +16,13 @@ module.exports = async function ({ github, context, core, dry }) {
1816
run_id: context.runId,
1917
per_page: 100,
2018
})
21-
).find(({ name }) => name == 'Check / cherry-pick').html_url +
19+
).find(({ name }) => name === 'Check / cherry-pick').html_url +
2220
'?pr=' +
2321
pull_number
2422

2523
async function extract({ sha, commit }) {
2624
const noCherryPick = Array.from(
27-
commit.message.matchAll(/^Not-cherry-picked-because: (.*)$/g)
25+
commit.message.matchAll(/^Not-cherry-picked-because: (.*)$/g),
2826
).at(0)
2927

3028
if (noCherryPick)
@@ -148,8 +146,7 @@ module.exports = async function ({ github, context, core, dry }) {
148146

149147
const fetch = extracted
150148
.filter(({ severity }) => !severity)
151-
.map(({ sha, original_sha }) => [ sha, original_sha ])
152-
.flat()
149+
.flatMap(({ sha, original_sha }) => [sha, original_sha])
153150

154151
if (fetch.length > 0) {
155152
// Fetching all commits we need for diff at once is much faster than any other method.
@@ -163,7 +160,9 @@ module.exports = async function ({ github, context, core, dry }) {
163160
])
164161
}
165162

166-
const results = extracted.map(result => result.severity ? result : diff(result))
163+
const results = extracted.map((result) =>
164+
result.severity ? result : diff(result),
165+
)
167166

168167
// Log all results without truncation, with better highlighting and all whitespace changes to the job log.
169168
results.forEach(({ sha, commit, severity, message, colored_diff }) => {
@@ -177,7 +176,7 @@ module.exports = async function ({ github, context, core, dry }) {
177176

178177
// Only create step summary below in case of warnings or errors.
179178
// Also clean up older reviews, when all checks are good now.
180-
if (results.every(({ severity }) => severity == 'info')) {
179+
if (results.every(({ severity }) => severity === 'info')) {
181180
if (!dry) {
182181
await Promise.all(
183182
(
@@ -186,9 +185,9 @@ module.exports = async function ({ github, context, core, dry }) {
186185
pull_number,
187186
})
188187
)
189-
.filter((review) => review.user.login == 'github-actions[bot]')
188+
.filter((review) => review.user.login === 'github-actions[bot]')
190189
.map(async (review) => {
191-
if (review.state == 'CHANGES_REQUESTED') {
190+
if (review.state === 'CHANGES_REQUESTED') {
192191
await github.rest.pulls.dismissReview({
193192
...context.repo,
194193
pull_number,
@@ -214,34 +213,64 @@ module.exports = async function ({ github, context, core, dry }) {
214213

215214
// In the case of "error" severity, we also fail the job.
216215
// Those should be considered blocking and not be dismissable via review.
217-
if (results.some(({ severity }) => severity == 'error'))
216+
if (results.some(({ severity }) => severity === 'error'))
218217
process.exitCode = 1
219218

220-
core.summary.addRaw('This report is automatically generated by the `PR / Check / cherry-pick` CI workflow.', true)
219+
core.summary.addRaw(
220+
'This report is automatically generated by the `PR / Check / cherry-pick` CI workflow.',
221+
true,
222+
)
221223
core.summary.addEOL()
222-
core.summary.addRaw("Some of the commits in this PR require the author's and reviewer's attention.", true)
224+
core.summary.addRaw(
225+
"Some of the commits in this PR require the author's and reviewer's attention.",
226+
true,
227+
)
223228
core.summary.addEOL()
224229

225230
if (results.some(({ type }) => type === 'no-commit-hash')) {
226-
core.summary.addRaw('Please follow the [backporting guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#how-to-backport-pull-requests) and cherry-pick with the `-x` flag.', true)
227-
core.summary.addRaw('This requires changes to the unstable `master` and `staging` branches first, before backporting them.', true)
231+
core.summary.addRaw(
232+
'Please follow the [backporting guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#how-to-backport-pull-requests) and cherry-pick with the `-x` flag.',
233+
true,
234+
)
235+
core.summary.addRaw(
236+
'This requires changes to the unstable `master` and `staging` branches first, before backporting them.',
237+
true,
238+
)
228239
core.summary.addEOL()
229-
core.summary.addRaw('Occasionally, commits are not cherry-picked at all, for example when updating minor versions of packages which have already advanced to the next major on unstable.', true)
230-
core.summary.addRaw('These commits can optionally be marked with a `Not-cherry-picked-because: <reason>` footer.', true)
240+
core.summary.addRaw(
241+
'Occasionally, commits are not cherry-picked at all, for example when updating minor versions of packages which have already advanced to the next major on unstable.',
242+
true,
243+
)
244+
core.summary.addRaw(
245+
'These commits can optionally be marked with a `Not-cherry-picked-because: <reason>` footer.',
246+
true,
247+
)
231248
core.summary.addEOL()
232249
}
233250

234251
if (results.some(({ type }) => type === 'diff')) {
235-
core.summary.addRaw('Sometimes it is not possible to cherry-pick exactly the same patch.', true)
236-
core.summary.addRaw('This most frequently happens when resolving merge conflicts.', true)
237-
core.summary.addRaw('The range-diff will help to review the resolution of conflicts.', true)
252+
core.summary.addRaw(
253+
'Sometimes it is not possible to cherry-pick exactly the same patch.',
254+
true,
255+
)
256+
core.summary.addRaw(
257+
'This most frequently happens when resolving merge conflicts.',
258+
true,
259+
)
260+
core.summary.addRaw(
261+
'The range-diff will help to review the resolution of conflicts.',
262+
true,
263+
)
238264
core.summary.addEOL()
239265
}
240266

241-
core.summary.addRaw('If you need to merge this PR despite the warnings, please [dismiss](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/dismissing-a-pull-request-review) this review shortly before merging.', true)
267+
core.summary.addRaw(
268+
'If you need to merge this PR despite the warnings, please [dismiss](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/dismissing-a-pull-request-review) this review shortly before merging.',
269+
true,
270+
)
242271

243272
results.forEach(({ severity, message, diff }) => {
244-
if (severity == 'info') return
273+
if (severity === 'info') return
245274

246275
// The docs for markdown alerts only show examples with markdown blockquote syntax, like this:
247276
// > [!WARNING]
@@ -256,7 +285,7 @@ module.exports = async function ({ github, context, core, dry }) {
256285
// Whether this is intended or just an implementation detail is unclear.
257286
core.summary.addRaw('<blockquote>')
258287
core.summary.addRaw(
259-
`\n\n[!${({ important: 'IMPORTANT', warning: 'WARNING', error: 'CAUTION' })[severity]}]`,
288+
`\n\n[!${{ important: 'IMPORTANT', warning: 'WARNING', error: 'CAUTION' }[severity]}]`,
260289
true,
261290
)
262291
core.summary.addRaw(`${message}`, true)
@@ -305,18 +334,18 @@ module.exports = async function ({ github, context, core, dry }) {
305334
})
306335
).find(
307336
(review) =>
308-
review.user.login == 'github-actions[bot]' &&
337+
review.user.login === 'github-actions[bot]' &&
309338
// If a review is still pending, we can just update this instead
310339
// of posting a new one.
311-
(review.state == 'CHANGES_REQUESTED' ||
340+
(review.state === 'CHANGES_REQUESTED' ||
312341
// No need to post a new review, if an older one with the exact
313342
// same content had already been dismissed.
314-
review.body == body),
343+
review.body === body),
315344
)
316345

317346
if (dry) {
318347
if (pendingReview)
319-
core.info('pending review found: ' + pendingReview.html_url)
348+
core.info(`pending review found: ${pendingReview.html_url}`)
320349
else core.info('no pending review found')
321350
} else {
322351
// Either of those two requests could fail for very long comments. This can only happen

ci/github-script/labels.js

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = async function ({ github, context, core, dry }) {
1+
module.exports = async ({ github, context, core, dry }) => {
22
const path = require('node:path')
33
const { DefaultArtifactClient } = require('@actions/artifact')
44
const { readFile, writeFile } = require('node:fs/promises')
@@ -27,7 +27,7 @@ module.exports = async function ({ github, context, core, dry }) {
2727

2828
const approvals = new Set(
2929
reviews
30-
.filter((review) => review.state == 'APPROVED')
30+
.filter((review) => review.state === 'APPROVED')
3131
.map((review) => review.user?.id),
3232
)
3333

@@ -37,7 +37,7 @@ module.exports = async function ({ github, context, core, dry }) {
3737
// This is intentionally less than the time that Eval takes, so that the label job
3838
// running after Eval can indeed label the PR as conflicted if that is the case.
3939
const merge_commit_sha_valid =
40-
new Date() - new Date(pull_request.created_at) > 3 * 60 * 1000
40+
Date.now() - new Date(pull_request.created_at) > 3 * 60 * 1000
4141

4242
const prLabels = {
4343
// We intentionally don't use the mergeable or mergeable_state attributes.
@@ -53,8 +53,8 @@ module.exports = async function ({ github, context, core, dry }) {
5353
// The second pass will then read the result from the first pass and set the label.
5454
'2.status: merge conflict':
5555
merge_commit_sha_valid && !pull_request.merge_commit_sha,
56-
'12.approvals: 1': approvals.size == 1,
57-
'12.approvals: 2': approvals.size == 2,
56+
'12.approvals: 1': approvals.size === 1,
57+
'12.approvals: 2': approvals.size === 2,
5858
'12.approvals: 3+': approvals.size >= 3,
5959
'12.first-time contribution': [
6060
'NONE',
@@ -104,8 +104,8 @@ module.exports = async function ({ github, context, core, dry }) {
104104
// existing reviews, too.
105105
'9.needs: reviewer':
106106
!pull_request.draft &&
107-
pull_request.requested_reviewers.length == 0 &&
108-
reviews.length == 0,
107+
pull_request.requested_reviewers.length === 0 &&
108+
reviews.length === 0,
109109
})
110110
}
111111

@@ -125,8 +125,7 @@ module.exports = async function ({ github, context, core, dry }) {
125125
// called "comparison", yet, will skip the download.
126126
const expired =
127127
!artifact ||
128-
new Date(artifact?.expires_at ?? 0) <
129-
new Date(new Date().getTime() + 60 * 1000)
128+
new Date(artifact?.expires_at ?? 0) < new Date(Date.now() + 60 * 1000)
130129
log('Artifact expires at', artifact?.expires_at ?? '<n/a>')
131130
if (!expired) {
132131
stats.artifacts++
@@ -175,7 +174,7 @@ module.exports = async function ({ github, context, core, dry }) {
175174
async function handle({ item, stats }) {
176175
try {
177176
const log = (k, v, skip) => {
178-
core.info(`#${item.number} - ${k}: ${v}` + (skip ? ' (skipped)' : ''))
177+
core.info(`#${item.number} - ${k}: ${v}${skip ? ' (skipped)' : ''}`)
179178
return skip
180179
}
181180

@@ -257,7 +256,7 @@ module.exports = async function ({ github, context, core, dry }) {
257256

258257
// No need for an API request, if all labels are the same.
259258
const hasChanges = Object.keys(after).some(
260-
(name) => (before[name] ?? false) != after[name],
259+
(name) => (before[name] ?? false) !== after[name],
261260
)
262261
if (log('Has changes', hasChanges, !hasChanges)) return
263262

@@ -297,13 +296,15 @@ module.exports = async function ({ github, context, core, dry }) {
297296
// Go back as far as the last successful run of this workflow to make sure
298297
// we are not leaving anyone behind on GHA failures.
299298
// Defaults to go back 1 hour on the first run.
300-
new Date(lastRun?.created_at ?? new Date().getTime() - 1 * 60 * 60 * 1000).getTime(),
299+
new Date(
300+
lastRun?.created_at ?? Date.now() - 1 * 60 * 60 * 1000,
301+
).getTime(),
301302
// Go back max. 1 day to prevent hitting all API rate limits immediately,
302303
// when GH API returns a wrong workflow by accident.
303-
new Date().getTime() - 24 * 60 * 60 * 1000,
304+
Date.now() - 24 * 60 * 60 * 1000,
304305
),
305306
)
306-
core.info('cutoff timestamp: ' + cutoff.toISOString())
307+
core.info(`cutoff timestamp: ${cutoff.toISOString()}`)
307308

308309
const updatedItems = await github.paginate(
309310
github.rest.search.issuesAndPullRequests,
@@ -400,12 +401,12 @@ module.exports = async function ({ github, context, core, dry }) {
400401
.concat(updatedItems, allItems.data)
401402
.filter(
402403
(thisItem, idx, arr) =>
403-
idx ==
404-
arr.findIndex((firstItem) => firstItem.number == thisItem.number),
404+
idx ===
405+
arr.findIndex((firstItem) => firstItem.number === thisItem.number),
405406
)
406407

407408
;(await Promise.allSettled(items.map((item) => handle({ item, stats }))))
408-
.filter(({ status }) => status == 'rejected')
409+
.filter(({ status }) => status === 'rejected')
409410
.map(({ reason }) =>
410411
core.setFailed(`${reason.message}\n${reason.cause.stack}`),
411412
)

ci/github-script/prepare.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = async function ({ github, context, core }) {
1+
module.exports = async ({ github, context, core }) => {
22
const pull_number = context.payload.pull_request.number
33

44
for (const retryInterval of [5, 10, 20, 40, 80]) {

ci/github-script/withRateLimit.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = async function ({ github, core }, callback) {
1+
module.exports = async ({ github, core }, callback) => {
22
const Bottleneck = require('bottleneck')
33

44
const stats = {
@@ -23,7 +23,7 @@ module.exports = async function ({ github, core }, callback) {
2323
// Requests to a different host do not count against the rate limit.
2424
if (options.url.startsWith('https://github.com')) return request(options)
2525
// Requests to the /rate_limit endpoint do not count against the rate limit.
26-
if (options.url == '/rate_limit') return request(options)
26+
if (options.url === '/rate_limit') return request(options)
2727
// Search requests are in a different resource group, which allows 30 requests / minute.
2828
// We do less than a handful each run, so not implementing throttling for now.
2929
if (options.url.startsWith('/search/')) return request(options)

ci/supportedBranches.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ const typeConfig = {
1515
}
1616

1717
function split(branch) {
18-
return { ...branch.match(/(?<prefix>.+?)(-(?<version>\d{2}\.\d{2}|unstable)(?:-(?<suffix>.*))?)?$/).groups }
18+
return {
19+
...branch.match(
20+
/(?<prefix>.+?)(-(?<version>\d{2}\.\d{2}|unstable)(?:-(?<suffix>.*))?)?$/,
21+
).groups,
22+
}
1923
}
2024

2125
function classify(branch) {
2226
const { prefix, version } = split(branch)
2327
return {
2428
stable: (version ?? 'unstable') !== 'unstable',
25-
type: typeConfig[prefix] ?? [ 'wip' ]
29+
type: typeConfig[prefix] ?? ['wip'],
2630
}
2731
}
2832

doc/anchor-use.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
document.addEventListener('DOMContentLoaded', function(event) {
2-
anchors.add('h1[id]:not(div.note h1, div.warning h1, div.tip h1, div.caution h1, div.important h1), h2[id]:not(div.note h2, div.warning h2, div.tip h2, div.caution h2, div.important h2), h3[id]:not(div.note h3, div.warning h3, div.tip h3, div.caution h3, div.important h3), h4[id]:not(div.note h4, div.warning h4, div.tip h4, div.caution h4, div.important h4), h5[id]:not(div.note h5, div.warning h5, div.tip h5, div.caution h5, div.important h5), h6[id]:not(div.note h6, div.warning h6, div.tip h6, div.caution h6, div.important h6)');
3-
});
1+
document.addEventListener('DOMContentLoaded', () => {
2+
anchors.add(
3+
'h1[id]:not(div.note h1, div.warning h1, div.tip h1, div.caution h1, div.important h1), h2[id]:not(div.note h2, div.warning h2, div.tip h2, div.caution h2, div.important h2), h3[id]:not(div.note h3, div.warning h3, div.tip h3, div.caution h3, div.important h3), h4[id]:not(div.note h4, div.warning h4, div.tip h4, div.caution h4, div.important h4), h5[id]:not(div.note h5, div.warning h5, div.tip h5, div.caution h5, div.important h5), h6[id]:not(div.note h6, div.warning h6, div.tip h6, div.caution h6, div.important h6)',
4+
)
5+
})

0 commit comments

Comments
 (0)