all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fe64:206d
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 2579b4a1-b851-4d8e-adbf-c0b4ee702445
        host_id: 0d3d02185f810c959252bd1d303ec55040bf5bb0b401cceef814c3a7
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fe64:206d
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.0.100
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.193.70
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fe64:206d
        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 python-black explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-jobs/.zuul.yaml@main#54>'
      - '<Job python-black explicit: None implied: None source: osism/python-osism/.zuul.yaml@main#138>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: c6fa6f69917843bca0619acef880b176
      build_refs:
      - branch: main
        change: '2370'
        change_message: "sonic: enforce per-key ownership of ACL tables\n\n## Problem\n\n`ACL_TABLE`
          and `ACL_RULE` are owned by more than one control-plane section helper (SSH,
          SNMP, gNMI). The ownership model settled in the `generate_sonic_config`
          docstring covers whole-table ownership but not how several helpers share
          one owned table. The open ACL PRs each rebind the whole table \u2014 `config[\"ACL_TABLE\"]
          = {...}` \u2014 so whichever helper runs second drops the first's entries,
          leaving SSH *or* SNMP/gNMI unrestricted. Each PR passes its own tests because
          neither calls the other helper, so the collision is invisible when the PRs
          are reviewed in isolation.\n\n## Change\n\nCo-owned tables must be merged
          per named entry, never rebound. The rule is locked in code rather than left
          to review, so a divergent PR fails CI before it can merge:\n\n- `MULTI_OWNER_OWNED_TABLE_KEYS`
          lists `ACL_TABLE`/`ACL_RULE`.\n- A static guard (`TestMultiOwnerTableGuard`)
          parses the generator source and fails on every form that rebinds a listed
          table wholesale on `config`: `config[\"X\"] = <expr>`, `config.update({\"X\":
          ...})`, `config |= {\"X\": ...}`, and `config = {**config, \"X\": ...}`.
          These mirror the wholesale-write forms the existing mutation backstop recognizes,
          so no analyzable write can rebind a listed table without being caught.\n-
          In-place forms that mutate the table dict are left alone: `config[\"X\"][\"k\"]
          = ...`, `config[\"X\"].update(...)`, `config[\"X\"] |= ...`, and `config.setdefault(\"X\",
          {})`. Synthetic-source detector tests prove the guard catches each rebind
          form and passes the in-place forms, so it cannot pass vacuously.\n\nThe
          tables are listed ahead of the helpers that introduce them, so the first
          ACL helper to land is forced onto the per-key pattern rather than establishing
          the unsafe one. Two invariants tie the list to the rest of the model: a
          referenced multi-owner table must also be in `OWNED_TABLE_KEYS` (so the
          central up-front drop clears it and no stale entry survives the merge),
          and multi-owner tables must not be inherited or image-consumed (those regimes
          are not dropped). Both hold now and after the ACL helpers add `ACL_TABLE`/`ACL_RULE`
          to `ON_DEMAND_OWNED_TABLE_KEYS`.\n\n## Note for the ACL PRs\n\nThis guard
          is dormant until a helper references the tables. When the control-plane
          ACL work lands, each helper must merge its own keys and the PR must add
          `ACL_TABLE`/`ACL_RULE` to `ON_DEMAND_OWNED_TABLE_KEYS` in the same change
          (the `test_referenced_multi_owner_tables_are_owned` invariant enforces this).\n\n##
          Related\n\n- osism/python-osism#2340\n- osism/python-osism#2339\n- osism/python-osism#2337\n-
          osism/python-osism#2338"
        change_url: https://github.com/osism/python-osism/pull/2370
        commit_id: cbce709e83be001a3984f8fe3878f1df1476e8da
        patchset: cbce709e83be001a3984f8fe3878f1df1476e8da
        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: fe7aca52404d42448c323374ead74707
      buildset_refs:
      - branch: main
        change: '2370'
        change_message: "sonic: enforce per-key ownership of ACL tables\n\n## Problem\n\n`ACL_TABLE`
          and `ACL_RULE` are owned by more than one control-plane section helper (SSH,
          SNMP, gNMI). The ownership model settled in the `generate_sonic_config`
          docstring covers whole-table ownership but not how several helpers share
          one owned table. The open ACL PRs each rebind the whole table \u2014 `config[\"ACL_TABLE\"]
          = {...}` \u2014 so whichever helper runs second drops the first's entries,
          leaving SSH *or* SNMP/gNMI unrestricted. Each PR passes its own tests because
          neither calls the other helper, so the collision is invisible when the PRs
          are reviewed in isolation.\n\n## Change\n\nCo-owned tables must be merged
          per named entry, never rebound. The rule is locked in code rather than left
          to review, so a divergent PR fails CI before it can merge:\n\n- `MULTI_OWNER_OWNED_TABLE_KEYS`
          lists `ACL_TABLE`/`ACL_RULE`.\n- A static guard (`TestMultiOwnerTableGuard`)
          parses the generator source and fails on every form that rebinds a listed
          table wholesale on `config`: `config[\"X\"] = <expr>`, `config.update({\"X\":
          ...})`, `config |= {\"X\": ...}`, and `config = {**config, \"X\": ...}`.
          These mirror the wholesale-write forms the existing mutation backstop recognizes,
          so no analyzable write can rebind a listed table without being caught.\n-
          In-place forms that mutate the table dict are left alone: `config[\"X\"][\"k\"]
          = ...`, `config[\"X\"].update(...)`, `config[\"X\"] |= ...`, and `config.setdefault(\"X\",
          {})`. Synthetic-source detector tests prove the guard catches each rebind
          form and passes the in-place forms, so it cannot pass vacuously.\n\nThe
          tables are listed ahead of the helpers that introduce them, so the first
          ACL helper to land is forced onto the per-key pattern rather than establishing
          the unsafe one. Two invariants tie the list to the rest of the model: a
          referenced multi-owner table must also be in `OWNED_TABLE_KEYS` (so the
          central up-front drop clears it and no stale entry survives the merge),
          and multi-owner tables must not be inherited or image-consumed (those regimes
          are not dropped). Both hold now and after the ACL helpers add `ACL_TABLE`/`ACL_RULE`
          to `ON_DEMAND_OWNED_TABLE_KEYS`.\n\n## Note for the ACL PRs\n\nThis guard
          is dormant until a helper references the tables. When the control-plane
          ACL work lands, each helper must merge its own keys and the PR must add
          `ACL_TABLE`/`ACL_RULE` to `ON_DEMAND_OWNED_TABLE_KEYS` in the same change
          (the `test_referenced_multi_owner_tables_are_owned` invariant enforces this).\n\n##
          Related\n\n- osism/python-osism#2340\n- osism/python-osism#2339\n- osism/python-osism#2337\n-
          osism/python-osism#2338"
        change_url: https://github.com/osism/python-osism/pull/2370
        commit_id: cbce709e83be001a3984f8fe3878f1df1476e8da
        patchset: cbce709e83be001a3984f8fe3878f1df1476e8da
        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: '2370'
      change_message: "sonic: enforce per-key ownership of ACL tables\n\n## Problem\n\n`ACL_TABLE`
        and `ACL_RULE` are owned by more than one control-plane section helper (SSH,
        SNMP, gNMI). The ownership model settled in the `generate_sonic_config` docstring
        covers whole-table ownership but not how several helpers share one owned table.
        The open ACL PRs each rebind the whole table \u2014 `config[\"ACL_TABLE\"]
        = {...}` \u2014 so whichever helper runs second drops the first's entries,
        leaving SSH *or* SNMP/gNMI unrestricted. Each PR passes its own tests because
        neither calls the other helper, so the collision is invisible when the PRs
        are reviewed in isolation.\n\n## Change\n\nCo-owned tables must be merged
        per named entry, never rebound. The rule is locked in code rather than left
        to review, so a divergent PR fails CI before it can merge:\n\n- `MULTI_OWNER_OWNED_TABLE_KEYS`
        lists `ACL_TABLE`/`ACL_RULE`.\n- A static guard (`TestMultiOwnerTableGuard`)
        parses the generator source and fails on every form that rebinds a listed
        table wholesale on `config`: `config[\"X\"] = <expr>`, `config.update({\"X\":
        ...})`, `config |= {\"X\": ...}`, and `config = {**config, \"X\": ...}`. These
        mirror the wholesale-write forms the existing mutation backstop recognizes,
        so no analyzable write can rebind a listed table without being caught.\n-
        In-place forms that mutate the table dict are left alone: `config[\"X\"][\"k\"]
        = ...`, `config[\"X\"].update(...)`, `config[\"X\"] |= ...`, and `config.setdefault(\"X\",
        {})`. Synthetic-source detector tests prove the guard catches each rebind
        form and passes the in-place forms, so it cannot pass vacuously.\n\nThe tables
        are listed ahead of the helpers that introduce them, so the first ACL helper
        to land is forced onto the per-key pattern rather than establishing the unsafe
        one. Two invariants tie the list to the rest of the model: a referenced multi-owner
        table must also be in `OWNED_TABLE_KEYS` (so the central up-front drop clears
        it and no stale entry survives the merge), and multi-owner tables must not
        be inherited or image-consumed (those regimes are not dropped). Both hold
        now and after the ACL helpers add `ACL_TABLE`/`ACL_RULE` to `ON_DEMAND_OWNED_TABLE_KEYS`.\n\n##
        Note for the ACL PRs\n\nThis guard is dormant until a helper references the
        tables. When the control-plane ACL work lands, each helper must merge its
        own keys and the PR must add `ACL_TABLE`/`ACL_RULE` to `ON_DEMAND_OWNED_TABLE_KEYS`
        in the same change (the `test_referenced_multi_owner_tables_are_owned` invariant
        enforces this).\n\n## Related\n\n- osism/python-osism#2340\n- osism/python-osism#2339\n-
        osism/python-osism#2337\n- osism/python-osism#2338"
      change_url: https://github.com/osism/python-osism/pull/2370
      child_jobs: []
      commit_id: cbce709e83be001a3984f8fe3878f1df1476e8da
      event_id: cdf7cfa0-6715-11f1-88e1-1f4cc9e87866
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/c6fa6f69917843bca0619acef880b176/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/c6fa6f69917843bca0619acef880b176/work/logs
        result_data_file: /var/lib/zuul/builds/c6fa6f69917843bca0619acef880b176/work/results.json
        src_root: /var/lib/zuul/builds/c6fa6f69917843bca0619acef880b176/work/src
        work_root: /var/lib/zuul/builds/c6fa6f69917843bca0619acef880b176/work
      include_vars: []
      items:
      - branch: main
        change: '2370'
        change_message: "sonic: enforce per-key ownership of ACL tables\n\n## Problem\n\n`ACL_TABLE`
          and `ACL_RULE` are owned by more than one control-plane section helper (SSH,
          SNMP, gNMI). The ownership model settled in the `generate_sonic_config`
          docstring covers whole-table ownership but not how several helpers share
          one owned table. The open ACL PRs each rebind the whole table \u2014 `config[\"ACL_TABLE\"]
          = {...}` \u2014 so whichever helper runs second drops the first's entries,
          leaving SSH *or* SNMP/gNMI unrestricted. Each PR passes its own tests because
          neither calls the other helper, so the collision is invisible when the PRs
          are reviewed in isolation.\n\n## Change\n\nCo-owned tables must be merged
          per named entry, never rebound. The rule is locked in code rather than left
          to review, so a divergent PR fails CI before it can merge:\n\n- `MULTI_OWNER_OWNED_TABLE_KEYS`
          lists `ACL_TABLE`/`ACL_RULE`.\n- A static guard (`TestMultiOwnerTableGuard`)
          parses the generator source and fails on every form that rebinds a listed
          table wholesale on `config`: `config[\"X\"] = <expr>`, `config.update({\"X\":
          ...})`, `config |= {\"X\": ...}`, and `config = {**config, \"X\": ...}`.
          These mirror the wholesale-write forms the existing mutation backstop recognizes,
          so no analyzable write can rebind a listed table without being caught.\n-
          In-place forms that mutate the table dict are left alone: `config[\"X\"][\"k\"]
          = ...`, `config[\"X\"].update(...)`, `config[\"X\"] |= ...`, and `config.setdefault(\"X\",
          {})`. Synthetic-source detector tests prove the guard catches each rebind
          form and passes the in-place forms, so it cannot pass vacuously.\n\nThe
          tables are listed ahead of the helpers that introduce them, so the first
          ACL helper to land is forced onto the per-key pattern rather than establishing
          the unsafe one. Two invariants tie the list to the rest of the model: a
          referenced multi-owner table must also be in `OWNED_TABLE_KEYS` (so the
          central up-front drop clears it and no stale entry survives the merge),
          and multi-owner tables must not be inherited or image-consumed (those regimes
          are not dropped). Both hold now and after the ACL helpers add `ACL_TABLE`/`ACL_RULE`
          to `ON_DEMAND_OWNED_TABLE_KEYS`.\n\n## Note for the ACL PRs\n\nThis guard
          is dormant until a helper references the tables. When the control-plane
          ACL work lands, each helper must merge its own keys and the PR must add
          `ACL_TABLE`/`ACL_RULE` to `ON_DEMAND_OWNED_TABLE_KEYS` in the same change
          (the `test_referenced_multi_owner_tables_are_owned` invariant enforces this).\n\n##
          Related\n\n- osism/python-osism#2340\n- osism/python-osism#2339\n- osism/python-osism#2337\n-
          osism/python-osism#2338"
        change_url: https://github.com/osism/python-osism/pull/2370
        commit_id: cbce709e83be001a3984f8fe3878f1df1476e8da
        patchset: cbce709e83be001a3984f8fe3878f1df1476e8da
        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: python-black
      jobtags: []
      max_attempts: 3
      message: c29uaWM6IGVuZm9yY2UgcGVyLWtleSBvd25lcnNoaXAgb2YgQUNMIHRhYmxlcwoKIyMgUHJvYmxlbQoKYEFDTF9UQUJMRWAgYW5kIGBBQ0xfUlVMRWAgYXJlIG93bmVkIGJ5IG1vcmUgdGhhbiBvbmUgY29udHJvbC1wbGFuZSBzZWN0aW9uIGhlbHBlciAoU1NILCBTTk1QLCBnTk1JKS4gVGhlIG93bmVyc2hpcCBtb2RlbCBzZXR0bGVkIGluIHRoZSBgZ2VuZXJhdGVfc29uaWNfY29uZmlnYCBkb2NzdHJpbmcgY292ZXJzIHdob2xlLXRhYmxlIG93bmVyc2hpcCBidXQgbm90IGhvdyBzZXZlcmFsIGhlbHBlcnMgc2hhcmUgb25lIG93bmVkIHRhYmxlLiBUaGUgb3BlbiBBQ0wgUFJzIGVhY2ggcmViaW5kIHRoZSB3aG9sZSB0YWJsZSDigJQgYGNvbmZpZ1siQUNMX1RBQkxFIl0gPSB7Li4ufWAg4oCUIHNvIHdoaWNoZXZlciBoZWxwZXIgcnVucyBzZWNvbmQgZHJvcHMgdGhlIGZpcnN0J3MgZW50cmllcywgbGVhdmluZyBTU0ggKm9yKiBTTk1QL2dOTUkgdW5yZXN0cmljdGVkLiBFYWNoIFBSIHBhc3NlcyBpdHMgb3duIHRlc3RzIGJlY2F1c2UgbmVpdGhlciBjYWxscyB0aGUgb3RoZXIgaGVscGVyLCBzbyB0aGUgY29sbGlzaW9uIGlzIGludmlzaWJsZSB3aGVuIHRoZSBQUnMgYXJlIHJldmlld2VkIGluIGlzb2xhdGlvbi4KCiMjIENoYW5nZQoKQ28tb3duZWQgdGFibGVzIG11c3QgYmUgbWVyZ2VkIHBlciBuYW1lZCBlbnRyeSwgbmV2ZXIgcmVib3VuZC4gVGhlIHJ1bGUgaXMgbG9ja2VkIGluIGNvZGUgcmF0aGVyIHRoYW4gbGVmdCB0byByZXZpZXcsIHNvIGEgZGl2ZXJnZW50IFBSIGZhaWxzIENJIGJlZm9yZSBpdCBjYW4gbWVyZ2U6CgotIGBNVUxUSV9PV05FUl9PV05FRF9UQUJMRV9LRVlTYCBsaXN0cyBgQUNMX1RBQkxFYC9gQUNMX1JVTEVgLgotIEEgc3RhdGljIGd1YXJkIChgVGVzdE11bHRpT3duZXJUYWJsZUd1YXJkYCkgcGFyc2VzIHRoZSBnZW5lcmF0b3Igc291cmNlIGFuZCBmYWlscyBvbiBldmVyeSBmb3JtIHRoYXQgcmViaW5kcyBhIGxpc3RlZCB0YWJsZSB3aG9sZXNhbGUgb24gYGNvbmZpZ2A6IGBjb25maWdbIlgiXSA9IDxleHByPmAsIGBjb25maWcudXBkYXRlKHsiWCI6IC4uLn0pYCwgYGNvbmZpZyB8PSB7IlgiOiAuLi59YCwgYW5kIGBjb25maWcgPSB7Kipjb25maWcsICJYIjogLi4ufWAuIFRoZXNlIG1pcnJvciB0aGUgd2hvbGVzYWxlLXdyaXRlIGZvcm1zIHRoZSBleGlzdGluZyBtdXRhdGlvbiBiYWNrc3RvcCByZWNvZ25pemVzLCBzbyBubyBhbmFseXphYmxlIHdyaXRlIGNhbiByZWJpbmQgYSBsaXN0ZWQgdGFibGUgd2l0aG91dCBiZWluZyBjYXVnaHQuCi0gSW4tcGxhY2UgZm9ybXMgdGhhdCBtdXRhdGUgdGhlIHRhYmxlIGRpY3QgYXJlIGxlZnQgYWxvbmU6IGBjb25maWdbIlgiXVsiayJdID0gLi4uYCwgYGNvbmZpZ1siWCJdLnVwZGF0ZSguLi4pYCwgYGNvbmZpZ1siWCJdIHw9IC4uLmAsIGFuZCBgY29uZmlnLnNldGRlZmF1bHQoIlgiLCB7fSlgLiBTeW50aGV0aWMtc291cmNlIGRldGVjdG9yIHRlc3RzIHByb3ZlIHRoZSBndWFyZCBjYXRjaGVzIGVhY2ggcmViaW5kIGZvcm0gYW5kIHBhc3NlcyB0aGUgaW4tcGxhY2UgZm9ybXMsIHNvIGl0IGNhbm5vdCBwYXNzIHZhY3VvdXNseS4KClRoZSB0YWJsZXMgYXJlIGxpc3RlZCBhaGVhZCBvZiB0aGUgaGVscGVycyB0aGF0IGludHJvZHVjZSB0aGVtLCBzbyB0aGUgZmlyc3QgQUNMIGhlbHBlciB0byBsYW5kIGlzIGZvcmNlZCBvbnRvIHRoZSBwZXIta2V5IHBhdHRlcm4gcmF0aGVyIHRoYW4gZXN0YWJsaXNoaW5nIHRoZSB1bnNhZmUgb25lLiBUd28gaW52YXJpYW50cyB0aWUgdGhlIGxpc3QgdG8gdGhlIHJlc3Qgb2YgdGhlIG1vZGVsOiBhIHJlZmVyZW5jZWQgbXVsdGktb3duZXIgdGFibGUgbXVzdCBhbHNvIGJlIGluIGBPV05FRF9UQUJMRV9LRVlTYCAoc28gdGhlIGNlbnRyYWwgdXAtZnJvbnQgZHJvcCBjbGVhcnMgaXQgYW5kIG5vIHN0YWxlIGVudHJ5IHN1cnZpdmVzIHRoZSBtZXJnZSksIGFuZCBtdWx0aS1vd25lciB0YWJsZXMgbXVzdCBub3QgYmUgaW5oZXJpdGVkIG9yIGltYWdlLWNvbnN1bWVkICh0aG9zZSByZWdpbWVzIGFyZSBub3QgZHJvcHBlZCkuIEJvdGggaG9sZCBub3cgYW5kIGFmdGVyIHRoZSBBQ0wgaGVscGVycyBhZGQgYEFDTF9UQUJMRWAvYEFDTF9SVUxFYCB0byBgT05fREVNQU5EX09XTkVEX1RBQkxFX0tFWVNgLgoKIyMgTm90ZSBmb3IgdGhlIEFDTCBQUnMKClRoaXMgZ3VhcmQgaXMgZG9ybWFudCB1bnRpbCBhIGhlbHBlciByZWZlcmVuY2VzIHRoZSB0YWJsZXMuIFdoZW4gdGhlIGNvbnRyb2wtcGxhbmUgQUNMIHdvcmsgbGFuZHMsIGVhY2ggaGVscGVyIG11c3QgbWVyZ2UgaXRzIG93biBrZXlzIGFuZCB0aGUgUFIgbXVzdCBhZGQgYEFDTF9UQUJMRWAvYEFDTF9SVUxFYCB0byBgT05fREVNQU5EX09XTkVEX1RBQkxFX0tFWVNgIGluIHRoZSBzYW1lIGNoYW5nZSAodGhlIGB0ZXN0X3JlZmVyZW5jZWRfbXVsdGlfb3duZXJfdGFibGVzX2FyZV9vd25lZGAgaW52YXJpYW50IGVuZm9yY2VzIHRoaXMpLgoKIyMgUmVsYXRlZAoKLSBvc2lzbS9weXRob24tb3Npc20jMjM0MAotIG9zaXNtL3B5dGhvbi1vc2lzbSMyMzM5Ci0gb3Npc20vcHl0aG9uLW9zaXNtIzIzMzcKLSBvc2lzbS9weXRob24tb3Npc20jMjMzOA==
      patchset: cbce709e83be001a3984f8fe3878f1df1476e8da
      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/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: 0c74c57cedff2b36bb37ca68a5338d1c49991496
          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
        playbooks:
        - path: untrusted/project_0/github.com/osism/zuul-jobs/playbooks/python-black/run.yml
          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: 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: f09d0f79a935e3ff7dfeb82ed40122f9997b6892
          name: osism/python-osism
          required: false
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
      ref: refs/pull/2370/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
