all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fe4e:cf95
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 3c29cddb-ba55-47dd-9651-81ea5af22aff
        host_id: 4ba4344415ca7057d9956ea5de826bbc0b830981e82c0e0f191fa07b
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fe4e:cf95
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.50
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.192.179
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fe4e:cf95
        region: null
        slot: null
  vars:
    zuul:
      _inheritance_path:
      - '<Job base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-config/zuul.d/jobs.yaml@main#2>'
      - '<Job mypy explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-jobs/.zuul.yaml@main#42>'
      - '<Job mypy explicit: None implied: None source: osism/python-osism/.zuul.yaml@main#143>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: f8af0923767c45b0b32889cccc57d3ae
      build_refs:
      - branch: main
        change: '2367'
        change_message: "Add unit tests for conductor ironic sync orchestrators\n\nCloses
          #2227.\r\n\r\nAdds `tests/unit/tasks/conductor/test_ironic_sync.py` covering
          the four\r\nsync orchestrators in `osism/tasks/conductor/ironic.py`. Tests
          focus on\r\nstate transitions and branch coverage, asserting on `push_task_output`\r\n**substrings**
          rather than exact strings, as the issue requests.\r\n\r\n## What the single
          commit adds\r\n\r\nA new test module organised into four clearly-labelled
          sections, one per\r\ntarget function. It patches the module-level imports\r\n(`osism_utils`,
          `openstack`, `netbox`, `deep_compare`, `mask_secrets`,\r\n`_matches_netbox_filter`,
          `_prepare_node_attributes`,\r\n`_sync_ironic_device`, `_sync_ironic_device_dry_run`)
          following the\r\nexisting `mocker` + `SimpleNamespace` conventions used
          in the sibling\r\n`test_netbox.py` / `test_config.py`.\r\n\r\n### `_sync_ironic_device`
          (`ironic.py:354`)\r\n- **Create path**: node created with `automated_clean=False`;\r\n
          \ `target_raid_config` applied via `baremetal_node_set_target_raid_config`;\r\n
          \ a `(False, \"error\")` result raises an exception mentioning\r\n  `target_raid_config`.\r\n-
          **Update path**: `deep_compare` populates `node_updates` \u2192 update with\r\n
          \ full `node_attributes`; the driver password key (resolved via\r\n  `driver_params[driver][\"password\"]`)
          is popped, and a password-only\r\n  delta drops `driver_info` so no update
          happens unless `force=True`.\r\n- **Port reconciliation**: extra ports deleted,
          new MACs created,\r\n  comparison is case-insensitive.\r\n- **State machine**:
          management-validation failure returns early;\r\n  `enroll` / `clean failed`
          move to `manageable`; power is forced off;\r\n  boot-validation failure
          on `available` demotes to `manageable`;\r\n  adoption from `manageable`
          and from `available`; the normal\r\n  `manage`\u2192`provide`\u2192`available`
          path including the `automated_clean`\r\n  toggles; `set_boot_device` failure
          is caught; `is_adoption` derives\r\n  from the `provision_state == \"active\"`
          custom field.\r\n\r\n### `_sync_ironic_device_dry_run` (`ironic.py:570`)\r\n-
          Secret values collected from `password`/`secret`/`ironic_osism_*`\r\n  string
          keys and passed to `mask_secrets` (call args verified;\r\n  non-strings
          and unrelated keys ignored).\r\n- Create branch (adopt vs. available, with
          `active` implying adopt) and\r\n  update branch (update vs. no-update-needed,
          port create/delete,\r\n  current `provision_state` reported).\r\n\r\n###
          `sync_ironic` (`ironic.py:681`)\r\n- NetBox/Ironic unreachable \u2192 `finish_task_output(rc=1)`;
          `node_name`\r\n  not found; dry-run path; lock acquired (device synced and
          released in\r\n  `finally`, even on exception) and lock contention; stale-node
          cleanup\r\n  (delete, dry-run \"Would delete\", `clean failed` \u2192 `manageable`
          first,\r\n  ineligible \"Cannot remove\"); `skip`/`extra_kernel_params`
          propagation;\r\n  `ports_attributes` filtering by `enabled and not mgmt_only
          and\r\n  mac_address`.\r\n\r\n### `sync_netbox_from_ironic` (`ironic.py:877`)\r\n-
          Filtered selection (primary match, secondary fallback, no match, all\r\n
          \ unreachable) and unfiltered selection (primary unreachable, all/one\r\n
          \ secondary reachable, no secondaries message); node-name not found;\r\n
          \ `set_*` called with `secondary_nb_list=reachable_secondaries`;\r\n  failed-device
          reporting; Ironic unreachable.\r\n\r\n## Verification\r\n- `black --check`
          and `flake8` pass on the new file.\r\n- `pytest` was not run in this local
          environment per my standing\r\n  workflow preference of letting CI run the
          suite; the Zuul\r\n  `python-osism-unit-tests` job is the verification gate
          for this draft.\r\n\r\n## Notes\r\n- The change is purely additive (one
          new test file); no production code\r\n  is touched.\r\n- Per the issue,
          coverage of some defensive `except` branches and\r\n  message-only push
          paths is intentionally left lower.\r\n\r\nAssisted-by: Claude:claude-opus-4-8\r\n"
        change_url: https://github.com/osism/python-osism/pull/2367
        commit_id: 203025d5d3ae17ff8926afc14e4eef1c4940b913
        patchset: 203025d5d3ae17ff8926afc14e4eef1c4940b913
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
        src_dir: src/github.com/osism/python-osism
        topic: null
      buildset: d3decf8db53a4eeda5fc39a5ea4b6923
      buildset_refs:
      - branch: main
        change: '2367'
        change_message: "Add unit tests for conductor ironic sync orchestrators\n\nCloses
          #2227.\r\n\r\nAdds `tests/unit/tasks/conductor/test_ironic_sync.py` covering
          the four\r\nsync orchestrators in `osism/tasks/conductor/ironic.py`. Tests
          focus on\r\nstate transitions and branch coverage, asserting on `push_task_output`\r\n**substrings**
          rather than exact strings, as the issue requests.\r\n\r\n## What the single
          commit adds\r\n\r\nA new test module organised into four clearly-labelled
          sections, one per\r\ntarget function. It patches the module-level imports\r\n(`osism_utils`,
          `openstack`, `netbox`, `deep_compare`, `mask_secrets`,\r\n`_matches_netbox_filter`,
          `_prepare_node_attributes`,\r\n`_sync_ironic_device`, `_sync_ironic_device_dry_run`)
          following the\r\nexisting `mocker` + `SimpleNamespace` conventions used
          in the sibling\r\n`test_netbox.py` / `test_config.py`.\r\n\r\n### `_sync_ironic_device`
          (`ironic.py:354`)\r\n- **Create path**: node created with `automated_clean=False`;\r\n
          \ `target_raid_config` applied via `baremetal_node_set_target_raid_config`;\r\n
          \ a `(False, \"error\")` result raises an exception mentioning\r\n  `target_raid_config`.\r\n-
          **Update path**: `deep_compare` populates `node_updates` \u2192 update with\r\n
          \ full `node_attributes`; the driver password key (resolved via\r\n  `driver_params[driver][\"password\"]`)
          is popped, and a password-only\r\n  delta drops `driver_info` so no update
          happens unless `force=True`.\r\n- **Port reconciliation**: extra ports deleted,
          new MACs created,\r\n  comparison is case-insensitive.\r\n- **State machine**:
          management-validation failure returns early;\r\n  `enroll` / `clean failed`
          move to `manageable`; power is forced off;\r\n  boot-validation failure
          on `available` demotes to `manageable`;\r\n  adoption from `manageable`
          and from `available`; the normal\r\n  `manage`\u2192`provide`\u2192`available`
          path including the `automated_clean`\r\n  toggles; `set_boot_device` failure
          is caught; `is_adoption` derives\r\n  from the `provision_state == \"active\"`
          custom field.\r\n\r\n### `_sync_ironic_device_dry_run` (`ironic.py:570`)\r\n-
          Secret values collected from `password`/`secret`/`ironic_osism_*`\r\n  string
          keys and passed to `mask_secrets` (call args verified;\r\n  non-strings
          and unrelated keys ignored).\r\n- Create branch (adopt vs. available, with
          `active` implying adopt) and\r\n  update branch (update vs. no-update-needed,
          port create/delete,\r\n  current `provision_state` reported).\r\n\r\n###
          `sync_ironic` (`ironic.py:681`)\r\n- NetBox/Ironic unreachable \u2192 `finish_task_output(rc=1)`;
          `node_name`\r\n  not found; dry-run path; lock acquired (device synced and
          released in\r\n  `finally`, even on exception) and lock contention; stale-node
          cleanup\r\n  (delete, dry-run \"Would delete\", `clean failed` \u2192 `manageable`
          first,\r\n  ineligible \"Cannot remove\"); `skip`/`extra_kernel_params`
          propagation;\r\n  `ports_attributes` filtering by `enabled and not mgmt_only
          and\r\n  mac_address`.\r\n\r\n### `sync_netbox_from_ironic` (`ironic.py:877`)\r\n-
          Filtered selection (primary match, secondary fallback, no match, all\r\n
          \ unreachable) and unfiltered selection (primary unreachable, all/one\r\n
          \ secondary reachable, no secondaries message); node-name not found;\r\n
          \ `set_*` called with `secondary_nb_list=reachable_secondaries`;\r\n  failed-device
          reporting; Ironic unreachable.\r\n\r\n## Verification\r\n- `black --check`
          and `flake8` pass on the new file.\r\n- `pytest` was not run in this local
          environment per my standing\r\n  workflow preference of letting CI run the
          suite; the Zuul\r\n  `python-osism-unit-tests` job is the verification gate
          for this draft.\r\n\r\n## Notes\r\n- The change is purely additive (one
          new test file); no production code\r\n  is touched.\r\n- Per the issue,
          coverage of some defensive `except` branches and\r\n  message-only push
          paths is intentionally left lower.\r\n\r\nAssisted-by: Claude:claude-opus-4-8\r\n"
        change_url: https://github.com/osism/python-osism/pull/2367
        commit_id: 203025d5d3ae17ff8926afc14e4eef1c4940b913
        patchset: 203025d5d3ae17ff8926afc14e4eef1c4940b913
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
        src_dir: src/github.com/osism/python-osism
        topic: null
      change: '2367'
      change_message: "Add unit tests for conductor ironic sync orchestrators\n\nCloses
        #2227.\r\n\r\nAdds `tests/unit/tasks/conductor/test_ironic_sync.py` covering
        the four\r\nsync orchestrators in `osism/tasks/conductor/ironic.py`. Tests
        focus on\r\nstate transitions and branch coverage, asserting on `push_task_output`\r\n**substrings**
        rather than exact strings, as the issue requests.\r\n\r\n## What the single
        commit adds\r\n\r\nA new test module organised into four clearly-labelled
        sections, one per\r\ntarget function. It patches the module-level imports\r\n(`osism_utils`,
        `openstack`, `netbox`, `deep_compare`, `mask_secrets`,\r\n`_matches_netbox_filter`,
        `_prepare_node_attributes`,\r\n`_sync_ironic_device`, `_sync_ironic_device_dry_run`)
        following the\r\nexisting `mocker` + `SimpleNamespace` conventions used in
        the sibling\r\n`test_netbox.py` / `test_config.py`.\r\n\r\n### `_sync_ironic_device`
        (`ironic.py:354`)\r\n- **Create path**: node created with `automated_clean=False`;\r\n
        \ `target_raid_config` applied via `baremetal_node_set_target_raid_config`;\r\n
        \ a `(False, \"error\")` result raises an exception mentioning\r\n  `target_raid_config`.\r\n-
        **Update path**: `deep_compare` populates `node_updates` \u2192 update with\r\n
        \ full `node_attributes`; the driver password key (resolved via\r\n  `driver_params[driver][\"password\"]`)
        is popped, and a password-only\r\n  delta drops `driver_info` so no update
        happens unless `force=True`.\r\n- **Port reconciliation**: extra ports deleted,
        new MACs created,\r\n  comparison is case-insensitive.\r\n- **State machine**:
        management-validation failure returns early;\r\n  `enroll` / `clean failed`
        move to `manageable`; power is forced off;\r\n  boot-validation failure on
        `available` demotes to `manageable`;\r\n  adoption from `manageable` and from
        `available`; the normal\r\n  `manage`\u2192`provide`\u2192`available` path
        including the `automated_clean`\r\n  toggles; `set_boot_device` failure is
        caught; `is_adoption` derives\r\n  from the `provision_state == \"active\"`
        custom field.\r\n\r\n### `_sync_ironic_device_dry_run` (`ironic.py:570`)\r\n-
        Secret values collected from `password`/`secret`/`ironic_osism_*`\r\n  string
        keys and passed to `mask_secrets` (call args verified;\r\n  non-strings and
        unrelated keys ignored).\r\n- Create branch (adopt vs. available, with `active`
        implying adopt) and\r\n  update branch (update vs. no-update-needed, port
        create/delete,\r\n  current `provision_state` reported).\r\n\r\n### `sync_ironic`
        (`ironic.py:681`)\r\n- NetBox/Ironic unreachable \u2192 `finish_task_output(rc=1)`;
        `node_name`\r\n  not found; dry-run path; lock acquired (device synced and
        released in\r\n  `finally`, even on exception) and lock contention; stale-node
        cleanup\r\n  (delete, dry-run \"Would delete\", `clean failed` \u2192 `manageable`
        first,\r\n  ineligible \"Cannot remove\"); `skip`/`extra_kernel_params` propagation;\r\n
        \ `ports_attributes` filtering by `enabled and not mgmt_only and\r\n  mac_address`.\r\n\r\n###
        `sync_netbox_from_ironic` (`ironic.py:877`)\r\n- Filtered selection (primary
        match, secondary fallback, no match, all\r\n  unreachable) and unfiltered
        selection (primary unreachable, all/one\r\n  secondary reachable, no secondaries
        message); node-name not found;\r\n  `set_*` called with `secondary_nb_list=reachable_secondaries`;\r\n
        \ failed-device reporting; Ironic unreachable.\r\n\r\n## Verification\r\n-
        `black --check` and `flake8` pass on the new file.\r\n- `pytest` was not run
        in this local environment per my standing\r\n  workflow preference of letting
        CI run the suite; the Zuul\r\n  `python-osism-unit-tests` job is the verification
        gate for this draft.\r\n\r\n## Notes\r\n- The change is purely additive (one
        new test file); no production code\r\n  is touched.\r\n- Per the issue, coverage
        of some defensive `except` branches and\r\n  message-only push paths is intentionally
        left lower.\r\n\r\nAssisted-by: Claude:claude-opus-4-8\r\n"
      change_url: https://github.com/osism/python-osism/pull/2367
      child_jobs: []
      commit_id: 203025d5d3ae17ff8926afc14e4eef1c4940b913
      event_id: 79a66280-758a-11f1-9baa-8e40cd235d81
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/f8af0923767c45b0b32889cccc57d3ae/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/f8af0923767c45b0b32889cccc57d3ae/work/logs
        result_data_file: /var/lib/zuul/builds/f8af0923767c45b0b32889cccc57d3ae/work/results.json
        src_root: /var/lib/zuul/builds/f8af0923767c45b0b32889cccc57d3ae/work/src
        work_root: /var/lib/zuul/builds/f8af0923767c45b0b32889cccc57d3ae/work
      include_vars: []
      items:
      - branch: main
        change: '2367'
        change_message: "Add unit tests for conductor ironic sync orchestrators\n\nCloses
          #2227.\r\n\r\nAdds `tests/unit/tasks/conductor/test_ironic_sync.py` covering
          the four\r\nsync orchestrators in `osism/tasks/conductor/ironic.py`. Tests
          focus on\r\nstate transitions and branch coverage, asserting on `push_task_output`\r\n**substrings**
          rather than exact strings, as the issue requests.\r\n\r\n## What the single
          commit adds\r\n\r\nA new test module organised into four clearly-labelled
          sections, one per\r\ntarget function. It patches the module-level imports\r\n(`osism_utils`,
          `openstack`, `netbox`, `deep_compare`, `mask_secrets`,\r\n`_matches_netbox_filter`,
          `_prepare_node_attributes`,\r\n`_sync_ironic_device`, `_sync_ironic_device_dry_run`)
          following the\r\nexisting `mocker` + `SimpleNamespace` conventions used
          in the sibling\r\n`test_netbox.py` / `test_config.py`.\r\n\r\n### `_sync_ironic_device`
          (`ironic.py:354`)\r\n- **Create path**: node created with `automated_clean=False`;\r\n
          \ `target_raid_config` applied via `baremetal_node_set_target_raid_config`;\r\n
          \ a `(False, \"error\")` result raises an exception mentioning\r\n  `target_raid_config`.\r\n-
          **Update path**: `deep_compare` populates `node_updates` \u2192 update with\r\n
          \ full `node_attributes`; the driver password key (resolved via\r\n  `driver_params[driver][\"password\"]`)
          is popped, and a password-only\r\n  delta drops `driver_info` so no update
          happens unless `force=True`.\r\n- **Port reconciliation**: extra ports deleted,
          new MACs created,\r\n  comparison is case-insensitive.\r\n- **State machine**:
          management-validation failure returns early;\r\n  `enroll` / `clean failed`
          move to `manageable`; power is forced off;\r\n  boot-validation failure
          on `available` demotes to `manageable`;\r\n  adoption from `manageable`
          and from `available`; the normal\r\n  `manage`\u2192`provide`\u2192`available`
          path including the `automated_clean`\r\n  toggles; `set_boot_device` failure
          is caught; `is_adoption` derives\r\n  from the `provision_state == \"active\"`
          custom field.\r\n\r\n### `_sync_ironic_device_dry_run` (`ironic.py:570`)\r\n-
          Secret values collected from `password`/`secret`/`ironic_osism_*`\r\n  string
          keys and passed to `mask_secrets` (call args verified;\r\n  non-strings
          and unrelated keys ignored).\r\n- Create branch (adopt vs. available, with
          `active` implying adopt) and\r\n  update branch (update vs. no-update-needed,
          port create/delete,\r\n  current `provision_state` reported).\r\n\r\n###
          `sync_ironic` (`ironic.py:681`)\r\n- NetBox/Ironic unreachable \u2192 `finish_task_output(rc=1)`;
          `node_name`\r\n  not found; dry-run path; lock acquired (device synced and
          released in\r\n  `finally`, even on exception) and lock contention; stale-node
          cleanup\r\n  (delete, dry-run \"Would delete\", `clean failed` \u2192 `manageable`
          first,\r\n  ineligible \"Cannot remove\"); `skip`/`extra_kernel_params`
          propagation;\r\n  `ports_attributes` filtering by `enabled and not mgmt_only
          and\r\n  mac_address`.\r\n\r\n### `sync_netbox_from_ironic` (`ironic.py:877`)\r\n-
          Filtered selection (primary match, secondary fallback, no match, all\r\n
          \ unreachable) and unfiltered selection (primary unreachable, all/one\r\n
          \ secondary reachable, no secondaries message); node-name not found;\r\n
          \ `set_*` called with `secondary_nb_list=reachable_secondaries`;\r\n  failed-device
          reporting; Ironic unreachable.\r\n\r\n## Verification\r\n- `black --check`
          and `flake8` pass on the new file.\r\n- `pytest` was not run in this local
          environment per my standing\r\n  workflow preference of letting CI run the
          suite; the Zuul\r\n  `python-osism-unit-tests` job is the verification gate
          for this draft.\r\n\r\n## Notes\r\n- The change is purely additive (one
          new test file); no production code\r\n  is touched.\r\n- Per the issue,
          coverage of some defensive `except` branches and\r\n  message-only push
          paths is intentionally left lower.\r\n\r\nAssisted-by: Claude:claude-opus-4-8\r\n"
        change_url: https://github.com/osism/python-osism/pull/2367
        commit_id: 203025d5d3ae17ff8926afc14e4eef1c4940b913
        patchset: 203025d5d3ae17ff8926afc14e4eef1c4940b913
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          name: osism/python-osism
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
        topic: null
      job: mypy
      jobtags: []
      max_attempts: 3
      message: QWRkIHVuaXQgdGVzdHMgZm9yIGNvbmR1Y3RvciBpcm9uaWMgc3luYyBvcmNoZXN0cmF0b3JzCgpDbG9zZXMgIzIyMjcuDQoNCkFkZHMgYHRlc3RzL3VuaXQvdGFza3MvY29uZHVjdG9yL3Rlc3RfaXJvbmljX3N5bmMucHlgIGNvdmVyaW5nIHRoZSBmb3VyDQpzeW5jIG9yY2hlc3RyYXRvcnMgaW4gYG9zaXNtL3Rhc2tzL2NvbmR1Y3Rvci9pcm9uaWMucHlgLiBUZXN0cyBmb2N1cyBvbg0Kc3RhdGUgdHJhbnNpdGlvbnMgYW5kIGJyYW5jaCBjb3ZlcmFnZSwgYXNzZXJ0aW5nIG9uIGBwdXNoX3Rhc2tfb3V0cHV0YA0KKipzdWJzdHJpbmdzKiogcmF0aGVyIHRoYW4gZXhhY3Qgc3RyaW5ncywgYXMgdGhlIGlzc3VlIHJlcXVlc3RzLg0KDQojIyBXaGF0IHRoZSBzaW5nbGUgY29tbWl0IGFkZHMNCg0KQSBuZXcgdGVzdCBtb2R1bGUgb3JnYW5pc2VkIGludG8gZm91ciBjbGVhcmx5LWxhYmVsbGVkIHNlY3Rpb25zLCBvbmUgcGVyDQp0YXJnZXQgZnVuY3Rpb24uIEl0IHBhdGNoZXMgdGhlIG1vZHVsZS1sZXZlbCBpbXBvcnRzDQooYG9zaXNtX3V0aWxzYCwgYG9wZW5zdGFja2AsIGBuZXRib3hgLCBgZGVlcF9jb21wYXJlYCwgYG1hc2tfc2VjcmV0c2AsDQpgX21hdGNoZXNfbmV0Ym94X2ZpbHRlcmAsIGBfcHJlcGFyZV9ub2RlX2F0dHJpYnV0ZXNgLA0KYF9zeW5jX2lyb25pY19kZXZpY2VgLCBgX3N5bmNfaXJvbmljX2RldmljZV9kcnlfcnVuYCkgZm9sbG93aW5nIHRoZQ0KZXhpc3RpbmcgYG1vY2tlcmAgKyBgU2ltcGxlTmFtZXNwYWNlYCBjb252ZW50aW9ucyB1c2VkIGluIHRoZSBzaWJsaW5nDQpgdGVzdF9uZXRib3gucHlgIC8gYHRlc3RfY29uZmlnLnB5YC4NCg0KIyMjIGBfc3luY19pcm9uaWNfZGV2aWNlYCAoYGlyb25pYy5weTozNTRgKQ0KLSAqKkNyZWF0ZSBwYXRoKio6IG5vZGUgY3JlYXRlZCB3aXRoIGBhdXRvbWF0ZWRfY2xlYW49RmFsc2VgOw0KICBgdGFyZ2V0X3JhaWRfY29uZmlnYCBhcHBsaWVkIHZpYSBgYmFyZW1ldGFsX25vZGVfc2V0X3RhcmdldF9yYWlkX2NvbmZpZ2A7DQogIGEgYChGYWxzZSwgImVycm9yIilgIHJlc3VsdCByYWlzZXMgYW4gZXhjZXB0aW9uIG1lbnRpb25pbmcNCiAgYHRhcmdldF9yYWlkX2NvbmZpZ2AuDQotICoqVXBkYXRlIHBhdGgqKjogYGRlZXBfY29tcGFyZWAgcG9wdWxhdGVzIGBub2RlX3VwZGF0ZXNgIOKGkiB1cGRhdGUgd2l0aA0KICBmdWxsIGBub2RlX2F0dHJpYnV0ZXNgOyB0aGUgZHJpdmVyIHBhc3N3b3JkIGtleSAocmVzb2x2ZWQgdmlhDQogIGBkcml2ZXJfcGFyYW1zW2RyaXZlcl1bInBhc3N3b3JkIl1gKSBpcyBwb3BwZWQsIGFuZCBhIHBhc3N3b3JkLW9ubHkNCiAgZGVsdGEgZHJvcHMgYGRyaXZlcl9pbmZvYCBzbyBubyB1cGRhdGUgaGFwcGVucyB1bmxlc3MgYGZvcmNlPVRydWVgLg0KLSAqKlBvcnQgcmVjb25jaWxpYXRpb24qKjogZXh0cmEgcG9ydHMgZGVsZXRlZCwgbmV3IE1BQ3MgY3JlYXRlZCwNCiAgY29tcGFyaXNvbiBpcyBjYXNlLWluc2Vuc2l0aXZlLg0KLSAqKlN0YXRlIG1hY2hpbmUqKjogbWFuYWdlbWVudC12YWxpZGF0aW9uIGZhaWx1cmUgcmV0dXJucyBlYXJseTsNCiAgYGVucm9sbGAgLyBgY2xlYW4gZmFpbGVkYCBtb3ZlIHRvIGBtYW5hZ2VhYmxlYDsgcG93ZXIgaXMgZm9yY2VkIG9mZjsNCiAgYm9vdC12YWxpZGF0aW9uIGZhaWx1cmUgb24gYGF2YWlsYWJsZWAgZGVtb3RlcyB0byBgbWFuYWdlYWJsZWA7DQogIGFkb3B0aW9uIGZyb20gYG1hbmFnZWFibGVgIGFuZCBmcm9tIGBhdmFpbGFibGVgOyB0aGUgbm9ybWFsDQogIGBtYW5hZ2Vg4oaSYHByb3ZpZGVg4oaSYGF2YWlsYWJsZWAgcGF0aCBpbmNsdWRpbmcgdGhlIGBhdXRvbWF0ZWRfY2xlYW5gDQogIHRvZ2dsZXM7IGBzZXRfYm9vdF9kZXZpY2VgIGZhaWx1cmUgaXMgY2F1Z2h0OyBgaXNfYWRvcHRpb25gIGRlcml2ZXMNCiAgZnJvbSB0aGUgYHByb3Zpc2lvbl9zdGF0ZSA9PSAiYWN0aXZlImAgY3VzdG9tIGZpZWxkLg0KDQojIyMgYF9zeW5jX2lyb25pY19kZXZpY2VfZHJ5X3J1bmAgKGBpcm9uaWMucHk6NTcwYCkNCi0gU2VjcmV0IHZhbHVlcyBjb2xsZWN0ZWQgZnJvbSBgcGFzc3dvcmRgL2BzZWNyZXRgL2Bpcm9uaWNfb3Npc21fKmANCiAgc3RyaW5nIGtleXMgYW5kIHBhc3NlZCB0byBgbWFza19zZWNyZXRzYCAoY2FsbCBhcmdzIHZlcmlmaWVkOw0KICBub24tc3RyaW5ncyBhbmQgdW5yZWxhdGVkIGtleXMgaWdub3JlZCkuDQotIENyZWF0ZSBicmFuY2ggKGFkb3B0IHZzLiBhdmFpbGFibGUsIHdpdGggYGFjdGl2ZWAgaW1wbHlpbmcgYWRvcHQpIGFuZA0KICB1cGRhdGUgYnJhbmNoICh1cGRhdGUgdnMuIG5vLXVwZGF0ZS1uZWVkZWQsIHBvcnQgY3JlYXRlL2RlbGV0ZSwNCiAgY3VycmVudCBgcHJvdmlzaW9uX3N0YXRlYCByZXBvcnRlZCkuDQoNCiMjIyBgc3luY19pcm9uaWNgIChgaXJvbmljLnB5OjY4MWApDQotIE5ldEJveC9Jcm9uaWMgdW5yZWFjaGFibGUg4oaSIGBmaW5pc2hfdGFza19vdXRwdXQocmM9MSlgOyBgbm9kZV9uYW1lYA0KICBub3QgZm91bmQ7IGRyeS1ydW4gcGF0aDsgbG9jayBhY3F1aXJlZCAoZGV2aWNlIHN5bmNlZCBhbmQgcmVsZWFzZWQgaW4NCiAgYGZpbmFsbHlgLCBldmVuIG9uIGV4Y2VwdGlvbikgYW5kIGxvY2sgY29udGVudGlvbjsgc3RhbGUtbm9kZSBjbGVhbnVwDQogIChkZWxldGUsIGRyeS1ydW4gIldvdWxkIGRlbGV0ZSIsIGBjbGVhbiBmYWlsZWRgIOKGkiBgbWFuYWdlYWJsZWAgZmlyc3QsDQogIGluZWxpZ2libGUgIkNhbm5vdCByZW1vdmUiKTsgYHNraXBgL2BleHRyYV9rZXJuZWxfcGFyYW1zYCBwcm9wYWdhdGlvbjsNCiAgYHBvcnRzX2F0dHJpYnV0ZXNgIGZpbHRlcmluZyBieSBgZW5hYmxlZCBhbmQgbm90IG1nbXRfb25seSBhbmQNCiAgbWFjX2FkZHJlc3NgLg0KDQojIyMgYHN5bmNfbmV0Ym94X2Zyb21faXJvbmljYCAoYGlyb25pYy5weTo4NzdgKQ0KLSBGaWx0ZXJlZCBzZWxlY3Rpb24gKHByaW1hcnkgbWF0Y2gsIHNlY29uZGFyeSBmYWxsYmFjaywgbm8gbWF0Y2gsIGFsbA0KICB1bnJlYWNoYWJsZSkgYW5kIHVuZmlsdGVyZWQgc2VsZWN0aW9uIChwcmltYXJ5IHVucmVhY2hhYmxlLCBhbGwvb25lDQogIHNlY29uZGFyeSByZWFjaGFibGUsIG5vIHNlY29uZGFyaWVzIG1lc3NhZ2UpOyBub2RlLW5hbWUgbm90IGZvdW5kOw0KICBgc2V0XypgIGNhbGxlZCB3aXRoIGBzZWNvbmRhcnlfbmJfbGlzdD1yZWFjaGFibGVfc2Vjb25kYXJpZXNgOw0KICBmYWlsZWQtZGV2aWNlIHJlcG9ydGluZzsgSXJvbmljIHVucmVhY2hhYmxlLg0KDQojIyBWZXJpZmljYXRpb24NCi0gYGJsYWNrIC0tY2hlY2tgIGFuZCBgZmxha2U4YCBwYXNzIG9uIHRoZSBuZXcgZmlsZS4NCi0gYHB5dGVzdGAgd2FzIG5vdCBydW4gaW4gdGhpcyBsb2NhbCBlbnZpcm9ubWVudCBwZXIgbXkgc3RhbmRpbmcNCiAgd29ya2Zsb3cgcHJlZmVyZW5jZSBvZiBsZXR0aW5nIENJIHJ1biB0aGUgc3VpdGU7IHRoZSBadXVsDQogIGBweXRob24tb3Npc20tdW5pdC10ZXN0c2Agam9iIGlzIHRoZSB2ZXJpZmljYXRpb24gZ2F0ZSBmb3IgdGhpcyBkcmFmdC4NCg0KIyMgTm90ZXMNCi0gVGhlIGNoYW5nZSBpcyBwdXJlbHkgYWRkaXRpdmUgKG9uZSBuZXcgdGVzdCBmaWxlKTsgbm8gcHJvZHVjdGlvbiBjb2RlDQogIGlzIHRvdWNoZWQuDQotIFBlciB0aGUgaXNzdWUsIGNvdmVyYWdlIG9mIHNvbWUgZGVmZW5zaXZlIGBleGNlcHRgIGJyYW5jaGVzIGFuZA0KICBtZXNzYWdlLW9ubHkgcHVzaCBwYXRocyBpcyBpbnRlbnRpb25hbGx5IGxlZnQgbG93ZXIuDQoNCkFzc2lzdGVkLWJ5OiBDbGF1ZGU6Y2xhdWRlLW9wdXMtNC04DQo=
      patchset: 203025d5d3ae17ff8926afc14e4eef1c4940b913
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          trusted/project_1/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
          trusted/project_2/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 1d71e58c93442038e695a5d883d57a603182c7ae
          untrusted/project_0/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 1d71e58c93442038e695a5d883d57a603182c7ae
          untrusted/project_1/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          untrusted/project_2/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
        playbooks:
        - path: untrusted/project_0/github.com/osism/zuul-jobs/playbooks/mypy/run.yaml
          roles:
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_0/zuul-config
            link_target: untrusted/project_1/github.com/osism/zuul-config
            role_path: ansible/playbook_0/role_0/zuul-config/roles
          - checkout: master
            checkout_description: project default branch
            link_name: ansible/playbook_0/role_1/openinfra-zuul-jobs
            link_target: untrusted/project_2/github.com/osism/openinfra-zuul-jobs
            role_path: ansible/playbook_0/role_1/openinfra-zuul-jobs/roles
          - checkout: main
            checkout_description: playbook branch
            link_name: ansible/playbook_0/role_2/zuul-jobs
            link_target: untrusted/project_0/github.com/osism/zuul-jobs
            role_path: ansible/playbook_0/role_2/zuul-jobs/roles
      post_review: false
      post_timeout: 1800
      pre_timeout: null
      project:
        canonical_hostname: github.com
        canonical_name: github.com/osism/python-osism
        name: osism/python-osism
        short_name: python-osism
        src_dir: src/github.com/osism/python-osism
      projects:
        github.com/osism/python-osism:
          canonical_hostname: github.com
          canonical_name: github.com/osism/python-osism
          checkout: main
          checkout_description: zuul branch
          commit: e7e5af13cc89f7575036c7a3a7369885374b68ee
          name: osism/python-osism
          required: false
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
      ref: refs/pull/2367/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
