Skip to content

fix(job): render Config column in job list from the Queue API's config field - #662

Merged
padak merged 1 commit into
mainfrom
fix/job-list-config-column
Aug 23, 2026
Merged

fix(job): render Config column in job list from the Queue API's config field#662
padak merged 1 commit into
mainfrom
fix/job-list-config-column

Conversation

@padak

@padak padak commented Aug 23, 2026

Copy link
Copy Markdown
Member

Summary

The human-mode table for kbagent job list rendered an always-empty Config column.

format_jobs_table built the cell as job.get("configId", job.get("config_id", "")), but the Queue API job resource names that field config -- and JobService._fetch_project_jobs returns the API row verbatim (it only adds project_alias), so neither key ever exists. The repo's own realistic fixture confirms the shape: JOB_DETAIL_RESPONSE in tests/test_cli.py uses "config": "123", and the job-detail renderer already reads config first.

This is the Python-side counterpart of the frontend fix in #658 (same invented configId key on the Job type; that PR was deliberately frontend-only).

Changes

  • output.py: the jobs-table Config cell now reads config first, with a tolerant configId fallback -- identical precedence to the job-detail renderer.
  • tests/test_output.py, tests/test_services.py: job fixtures hand-wrote the same invented configId key the renderer read, so they passed while real output was blank. They now use config, matching the real API shape, and test_jobs_table_with_jobs asserts the config values actually appear in the rendered table (this assertion fails against the old renderer).

Audited the rest of src/ for configId reads off Queue API job rows: the only other one is the job-detail renderer, which was already correct. Remaining configId usages belong to other APIs (Data Science apps, flow task configs, and the grouped-jobs endpoint whose group key genuinely is configId).

Testing

  • make check passes (6009 passed, 12 skipped).
  • TDD: fixture fix + new assertion first (observed the failure on the blank column), then the one-line renderer fix.

No version bump / changelog entry per the release-PR process; no version-gated docs affected (human-mode rendering fix only).


Open in Devin Review

…g field

The human-mode table for `kbagent job list` built the Config ID cell
from `configId` (with a `config_id` fallback) -- but the Queue API job
resource names the field `config`, and JobService returns the API row
verbatim, so the column was always blank. Read `config` first with a
tolerant `configId` fallback, matching the job-detail renderer.

The unit-test fixtures in test_output.py and test_services.py hand-wrote
the same invented `configId` key the renderer read, so they passed while
real output was empty. Fixtures now use `config` (the real API shape,
same as JOB_DETAIL_RESPONSE in test_cli.py) and the jobs-table test
asserts the config values actually render.

Python-side counterpart of the frontend fix in #658.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@padak padak left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of #662 — fix(job): render Config column in job list from the Queue API's config field

Generated by kbagent-pr-reviewer subagent. Verdict and findings below
are advisory; the human author retains every veto. CI-coverable issues
(lint, format, tests) are confirmed via make check, not duplicated here.

Summary

This is a minimal, well-scoped bug fix: format_jobs_table in output.py read a nonexistent configId/config_id key when rendering the human-mode job list table, so the Config column always rendered blank — the Queue API job resource actually names the field config (verified against JOB_DETAIL_RESPONSE in tests/test_cli.py and against the job-detail renderer, which already read config first). The fix flips the read order and updates five test fixtures across two files to match the real API shape, adding an explicit assertion that the rendered values now appear. Verdict: APPROVE — no blocking or non-blocking findings; only a couple of optional nits.

Verdict

  • Verdict: APPROVE
  • Blocking findings: 0
  • Non-blocking findings: 0
  • Nits: 1

Blocking findings

(none)

Non-blocking findings

(none)

Nits

  • [NIT-1] src/keboola_agent_cli/output.py:412 — the fallback chain job.get("config", job.get("configId", "")) keeps configId as a defensive fallback even though the audit in the PR description found no live source that populates it on a Queue API job row. Harmless to keep (it costs nothing and guards against a future API variant), but if the intent is strictly "read what the API actually sends," it could be simplified to job.get("config", "") to match the job-detail renderer's equivalent line 470 exactly (which also keeps the configId fallback, so this is consistent as-is — flagging only for symmetry consideration, not a defect).

