mirror of
https://github.com/oven-sh/bun.git
synced 2026-10-25 21:40:30 +08:00
### What does this PR do? Bun's own CI lints with `bun lint` and formats with `bun fmt`. oxlint and Prettier are gone from GitHub Actions. It also gives the linter its own tab in the docs, and records what `bun lint` reports in the docs' examples, for the website. #### CI | Workflow | Before | After | |---|---|---| | `lint.yml` | `oxlint --config=oxlint.json --format=github src/js` | `bun lint --format=github` | | `format.yml` | `prettier --plugin=prettier-plugin-organize-imports --write <paths>` | `bun fmt --plugin=prettier-plugin-organize-imports` | | `packages-ci.yml` | `bunx oxlint@0.15 --deny-warnings`, `bunx prettier --check .` | `bun lint --deny-warnings`, `bun fmt --check .` | - **`lint.yml` and `format.yml` install `canary`** instead of 1.4.2, because neither command is in a release yet. `packages-ci.yml` already did. There's a comment to pin them to 1.5.0 once it's out. **These two checks can't pass until canary has #45043.** - **What gets linted and formatted moves from arguments into `bunfig.toml`**, so `bun lint` and `bun fmt` do the right thing with no arguments. `oxlint.json`, `.prettierrc` and `.prettierignore` are unchanged, and Bun reads all three. - **The `fmt`, `lint`, `lint:fix` and `prettier` scripts are removed, not pointed at the new commands.** A project's own script wins over the command, and on a released Bun, where `bun fmt` doesn't exist, a `fmt` script that runs `bun fmt` calls itself: 616 nested processes in 5 seconds on 1.4.3. Without the scripts, an old Bun says `Script not found "fmt"`. - `oxlint` and `prettier-plugin-organize-imports` are removed from `devDependencies` (46 lines of `bun.lock`). The plugin is built into `bun fmt`. - **`prettier` stays, for editors**: `.vscode/settings.json` points format-on-save at `./node_modules/prettier`. It goes from 3.6.2 to 3.9.9, the version `bun fmt` matches, so that saving a file and CI agree. - The plugin stays a flag in CI and isn't in `.prettierrc`, as before. On save it would remove an import that the next edit is about to use. #### What the switch flagged - **75 files reformatted**, in a commit of their own. All are differences between Prettier 3.6.2 and 3.9.9: `for (;;)` without a space before `)`, unions that fit on one line, `{/* comment */}`, table widths. - **5 lint errors in `src/js`** that oxlint 1.87 reports and 1.70 didn't: four unused `_` parameters, renamed or removed, and the fuzzer harness's `eval`, which gets a disable comment. - **`packages/bun-plugin-svelte`** has no lint config, so it now gets Bun's default rules. `--fix` turned three `var`s and one `let` into `let` or `const`. `no-explicit-any` is off for that package, because its tests pass values of the wrong type on purpose. #### Docs The linter was a group inside the Runtime tab. It's now a **Linter** tab between Test Runner and Guides, which opens on the guide: | Group | Page | URL | |---|---|---| | Getting Started | Linter | `/docs/lint` (was `/docs/runtime/lint`) | | Rules | Lint rules | `/docs/lint/rules` | | | ESLint plugins | `/docs/lint/plugins` | | Formatter | Formatter | `/docs/format` (was `/docs/runtime/format`) | | Migrate | the four migration guides | unchanged | Neither old URL has been in a release. The 25 references to them are updated, including the two in `--help` and the one in the SARIF output. The site redirects the old URLs. **`docs/lint/rules/reports.json`** is new: what `bun lint` reports in each example on the rule pages, with the exact span and message. 3,047 reports in 4,173 examples, one line per page. The website uses it to underline the problems in the examples, like an editor (oven-sh/site#291). - `bun src/codegen/lint-rule-docs.ts --write` generates it, together with the rest of the generated docs. - The code that sets up each example as a small project and lints it moved from `rule-docs.test.ts` into that module, so the generator and the test run the same thing. The test's checks are unchanged, and it now also fails if `reports.json` is stale, naming the page and the command. - A few messages name a file by its whole path. That becomes `/project/file.js`, so the file is the same on every machine. - It isn't embedded in the binary. ### How did you verify your code works? With a build of `main` at #45043: | | | |---|---| | files `bun fmt` visits with no arguments, against the Prettier script's arguments (`--list-files`) | the same 3,350 | | the 75 reformatted files, against real Prettier 3.9.9 with the real plugin | 75 of 75 byte-identical | | …against real Prettier 3.6.2 | it leaves all 75 as they were, so they are version differences | | the 65 of them that are JS or TS, transpiled before and after | 65 of 65 the same bytes | | a second `bun fmt` | changes 0 files, so autofix can't ping-pong | | real Prettier 3.9.9 **without** the plugin (what an editor runs) on all 3,350 files | all formatted | | `bun lint` with no arguments, against `bun lint --config=oxlint.json src/js` | identical output | | the 5 lint errors, against real oxlint 1.87 | the same 5 | | a violation of the repo's own JS plugin rule, planted in `src/js` | reported, with real oxlint's message, position and order | | `debugger;` planted in `bench/` and in `src/` outside `src/js` | not reported | | `bun install --frozen-lockfile` | accepts the lockfile | | Bun 1.4.3 with the new `bunfig.toml` | runs. `bun fmt` says `Script not found "fmt"` | All four changed CI steps exit 0 on this branch. `bun lint` takes 140 ms for 202 files, and `bun fmt` 110 ms for 3,350. `rule-docs.test.ts` passes (123 tests), and fails with `eslint/eqeqeq: reports.json is out of date` when one message in the file is changed by hand. A build of the first two commits passes the lint, format and check suites, and `fs.glob`, `fs`, `undici`, `node:module`, `require.cache`, `node:net` and the `bun-types` tests, which cover the built-in modules that were edited. Known: `bunfig.toml` and `.prettierignore` are read from the current directory only, so `bun fmt` run from inside `test/` doesn't see the scope and would format the fixtures too. `prettier --write .` in `test/` has always done the same.