feat(0.22.0): ErrorCode enum + sync init --adopt-existing - #201
feat(0.22.0): ErrorCode enum + sync init --adopt-existing#201ottomansky wants to merge 7 commits into
Conversation
P2-1: Add ErrorCode(StrEnum) to errors.py with 46 typed constants. All error_code="STRING" literals across 28 source files replaced with ErrorCode.<MEMBER>. Wire format unchanged (StrEnum is a str subtype). CI guard scripts/check_error_codes.py wired into 'make check'. docs/error-codes.md documents semver policy for adding/renaming codes. P2-2: sync init --adopt-existing idempotently adopts a .keboola/manifest.json written by the kbc Go CLI without overwriting it. Validates manifest project_id against the alias token; rejects mismatch with ConfigError (exit 5). Falls through to normal init when no manifest exists. Manifest.git_branching gains a default_factory so minimal manifests without the field parse cleanly.
Replacing with English version for broader team visibility.
padak
left a comment
There was a problem hiding this comment.
Approve with a small follow-up
The refactor to the ErrorCode enum is non-breaking (StrEnum), the AST-based (not regex) guard script is clean, tests + docs are complete. Before merge please also:
Required fix
src/keboola_agent_cli/commands/context.py (~line 95) — the sync init signature is missing --adopt-existing:
kbagent sync init --project ALIAS [--directory DIR] [--git-branching] [--adopt-existing]
kbagent context is the primary reference for AI agents (CONTRIBUTING.md line 200); without this entry the agent won't know the flag exists.
Nice-to-have (follow-up)
scripts/migrate_error_codes.pyis a one-shot migration script — after merge either delete it, or refactor it to parseerrors.pydynamically (otherwise the staticVALID_CODESlist will drift out of sync with the enum).src/keboola_agent_cli/errors.py:53+:85both have a# Storagesection comment — merge them into one section.- For future PRs: the commit
1b9cefe feat(0.22.0): ErrorCode enum + sync init --adopt-existingmixes two independent units (P2-1 refactor + P2-2 feature). CONTRIBUTING.md requires "One logical change per commit" — split next time into two commits/PRs.
Positives
- The StrEnum trick preserves wire format → zero breaking change for consumers.
- The
make checkAST guard will keep this (and others) from regressing. docs/error-codes.md(46 codes) + semver policy is a great artifact.- 218 raise sites migrated cleanly (
grep -r 'error_code="' src/→ 0 hits).
|
Addressed the required fix + both nice-to-haves:
Targeted tests: 23/23 pass. Noted the meta-feedback on mixed-scope commits — will split into two PRs next time. |
P2-1: ErrorCode(StrEnum) in errors.py with 49 typed constants (46 original + 3 new: JOB_TIMEOUT_TERMINATED, INVALID_FLOW_DAG, SCHEDULE_DELETE_FAILED). All error_code='STRING' literals across 30+ source files replaced with ErrorCode.<MEMBER>. Wire format unchanged (StrEnum subclasses str). P2-2: sync init --adopt-existing idempotently adopts a .keboola/manifest.json written by the kbc Go CLI without overwriting it. Validates manifest project_id against the alias token; rejects mismatch with ConfigError. scripts/check_error_codes.py CI guard rejects new raw literals. docs/error-codes.md documents semver policy.
|
Integrated into Full integration PR coming as release/0.22.0 -> main. |
- sync-workflow.md: new "Adopting an existing kbc Go CLI checkout" section for sync init --adopt-existing (#201). - gotchas.md: new entries for exit code 7 (JOB_TIMEOUT_TERMINATED), --poll-strategy fixed, --log-tail-lines N, logTail response semantics (#202); new section for --deny-writes / --deny-destructive (#203); new section for sync init --adopt-existing (#201). - workspace-workflow.md: new "Orphan detection + garbage collection" section for workspace list --orphaned + workspace gc (#204). - commands-reference.md: sync init --adopt-existing flag documented. - README.md: "What it does" table + "All commands" block updated with the 15 new commands shipped in 0.22.0 (flow CRUD, config metadata, workspace GC, storage describe, project pin + firewall, queue polling parity).
…tion Three PRs' changelog entries were dropped during the git merge --squash conflict resolution of release/0.22.0: - keboola#201 ErrorCode enum + sync init --adopt-existing (3 entries) - keboola#202 queue polling parity (5 entries) - keboola#205 storage describe-bucket/table/column/batch (6 entries) Without this fix, 'kbagent changelog' on installed 0.22.0 would show only 18 of the 32 features shipped in this release. Adding the missing 14 entries before tagging v0.22.0.
Summary
ErrorCode(StrEnum)inerrors.pywith 46 typed constants. Allerror_code="STRING"literals across 28 source files replaced withErrorCode.<MEMBER>. Wire format unchanged (StrEnum is a str subtype).scripts/check_error_codes.pyCI guard wired intomake checkrejects new raw literals.docs/error-codes.mddocuments semver policy (add=minor, rename/remove=major)..keboola/manifest.jsonwritten by the kbc Go CLI without overwriting it. Validates manifestproject_idagainst the alias token; rejects mismatch withConfigError(exit 5). Falls through to normal init when no manifest exists.Manifest.git_branchinggainsdefault_factoryso minimal manifests without the field parse cleanly.Resolution
Both features close FIIA gap items P2-1 and P2-2. The ErrorCode enum is a pure refactor — no wire-format change. The adopt-existing path is additive (new flag, new code path, no changes to existing init/pull behavior).
Architecture
ErrorCode(StrEnum)inerrors.py— StrEnum members arestrsubtypes so they compare equal to and serialize as plain strings everywhere.ast.walkto detecterror_codekeyword args withast.Constantstring values; skipserrors.py,tests/, and migration tooling._adopt_existing_manifest()insync_service.py— callsclient.verify_token()to get the realproject_id, compares to manifest, raisesConfigErroron mismatch, callssave_manifest()for a clean round-trip on adopt.Manifest.git_branchingdefault:default_factory=ManifestGitBranchingso kbc manifests that omit the field parse cleanly.Test plan
tests/test_errors.py::TestErrorCode— 7 tests: str equality, isinstance(str), json.dumps, no duplicates, known codes present, default uses enum, accepts enumtests/test_sync_service.py::TestAdoptExistingManifest— 5 tests: happy path, project_id mismatch, missing manifest falls through, no-flag still raises on existing, idempotent re-runtests/test_sync_cli.py::TestSyncInitAdoptExistingCli— 4 tests: flag in --help, JSON output, human output shows "Adopted", ConfigError exits 5tests/test_integration.py::TestCheckErrorCodesGuard— 3 tests: clean source passes, planted literal caught, enum usage ignoredtests/test_e2e.py::TestE2ESyncAdoptExisting— 2 tests againstconnection.europe-west3.gcp.keboola.com: adopt success + sync status works, wrong project_id rejected with exit 5make check: lint + format + error-code guard all cleanPre-PR review loop
Three parallel agents reviewed the diff before commit:
Manifest.git_branchingmissing-default was CRITICAL — fixed by addingdefault_factory=ManifestGitBranching.assert err.error_code is ErrorCode.QUEUE_JOB_FAILEDidentity check (HIGH) — fixed to==._adopt_existing_manifestpropagatesFileNotFoundErrornaturally viaload_manifest.