Skip to content

fix(sync): push deletes only with --force and skips remote-deleted configs (#792 G, H) - #811

Merged
soustruh merged 2 commits into
mainfrom
fix/792-push-force-gate-remote-deleted
Sep 30, 2026
Merged

soustruh merged 2 commits into
mainfrom
fix/792-push-force-gate-remote-deleted

Conversation

@soustruh

@soustruh soustruh commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What was wrong

  • G: sync push deleted a remote config or row as soon as its local files were missing, also without --force. The --force help says that --force allows this deletion. Commit 8859949 removed the check and did not change the help.
  • H: when someone deleted a config or row on the remote after the last pull, the next push created it again under a new ID. The output did not tell the user.

What changed

  • Without --force, push deletes nothing on the remote, configs and rows alike. It lists each held-back deletion under skipped_deletions with skipped_deletions_reason, also for --dry-run. In --dry-run, summary.deleted counts only the deletions that push applies. The human output names each deletion and the fix.
  • sync diff reports a config or row as remote_deleted when the manifest fetched it from the target branch (it has a pull_hash) and it is missing on the remote. The human output shows - REMOTE DELETED, and the summary has remote_deleted. A local row under such a config is remote_deleted too. Push does not apply these changes and reports them under skipped with skipped_reason. These two keys are now in every push result, not only when the status is no_changes.
  • Push still creates configs that were never fetched from the target: a promote push from main/ into a dev branch, a placeholder entry written by hand, and a sync clone copy. sync clone now drops the pull_hash that the copied entries carry from the source project.
  • The kbagent-promotion-pipeline workflows now pass --force to the validate dry-run and to the push, because the pipeline promises that a deletion in the source reaches the destination.
  • The push output helpers moved to commands/_sync_push_render.py, because commands/sync.py is at its size limit.

Behavior changes

These changes are intended. The old behavior contradicted the --force help, and push could delete or create again a remote config without notice. kbagent usage telemetry from 2026-09-20 to 2026-09-29 shows no sync push from a GitHub-hosted runner.

  • A script or CI job that deletes remote configs by removing their directories must add --force. The kbagent-cicd-migration workflow already passes --force only when its allow_delete input is set. Before this change, push deleted also when allow_delete was off.
  • A promotion pipeline generated before this change needs --force in its validate and push steps.
  • sync diff and sync push --dry-run can return the new change type remote_deleted. sync diff marks deletions as "to delete (push --force)".

Tests

  • The G and H tests in tests/test_sync_formal_counterexamples.py are ordinary regression tests now (no xfail).
  • New tests cover --dry-run with and without --force, row deletions without --force, a locally edited config deleted on the remote, rows of a deleted config (a new local row included), --force with remote_deleted changes, the rules in the diff engine and in scope_manifest, the promotion pipeline flags and the human output.
  • The test for F used a remote-deleted config as its precondition, which push no longer creates again. It now reaches the aborted create through a promote push and still reproduces F (xfail(strict=True)).
  • make check passes.

Merge order

This PR needs #796 and #795 on main first. services/sync_service.py is frozen at 1655 code lines. On main alone this change is over that limit, and #796 and #795 make it smaller. The branch was tested on main with #796, #795, #794 and #810 merged.

Docs: gotchas.md (since vNEXT), sync-workflow.md, sync-rows-workflow.md, commands-reference.md, keboola-expert.md, the kbagent-cicd-migration and kbagent-promotion-pipeline skills, context.py, CLAUDE.md and formal/sync/README.md. No version bump, no changelog entry.

Refs #792

@keboola-pr-reviewer-bot keboola-pr-reviewer-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.

Verdict: needs_human (risk 3/5) · profile keboola-mcp-server

Well-tested sync-push safety fix, but a silent behavior change with downstream CI impact and a stated merge-order dependency warrant a human sign-off.

Concerns:

  • plugins/kbagent/skills/kbagent-cicd-migration/SKILL.md: Silent behavior change: plain push stops deleting; pre-existing CI relying on delete-without-force breaks.
  • src/keboola_agent_cli/services/sync_service.py: Declared merge-order dependency (#795/#796) and LOC-cap freeze unverifiable against main.
  • plugins/kbagent/skills/kbagent-promotion-pipeline/scripts/generate_promotion_pipeline.py: Pipelines generated before this need manual --force or source deletions no longer propagate.

@zajca zajca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Actionable findings from the automated review.

Comment thread src/keboola_agent_cli/sync/diff_engine.py
@soustruh
soustruh merged commit 04262c9 into main Sep 30, 2026
4 checks passed
@soustruh
soustruh deleted the fix/792-push-force-gate-remote-deleted branch September 30, 2026 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants