)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"90b064d1b954dc132a10793071ad6a8446e8ceeb","unresolved":false,"context_lines":[{"line_number":1,"context_line":"Parent:     2a84b2b6 (Add NVMe device type and bump Device object to v1.4)"},{"line_number":2,"context_line":"Author:     Chandan Kumar (raukadah) \u003cchkumar@redhat.com\u003e"},{"line_number":3,"context_line":"AuthorDate: 2026-08-06 10:57:58 +0530"},{"line_number":4,"context_line":"Commit:     Chandan Kumar (raukadah) \u003cchkumar@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":16,"id":"73501a5a_f78ae15f","line":1,"updated":"2026-08-20 04:07:46.000000000","message":"The message describes the migration but never states that operators must run cyborg-dbsync upgrade before starting updated services. The immediately preceding commit in this series (2a84b2b) explicitly called out this requirement, establishing the local convention for schema-changing commits in this very change series.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Operators reading the permanent change history are not told the schema must be upgraded first; starting new services against an un-migrated DB fails on the new column.\n\n**Suggestion**:\nAdd one sentence to the commit body (before Change-Id) noting that operators must run \u0027cyborg-dbsync upgrade\u0027 before deploying services with this change, matching the phrasing in 2a84b2b.","commit_id":"e3859bcba0902de308d323f589514ebb217f00bc"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c70631c5cd726dfcc8341a282483b18053324e00","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"61b041c3_fbbd2ff1","updated":"2026-08-19 11:31:47.000000000","message":"-1 is mainly for the release note\n\nwhile almsot all bugs shoudl have a release note generally there shoudl be only one relase note for an entire feature and release ntoe shoudl eb writeen for operator and end users not developer so detail fo the db schema and internal implementaion shoudl not be inlcuded in general unless it impact end user or operators.","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"b4a246a2238906a2c906baef43115d8358fe0c81","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"9184ab0b_a6aa9270","in_reply_to":"61b041c3_fbbd2ff1","updated":"2026-08-20 03:45:36.000000000","message":"I have dropped the release notes from this patchset.","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"}],"cyborg/api/controllers/v2/devices.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5aca8bb70272f43c0450dec627eaa6c70d161f93","unresolved":false,"context_lines":[{"line_number":67,"context_line":"    status \u003d wtypes.text"},{"line_number":68,"context_line":"    \"\"\"The status of the device\"\"\""},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    device_state \u003d wtypes.text"},{"line_number":71,"context_line":"    \"\"\"The lifecycle state of the device\"\"\""},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    links \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":18,"id":"b15e3bee_e719a0e3","line":70,"updated":"2026-08-24 04:57:36.000000000","message":"The new device_state attribute is added to the v2 Device API type and serialized to every client, but unlike the analogous status field it is not gated by a microversion. MINOR_MAX_VERSION remains 3 and cyborg/api/rest_api_version_history.rst has no entry for the new field, although versions.py explicitly instructs that both be updated when adding a version.\n\n**Severity**: HIGH | **Confidence**: 0.85\n\n**Impact**: Clients pinned to microversions 2.0-2.3 receive an unexpected device_state field, which can break strict-schema consumers, and the API change is invisible to the microversion negotiation that consumers rely on.\n\n**Priority**: Before merge\n**Recommendation**:\nAdd MINOR_4_DEVICE_STATE \u003d 4, bump MINOR_MAX_VERSION, document 2.4 in cyborg/api/rest_api_version_history.rst, and hide device_state in convert_with_links for requests below 2.4, mirroring the existing status handling; cover it with a microversion functional test.","commit_id":"25185a7a0a75d8e587458fb18ee33c373f0da440"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"1b9a58ff528e0b46d5d31fb51c727de38a642829","unresolved":false,"context_lines":[{"line_number":67,"context_line":"    status \u003d wtypes.text"},{"line_number":68,"context_line":"    \"\"\"The status of the device\"\"\""},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    device_state \u003d wtypes.text"},{"line_number":71,"context_line":"    \"\"\"The lifecycle state of the device\"\"\""},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    links \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":19,"id":"216cd90e_49d23edd","line":70,"updated":"2026-08-24 05:34:43.000000000","message":"The new device_state field is serialized for every /v2/devices response regardless of the client\u0027s requested API version. Cyborg\u0027s established convention for adding device response fields is to bump the minor version, gate the field on it, and update the version history: the previous device field addition did exactly this (versions.py \u0027v2.3: Add status info for device API\u0027, and devices.py deletes \u0027status\u0027 below MINOR_3_DEVICE_STATUS). This change adds device_state with no MINOR_4 constant, no MINOR_MAX_VERSION update, no conditional gating, and no version-history entry, violating the documented rule in versions.py (\u0027When adding another version, update: MINOR_MAX_VERSION, ...version-history\u0027).\n\n**Severity**: HIGH | **Confidence**: 0.88\n\n**Impact**: Clients pinned to accelerator 2.0-2.3 receive a new response field they did not negotiate; strict schema-validating consumers can reject responses. Once merged, exposure at all microversions cannot be withdrawn, and the API version history no longer reflects what each version returns.\n\n**Priority**: Before merge\n**Recommendation**:\nAdd MINOR_4_DEVICE_STATE to versions.py, set MINOR_MAX_VERSION to it, add a version-history changelog entry, and gate the field in Device.convert_with_links the same way status is gated (\u0027if not api.request.version.minor \u003e\u003d versions.MINOR_4_DEVICE_STATE: delattr(api_device, \"device_state\")\u0027). Also consider adding a reno release note for the API-visible change and a functional assertion that the field is absent below and present at the new microversion.","commit_id":"45982384b131b061849cc9edab0f9d021b800e6f"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a77b8d56b2956c0b82ef0fd5cef0fced197434c9","unresolved":false,"context_lines":[{"line_number":67,"context_line":"    status \u003d wtypes.text"},{"line_number":68,"context_line":"    \"\"\"The status of the device\"\"\""},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    device_state \u003d wtypes.text"},{"line_number":71,"context_line":"    \"\"\"The lifecycle state of the device\"\"\""},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    links \u003d wsme.wsattr([link.Link], readonly\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":20,"id":"a682fa20_b12ca18d","line":70,"updated":"2026-08-24 06:50:32.000000000","message":"The change adds device_state to the v2 Device API response without adding a new microversion. Cyborg\u0027s v2 API is microversioned and its own convention, established for the nearly identical \u0027status\u0027 field, is to gate new response fields behind a minor version bump: Device.convert_with_links deletes \u0027status\u0027 when api.request.version.minor \u003c versions.MINOR_3_DEVICE_STATUS, and versions.py instructs contributors to bump MINOR_MAX_VERSION and add an entry to cyborg/api/rest_api_version_history.rst when adding a version. This change returns device_state unconditionally at all supported microversions (2.0-2.3), does not define a MINOR_4 constant, does not bump MINOR_MAX_VERSION, and does not update rest_api_version_history.rst.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: Clients pinned to microversion 2.0-2.3 receive a new response field they never negotiated, and the API\u0027s version discovery documents nothing about device_state. This breaks the project\u0027s own API contract for the same class of change that was version-gated as v2.3, and leaves the API docs inconsistent with actual behavior.\n\n**Suggestion**:\nAdd MINOR_4_DEVICE_STATE \u003d 4, set MINOR_MAX_VERSION to it, strip device_state in convert_with_links when the request version is below 2.4 (mirroring the status handling), and add a 2.4 entry to cyborg/api/rest_api-version-history.rst. Optionally add an assertion to cyborg/tests/unit/api/controllers/v2/test_devices.py that the field appears only at 2.4+.","commit_id":"602a47e5656c169de3b239f9e4622f3c30c6733e"}],"cyborg/db/sqlalchemy/alembic/versions/b47c8f2d1e3a_add_device_state.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"6d84f1093f18bffbf93f630847a011ebc5ebd80d","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"def upgrade():"},{"line_number":20,"context_line":"    device_state_enum \u003d sa.Enum("},{"line_number":21,"context_line":"        \u0027available\u0027,"},{"line_number":22,"context_line":"        \u0027allocated\u0027,"},{"line_number":23,"context_line":"        \u0027pending_cleaning\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"6d1e847e_5c93b673","line":20,"updated":"2026-08-15 15:37:59.000000000","message":"The Alembic migration defines the device_state enum in order available, allocated, pending_cleaning, cleaning, error, while models.py defines allocated, available, pending_cleaning, cleaning, error. The two definitions must be identical because the model metadata is used for create_schema and for...\n\n**Severity**: CRITICAL | **Confidence**: 0.9\n\n**Risk**: On MySQL, cyborg-dbsync online_data_migrations/upgrade or the model-vs-DB comparison will see the devices.device_state ENUM as different from the model definition, causing spurious diffs or failed sync; on PostgreSQL, re-running DDL that reconciles the enum (e.g. create_schema after an upgrade, o...\n\n**Priority**: Immediate\n**Why This Matters**: On MySQL, cyborg-dbsync online_data_migrations/upgrade or the model-vs-DB comparison will see the devices.device_state ENUM as different from the model definition, causing spurious diffs or failed sync; on PostgreSQL, re-running DDL that reconciles the enum (e.g. create_schema after an upgrade, o...\n\n**Recommendation**:\nMake models.py use constants.DEVICE_STATES in the Enum definition (as it already does for the type column with constants.DEVICE_TYPE) so a single source of truth feeds both the model and, ideally, the migration. At minimum, reorder the model Enum to match the migration exactly.","commit_id":"2191851f77c32ba7df17b05828c9d00fc66970e9"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"90b064d1b954dc132a10793071ad6a8446e8ceeb","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"def upgrade():"},{"line_number":20,"context_line":"    device_state_enum \u003d sa.Enum("},{"line_number":21,"context_line":"        \u0027available\u0027,"},{"line_number":22,"context_line":"        \u0027allocated\u0027,"},{"line_number":23,"context_line":"        \u0027pending_cleaning\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"c6bfaa36_0bcca27e","line":20,"updated":"2026-08-20 04:07:46.000000000","message":"The migration adds device_state via op.add_column with a new named native sa.Enum. Alembic\u0027s op.add_column issues only the ALTER TABLE ADD COLUMN DDL; it does not dispatch the table before_create events that create PostgreSQL schema types (only create_table does). The compiled statement is \u0027ALTER TABLE devices ADD COLUMN device_state device_state\u0027, referencing a type that was never created, so cyborg-dbsync upgrade aborts on PostgreSQL deployments.\n\n**Severity**: HIGH | **Confidence**: 0.85\n\n**Impact**: PostgreSQL deployments cannot complete cyborg-dbsync upgrade after installing this release, blocking the supported upgrade path for that set of deployments until the enum is created manually.\n\n**Priority**: Before merge\n**Recommendation**:\nCreate the type before adding the column: call device_state_enum.create(op.get_bind(), checkfirst\u003dTrue) before op.add_column (a no-op on MySQL/SQLite), or use postgresql.ENUM(..., name\u003d\u0027device_state\u0027) with explicit create. Optionally have _check_b47c8f2d1e3a assert the enum values so the walk test detects this class of failure.","commit_id":"e3859bcba0902de308d323f589514ebb217f00bc"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ae0f252e9a37c5a7f9572a95a0bb24b76a7b8411","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"def upgrade():"},{"line_number":20,"context_line":"    device_state_enum \u003d sa.Enum("},{"line_number":21,"context_line":"        \u0027available\u0027,"},{"line_number":22,"context_line":"        \u0027allocated\u0027,"},{"line_number":23,"context_line":"        \u0027pending_cleaning\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"0597fbc3_6f4185c1","line":20,"in_reply_to":"6700f7c0_53f5227c","updated":"2026-08-24 06:09:17.000000000","message":"Done","commit_id":"e3859bcba0902de308d323f589514ebb217f00bc"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"af638e93179265465f932fcd3ab97bd758f07b06","unresolved":true,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"def upgrade():"},{"line_number":20,"context_line":"    device_state_enum \u003d sa.Enum("},{"line_number":21,"context_line":"        \u0027available\u0027,"},{"line_number":22,"context_line":"        \u0027allocated\u0027,"},{"line_number":23,"context_line":"        \u0027pending_cleaning\u0027,"}],"source_content_type":"text/x-python","patch_set":16,"id":"6700f7c0_53f5227c","line":20,"in_reply_to":"c6bfaa36_0bcca27e","updated":"2026-08-21 14:34:03.000000000","message":"on one hand we do not support PostgreSQL anymore\n\non the other hadn  adding \n\ndevice_state_enum.create(op.get_bind(), checkfirst\u003dTrue)  is easy to make it work  now so if you respin this change lets add that","commit_id":"e3859bcba0902de308d323f589514ebb217f00bc"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5aca8bb70272f43c0450dec627eaa6c70d161f93","unresolved":false,"context_lines":[{"line_number":28,"context_line":"    device_state_enum.create(op.get_bind(), checkfirst\u003dTrue)"},{"line_number":29,"context_line":"    op.add_column("},{"line_number":30,"context_line":"        \u0027devices\u0027,"},{"line_number":31,"context_line":"        sa.Column(\u0027device_state\u0027, device_state_enum, nullable\u003dTrue),"},{"line_number":32,"context_line":"    )"}],"source_content_type":"text/x-python","patch_set":18,"id":"d3b8d16a_82807b0f","line":31,"updated":"2026-08-24 04:57:36.000000000","message":"The migration adds a nullable device_state column with no server_default or backfill, the object field has no default, and the only production path creating Device rows (DriverDevice.create, used during agent device discovery) never sets device_state. As a result DEVICE_STATE_AVAILABLE is defined but no code path ever assigns it, and consumers must treat NULL as available.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The stated lifecycle purpose is only partially realized: existing and newly discovered devices all have device_state NULL, forcing follow-up consumer code to special-case NULL as available, a second representation of the same state that can drift from the defined constant.\n\n**Suggestion**:\nSet server_default\u003d\u0027available\u0027 and backfill existing rows in the migration (and/or default the object field to DEVICE_STATE_AVAILABLE), or explicitly document that NULL means \u0027available\u0027 until the cleaning workflow lands.","commit_id":"25185a7a0a75d8e587458fb18ee33c373f0da440"}],"cyborg/db/sqlalchemy/models.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a9444c64bb32ea4205db260bc0d6c5faac33df8e","unresolved":false,"context_lines":[{"line_number":99,"context_line":"        default\u003d\u0027enabled\u0027,"},{"line_number":100,"context_line":"        nullable\u003dFalse,"},{"line_number":101,"context_line":"    )"},{"line_number":102,"context_line":"    device_state \u003d Column("},{"line_number":103,"context_line":"        Enum("},{"line_number":104,"context_line":"            \u0027available\u0027,"},{"line_number":105,"context_line":"            \u0027allocated\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"081bc688_dc7b6412","line":102,"updated":"2026-08-19 11:17:04.000000000","message":"The new device_state column in cyborg/db/sqlalchemy/models.py duplicates the five lifecycle state literals that were just defined in cyborg/common/constants.py as DEVICE_STATES. The same file already imports constants and uses constants.DEVICE_TYPE for the adjacent type column, so the project convention is to source enum domains from constants. The valid-value domain now has three independent copies (constants.py, models.py, migration), and the object layer\u0027s EnumField validates against constants while the DB layer enforces the hardcoded list.\n\n**Severity**: SUGGESTION | **Confidence**: 0.85\n\n**Impact**: When a future state is added or renamed (expected per the commit message: the cleanup workflow lands in a later release), a developer editing only constants.py will produce objects that pass the EnumField validation but fail the DB insert/update with an enum violation, and vice versa. The invariant has multiple owners that can drift.\n\n**Recommendation**:\nDeclare the column as Enum(*constants.DEVICE_STATES, name\u003d\u0027device_state\u0027) in models.py, matching the existing DEVICE_TYPE pattern. Keep the literals frozen in the Alembic migration file, which is standard practice.","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c70631c5cd726dfcc8341a282483b18053324e00","unresolved":true,"context_lines":[{"line_number":99,"context_line":"        default\u003d\u0027enabled\u0027,"},{"line_number":100,"context_line":"        nullable\u003dFalse,"},{"line_number":101,"context_line":"    )"},{"line_number":102,"context_line":"    device_state \u003d Column("},{"line_number":103,"context_line":"        Enum("},{"line_number":104,"context_line":"            \u0027available\u0027,"},{"line_number":105,"context_line":"            \u0027allocated\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"8944143c_4be56624","line":102,"in_reply_to":"081bc688_dc7b6412","updated":"2026-08-19 11:31:47.000000000","message":"ya i think that is valid\n\nwe nee to keep the constant and db column in sync so usign the constns enum to define the colume makse sense\n\nand its correct that type is already doign this\n\n```\n  type \u003d Column(\n        Enum(\n            *constants.DEVICE_TYPE,\n            name\u003d\u0027device_type\u0027,\n        ),\n        nullable\u003dFalse,\n    )\n```","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"b4a246a2238906a2c906baef43115d8358fe0c81","unresolved":false,"context_lines":[{"line_number":99,"context_line":"        default\u003d\u0027enabled\u0027,"},{"line_number":100,"context_line":"        nullable\u003dFalse,"},{"line_number":101,"context_line":"    )"},{"line_number":102,"context_line":"    device_state \u003d Column("},{"line_number":103,"context_line":"        Enum("},{"line_number":104,"context_line":"            \u0027available\u0027,"},{"line_number":105,"context_line":"            \u0027allocated\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"c53b4648_18a1a68c","line":102,"in_reply_to":"8944143c_4be56624","updated":"2026-08-20 03:45:36.000000000","message":"Done","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"}],"cyborg/objects/device.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"776a845eec2fd719f49fbe0f90304fa8a266ca8c","unresolved":true,"context_lines":[{"line_number":38,"context_line":"    fields \u003d {"},{"line_number":39,"context_line":"        \u0027id\u0027: object_fields.IntegerField(nullable\u003dFalse),"},{"line_number":40,"context_line":"        \u0027uuid\u0027: object_fields.UUIDField(nullable\u003dFalse),"},{"line_number":41,"context_line":"        \u0027type\u0027: object_fields.EnumField("},{"line_number":42,"context_line":"            valid_values\u003dconstants.DEVICE_TYPE, nullable\u003dFalse"},{"line_number":43,"context_line":"        ),"},{"line_number":44,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"},{"line_number":45,"context_line":"        \u0027model\u0027: object_fields.StringField(nullable\u003dFalse),"},{"line_number":46,"context_line":"        \u0027std_board_info\u0027: object_fields.StringField(nullable\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":11,"id":"637d07a7_a8b42476","line":43,"range":{"start_line":41,"start_character":3,"end_line":43,"end_character":10},"updated":"2026-08-18 11:32:33.000000000","message":"actully when we extended this we should have bumped the version\n\nand for the addtion of a new value rather then a new filed we rasie an exepction if you use a value that was intoduced in a new version instead of feleting ro poping it\n\nwe shoudl fix that first.\n\n1.3 should be the addtion of PCI/MDEV types\n1.4 shoudl be the addtion of nvme\n1.5 the addtion fo device_states\n\ncan you put a patch at the start of the serise for pci/mdev\nand update the parent of this chagne for NVME and update this to 1.5\n\nhere is an example\nhttps://github.com/openstack/nova/blob/master/nova/objects/image_meta.py#L277-L285\n\nwe do this enough in nova that we have a littel helper function for this\n\nhttps://github.com/openstack/nova/blob/master/nova/objects/base.py#L62-L69","commit_id":"3ef64188b79d6b4d6a44087487a4558f51ac4103"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"248efa8af3765efa5ddbc767be41dabd6f58fd18","unresolved":true,"context_lines":[{"line_number":38,"context_line":"    fields \u003d {"},{"line_number":39,"context_line":"        \u0027id\u0027: object_fields.IntegerField(nullable\u003dFalse),"},{"line_number":40,"context_line":"        \u0027uuid\u0027: object_fields.UUIDField(nullable\u003dFalse),"},{"line_number":41,"context_line":"        \u0027type\u0027: object_fields.EnumField("},{"line_number":42,"context_line":"            valid_values\u003dconstants.DEVICE_TYPE, nullable\u003dFalse"},{"line_number":43,"context_line":"        ),"},{"line_number":44,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"},{"line_number":45,"context_line":"        \u0027model\u0027: object_fields.StringField(nullable\u003dFalse),"},{"line_number":46,"context_line":"        \u0027std_board_info\u0027: object_fields.StringField(nullable\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":11,"id":"89d9a955_cbde6e3d","line":43,"range":{"start_line":41,"start_character":3,"end_line":43,"end_character":10},"in_reply_to":"637d07a7_a8b42476","updated":"2026-08-19 09:46:41.000000000","message":"Yes, correct, We need to add version bump info. \n\nBased on above suggestion here is what I have done and chained in order:\n1. [Bump Device object to v1.3 for MDEV and PCI type support](https://review.opendev.org/c/openstack/cyborg/+/1001474)\n  _ I have reused raise_on_too_new_values() helper function from nova for new fields additions\n  \n2. [Add NVME device type and bump Device object to v1.4](https://review.opendev.org/c/openstack/cyborg/+/999932)\n\n3. [Add device_state lifecycle field to the Device object](https://review.opendev.org/c/openstack/cyborg/+/999933)\n\nDo let me know if I missed anything here.","commit_id":"3ef64188b79d6b4d6a44087487a4558f51ac4103"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c70631c5cd726dfcc8341a282483b18053324e00","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    fields \u003d {"},{"line_number":39,"context_line":"        \u0027id\u0027: object_fields.IntegerField(nullable\u003dFalse),"},{"line_number":40,"context_line":"        \u0027uuid\u0027: object_fields.UUIDField(nullable\u003dFalse),"},{"line_number":41,"context_line":"        \u0027type\u0027: object_fields.EnumField("},{"line_number":42,"context_line":"            valid_values\u003dconstants.DEVICE_TYPE, nullable\u003dFalse"},{"line_number":43,"context_line":"        ),"},{"line_number":44,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"},{"line_number":45,"context_line":"        \u0027model\u0027: object_fields.StringField(nullable\u003dFalse),"},{"line_number":46,"context_line":"        \u0027std_board_info\u0027: object_fields.StringField(nullable\u003dTrue),"}],"source_content_type":"text/x-python","patch_set":11,"id":"a57faa6b_b7179f19","line":43,"range":{"start_line":41,"start_character":3,"end_line":43,"end_character":10},"in_reply_to":"89d9a955_cbde6e3d","updated":"2026-08-19 11:31:47.000000000","message":"in the first patch we shoudl have added the comnpat funciton for 1.1 and 1.2 as well but other wise it looked fine commeits in line in the relevnet commit","commit_id":"3ef64188b79d6b4d6a44087487a4558f51ac4103"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c70631c5cd726dfcc8341a282483b18053324e00","unresolved":true,"context_lines":[{"line_number":81,"context_line":"                (constants.DEVICE_NVME,),"},{"line_number":82,"context_line":"            )"},{"line_number":83,"context_line":"        if target_version \u003c (1, 5) and \u0027device_state\u0027 in primitive:"},{"line_number":84,"context_line":"            del primitive[\u0027device_state\u0027]"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    def create(self, context):"},{"line_number":87,"context_line":"        \"\"\"Create a device record in the DB.\"\"\""}],"source_content_type":"text/x-python","patch_set":14,"id":"ff318d53_f7b74a0e","line":84,"updated":"2026-08-19 11:31:47.000000000","message":"as noted in the prior patch we make object compatbale by going newset to oldes to we need to flip the order\n\n\nthis is for case where we rename files you want the new migration to backfill the old name and then the valition of the old files to continue to work","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"b4a246a2238906a2c906baef43115d8358fe0c81","unresolved":false,"context_lines":[{"line_number":81,"context_line":"                (constants.DEVICE_NVME,),"},{"line_number":82,"context_line":"            )"},{"line_number":83,"context_line":"        if target_version \u003c (1, 5) and \u0027device_state\u0027 in primitive:"},{"line_number":84,"context_line":"            del primitive[\u0027device_state\u0027]"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    def create(self, context):"},{"line_number":87,"context_line":"        \"\"\"Create a device record in the DB.\"\"\""}],"source_content_type":"text/x-python","patch_set":14,"id":"c3078f40_019d3aa4","line":84,"in_reply_to":"ff318d53_f7b74a0e","updated":"2026-08-20 03:45:36.000000000","message":"Acknowledged","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"44b88f89ba9e86746f9a7492c091014a61e957b1","unresolved":true,"context_lines":[{"line_number":33,"context_line":"    # Version 1.3: Add MDEV, PCI type"},{"line_number":34,"context_line":"    # Version 1.4: Add NVME type"},{"line_number":35,"context_line":"    # Version 1.5: Add device_state field"},{"line_number":36,"context_line":"    VERSION \u003d \u00271.5\u0027"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    dbapi \u003d dbapi.get_instance()"},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"cfc8d08c_97b9399a","line":36,"updated":"2026-08-21 18:02:48.000000000","message":"and aigain we need to update DriverDevice\n\nuntile we consoldiat them into one class","commit_id":"e3859bcba0902de308d323f589514ebb217f00bc"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"aa87104e15efb17ad721a969dfeb137983371dff","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    # Version 1.3: Add MDEV, PCI type"},{"line_number":34,"context_line":"    # Version 1.4: Add NVME type"},{"line_number":35,"context_line":"    # Version 1.5: Add device_state field"},{"line_number":36,"context_line":"    VERSION \u003d \u00271.5\u0027"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    dbapi \u003d dbapi.get_instance()"},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"61a715e3_57a097c6","line":36,"in_reply_to":"cfc8d08c_97b9399a","updated":"2026-08-24 06:08:42.000000000","message":"Done","commit_id":"e3859bcba0902de308d323f589514ebb217f00bc"}],"cyborg/objects/driver_objects/driver_device.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5aca8bb70272f43c0450dec627eaa6c70d161f93","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    # Version 1.2: Add MDEV, PCI type"},{"line_number":38,"context_line":"    # Version 1.3: Add NVMe type"},{"line_number":39,"context_line":"    # Version 1.4: Add device_state field"},{"line_number":40,"context_line":"    VERSION \u003d \u00271.4\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    fields \u003d {"},{"line_number":43,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":18,"id":"fa07caf9_75232b52","line":40,"updated":"2026-08-24 04:57:36.000000000","message":"DriverDevice\u0027s version history comment claims \u0027Version 1.4: Add device_state field\u0027 and the commit message says \u0027Bumped DriverDevice for device_state to 1.4\u0027, but no device_state field exists in DriverDevice.fields and create() does not copy any state into the Device object it creates. The class\u0027s own NOTE states fields absent from DriverDevice are DB-only.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: The permanent version history records a nonexistent field, misleading future maintainers, and drivers have no way to report a lifecycle state through the agent path; either the intended field/propagation is missing or the bump should not exist.\n\n**Suggestion**:\nEither add a device_state field to DriverDevice and propagate it in create(), or revert the 1.4 bump and comment until drivers actually report the state.","commit_id":"25185a7a0a75d8e587458fb18ee33c373f0da440"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"1b9a58ff528e0b46d5d31fb51c727de38a642829","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    # Version 1.1: Add AICHIP type"},{"line_number":37,"context_line":"    # Version 1.2: Add MDEV, PCI type"},{"line_number":38,"context_line":"    # Version 1.3: Add NVMe type"},{"line_number":39,"context_line":"    # Version 1.4: Add device_state field"},{"line_number":40,"context_line":"    VERSION \u003d \u00271.4\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    fields \u003d {"}],"source_content_type":"text/x-python","patch_set":19,"id":"d16ae43d_17cf241e","line":39,"updated":"2026-08-24 05:34:43.000000000","message":"The commit message states \u0027Bumped DriverDevice for device_state to 1.4\u0027 and the new version-history comment says \u0027Version 1.4: Add device_state field\u0027, but the DriverDevice fields dict contains no \u0027device_state\u0027 entry. Device added the field at v1.5, but the driver-side mirror object cannot carry it: DriverDevice.list() builds objects from Device without device_state, and DriverDevice.create() drops the attribute when persisting a Device. As a result the object version history claims a field that does not exist, and the stated mechanism for drivers/conductor to observe and report device lifecycle state (the stated purpose: \u0027NVMe devices require a lifecycle state to coordinate secure cleanup\u0027) is not wired through the driver object path.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Impact**: Drivers and the conductor RPC path can never carry device_state, so the lifecycle coordination this change claims to enable cannot work end-to-end. The object version history is permanently wrong: 1.4 advertises a field that does not exist, which misleads future backport handling (obj_make_compatible decisions) and any consumer reasoning about the 1.4 contract.\n\n**Priority**: Before merge\n**Recommendation**:\nEither add \u0027device_state\u0027 as an EnumField(valid_values\u003dconstants.DEVICE_STATES, nullable\u003dTrue) to DriverDevice, propagate it in DriverDevice.list() and create(), and add an obj_make_compatible guard dropping it below 1.4; or revert the VERSION bump, the \u0027Version 1.4: Add device_state field\u0027 comment, and the commit-message claim. Do not merge a version bump that describes a field the object does not have.","commit_id":"45982384b131b061849cc9edab0f9d021b800e6f"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a77b8d56b2956c0b82ef0fd5cef0fced197434c9","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    # Version 1.1: Add AICHIP type"},{"line_number":37,"context_line":"    # Version 1.2: Add MDEV, PCI type"},{"line_number":38,"context_line":"    # Version 1.3: Add NVMe type"},{"line_number":39,"context_line":"    # Version 1.4: Add device_state field"},{"line_number":40,"context_line":"    VERSION \u003d \u00271.4\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    fields \u003d {"}],"source_content_type":"text/x-python","patch_set":20,"id":"af38ca6b_69367c0e","line":39,"updated":"2026-08-24 06:50:32.000000000","message":"DriverDevice.VERSION is bumped from 1.3 to 1.4 with the history comment \u0027Version 1.4: Add device_state field\u0027, and the commit message states \u0027Bumped DriverDevice for device_state to 1.4\u0027. However, no device_state field is added to DriverDevice.fields, and DriverDevice.create() builds the DB-side Device without propagating any device_state. The version history now records a field that does not exist in the object.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Versioned-object history is the contract used for RPC backports between conductor and agent services; an entry claiming a field that was never added makes the recorded history wrong. Drivers also cannot report a lifecycle state through DriverDevice, so the intent stated in the commit message is unimplemented. When device_state is actually added, another bump is required or the history silently diverges, which is exactly the drift the preceding commits (Device v1.3/1.4 history repairs) were written to fix.\n\n**Suggestion**:\nEither add \u0027device_state\u0027: object_fields.EnumField(valid_values\u003dconstants.DEVICE_STATES, nullable\u003dTrue) to DriverDevice.fields (and propagate it in create() if drivers should report it), or revert the VERSION bump and history comment until a follow-up patch actually adds the field.","commit_id":"602a47e5656c169de3b239f9e4622f3c30c6733e"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"e45bf73535c4334342ce244bd63fa281e169c28f","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    # Version 1.2: Add MDEV, PCI type"},{"line_number":38,"context_line":"    # Version 1.3: Add NVMe type"},{"line_number":39,"context_line":"    # Version 1.4: Add device_state field"},{"line_number":40,"context_line":"    VERSION \u003d \u00271.4\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    fields \u003d {"},{"line_number":43,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":21,"id":"35e77cb4_04a2f0a9","line":40,"updated":"2026-08-24 07:40:31.000000000","message":"The change bumps DriverDevice VERSION from 1.3 to 1.4 with the comment \u0027Version 1.4: Add device_state field\u0027 (and the commit message states \u0027Bumped DriverDevice for device_state to 1.4\u0027), but no \u0027device_state\u0027 entry was added to DriverDevice.fields, no obj_make_compatible handling was added, and neither create() nor list() propagates device_state to/from the Device object. The version bump is an empty schema change: remote consumers backporting to 1.3 have nothing new to handle, while the bumped version claims a field that does not exist on the object.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Consumers of the DriverDevice version number receive a version advertising a device_state field that is never populated; code written against v1.4 expecting the field will hit AttributeError. If the field is later actually added, it needs another bump (1.5), or it gets squeezed into a version that already shipped claiming it existed.\n\n**Suggestion**:\nEither add device_state to DriverDevice.fields (nullable EnumField over constants.DEVICE_STATES), populate it in create()/list(), and add obj_make_compatible handling to pop it below 1.4; or revert VERSION to 1.3 and drop the \u0027Version 1.4\u0027 comment if device_state is intended to be DB-only like id/uuid/hostname/status.","commit_id":"70ab2196766751b253a413640cd976b408e5fa52"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"6d86dcd2dcef656401c94f20162c46f240762ac6","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    # Version 1.2: Add MDEV, PCI type"},{"line_number":38,"context_line":"    # Version 1.3: Add NVMe type"},{"line_number":39,"context_line":"    # Version 1.4: Add device_state field"},{"line_number":40,"context_line":"    VERSION \u003d \u00271.4\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    fields \u003d {"},{"line_number":43,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":21,"id":"41dcb442_2400d9ea","line":40,"in_reply_to":"2398186c_17373d15","updated":"2026-08-31 07:01:50.000000000","message":"Done.\n\nAdded device_state to DriverDevice.fields (nullable EnumField over constants.DEVICE_STATES), populate it in create()/list(), and add obj_make_compatible handling to pop it below 1.4;","commit_id":"70ab2196766751b253a413640cd976b408e5fa52"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9bde10012e31106fad8396e6d2b0e91794331a2a","unresolved":true,"context_lines":[{"line_number":37,"context_line":"    # Version 1.2: Add MDEV, PCI type"},{"line_number":38,"context_line":"    # Version 1.3: Add NVMe type"},{"line_number":39,"context_line":"    # Version 1.4: Add device_state field"},{"line_number":40,"context_line":"    VERSION \u003d \u00271.4\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    fields \u003d {"},{"line_number":43,"context_line":"        \u0027vendor\u0027: object_fields.StringField(nullable\u003dFalse),"}],"source_content_type":"text/x-python","patch_set":21,"id":"2398186c_17373d15","line":40,"in_reply_to":"35e77cb4_04a2f0a9","updated":"2026-08-26 19:32:30.000000000","message":"valid it was added in the non driver device and missed here","commit_id":"70ab2196766751b253a413640cd976b408e5fa52"}],"cyborg/tests/unit/db/test_migrations.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"8939a2dcde507bf17614da1b7a9dd8f0e6b5c151","unresolved":false,"context_lines":[{"line_number":126,"context_line":"        type_enum \u003d devices.c.type.type"},{"line_number":127,"context_line":"        self.assertIn(\u0027NVME\u0027, type_enum.enums)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    def _check_b47c8f2d1e3a(self, engine, data):"},{"line_number":130,"context_line":"        devices \u003d db_utils.get_table(engine, \u0027devices\u0027)"},{"line_number":131,"context_line":"        col_names \u003d [column.name for column in devices.c]"},{"line_number":132,"context_line":"        self.assertIn(\u0027device_state\u0027, col_names)"}],"source_content_type":"text/x-python","patch_set":8,"id":"0b9a75c8_acb36870","line":129,"updated":"2026-08-12 07:46:51.000000000","message":"The _check_b47c8f2d1e3a migration test checks column existence and Enum type but does not verify the specific enum values (available, allocated, pending_cleaning, cleaning, error), unlike the immediately preceding _check_a35b4295a0e5 test which verifies \u0027NVME\u0027 is in the type enum.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: If a typo or missing enum value is introduced in the Alembic migration, the test would still pass because it only verifies the column is an Enum type, not that the correct values are defined. This reduces the effectiveness of migration testing as a safety net.\n\n**Recommendation**:\nAdd assertions to verify the enum values match the expected set, similar to _check_a35b4295a0e5. For example: `enum_type \u003d devices.c.device_state.type; self.assertIn(\u0027available\u0027, enum_type.enums); self.assertIn(\u0027error\u0027, enum_type.enums)` or assert the full list of expected values.","commit_id":"c0d3840583b88aba82dbf2b72aa5e30c8f29ff37"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"6d84f1093f18bffbf93f630847a011ebc5ebd80d","unresolved":false,"context_lines":[{"line_number":326,"context_line":"        type_enum \u003d devices.c.type.type"},{"line_number":327,"context_line":"        self.assertIn(\u0027NVME\u0027, type_enum.enums)"},{"line_number":328,"context_line":""},{"line_number":329,"context_line":"    def _check_b47c8f2d1e3a(self, engine, data):"},{"line_number":330,"context_line":"        devices \u003d db_utils.get_table(engine, \u0027devices\u0027)"},{"line_number":331,"context_line":"        col_names \u003d [column.name for column in devices.c]"},{"line_number":332,"context_line":"        self.assertIn(\u0027device_state\u0027, col_names)"}],"source_content_type":"text/x-python","patch_set":10,"id":"9b8822c5_d2d0f1f5","line":329,"updated":"2026-08-15 15:37:59.000000000","message":"The new _check_b47c8f2d1e3a only asserts the column exists and is an Enum type; it never checks the allowed values. Combined with the value-order mismatch between the migration and models.py (CF-001), the test cannot catch enum divergence, including on MySQL where the test class runs.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: A schema drift between the migration and the model enum (present in this very patch) passes the migration tests, so future contributors lose the safety net that catches value-list regressions on MySQL and PostgreSQL.\n\n**Suggestion**:\nExtend the check to assert the expected value set, e.g. self.assertEqual({\u0027available\u0027,\u0027allocated\u0027,\u0027pending_cleaning\u0027,\u0027cleaning\u0027,\u0027error\u0027}, set(devices.c.device_state.type.enums)), mirroring _check_9625668549b5.","commit_id":"2191851f77c32ba7df17b05828c9d00fc66970e9"}],"cyborg/tests/unit/objects/test_device.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"2eab6a3e48012f7bd0545f75c3c53582b99fceeb","unresolved":false,"context_lines":[{"line_number":167,"context_line":"            ValueError, objects.Device, self.context, type\u003d\u0027OTHER_TYPE\u0027"},{"line_number":168,"context_line":"        )"},{"line_number":169,"context_line":""},{"line_number":170,"context_line":"    def test_supports_cleaning_nvme(self):"},{"line_number":171,"context_line":"        device \u003d objects.Device(self.context, type\u003d\u0027NVME\u0027)"},{"line_number":172,"context_line":"        self.assertTrue(device.supports_cleaning)"},{"line_number":173,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"757e71d4_661f4e95","line":170,"updated":"2026-08-06 16:03:33.000000000","message":"The existing test_device_type method verifies that constructing a Device with an invalid type raises ValueError. There is no equivalent test verifying that an invalid device_state value is rejected by the EnumField. Adding this test would close a testing gap consistent with the existing pattern.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Without this test, a future change that accidentally weakens the device_state EnumField validation could go unnoticed.\n\n**Recommendation**:\nAdd a test that constructs a Device with an invalid device_state (e.g., device_state\u003d\u0027invalid\u0027) and asserts ValueError is raised, mirroring the test_device_type pattern.","commit_id":"06cec519c1232c437994fb75670d52bc7060fa64"}],"releasenotes/notes/add-device-state-column-1a2b3c4d5e6f.yaml":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"8c9dc404b4f92364397f5a8dd06fe455d35946a5","unresolved":false,"context_lines":[{"line_number":2,"context_line":"upgrade:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    VARCHAR) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. The column is"},{"line_number":8,"context_line":"    populated automatically when a device transitions through the cleanup"}],"source_content_type":"text/x-yaml","patch_set":5,"id":"6cc29049_68f5a66f","line":5,"updated":"2026-08-07 06:07:17.000000000","message":"The release note states the new device_state column is a \"nullable VARCHAR\" but the Alembic migration and SQLAlchemy model both define it as a SQL Enum type with five valid values. This factual error could mislead operators performing schema introspection, writing manual queries, or planning data...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators reading the release note may expect a VARCHAR column and write application code or SQL queries assuming string storage, when the actual column is an Enum. On PostgreSQL this means a dedicated enum type; on MySQL it is a native ENUM. Schema introspection tools will report different types...\n\n**Suggestion**:\nReplace \u0027nullable VARCHAR\u0027 with \u0027nullable Enum\u0027 or \u0027nullable ENUM with values available, allocated, pending_cleaning, cleaning, and error\u0027 in the release note to accurately reflect the SQL type created by the migration.","commit_id":"b41d5805ad5e093019659dd3cc14d4c754787759"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"ff9b5933aa5773b2a474617507e60557d4a8e3c3","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"upgrade:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    VARCHAR) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. The column is"}],"source_content_type":"text/x-yaml","patch_set":6,"id":"76fe7004_4cfa03e8","line":4,"updated":"2026-08-09 04:28:38.000000000","message":"The release note states the device_state column is a \u0027nullable VARCHAR\u0027, but the Alembic migration and SQLAlchemy model both define it as a sa.Enum type. This factual error could mislead operators about the column\u0027s constraints.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators reading the release note would expect a free-form VARCHAR column and may attempt to insert arbitrary string values, which would fail against the Enum constraint. This could cause confusion during upgrade planning and testing.\n\n**Suggestion**:\nReplace \u0027nullable VARCHAR\u0027 with \u0027nullable ENUM\u0027 in the release note so the column type description matches the actual database schema.","commit_id":"701b1fb1d1bd45ba25f9e78435c34bdf701aef25"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"7a80868f2f390fc77445882e033fd9d95a14fc1b","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    ENUM) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. The column is"},{"line_number":8,"context_line":"    populated automatically when a device transitions through the cleanup"},{"line_number":9,"context_line":"    workflow; existing rows default to ``NULL`` (treated as available)."},{"line_number":10,"context_line":"    Run ``cyborg-dbsync upgrade`` to apply the schema change."}],"source_content_type":"text/x-yaml","patch_set":7,"id":"47f97358_1d1ae5aa","line":7,"updated":"2026-08-11 08:46:53.000000000","message":"The release note states that device_state is \u0027populated automatically when a device transitions through the cleanup workflow\u0027 and that NULL is \u0027treated as available\u0027. No code in this patch implements a cleanup workflow, automatically populates the column, or interprets NULL as available. This is...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators reading the release note will expect an automated cleanup workflow and NULL-as-available semantics after running cyborg-dbsync upgrade, but no such behavior exists. This could lead to confusion during deployment planning or incorrect assumptions about operational state.\n\n**Suggestion**:\nRevise the release note to describe only what this patch delivers: a nullable ENUM column and a versioned-object field. Either remove the claims about automatic population and NULL semantics, or rephrase them as forward-looking statements (e.g., \u0027Future patches will implement the cleanup workflow that populates this column\u0027).","commit_id":"7671436166f0cc2a243b71b06f7507c2d69b090b"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"e26abfed4aa68f0f9d5dffeecdb59c469440bd98","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    ENUM) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. The column is"},{"line_number":8,"context_line":"    populated automatically when a device transitions through the cleanup"},{"line_number":9,"context_line":"    workflow; existing rows default to ``NULL`` (treated as available)."},{"line_number":10,"context_line":"    Run ``cyborg-dbsync upgrade`` to apply the schema change."}],"source_content_type":"text/x-yaml","patch_set":9,"id":"756c18f3_391dd9b3","line":7,"updated":"2026-08-13 04:02:03.000000000","message":"The release note states \u0027The column is populated automatically when a device transitions through the cleanup workflow.\u0027 However, no cleanup workflow code exists anywhere in the codebase that sets or transitions device_state. This is misleading for operators upgrading to this release, as the colum...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators reading the release note will expect automatic state management that does not exist. This could lead to confusion during upgrades and operational planning.\n\n**Suggestion**:\nEither revise the release note to state that the column is added as infrastructure for a future cleanup workflow, or include the code that implements the cleanup workflow transitions in this patch.","commit_id":"f400e864aaba9408fa97cacb0f7c740934ebb51b"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"6d84f1093f18bffbf93f630847a011ebc5ebd80d","unresolved":false,"context_lines":[{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    ENUM) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. The column is"},{"line_number":8,"context_line":"    populated automatically when a device transitions through the cleanup"},{"line_number":9,"context_line":"    workflow; existing rows default to ``NULL`` (treated as available)."},{"line_number":10,"context_line":"    Run ``cyborg-dbsync upgrade`` to apply the schema change."}],"source_content_type":"text/x-yaml","patch_set":10,"id":"6ad546d2_a4aff753","line":7,"updated":"2026-08-15 15:37:59.000000000","message":"The reno note says the column \u0027is populated automatically when a device transitions through the cleanup workflow\u0027, but no such workflow is introduced in this change or exists anywhere in the cyborg tree. The field is a write-optional nullable column that nothing currently sets.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators reading the release notes will expect automatic lifecycle tracking after upgrade and will not know the column stays NULL until a follow-up patch lands, which can cause incorrect operational assumptions and support noise during upgrades.\n\n**Suggestion**:\nReword the note to state that the column is added as nullable and currently unused, and that lifecycle transitions will be implemented in a follow-up change. Alternatively, if a workflow patch is part of the same series, reference the series explicitly rather than claiming automatic population now.","commit_id":"2191851f77c32ba7df17b05828c9d00fc66970e9"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"30e70b39ba44e01dfe763d4c59958e360390b1cf","unresolved":false,"context_lines":[{"line_number":2,"context_line":"upgrade:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    ENUM) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. The column is"},{"line_number":8,"context_line":"    populated automatically when a device transitions through the cleanup"}],"source_content_type":"text/x-yaml","patch_set":12,"id":"0a4d80cb_d7a1dd98","line":5,"updated":"2026-08-19 10:04:01.000000000","message":"The reno note states \u0027The column is populated automatically when a device transitions through the cleanup workflow; existing rows default to NULL (treated as available).\u0027 No such cleanup workflow exists in this change or anywhere in the tree: nothing outside the new column definition, constants, object field, and tests reads or writes device_state, and the only logic referencing cleaning is the supports_cleaning property, which is a read-only predicate. The column will remain NULL for all devices until a future change implements the workflow.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators reading the released note will expect device_state to be maintained automatically after the upgrade and may rely on it for monitoring or automation; in reality the column stays NULL indefinitely, producing misleading operational expectations.\n\n**Suggestion**:\nReword the note to state that the column is added but not yet populated, and that transitions will be written by a future release that implements the cleaning workflow; alternatively remove the \u0027populated automatically\u0027 sentence until that workflow lands.","commit_id":"948c8cee02c65b289ae45a9ceda1882680479b0d"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"30e70b39ba44e01dfe763d4c59958e360390b1cf","unresolved":false,"context_lines":[{"line_number":8,"context_line":"    populated automatically when a device transitions through the cleanup"},{"line_number":9,"context_line":"    workflow; existing rows default to ``NULL`` (treated as available)."},{"line_number":10,"context_line":"    Run ``cyborg-dbsync upgrade`` to apply the schema change."},{"line_number":11,"context_line":"  - |"},{"line_number":12,"context_line":"    The ``Device`` versioned object has been bumped from version 1.2 to"},{"line_number":13,"context_line":"    1.3 to expose the new ``device_state`` field. Mixed-version"},{"line_number":14,"context_line":"    deployments (conductor at 1.3, agent at 1.2) are supported: the"}],"source_content_type":"text/x-yaml","patch_set":12,"id":"09f04ea9_7473c0e9","line":11,"updated":"2026-08-19 10:04:01.000000000","message":"The reno upgrade note says the Device versioned object \u0027has been bumped from version 1.2 to 1.3 to expose the new device_state field\u0027 and gives a mixed-version example of \u0027conductor at 1.3, agent at 1.2\u0027. The code actually bumps VERSION from \u00271.4\u0027 to \u00271.5\u0027 (cyborg/objects/device.py:36), and the commit message itself states \u0027bump it to v1.5\u0027. Before this change the object was already at 1.4 (added in commit 7dfcd58, NVME type).\n\n**Severity**: WARNING | **Confidence**: 0.97\n\n**Impact**: Operators and developers reading the shipped release notes get incorrect version numbers, which misleads anyone reasoning about RPC/object compatibility pinning (e.g. pinning conductors to 1.3 thinking that includes device_state, when 1.3 predates even the NVME type). Release notes are permanent documentation and are not corrected by later code changes.\n\n**Suggestion**:\nUpdate the second note entry to say the Device object is bumped from 1.4 to 1.5, and fix the mixed-version example (e.g. conductor at 1.5, agent at 1.4).","commit_id":"948c8cee02c65b289ae45a9ceda1882680479b0d"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"028f97a3e3bfd38a1eab187f1ddb4e2c12d897d0","unresolved":false,"context_lines":[{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. Existing rows"},{"line_number":8,"context_line":"    default to ``NULL`` (treated as available). A future release will"},{"line_number":9,"context_line":"    implement the cleanup workflow to populate this column as devices"},{"line_number":10,"context_line":"    transition through their lifecycle. Run ``cyborg-dbsync upgrade``"},{"line_number":11,"context_line":"    to apply the schema change, then ``cyborg-dbsync online_data_migrations``"},{"line_number":12,"context_line":"    to backfill the initial state for existing devices."},{"line_number":13,"context_line":"  - |"}],"source_content_type":"text/x-yaml","patch_set":13,"id":"af737741_0ca192a1","line":10,"updated":"2026-08-19 10:59:38.000000000","message":"The reno upgrade note instructs operators to run \u0027cyborg-dbsync online_data_migrations to backfill the initial state for existing devices\u0027. The online_data_migrations command (cyborg/cmd/dbsync.py) only invokes data_migrations.heal_arq_project_ids(); this change registers no device_state backfill migration, and the note itself states a future release will implement the workflow that populates the column. The note also claims existing NULL rows are \u0027treated as available\u0027, but no code in this change (or the tree) interprets NULL that way.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: Operators performing the documented upgrade procedure run online_data_migrations expecting a device_state backfill; the command reports \u0027Migrated 0 ARQ(s)\u0027 and performs no backfill, causing confusion and possibly skipped/duplicated upgrade steps. Readers may also rely on the unimplemented claim that NULL is treated as available when planning deployment behavior.\n\n**Suggestion**:\nRemove or correct the online_data_migrations instruction: either drop the sentence, or state that no data migration is required in this release because the column is nullable and remains NULL until the future cleanup workflow lands. Reword \u0027treated as available\u0027 to describe the future, not current, behavior.","commit_id":"db9bee572b465c35e6e9fdf812f175857ce7f395"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c70631c5cd726dfcc8341a282483b18053324e00","unresolved":true,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"upgrade:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    ENUM) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. Existing rows"},{"line_number":8,"context_line":"    default to ``NULL``. A future release will implement the cleanup"}],"source_content_type":"text/x-yaml","patch_set":14,"id":"e7227a10_587fa5be","line":5,"range":{"start_line":4,"start_character":1,"end_line":5,"end_character":9},"updated":"2026-08-19 11:31:47.000000000","message":"```suggestion\n    The ``devices`` table has a new ``device_state`` column (nullable ENUM)\n    that tracks the lifecycle state of devices that support\n```\ni feel like this is overly wraped.\n\n\nbut again this does not feel correct to incldue in the release notes in general\n\nthe upgrade section is for calling out actions an operato need to take when upgrading beyond basi db migration, i.e. if we remvoed a config option and then need to update there config.\n\ni dont hink this shoudl have its own relesae note","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"b4a246a2238906a2c906baef43115d8358fe0c81","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"upgrade:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    The ``devices`` table has a new ``device_state`` column (nullable"},{"line_number":5,"context_line":"    ENUM) that tracks the lifecycle state of devices that support"},{"line_number":6,"context_line":"    secure cleanup. Valid states are ``available``, ``allocated``,"},{"line_number":7,"context_line":"    ``pending_cleaning``, ``cleaning``, and ``error``. Existing rows"},{"line_number":8,"context_line":"    default to ``NULL``. A future release will implement the cleanup"}],"source_content_type":"text/x-yaml","patch_set":14,"id":"d5a8f205_a51279b8","line":5,"range":{"start_line":4,"start_character":1,"end_line":5,"end_character":9},"in_reply_to":"e7227a10_587fa5be","updated":"2026-08-20 03:45:36.000000000","message":"Dropping the release notes in favor of future single release note for nvme generic driver.","commit_id":"275b70b074fd71448d23afb3f7dbe4ab84bcdb62"}]}
