chore: upgrade dependencies and tooling (#232)

* chore: upgrade dependencies and tooling

* chore: upgrade dependencies and tooling
This commit is contained in:
Andrey Avtomonov 2026-05-29 11:56:55 +02:00 committed by GitHub
parent ed8f523362
commit d53cdac366
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 2737 additions and 2710 deletions

View file

@ -22,7 +22,7 @@ jobs:
github.event.issue.author_association != 'COLLABORATOR'
steps:
- name: Apply needs-triage label
uses: actions/github-script@v7
uses: actions/github-script@v9
with:
script: |
await github.rest.issues.addLabels({

View file

@ -14,6 +14,12 @@ repos:
- id: check-case-conflict
- id: mixed-line-ending
- repo: https://github.com/tombi-toml/tombi-pre-commit
rev: v1.1.0
hooks:
- id: tombi-format
args: ["--offline"]
- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:

View file

@ -12,7 +12,7 @@
"dependencies": {
"@xyflow/react": "^12.10.2",
"fumadocs-core": "16.8.10",
"fumadocs-mdx": "15.0.4",
"fumadocs-mdx": "15.0.7",
"fumadocs-ui": "16.8.10",
"next": "^16",
"react": "19.2.6",
@ -20,7 +20,7 @@
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^25.7.0",
"@types/node": "^25.9.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"tailwindcss": "^4",

View file

@ -4,7 +4,7 @@
"description": "Workspace root for ktx packages",
"private": true,
"type": "module",
"packageManager": "pnpm@11.1.1",
"packageManager": "pnpm@11.4.0",
"engines": {
"node": ">=22.0.0",
"pnpm": ">=10.20.0"
@ -24,6 +24,7 @@
"dead-code:fix": "biome check . --formatter-enabled=false --assist-enabled=false --write && knip --fix --format",
"dead-code:knip": "knip --reporter compact",
"dead-code:knip:production": "knip --production --reporter compact",
"deps:upgrade": "node scripts/upgrade-dependencies.mjs",
"docs": "kill $(lsof -ti:3000) 2>/dev/null; pnpm --filter ktx-docs run dev",
"ktx": "node scripts/run-ktx.mjs",
"link:dev": "node scripts/link-dev-cli.mjs",
@ -58,11 +59,11 @@
"@semantic-release/github": "^12.0.8",
"@semantic-release/npm": "^13.1.5",
"@semantic-release/release-notes-generator": "^14.1.1",
"@types/node": "^25.7.0",
"@types/node": "^25.9.1",
"better-sqlite3": "^12.10.0",
"conventional-changelog-conventionalcommits": "^9.3.1",
"knip": "^6.12.2",
"pg": "^8.20.0",
"knip": "^6.14.1",
"pg": "^8.21.0",
"semantic-release": "^25.0.3",
"typescript": "^6.0.3",
"yaml": "^2.9.0"

View file

@ -43,36 +43,36 @@
"search:pglite-sl-prototype": "node ../../scripts/pglite-sl-search-prototype.mjs"
},
"dependencies": {
"@ai-sdk/anthropic": "3.0.77",
"@ai-sdk/devtools": "0.0.17",
"@ai-sdk/google-vertex": "^4.0.128",
"@anthropic-ai/claude-agent-sdk": "0.3.142",
"@ai-sdk/anthropic": "3.0.78",
"@ai-sdk/devtools": "0.0.18",
"@ai-sdk/google-vertex": "^4.0.134",
"@anthropic-ai/claude-agent-sdk": "0.3.146",
"@clack/prompts": "1.4.0",
"@clickhouse/client": "^1.18.4",
"@clickhouse/client": "^1.18.5",
"@commander-js/extra-typings": "14.0.0",
"@google-cloud/bigquery": "^8.3.1",
"@looker/sdk": "^26.8.0",
"@looker/sdk-node": "^26.8.0",
"@looker/sdk-rtl": "^21.6.5",
"@modelcontextprotocol/sdk": "^1.29.0",
"@notionhq/client": "^5.21.0",
"ai": "^6.0.180",
"@notionhq/client": "^5.22.0",
"ai": "^6.0.188",
"better-sqlite3": "^12.10.0",
"commander": "14.0.3",
"fflate": "^0.8.2",
"fflate": "^0.8.3",
"handlebars": "^4.7.9",
"ink": "^7.0.2",
"ink": "^7.0.3",
"lookml-parser": "7.1.0",
"minimatch": "^10.2.5",
"mssql": "^12.5.2",
"mssql": "^12.5.4",
"mysql2": "^3.22.3",
"openai": "^6.37.0",
"openai": "^6.38.0",
"p-limit": "^7.3.0",
"pg": "^8.20.0",
"posthog-node": "^5.0.0",
"pg": "^8.21.0",
"posthog-node": "^5.34.9",
"react": "^19.2.6",
"simple-git": "3.36.0",
"snowflake-sdk": "^2.4.1",
"snowflake-sdk": "^2.4.2",
"yaml": "^2.9.0",
"zod": "^4.4.3"
},
@ -81,14 +81,14 @@
"@electric-sql/pglite-socket": "^0.1.5",
"@types/better-sqlite3": "^7.6.13",
"@types/mssql": "^12.3.0",
"@types/node": "^25.7.0",
"@types/node": "^25.9.1",
"@types/pg": "^8.20.0",
"@types/react": "^19.2.14",
"@vitest/coverage-v8": "^4.1.6",
"@types/react": "^19.2.15",
"@vitest/coverage-v8": "^4.1.7",
"ajv": "8.20.0",
"ink-testing-library": "^4.0.0",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
"vitest": "^4.1.7"
},
"license": "Apache-2.0",
"repository": {

3021
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -23,3 +23,4 @@ allowBuilds:
better-sqlite3: true
esbuild: true
sharp: true
minimumReleaseAge: 10080

View file

@ -13,10 +13,10 @@ Issues = "https://github.com/kaelio/ktx/issues"
[dependency-groups]
dev = [
"pre-commit>=4.6.0",
"pytest>=9.0.2",
"pytest-cov>=7.1.0",
"ruff>=0.8.4",
"pre-commit>=4.6.0",
"pytest>=9.0.2",
"pytest-cov>=7.1.0",
"ruff>=0.8.4",
]
[tool.uv]
@ -32,14 +32,14 @@ torch = { index = "pytorch-cpu" }
[tool.uv.workspace]
members = [
"python/ktx-sl",
"python/ktx-daemon",
"python/ktx-sl",
"python/ktx-daemon",
]
[tool.pytest.ini_options]
addopts = ["--import-mode=importlib"]
pythonpath = ["python/ktx-sl/tests"]
testpaths = [
"python/ktx-sl/tests",
"python/ktx-daemon/tests",
"python/ktx-sl/tests",
"python/ktx-daemon/tests",
]

View file

@ -6,18 +6,18 @@ readme = "README.md"
requires-python = ">=3.13"
license = "Apache-2.0"
dependencies = [
"fastapi>=0.115.0",
"ktx-sl",
"lkml>=1.3.7",
"numpy>=2.2.6",
"orjson>=3.11.4",
"pandas>=2.2.3",
"posthog>=7.0.0",
"psycopg[binary]>=3.2.0",
"pydantic>=2.9.0",
"requests>=2.32.0",
"sqlglot>=26",
"uvicorn[standard]>=0.32.0",
"fastapi>=0.136.3",
"ktx-sl",
"lkml>=1.3.7",
"numpy>=2.4.6",
"orjson>=3.11.9",
"pandas>=3.0.3",
"posthog>=7.16.1",
"psycopg[binary]>=3.3.4",
"pydantic>=2.13.4",
"requests>=2.34.2",
"sqlglot>=30",
"uvicorn[standard]>=0.48.0",
]
[project.scripts]
@ -25,8 +25,8 @@ ktx-daemon = "ktx_daemon.__main__:main"
[project.optional-dependencies]
local-embeddings = [
"sentence-transformers>=5.1.1",
"torch>=2.2.0",
"sentence-transformers>=5.1.1",
"torch>=2.2.0",
]
[project.urls]
@ -43,8 +43,8 @@ packages = ["src/ktx_daemon"]
[dependency-groups]
dev = [
"httpx>=0.28.1",
"pytest>=9.0.2",
"httpx>=0.28.1",
"pytest>=9.0.2",
]
[tool.uv.sources]

View file

@ -6,9 +6,9 @@ readme = "README.md"
requires-python = ">=3.13"
license = "Apache-2.0"
dependencies = [
"sqlglot>=26",
"pydantic>=2",
"pyyaml>=6",
"sqlglot>=30",
"pydantic>=2",
"pyyaml>=6",
]
[project.urls]
@ -18,13 +18,13 @@ Issues = "https://github.com/kaelio/ktx/issues"
[project.optional-dependencies]
dev = [
"pytest>=8",
"pytest-cov",
"ruff",
"pre-commit",
"pytest>=8",
"pytest-cov",
"ruff",
"pre-commit",
]
tpch = [
"duckdb>=1.0",
"duckdb>=1.0",
]
[tool.pytest.ini_options]
@ -40,9 +40,9 @@ branch = true
show_missing = true
skip_empty = true
exclude_lines = [
"pragma: no cover",
"if __name__ == .__main__.",
"if TYPE_CHECKING:",
"pragma: no cover",
"if __name__ == .__main__.",
"if TYPE_CHECKING:",
]
[build-system]
@ -54,6 +54,6 @@ packages = ["semantic_layer"]
[dependency-groups]
dev = [
"pytest>=9.0.2",
"pytest-cov>=7.1.0",
"pytest>=9.0.2",
"pytest-cov>=7.1.0",
]

View file

@ -0,0 +1,111 @@
#!/usr/bin/env node
import { execFile as execFileCallback } from 'node:child_process';
import { readFile as fsReadFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { promisify } from 'node:util';
const execFileAsync = promisify(execFileCallback);
const npmCheckUpdatesRejectArgs = ['--reject', 'fumadocs-core,fumadocs-ui'];
function ktxRootDir() {
return resolve(dirname(fileURLToPath(import.meta.url)), '..');
}
function failureText(error) {
const stdout = typeof error?.stdout === 'string' ? error.stdout.trim() : '';
const stderr = typeof error?.stderr === 'string' ? error.stderr.trim() : '';
const message = error instanceof Error ? error.message.trim() : String(error);
return [stderr, stdout, message].filter((line) => line.length > 0).join('\n') || 'Command failed';
}
function commandText(command, args) {
return [command, ...args].join(' ');
}
function pythonDependencyUpdatePhases() {
const manifests = ['pyproject.toml', 'python/ktx-sl/pyproject.toml', 'python/ktx-daemon/pyproject.toml'];
return manifests.map((manifest) => ({
name: `Python dependency constraints: ${manifest}`,
command: 'uvx',
args: ['dependency-check-updates', '--manifest', manifest, '-u'],
retry: commandText('uvx', ['dependency-check-updates', '--manifest', manifest, '-u']),
}));
}
async function pnpmMinimumReleaseAgeCooldown(rootDir, readFile) {
let workspaceConfig;
try {
workspaceConfig = await readFile(resolve(rootDir, 'pnpm-workspace.yaml'), 'utf8');
} catch (error) {
if (error?.code === 'ENOENT') {
return [];
}
throw error;
}
const match = workspaceConfig.match(/^\s*minimumReleaseAge:\s*(\d+)\s*$/m);
if (!match) {
return [];
}
return ['--cooldown', `${match[1]}m`];
}
export async function runDependencyUpgrade(options = {}) {
const rootDir = options.rootDir ?? ktxRootDir();
const execFile = options.execFile ?? execFileAsync;
const readFile = options.readFile ?? fsReadFile;
const log = options.log ?? ((line) => process.stdout.write(`${line}\n`));
const npmCheckUpdatesCooldownArgs = await pnpmMinimumReleaseAgeCooldown(rootDir, readFile);
const phases = [
{
name: 'TypeScript dependency constraints',
command: 'pnpm',
args: ['dlx', 'npm-check-updates', '-u', '--deep', ...npmCheckUpdatesRejectArgs, ...npmCheckUpdatesCooldownArgs],
retry: commandText('pnpm', [
'dlx',
'npm-check-updates',
'-u',
'--deep',
...npmCheckUpdatesRejectArgs,
...npmCheckUpdatesCooldownArgs,
]),
},
...pythonDependencyUpdatePhases(),
{
name: 'TypeScript lockfile',
command: 'pnpm',
args: ['install'],
retry: 'pnpm install',
},
{
name: 'Python lockfile',
command: 'uv',
args: ['lock', '--upgrade'],
retry: 'uv lock --upgrade',
},
];
for (const phase of phases) {
log(`RUN ${phase.name}: ${commandText(phase.command, phase.args)}`);
try {
await execFile(phase.command, phase.args, { cwd: rootDir, maxBuffer: 1024 * 1024 * 64 });
log(`PASS ${phase.name}`);
} catch (error) {
log(`FAIL ${phase.name}: ${failureText(error)}`);
log(`Retry: ${phase.retry}`);
return { ok: false, failedPhase: phase };
}
}
log('Dependency manifests and lockfiles were updated. Run `pnpm run check` before committing.');
return { ok: true };
}
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
const result = await runDependencyUpgrade();
if (!result.ok) {
process.exitCode = 1;
}
}

View file

@ -0,0 +1,123 @@
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import { test } from 'node:test';
import { runDependencyUpgrade } from './upgrade-dependencies.mjs';
test('runDependencyUpgrade updates TypeScript and Python manifests before regenerating lockfiles', async () => {
const calls = [];
const logs = [];
const result = await runDependencyUpgrade({
rootDir: '/workspace/ktx',
readFile: async (path) => {
assert.equal(path, '/workspace/ktx/pnpm-workspace.yaml');
return 'packages: []\nminimumReleaseAge: 10080\n';
},
execFile: async (command, args, options) => {
calls.push({ command, args, cwd: options.cwd });
return { stdout: '', stderr: '' };
},
log: (line) => logs.push(line),
});
assert.equal(result.ok, true);
assert.deepEqual(
calls.map((call) => [call.command, call.args]),
[
[
'pnpm',
[
'dlx',
'npm-check-updates',
'-u',
'--deep',
'--reject',
'fumadocs-core,fumadocs-ui',
'--cooldown',
'10080m',
],
],
['uvx', ['dependency-check-updates', '--manifest', 'pyproject.toml', '-u']],
['uvx', ['dependency-check-updates', '--manifest', 'python/ktx-sl/pyproject.toml', '-u']],
['uvx', ['dependency-check-updates', '--manifest', 'python/ktx-daemon/pyproject.toml', '-u']],
['pnpm', ['install']],
['uv', ['lock', '--upgrade']],
],
);
assert.equal(calls.every((call) => call.cwd === '/workspace/ktx'), true);
assert.equal(logs.some((line) => line.includes('PASS Python dependency constraints')), true);
});
test('runDependencyUpgrade stops at the failed phase and prints a retry command', async () => {
const calls = [];
const logs = [];
const result = await runDependencyUpgrade({
rootDir: '/workspace/ktx',
readFile: async () => 'packages: []\n',
execFile: async (command, args) => {
calls.push({ command, args });
if (command === 'uvx' && args.includes('python/ktx-sl/pyproject.toml')) {
const error = new Error('dependency-check-updates failed');
error.stdout = 'checking Python dependencies';
error.stderr = 'could not read pyproject.toml';
throw error;
}
return { stdout: '', stderr: '' };
},
log: (line) => logs.push(line),
});
assert.equal(result.ok, false);
assert.equal(result.failedPhase.name, 'Python dependency constraints: python/ktx-sl/pyproject.toml');
assert.equal(result.failedPhase.retry, 'uvx dependency-check-updates --manifest python/ktx-sl/pyproject.toml -u');
assert.deepEqual(
calls.map((call) => [call.command, call.args]),
[
['pnpm', ['dlx', 'npm-check-updates', '-u', '--deep', '--reject', 'fumadocs-core,fumadocs-ui']],
['uvx', ['dependency-check-updates', '--manifest', 'pyproject.toml', '-u']],
['uvx', ['dependency-check-updates', '--manifest', 'python/ktx-sl/pyproject.toml', '-u']],
],
);
assert.equal(logs.some((line) => line.includes('FAIL Python dependency constraints')), true);
assert.equal(logs.some((line) => line.includes('could not read pyproject.toml')), true);
assert.equal(logs.some((line) => line.includes('checking Python dependencies')), true);
assert.equal(
logs.some((line) => line.includes('Retry: uvx dependency-check-updates --manifest python/ktx-sl/pyproject.toml -u')),
true,
);
});
test('runDependencyUpgrade ignores missing pnpm minimum release age config', async () => {
const calls = [];
const result = await runDependencyUpgrade({
rootDir: '/workspace/ktx',
readFile: async () => {
throw Object.assign(new Error('missing'), { code: 'ENOENT' });
},
execFile: async (command, args) => {
calls.push({ command, args });
return { stdout: '', stderr: '' };
},
log: () => undefined,
});
assert.equal(result.ok, true);
assert.deepEqual(calls[0], {
command: 'pnpm',
args: ['dlx', 'npm-check-updates', '-u', '--deep', '--reject', 'fumadocs-core,fumadocs-ui'],
});
assert.equal(
calls
.filter((call) => call.command === 'uvx')
.every((call) => call.args.includes('--manifest') && !call.args.includes('-d')),
true,
);
});
test('package scripts expose the full dependency upgrade command', async () => {
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
assert.equal(packageJson.scripts['deps:upgrade'], 'node scripts/upgrade-dependencies.mjs');
});

5
tombi.toml Normal file
View file

@ -0,0 +1,5 @@
[[schemas]]
path = "tombi://www.schemastore.org/pyproject.json"
include = ["**/pyproject.toml"]
format.rules.array-values-order.enabled = false
format.rules.table-keys-order.enabled = false

2055
uv.lock generated

File diff suppressed because it is too large Load diff