feat(cli): support local templates via create.templates in vp create#1777
Conversation
✅ Deploy Preview for viteplus-preview canceled.
|
|
✅ Staging deployment successful! Preview: https://viteplus-staging.void.app/ |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Workspace packages scaffolded by `vp create vite:generator` carry the `bingo-template` keyword and are flagged as template packages during workspace detection, but the interactive `vp create` picker only listed built-in templates, so local generators were never offered. `getInitialTemplateOptions` now accepts the workspace packages and appends an option per template package (after the built-ins, monorepo only), with the package name as value and its description as hint. Selecting one flows into the existing `discoverTemplate` local-package path, which already runs bingo templates via their bin entry with `--skip-requests`.
Add a Code Generators section to the create guide covering how to scaffold a generator with `vp create vite:generator`, run it from the interactive picker or by package name, and customize the template.
…project Explain how the global vp resolves the project-local vite-plus first, how to link a checkout into a test project with pnpm link, and when pnpm bootstrap-cli is needed for Rust global CLI changes.
The generator template scaffolded by `vp create vite:generator` crashed with ERR_MODULE_NOT_FOUND whenever the generator was run: its bin imported '../src/template.js' (a tsc-style specifier), but vp create executes the template directly with `node bin/index.ts`, where Node type stripping does not remap .js specifiers to .ts files. - import '../src/template.ts' directly and cast for runTemplateCLI, whose parameter type is wider than createTemplate's return under TS 6 - update bingo to 0.9.3 (latest) in the catalog and the template - align the catalog zod with bingo, which depends on zod 3 and introspects schemas via zod 3 internals; the generator template is the only zod consumer in the repo - move bingo/zod to vite-plus devDependencies: they are the generator template's dependencies and snap tests resolve modules from the CLI package's node_modules - bump the template engines to >=22.18.0, the first Node version that runs .ts files without the --experimental-strip-types flag - add a unit test that runs the template bin directly with node
The only generator snap test covered the error path outside a monorepo. The new create-generator-monorepo case scaffolds a generator inside a monorepo with vite:generator, locks the template package.json contract into the snapshot, runs the generator through `vp create my-generator` (the path that crashed before the template fix), and verifies the generated files.
pnpm 11 records the link as a vite-plus link: override in pnpm-workspace.yaml (or pnpm.overrides in package.json), so it survives later installs instead of being restored by them.
The bingo-template keyword / bingo dependency check was duplicated between discoverWorkspacePackages and discoverTemplate. Both now use a single isBingoTemplate helper so the detection criteria live in one place. Also drop the unreachable '' fallback for the picker hint, the package path is always set.
Spinner frames such as '◒ Preparing local Git repository...' appear in snap output intermittently depending on timing, while the final '◇'/'◆' state line is stable. Normalize them away in replaceUnstableOutput and regenerate the create-generator-monorepo snapshot without the transient frame.
The case scaffolds a generator and prints its package.json, which now carries bingo ^0.9.3 and engines >=22.18.0.
A workspace package carrying the vite-plus-template keyword but no bin field was offered by the create picker, then discoverTemplate silently fell through to expandCreateShorthand and would install and run the unrelated npm package create-<name>. The fallthrough predates the picker, but the picker made it reachable interactively. - extract isTemplatePackage() so the picker and discovery share the template classification - discoverTemplate now throws a clear error for a template package without a bin entry instead of falling through to npm - use || for the picker hint so an empty description falls back to the package path - strip clack spinner frames at end-of-output without a trailing newline - document why the catalog pins zod to v3 (bingo introspects schemas via zod 3 internals)
Running a local generator in a monorepo with multiple parent dirs (e.g. apps/* and tools/*) placed the generated package under apps/ because inferParentDir only recognized the literal vite:generator builtin and fell back to the default app rule for a local generator's package name. inferParentDir now resolves a local template package to its own parent directory, so a generator under tools/ scaffolds its output into tools/ rather than apps/. The create-generator-monorepo snap fixture gains an apps/* parent so it actually exercises the multi-parent case the tools-only fixture missed. Closes review comment on #1777.
676352f to
0080cda
Compare
Extract findLocalPackage so discoverTemplate and inferParentDir resolve a template specifier to a workspace package the same way. Also tighten the inferParentDir test to exercise the isTemplatePackage guard with a non-template package instead of re-checking the default rule.
…nd harden multi-bin resolution Two robustness fixes for local template packages now that they are directly selectable from the create picker: - isTemplatePackage (picker visibility) now requires the vite-plus-template or bingo-template keyword. A plain `bingo` dependency no longer surfaces a normal workspace package as a template; it remains an execution hint in isBingoTemplate (controls --skip-requests), separating 'is this offered' from 'how is it run'. - discoverTemplate resolves a package's bin via resolveLocalBinPath: a single bin (string or one-entry object) is used directly, a multi-bin package prefers the entry named after the package (scoped or unscoped), and an ambiguous multi-bin package with no matching entry throws a clear error instead of silently picking the first key.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
registerLocalTemplate found the config via a trimmed list (.ts/.js/.mjs), so a monorepo whose only config was vite.config.mts/.cts/.cjs got a stray new vite.config.ts with the create.templates block, leaving the real config untouched. Reuse the canonical config finder: add findViteConfig (all six extensions) to resolve-vite-config.ts and call it, dropping register-template's private list. Closes the bugbot wrong-config-target report.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Three review fixes:
- Do not re-match an org-resolved specifier against local create.templates:
an org entry { name: 'web', template: 'component' } no longer redirects to
a local entry also named 'component' (guard the local match with a
resolvedByOrg flag).
- Do not clobber the create block when the root config exists but cannot be
evaluated: getConfiguredCreate gains throwOnReadError so registration aborts
instead of overwriting with only the new entry. The generator is already
scaffolded, so bin.ts warns and points at the manual edit rather than
failing the whole create.
- Write the merge temp file to a unique OS-temp path instead of a fixed
.vite-plus-create-register.json in the workspace, which could overwrite a
user file of that name.
This comment was marked as resolved.
This comment was marked as resolved.
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Generator registration formatted a hardcoded vite.config.ts in a separate step, which both missed other extensions (.mts/.cts/.cjs) and formatted the wrong file. Drop the dedicated format: registerLocalTemplate now returns the path it wrote, and the existing monorepo format pass formats that file alongside the new package, so the right config is always reformatted and no separate step is needed.
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit a9a2fc3. Configure here.
cpojer
left a comment
There was a problem hiding this comment.
Love it. We need to raise awareness of how useful this can be to large company monorepos.
…ution Code-review fixes for the create.templates flow: - Replace replace_json_config with upsert_json_config: only direct config objects are edited (a create key inside a nested function return, e.g. an inline plugin's config() hook, is never spliced), shorthand `create` properties are replaced in place, the key is inserted when missing, and unsupported shapes report updated: false instead of being corrupted by the merge fallback - registerLocalTemplate throws when the config shape is unsupported so the caller warns with the add-it-by-hand snippet instead of reporting a registration that never happened; it also warns when a same-name entry already points at a different template - vp create exits cleanly on a malformed create.templates (no stack dump), warns when the root config cannot be evaluated instead of silently letting a registered name fall through to an npm package, and no longer aborts the whole create when the scaffolded generator's package.json is unreadable - getConfiguredDefaultTemplate rethrows CreateConfigSchemaError so a valid defaultTemplate is not silently dropped in standalone projects - discoverTemplate errors when a by-name entry matches no workspace package instead of dlx-running the same-named npm package - inferParentDir only co-locates for create.templates resolutions, so an npm template colliding with a workspace package name keeps the apps rule - WorkspacePackage.path is normalized to forward slashes, fixing co-location under multi-segment parent dirs on Windows - VITE_CONFIG_FILES matches Vite's DEFAULT_CONFIG_FILES order so registration reads and writes the same file when multiple configs exist - create.templates entry names starting with vite: are rejected at validation to keep builtins from being shadowed - register-template tests run in self-contained os.tmpdir workspaces with a stubbed vite-plus instead of inside the repo's node_modules
WorkspacePackage.path is now normalized to forward slashes, so the Windows-only path.join expectation no longer applies.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
main removed WorkspacePackage.isTemplatePackage (#1777 follow-up in 0315153) and added tools specs importing the deleted @voidzero-dev/vite-plus-test wrapper; drop the stale property from the migration spec literals and import the tools specs from vitest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
main removed WorkspacePackage.isTemplatePackage (#1777 follow-up in 0315153) and added tools specs importing the deleted @voidzero-dev/vite-plus-test wrapper; drop the stale property from the migration spec literals and import the tools specs from vitest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
main removed WorkspacePackage.isTemplatePackage (#1777 follow-up in 0315153) and added tools specs importing the deleted @voidzero-dev/vite-plus-test wrapper; drop the stale property from the migration spec literals and import the tools specs from vitest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Release vite-plus v0.2.0. Vite+ now consumes upstream Vitest directly (no wrapper), raises the minimum supported Node.js version to 22.18.0, and ships corepack and devEngines support. ### Highlights - **`vp test` now runs upstream Vitest directly (breaking)**: Vite+ used to ship `@voidzero-dev/vite-plus-test`, a rebundled copy of Vitest that lagged upstream releases. That package is removed; `vp test` now runs the real upstream `vitest`, which is installed automatically as a dependency of `vite-plus` (you no longer add `vitest` or `@vitest/*` yourself, and `vite` still resolves to `@voidzero-dev/vite-plus-core` via package-manager overrides). Your `import ... from 'vite-plus/test'` code keeps working unchanged and `vp migrate` updates existing projects ([#1588](#1588)), by @Brooooooklyn - **Minimum supported Node.js version raised to `^22.18.0 || >=24.11.0` (breaking)**: Node 20 reached end-of-life and the bundled tsdown already required `^22.18.0`, so the published engines range now matches what `vp pack` can actually deliver; `vp exec` / `vp run` / `vp dlx` reject projects resolving an older Node with the existing incompatibility error ([#1813](#1813)), by @fengmk2 - **Corepack now works under Vite+**: `corepack` is a default `vp env setup` shim, resolved managed-global, then Node-bundled (Node <= 24), then auto-installed (Node 25+, which dropped corepack); `corepack enable` / `disable` land their pnpm/yarn launchers on PATH and Vite+-owned shims are restored if corepack replaces them ([#1808](#1808)), by @fengmk2 - **devEngines support for runtime and package-manager selection**: Vite+ reads `devEngines.runtime` (ranked above `engines.node`) and `devEngines.packageManager`; auto-pin and `vp migrate` write `devEngines.packageManager`, `vp env pin` / `unpin` target `devEngines.runtime`, and `vp env doctor` reports conflicts instead of silently resolving them ([#1760](#1760)), by @fengmk2 ### Features - `vp pm approve-builds`: forward to npm's new `approve-scripts` / `deny-scripts` (npm >= 11.16.0) instead of the previous no-op, matching `pnpm approve-builds` / `bun pm trust`; mixed approve+deny is rejected with actionable guidance and npm's advisory-only caveat is surfaced ([#1733](#1733)), by @fengmk2 - `vp create`: support local monorepo templates declared in `create.templates` in `vite.config.ts`; `vp create vite:generator` scaffolds a Bingo generator and auto-registers it in the picker, replacing the old package.json-keyword inference ([#1777](#1777)), by @fengmk2 - `vp create`: detect direct dependencies whose build scripts the package manager gated (e.g. native builds like `better-sqlite3`) and act on them; prompt to approve each (default off) interactively, point at `vp pm approve-builds` non-interactively, or build them with `--approve-builds` ([#1828](#1828)), by @fengmk2 - `vp config`: add `--no-hooks` and `--no-agent` opt-outs to skip git-hook installation and coding-agent instruction updates ([#1842](#1842)), by @leno23 - `vp list -g`: sort the global package list output so entries appear in a stable order ([#1748](#1748)), by @liangmiQwQ - Upgrade upstream dependencies: rolldown `1.0.3 -> 1.1.1`, tsdown `0.22.1 -> 0.22.3`, oxlint `1.67.0 -> 1.70.0`, oxfmt `0.52.0 -> 0.55.0`, vitest `4.1.8 -> 4.1.9`, and the oxc toolchain `0.133.0 -> 0.136.0` ([#1749](#1749), [#1767](#1767), [#1812](#1812), [#1834](#1834), [#1855](#1855)), by @voidzero-guard[bot] ### Fixes & Enhancements - Security: resolve open Rust Dependabot advisories by bumping transitive `openssl` `0.10.76 -> 0.10.80` (`openssl-sys` `0.9.112 -> 0.9.116`), fixing five high-severity rust-openssl issues (buffer overflows in key derivation, AES key wrap, and digest finalization; an unchecked PSK/cookie trampoline length leaking adjacent memory; and OCSP-responder undefined behavior: [GHSA-pqf5-4pqq-29f5](GHSA-pqf5-4pqq-29f5), [GHSA-8c75-8mhr-p7r9](GHSA-8c75-8mhr-p7r9), [GHSA-ghm9-cr32-g9qj](GHSA-ghm9-cr32-g9qj), [GHSA-hppc-g8h3-xhp3](GHSA-hppc-g8h3-xhp3), [GHSA-xp3w-r5p5-63rr](GHSA-xp3w-r5p5-63rr)), and drop the unmaintained, unsound `libyml` ([GHSA-gfxp-f68g-8x78](GHSA-gfxp-f68g-8x78), high) by removing dead `serde_yml` code ([#1742](#1742)), by @fengmk2 - Security (docs site): update `mermaid` `11.13.0 -> 11.15.0` to fix improper `classDef` sanitization in state diagrams that allowed HTML injection ([CVE-2026-41149](https://nvd.nist.gov/vuln/detail/CVE-2026-41149) / [GHSA-ghcm-xqfw-q4vr](GHSA-ghcm-xqfw-q4vr), medium severity; `<script>` tags are stripped so it does not reach XSS) ([#1745](#1745)), by @renovate[bot] - `vp check --fix` / `vp staged`: create/migrate now wrap inline Vite `plugins: [...]` arrays with `lazyPlugins(...)` so plugin factories aren't eagerly executed (and don't hang on open handles) during lint/format/check config loading ([#1752](#1752)), by @jong-kyung - `vp migrate`: complete pending migration work for projects that already have `vite-plus` installed (scripts, imports, tsconfig types, ESLint/Prettier, legacy hooks, package-manager settings) instead of treating `vite-plus` as migration-complete; fully migrated projects stay idempotent ([#1821](#1821)), by @jong-kyung - `vp create` / `vp migrate`: detect shorthand `fmt,` / `lint,` config keys so a duplicate inline block is no longer injected ([#1843](#1843)), by @fengmk2 - IDE oxlint/oxfmt wrappers: set `VP_COMMAND` so `lazyPlugins()` skips framework plugins during LSP config reads, preventing a stray `.svelte-kit` (and similar) directory at the monorepo root ([#1764](#1764)), by @jong-kyung - `vp lint` / `vp run -r lint` on Windows: keep the absolute `tsgolint` path for workspace lint runs instead of downgrading it to a wrong cwd-relative path ([#1758](#1758)), by @semimikoh - oxlint wrapper: set the `tsgolint` path so type-aware lint resolves it ([#1811](#1811)), by @jong-kyung - `vp install -g`: use a unique backup directory and treat stale-backup cleanup as best-effort so a locked Windows binary no longer fails an otherwise successful reinstall ([#1753](#1753)), by @fengmk2 - `vp install -g`: remove stale managed binary shims when a reinstalled package drops a bin from its `package.json#bin` ([#1765](#1765)), by @liangmiQwQ - `vp create --git`: surface git's actual stdout/stderr when the initial commit fails instead of always blaming `user.name` / `user.email` ([#1819](#1819)), by @fengmk2 - `vp create vite:generator`: reject `--git` / `--no-git`, since adding a generator to an existing monorepo does not initialize git ([#1788](#1788)), by @jong-kyung - Global CLI: harden `find_system_tool` against a self-exec loop (skip the running executable's own bin directory) and fix two `vite_global_cli` tests that could hang ([#1820](#1820)), by @fengmk2 - CLI help: unify alias display ([#1832](#1832)), show supported `run` options ([#1797](#1797)), show `--fail-if-no-match` in `exec` help ([#1798](#1798)), add the `implode` documentation link ([#1796](#1796)), and handle nested-command typo help ([#1803](#1803)), by @jong-kyung ### Docs - Document `vp create` opt-out options ([#1790](#1790)), by @jong-kyung - Document `vp upgrade` options ([#1847](#1847)), by @jong-kyung - Align the config overview with the sidebar ([#1846](#1846)), by @jong-kyung - Sync the documented command lists with the help output ([#1850](#1850)), by @jong-kyung - Clarify lazy plugin side effects ([#1841](#1841)), by @leno23 - Add JongKyung's X profile ([#1844](#1844)) and update Christoph's X profile ([#1845](#1845)) on the team page, by @jong-kyung ### Refactor - Remove the CLI tips system; the shortcuts it printed on `vp install` are already covered by the help system and added unnecessary complexity ([#1799](#1799)), by @cpojer ### Chore - Re-enable Renovate dependency updates with a targeted ignore-list ([#1744](#1744)), by @fengmk2 - Keep generated NAPI bindings during upgrade-deps ([#1759](#1759)), by @fengmk2 - Remove the `vite_glob` dependency from vite-plus ([#1763](#1763)), by @wan9chi - Keep `sync-remote` from churning `pnpm-workspace.yaml` (dedupe `minimumReleaseAgeExclude`, preserve comments) ([#1787](#1787)), by @fengmk2 - Make unix `just test` runnable ([#1755](#1755)), by @situ2001 - CI: reuse `just lint` and `just test` as the single source of truth ([#1809](#1809)), pin `cargo-zigbuild` to a git rev to fix the aarch64-musl link failure ([#1815](#1815)), and keep upgrade-deps green when rolldown bumps oxc ([#1833](#1833)), by @fengmk2 - Update Rust to nightly-2026-06-10 ([#1725](#1725)), typos to v1.47.1 / v1.47.2 ([#1772](#1772), [#1775](#1775)), GitHub Actions ([#1778](#1778), [#1829](#1829)), and npm packages ([#1779](#1779)), by @renovate[bot] - Bump `oxc-project/setup-node` to v1.3.1 ([#1792](#1792)), by @Boshen - Refresh trusted stack stats on the docs homepage ([#1786](#1786), [#1837](#1837)), by @voidzero-guard[bot] ### Bundled Versions | Tool | Version | Source | | --- | --- | --- | | vite | `8.0.16` | [`f94df87`](vitejs/vite@f94df87) | | rolldown | `1.1.1` | [`d7f919c`](rolldown/rolldown@d7f919c) | | tsdown | `0.22.3` | [npm](https://npmx.dev/package/tsdown/v/0.22.3) | | vitest | `4.1.9` | [npm](https://npmx.dev/package/vitest/v/4.1.9) | | oxlint | `1.70.0` | [npm](https://npmx.dev/package/oxlint/v/1.70.0) | | oxlint-tsgolint | `0.23.0` | [npm](https://npmx.dev/package/oxlint-tsgolint/v/0.23.0) | | oxfmt | `0.55.0` | [npm](https://npmx.dev/package/oxfmt/v/0.55.0) | ### Upgrading from 0.1.24 to 0.2.0 This release has two breaking changes. For most projects the upgrade is `vp upgrade`, bump the project's `vite-plus`, then `vp migrate`. #### 1. Update the CLI ```bash vp upgrade ``` #### 2. Node.js 20 is no longer supported The minimum supported Node.js version is now `^22.18.0 || >=24.11.0` (Node 20 reached end-of-life). If you are still on Node 20: - Check your version: `node --version` (or `vp env doctor`) - Move to a supported release: `vp env pin 22.18.0` (or a newer LTS), or update your `.node-version` / `devEngines.runtime` `vp exec` / `vp run` / `vp dlx` now refuse to run against a project that resolves Node < 22.18.0. #### 3. Vitest is now upstream (the wrapper is gone) `@voidzero-dev/vite-plus-test` has been removed; Vite+ consumes upstream `vitest` directly. Bump `vite-plus` first, then migrate: ```bash vp update vite-plus --latest # project's vite-plus -> 0.2.0 (ignores the old range, updates the lockfile); monorepo: add -r vp migrate # local vite-plus is now 0.2.0, so the new migration runs ``` `vp update --latest` re-resolves `vite-plus` to the newest release regardless of the old semver range, so the lockfile cannot pin you back to 0.1.24. The project's local `vite-plus` is then 0.2.0, and since the global `vp` delegates `migrate` to the project's local install, `vp migrate` runs the new migration. - Your `import { vi, ... } from 'vite-plus/test'` code is unchanged. `vp migrate` rewrites any leftover `vitest` / `@vitest/*` imports and normalizes stale `vitest: npm:@voidzero-dev/vite-plus-test@*` aliases. - You no longer add `vitest` or `@vitest/*` yourself; they arrive transitively through `vite-plus`. ### New Contributors Welcome to our new contributor @situ2001! 🎉 **Full Changelog**: v0.1.24...v0.2.0 --- Merging this PR will trigger the release workflow. --------- Co-authored-by: voidzero-guard[bot] <278573678+voidzero-guard[bot]@users.noreply.github.com> Co-authored-by: MK <fengmk2@gmail.com>
Summary
Adds first-class support for local templates in
vp create, declared increate.templatesin a monorepo'svite.config.ts(the design agreed with @cpojer). This replaces the earlier implicit package.json keyword detection.What it does
create.templatesconfig: declare local templates as{ name, description, template }entries (reusing the org manifest schema and validator). Inside a monorepo, thevp createpicker lists these entries; selecting one (orvp create <name>) resolves the entry'stemplatespecifier through the normal discovery path.vp create vite:generatorscaffolds a Bingo generator and registers it increate.templatesautomatically (idempotent, preserving anydefaultTemplate), so it appears in the picker with no manual edit.node bin/index.ts(.tsimports, bingo 0.9.3, zod v3 aligned with bingo, Node>=22.18.0).bingo/zodmove from the repo root intovite-plusdevDependencies.bingodependency is only a run hint (auto--skip-requests). A declared template without abinerrors clearly instead of falling through to npmcreate-<name>.Behavior change
vp create <workspace-package>runs as a template only when that package is declared increate.templates; otherwise it resolves as an npmcreate-<name>package as before.Docs and tests
create.templatesconfig reference, the Code Generators guide, and both create RFCs are updated. Adds unit tests, acreate-generator-monoreposnap (scaffold, auto-registration, and run end to end), and global snap updates.Note
Medium Risk
Changes how workspace package names resolve in
vp create(breaking if teams relied on unregistered local packages) and modifies config via AST splice plus read-modify-write ofvite.config.ts.Overview
Introduces
create.templatesinvite.config.tsas the explicit registry for monorepo-localvp createtemplates (name,description,template). In a monorepo, the picker lists these entries andvp create <name>resolves to each entry’stemplatespecifier; workspace package names no longer run as templates unless registered (otherwise behavior stayscreate-<name>on npm).vp create vite:generatornow auto-appends an idempotent entry (preservingdefaultTemplate) via newregisterLocalTemplate, backed by RustreplaceJsonConfigto overwrite an existing top-level config key instead of duplicating it with merge. Local runs usediscoverTemplatewith stricterbinresolution,bingo-only--skip-requests, and output co-located under the generator’s parent dir; missingbinerrors instead of npm fallthrough.Removes keyword-based template inference and
isTemplatePackage; skips git init when adding packages inside an existing monorepo. Generator scaffold updates (bingo 0.9.3, zod v3, directnode bin/index.ts). Docs, RFCs, CONTRIBUTING local-validation notes, and snap/unit tests added or updated.Reviewed by Cursor Bugbot for commit a9a2fc3. Configure here.