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