Skip to content

fix(publish): restore target version's DingTalk channels on rollback#74

Draft
totalfrank wants to merge 1 commit into
devfrom
claude/dingtalk-card-rollback-244tpp
Draft

fix(publish): restore target version's DingTalk channels on rollback#74
totalfrank wants to merge 1 commit into
devfrom
claude/dingtalk-card-rollback-244tpp

Conversation

@totalfrank

Copy link
Copy Markdown
Collaborator

Problem

Reported for teclaw bot 20260629_tl7vfiw7: editing the DingTalk card templateId, publishing the bot, then rolling back does not restore the previous card templateId.

Root cause

For a teclaw bot, DingTalk channel config (client_id, card_template_id, …) is not baked into the frozen build artifact. At each promotion stage the publish flow instead:

  1. Live-reads the bot's active channel rows for that stage from the DB, overlays them onto the artifact via _artifact_for_stage(...), and delivers that.
  2. Snapshots those overrides into ext["engine_overrides_by_stage"][stage] on the publish record.

The restart path (_restart_bot_async) already re-delivers using that stored snapshot — deliberately reproducing what was promoted, not a live re-fetch.

execute_rollback did not follow this: it passed the target version's config_artifact to upgrade_async raw, never overlaying engine_overrides_by_stage.online. Since the stored artifact carries only the build-time channels, rollback shipped an artifact without the target version's real online channel config, and the DB's live online row still held the newly-edited card templateId — so nothing restored the old one.

Fix

In execute_rollback, before redeploying, overlay the target version's stored online engine_overrides and re-stamp engine_ext.stage=release, mirroring the per-stage replay _restart_bot_async performs:

stored_overrides = (target_ext.get("engine_overrides_by_stage") or {}).get(
    PublishStage.ONLINE.value
)
config_artifact = self._artifact_for_stage(
    config_artifact, PublishStage.ONLINE, stored_overrides
)

Safe for existing paths:

  • ARCA (no config_artifact, migration_path only) → _artifact_for_stage returns None, no-op.
  • Pre-feature records (no engine_overrides_by_stage) → overlay no-ops, raw artifact delivered as before.
  • Teclaw with snapshot → the target's stored online channels (old card templateId) are restored.

Tests

  • Updated test_execute_rollback_with_config_artifact to use a realistic dict artifact and assert the restamped artifact is delivered.
  • Added test_execute_rollback_overlays_stored_online_channel_overrides as the regression guard: with engine_overrides_by_stage.online present, the delivered artifact carries the stored online channels (old card_template_id), not the build-time draft channels.
  • Full service_bot, channel, and endpoints suites pass (1097 tests).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Le8yEghGao6nhTR5jLL1n8


Generated by Claude Code

execute_rollback delivered the target version's frozen config_artifact
raw, without overlaying that version's stored online channel
engine_overrides. Because teclaw channel config (including
card_template_id) is snapshotted per-stage at publish and NOT baked into
the build artifact, rollback shipped the build-time channels and left the
running bot on the current (post-edit) DB channel config — so editing a
card template id, publishing, then rolling back did not restore the
previous card template id.

Overlay the target version's stored engine_overrides_by_stage.online and
re-stamp engine_ext.stage=release before redeploy, mirroring the per-stage
replay _restart_bot_async already performs. No-ops for ARCA (no
config_artifact) and pre-feature records (no stored overrides).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Le8yEghGao6nhTR5jLL1n8
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

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.

2 participants