Verification log

  • gh pr view 662 --json title,body,files,additions,deletions,baseRefName,headRefName,labels,state → OPEN, fix(job): prefix matches change type (bug fix), 3 files changed (+14/-10): src/keboola_agent_cli/output.py, tests/test_output.py, tests/test_services.py
  • git rev-parse --abbrev-ref HEADfix/job-list-config-column, matches <branch> input ✓
  • Read CONTRIBUTING.md "Checklist: Adding a New CLI Command", "Plugin synchronization map", "Releasing a new version" — this PR adds no new command, no new flag, no version-gated behavior, so none of the silent-drift surfaces (AGENT_CONTEXT, CLAUDE.md command list, keboola-expert.md, commands-reference.md, gotchas.md, OPERATION_REGISTRY) apply. Confirmed no command/permission/route files touched in the diff ✓
  • gh pr diff 662 (113 lines) → confirmed change is exactly: one line in output.py (read-order fix) + fixture key renames (configIdconfig) + one new assertion in test_output.py::test_jobs_table_with_jobs
  • Layer-violation greps (typer/click/httpx/requests in wrong layer) on the diff → all empty; change is entirely within output.py (commands layer output formatting), no layer boundary crossed ✓
  • grep -n "_fetch_project_jobs" -A 20 src/keboola_agent_cli/services/job_service.py → confirms the service returns the Queue API job dict verbatim (only client.list_jobs() result, no key remapping), supporting the PR's root-cause claim ✓
  • grep -n "JOB_DETAIL_RESPONSE" -A 15 tests/test_cli.py → confirms real fixture uses "config": "123" (not configId), matching the PR's claimed Queue API shape ✓
  • grep -rn "configId" src/ → the only other Queue-API-adjacent hit is output.py:470 (job-detail renderer), which already read config first pre-PR; remaining hits are unrelated APIs (Data Science apps configId, flow task configId, result_models.py AliasChoices which is already tolerant of all three key spellings) — audit claim in PR description holds ✓
  • Confirmed --json mode is unaffected: format_jobs_table is only called from the human-mode branch (commands/job.py, if not formatter.json_mode: guard around line 401); the JSON payload passes the API dict through unchanged regardless of this fix ✓
  • make check6009 passed, 12 skipped, 169 deselected in 168.35s, exit code 0 ✓
  • uv run pytest tests/test_output.py::TestFormatJobsTable::test_jobs_table_with_jobs -v → PASSED individually, confirming the new "101" in output / "201" in output assertions actually exercise the real Rich-rendered table (not a mock) ✓
  • Convention greps (magic numbers, raw error_code strings, bare except:, print(), token leakage, new tuple[...] returns) on the diff → all empty; no signature changes, no new returns in this diff ✓
  • Could not reproduce against a live Keboola project (no registered project/config-dir available in this sandboxed review session) — relied on the unit-level reproduction above (real format_jobs_table + real Rich Console capture against realistic fixtures), which is sufficient for a pure rendering fix with no API-shape ambiguity left unverified.

Open questions for the author

(none)

@padak
padak merged commit da4fb98 into main Aug 23, 2026
5 checks passed
@padak
padak deleted the fix/job-list-config-column branch August 23, 2026 16:39
@padak padak mentioned this pull request Aug 23, 2026
10 tasks
padak added a commit that referenced this pull request Aug 23, 2026
* chore(release): 0.90.0

Bumps pyproject.toml to 0.90.0 and adds the changelog entry covering every
PR merged since v0.89.0 (#658, #662, #661, #663, #665, #666, #664, #668,
#667, #623), resolves the vNEXT placeholders those PRs left behind, and
adds the curated What's new reel for the release.

* docs(web-server): keep the What's-new anchor stable across releases

The '### What's-new popup *(since vNEXT)*' heading put the version gate in
the heading itself, so resolving the placeholder to 0.90.0 changed the
generated slug to 'whats-new-popup-since-0900' and broke the in-page link
at line 138 -- and would have broken it again on every future release.

Moved the '(since 0.90.0)' tag to the first body line: the anchor is now
the stable 'whats-new-popup', the gate stays visible, and
check_version_gates.py still sees it (it scans the whole file, not just
headings).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant