원클릭으로
find-bugs
Review newly written charm code for common charm bugs before finishing a BUILD task
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Review newly written charm code for common charm bugs before finishing a BUILD task
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Known-good Juju bundle shapes (COS Lite, 12-Factor + COS, Identity Platform, Charmed Kubeflow) — canonical app lists and relation edges
Implementing Juju actions for operational tasks in charms. WHEN: add Juju actions to a charm, implement backup / rotate-credentials / restore actions, declare actions in charmcraft.yaml, write action handlers, test actions with Scenario, run actions with juju run.
Adding and validating charm configuration options. WHEN: add charm configuration options, declare config in charmcraft.yaml, validate config values in config-changed, apply config to a Pebble layer, apply config to a machine charm, write Scenario tests for config.
End-to-end workflow for building ops-framework charms for custom applications (K8s and machine). WHEN: build a custom Juju charm, write src/charm.py with Pebble, write a machine charm with systemd, decide K8s vs machine substrate, scaffold a non-paas-charm with charmcraft init, customise the ops framework charm lifecycle.
Workflow for charming infrastructure software (databases, caches, message brokers, proxies, monitoring). WHEN: charm infrastructure software, charm a database / cache / message broker / proxy / monitoring system, implement peer relations, leader election, primary/replica failover, backup and restore actions, clustering.
Expert guidance for developing, building, testing, and publishing Juju charms using charmcraft. WHEN: edit charmcraft.yaml, run charmcraft pack, run charmcraft init, manage charm libraries, publish a charm to Charmhub, set up multi-base builds, configure relations / config options, set up storage or containers.
| name | find-bugs |
| description | Review newly written charm code for common charm bugs before finishing a BUILD task |
A bug-hunting pass over charm code you just wrote. Focused on the mistakes
that recur across charms — not a general code review. Run this alongside
security-review before declaring a BUILD task done.
charm_validate or ruff already caught —
focus on semantics, not style.Every charm must end each hook in a defined status. The common bug is a
code path that returns without updating self.unit.status or
self.app.status.
Checklist:
self.unit.status is set before each return in a hook handler.BlockedStatus is used for missing relations / bad config, not
ErrorStatus.ActiveStatus is only set when the workload is actually ready
(Pebble service running for K8s, systemd unit active for machine).MaintenanceStatus is set at the start of long operations and
cleared at the end.__init__, not in a hook handler
(observers registered at hook time fire on the next hook, not this one).self.framework.observe(self.on.install, self._on_install) inside
a method other than __init__.relation.app for None (happens briefly
during relation-broken).container.add_layer(layer_name, layer, combine=True) — combine
must be True if you're updating an existing layer.container.replan(), not container.restart()
(replan handles both first-time start and subsequent restarts).add_layer: compare the current plan to the
desired one and skip the add_layer if unchanged (avoids churn).relation.data[self.app] are guarded by
self.unit.is_leader() — non-leaders cannot write to app databag.relation.data[relation.app] handle the empty-dict case
(data not yet published).json.dumps'd. A common
bug is relation.data[self.app]['units'] = 3 (fails; must be '3').relation.data (may be gone).secret_changed, secret_rotate,
secret_expired, secret_remove) are registered if the charm uses
secrets.secret.get_content(refresh=True) is called in secret_changed,
otherwise you read stale data.owner="app" (not "unit") for secrets that survive unit churn.storage-attached / storage-detaching handlers exist if
charmcraft.yaml declares storage.self.model.storages['name'], not
hardcoded (/var/lib/mycharm).update-status exists if the charm has any state that can drift
(workload health, peer connectivity).performance skill.event.set_results(...) (not event.results = ...).event.fail(msg) is called on failure; no bare raise.event.log(msg), visible to the user running the action.event.log periodically so the user sees progress.upgrade-charm handler exists if the charm's internal state shape
can change between versions.upgrade-charm are idempotent (can re-run on
retry).upgrade-charm use combine=True so they
merge with the running layer.tracing relation present on PaaS / Path B / Path C.self._tracing = ops_tracing.Tracing(self, "<relation_name>") constructed from __init__ (after super().__init__); the relation name matches a requires: entry of interface tracing in charmcraft.yaml. The legacy ops_tracing.setup(self) shorthand is gone — flag it if seen.loki-push-api relation consumer wired up for machine charms.juju offer declared in design, not hardcoded to
same controller.except Exception: pass in a hook handler — silently swallows hook
failures and leaves the status stale.try: self.container.push(...) except ChangeError: pass — hides
Pebble failures; the user sees "active" while the workload is
misconfigured.ops.framework.UncaughtException — if you're catching the
framework's own signal, you're working around a bug rather than fixing it.asyncio, you are
probably wrong — ops already handles the event loop.threading.Thread for background work inside a hook. The hook
must complete within ~30 seconds; threads leak between hooks.[find-bugs] <N> HIGH, <M> MEDIUM, <K> LOW
HIGH: src/charm.py:87 — missing status update on config-changed error path
Evidence: the `except ValueError` branch returns without setting status,
so the unit stays in the prior status (probably Active) even though
config is invalid.
Fix: set BlockedStatus("invalid config: ...") before returning.
MEDIUM: src/charm.py:142 — relation data written without leadership check
Evidence: self.relation.data[self.app]["count"] = str(n)
Fix: guard with `if self.unit.is_leader():`.
If you find nothing:
[find-bugs] no findings
Otherwise, run it. These bugs are the ones that reach the user as "charm just went into Blocked and I don't know why".