Repository navigation
Switch to uv and prek, and enforce the shared lint suite #100
Copy link
Copy link
Open
Labels
dependenciesPull requests that update a dependency filePull requests that update a dependency filegithub_actionsPull requests that update GitHub Actions codePull requests that update GitHub Actions code
Description
Activity
- addeddependenciesPull requests that update a dependency filePull requests that update a dependency filegithub_actionsPull requests that update GitHub Actions codePull requests that update GitHub Actions code
on Sep 26, 2026 The 13 ESLint errors on
mainare 12no-consoleand onemax-len, at 0ce46cf:.github/scripts/generate-automation.js
Lines 258 to 298 in 0ce46cf
...Object.entries(buildReusableWorkflows(automations, retiredSecrets)).map(([file, content]) => [ path.join(WORKFLOWS_DIR, file), content, ]), [TEMPLATE_PATH, buildTemplateYml(automations, secrets, 'Caller template: copy this file to .github/workflows/automation.yml in a consumer repo.\n' + '# No edits are needed - the on: block is the exhaustive union of every enabled automation.')], [DOGFOOD_PATH, buildTemplateYml(automations, secrets, 'This repo\'s own automation caller - .github acts as consumer zero and stays in sync automatically.')], ]; const targetPaths = new Set(targets.map(([target]) => target)); const stale = fs .readdirSync(WORKFLOWS_DIR) .filter((f) => f.startsWith(GROUP_PREFIX)) .map((f) => path.join(WORKFLOWS_DIR, f)) .filter((f) => !targetPaths.has(f)); if (check) { let drifted = false; for (const [target, content] of targets) { const current = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : null; if (current !== content) { console.error(`Drift detected in ${path.relative(ROOT, target)} - run \`node scripts/generate-automation.js\``); drifted = true; } } for (const target of stale) { console.error(`Stale ${path.relative(ROOT, target)} - run \`node scripts/generate-automation.js\``); drifted = true; } process.exit(drifted ? 1 : 0); } for (const [target, content] of targets) { fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, content); console.log(`Wrote ${path.relative(ROOT, target)}`); } for (const target of stale) { fs.unlinkSync(target); console.log(`Removed ${path.relative(ROOT, target)}`); .github/scripts/sync-automation-template.js
Lines 312 to 348 in 0ce46cf
console.log(`${r.repo.padEnd(26)} ${r.state.padEnd(20)} ${extra}`); } const problems = results.filter((r) => PROBLEM_STATES.includes(r.state)); const drifted = results.filter((r) => r.state !== 'in-sync'); console.log(`\n${results.length} consumers, ${drifted.length} not in sync, ${problems.length} needing attention.`); for (const p of problems) { console.log(`::error title=${p.repo}::${p.state}${p.detail ? `: ${p.detail}` : ''}`); } return problems.length; } // Both spellings, because an --only nobody parses is a full run against every // consumer, which is the opposite of what it asks for. function parseArgs(argv) { const i = argv.findIndex((a) => a === '--only' || a.startsWith('--only=')); let only; if (i !== -1) { only = argv[i] === '--only' ? argv[i + 1] : argv[i].slice('--only='.length); if (!only || only.startsWith('--')) throw new Error('--only needs a repo name'); } return { dryRun: argv.includes('--dry-run'), only }; } async function main() { const token = process.env.GITHUB_TOKEN; if (!token) { console.error('GITHUB_TOKEN is not set.'); process.exit(1); } const template = fs.readFileSync(TEMPLATE_PATH, 'utf8'); const results = await run(httpApi(token), template, parseArgs(process.argv.slice(2))); process.exit(report(results) ? 1 : 0); } if (require.main === module) { main().catch((err) => { console.error(err.message); .github/scripts/sync-automation-template.test.js
Lines 352 to 364 in 0ce46cf
const quiet = console.log; console.log = () => {}; try { const problems = report([ { repo: 'a', state: 'in-sync' }, { repo: 'b', state: 'opened', pr: 1 }, { repo: 'c', state: 'declined', pr: 2 }, { repo: 'd', state: 'error', detail: 'no access' }, { repo: 'e', state: 'toolchain-conflict', pr: 3 }, ]); assert.equal(problems, 2, 'error and toolchain-conflict each need attention'); } finally { console.log = quiet;
Until they are fixed,
yarn lintexits 1, so #109's "yarn lintpasses" criterion can't be met.
Written by rtibblesbot, an LLM-based coding agent.
Metadata
Metadata
Assignees
Labels
dependenciesPull requests that update a dependency filePull requests that update a dependency filegithub_actionsPull requests that update GitHub Actions codePull requests that update GitHub Actions code
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
Nothing in this repo enforces the JS or Python linting our other repos run: ESLint reports 13 errors and Prettier flags 9 files on
main. This brings its tooling in line with Kolibri, Studio, and Morango.Complexity: Low
Target branch:
mainContext
.pre-commit-config.yamlruns pre-commit-hooks v4.1.0, yamlfmt v0.14.0, actionlint v1.7.7, and the localgenerate-automationdrift check.requirements-dev.txtlistspre-commit;pre-commit.ymlinstalls prek withpipx install prek.scripts/(ESLint and Prettier configured inpackage.json,.eslintrc.js,.prettierrc.js) and two Python scripts underscripts/..github/dependabot.ymlcovers npm, pip, and github-actions monthly with a 7-day cooldown.The Change
requestsfor the Python scripts andprekin a dev group..pre-commit-config.yamlshould run the suite our other repos run: pre-commit-hooks, ruff and ruff-format, yamlfmt, actionlint, zizmor, uv-lock, and ESLint and Prettier on the JS, alongside the existinggenerate-automationcheck.pipentry withuvand add thepre-commitecosystem, monthly with the 7-day cooldown, hook bumps grouped into one PR.Out of Scope
Acceptance Criteria
uv sync --group devthenuv run prek run --all-filespasses.pre-commit.ymlruns the same hooks through uv and passes onmain.requirements-dev.txtis removed and no workflow runspip install.uv,pre-commit,npm, andgithub-actions, and nopip.docs/covers setting up a dev environment: installing the Python and JS dependencies and the prek git hook.References
pre-commitecosystem: https://github.blog/changelog/2026-03-10-dependabot-now-supports-pre-commit-hooks/AI usage
I chose the scope: prek and uv as in our other repos, Dependabot over a scheduled autoupdate job, and autofix left out. Claude Code surveyed this repo's and Kolibri's configs and drafted the sections, which I reviewed one by one.