all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fec6:ecaf
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 1f44877a-7d5e-401f-84d5-0061e58010f2
        host_id: 4ba4344415ca7057d9956ea5de826bbc0b830981e82c0e0f191fa07b
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fec6:ecaf
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.157
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.193.39
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fec6:ecaf
        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-osism-unit-tests explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/python-osism/.zuul.yaml@main#133>'
      - '<Job python-osism-unit-tests explicit: None implied: None source: osism/python-osism/.zuul.yaml@main#138>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: baa9a9b3c6534acea8b4dc7bf9c17b9d
      build_refs:
      - branch: main
        change: '2339'
        change_message: "sonic: Enforce config table ownership statically\n\n## Purpose\n\nThis
          PR establishes a single, enforced ownership model for the SONiC config\ngenerator
          so that all forthcoming PRs touching the generator converge on one\nconsistent
          approach rather than each inventing its own. Several SONiC features\nare
          in flight (ACL hardening, BFD, EVPN, static routes, \u2026); without a\nself-enforcing
          model they drift \u2014 adding tables the generator does not\nclassify,
          which silently reintroduces the stale-config bug the ownership model\nexists
          to prevent. This change turns the model from documentation into a CI\ngate:
          a new table that is not classified fails the build with a message\npointing
          at the right list.\n\n(A GitHub issue with the full context and the related
          ownership decisions will\nbe linked here; this PR stands on its own as the
          enforcement mechanism.)\n\n## What\n\nThe generator owns selected `config_db.json`
          tables (dropped and rebuilt every\nregen), but the ownership registry was
          a hand-maintained allowlist with no\nenforcement: a table the generator
          references but forgets to classify falls\ninto the unpoliced pass-through
          tier and silently accumulates stale config. The\nexisting tests only checked
          relationships between the registered constants, so\nthey could not catch
          an omission, and the model lived in a single docstring far\nfrom the helpers
          that must honour it.\n\n## Changes\n\n- **Static guard test.** Parses `config_generator.py`
          and collects every\n  top-level `config_db` table referenced on `config`
          \u2014 `config[\"X\"]`\n  subscripts, the defensive `config.get/setdefault/pop(\"X\")`
          accessors (a\n  `.get()` read is a real dependency), and every literal-keyed
          merge form\n  (`update({...})`, `update(X=...)`, `update(**{...})`, `|=`,
          `config | {...}`,\n  `{**config, ...}`). The test fails when any referenced
          table is not\n  classified as owned, inherited, or image-consumed, naming
          the table and the\n  list to add it to. Static rather than runtime so it
          catches tables that emit\n  only when NetBox carries their data, which a
          generate-and-inspect test would\n  miss.\n\n- **Mutation backstop.** A second
          guard rejects any `config` mutation the\n  collector cannot statically read
          \u2014 an unrecognized method call or a\n  reassignment that is not a dict
          display, a dict-merge, or a whitelisted base\n  load \u2014 so coverage
          cannot erode silently. The one accepted blind spot is a\n  dynamic key in
          a recognized form (`config[var]`, `config.update(name)`),\n  which the scaffold
          and drop loops rely on.\n\n- **Fourth ownership category, `IMAGE_CONSUMED_TABLE_KEYS`.**
          For tables read\n  from the image base config but never modified (read-only
          inputs that pass\n  through to output). Empty for now; the first consumer
          is the gNMI listen port\n  read from `TELEMETRY`. Disjointness invariants
          complete pairwise across\n  owned / inherited / image-consumed.\n\n- **Docstring
          + comments** rewritten around the four categories\n  (owned / inherited
          / image-consumed / pass-through), with the inherited\n  category corrected
          to \"preserves base content, updates selected fields in\n  place\" rather
          than \"emitted unchanged\".\n\n## Notes\n\n- Verified clean on the current
          tree: all referenced tables classify, the\n  backstop passes, full suite
          green.\n- Several open SONiC PRs add tables that are not yet registered
          (e.g. BFD,\n  EVPN); once this lands they will get a red check pointing
          at the right list\n  rather than shipping latent stale-config data loss.\n\n\U0001F916
          Generated with [Claude Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/python-osism/pull/2339
        commit_id: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
        patchset: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
        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: 228c05f5a7ec47e5bd1111eb119f5b30
      buildset_refs:
      - branch: main
        change: '2339'
        change_message: "sonic: Enforce config table ownership statically\n\n## Purpose\n\nThis
          PR establishes a single, enforced ownership model for the SONiC config\ngenerator
          so that all forthcoming PRs touching the generator converge on one\nconsistent
          approach rather than each inventing its own. Several SONiC features\nare
          in flight (ACL hardening, BFD, EVPN, static routes, \u2026); without a\nself-enforcing
          model they drift \u2014 adding tables the generator does not\nclassify,
          which silently reintroduces the stale-config bug the ownership model\nexists
          to prevent. This change turns the model from documentation into a CI\ngate:
          a new table that is not classified fails the build with a message\npointing
          at the right list.\n\n(A GitHub issue with the full context and the related
          ownership decisions will\nbe linked here; this PR stands on its own as the
          enforcement mechanism.)\n\n## What\n\nThe generator owns selected `config_db.json`
          tables (dropped and rebuilt every\nregen), but the ownership registry was
          a hand-maintained allowlist with no\nenforcement: a table the generator
          references but forgets to classify falls\ninto the unpoliced pass-through
          tier and silently accumulates stale config. The\nexisting tests only checked
          relationships between the registered constants, so\nthey could not catch
          an omission, and the model lived in a single docstring far\nfrom the helpers
          that must honour it.\n\n## Changes\n\n- **Static guard test.** Parses `config_generator.py`
          and collects every\n  top-level `config_db` table referenced on `config`
          \u2014 `config[\"X\"]`\n  subscripts, the defensive `config.get/setdefault/pop(\"X\")`
          accessors (a\n  `.get()` read is a real dependency), and every literal-keyed
          merge form\n  (`update({...})`, `update(X=...)`, `update(**{...})`, `|=`,
          `config | {...}`,\n  `{**config, ...}`). The test fails when any referenced
          table is not\n  classified as owned, inherited, or image-consumed, naming
          the table and the\n  list to add it to. Static rather than runtime so it
          catches tables that emit\n  only when NetBox carries their data, which a
          generate-and-inspect test would\n  miss.\n\n- **Mutation backstop.** A second
          guard rejects any `config` mutation the\n  collector cannot statically read
          \u2014 an unrecognized method call or a\n  reassignment that is not a dict
          display, a dict-merge, or a whitelisted base\n  load \u2014 so coverage
          cannot erode silently. The one accepted blind spot is a\n  dynamic key in
          a recognized form (`config[var]`, `config.update(name)`),\n  which the scaffold
          and drop loops rely on.\n\n- **Fourth ownership category, `IMAGE_CONSUMED_TABLE_KEYS`.**
          For tables read\n  from the image base config but never modified (read-only
          inputs that pass\n  through to output). Empty for now; the first consumer
          is the gNMI listen port\n  read from `TELEMETRY`. Disjointness invariants
          complete pairwise across\n  owned / inherited / image-consumed.\n\n- **Docstring
          + comments** rewritten around the four categories\n  (owned / inherited
          / image-consumed / pass-through), with the inherited\n  category corrected
          to \"preserves base content, updates selected fields in\n  place\" rather
          than \"emitted unchanged\".\n\n## Notes\n\n- Verified clean on the current
          tree: all referenced tables classify, the\n  backstop passes, full suite
          green.\n- Several open SONiC PRs add tables that are not yet registered
          (e.g. BFD,\n  EVPN); once this lands they will get a red check pointing
          at the right list\n  rather than shipping latent stale-config data loss.\n\n\U0001F916
          Generated with [Claude Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/python-osism/pull/2339
        commit_id: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
        patchset: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
        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: '2339'
      change_message: "sonic: Enforce config table ownership statically\n\n## Purpose\n\nThis
        PR establishes a single, enforced ownership model for the SONiC config\ngenerator
        so that all forthcoming PRs touching the generator converge on one\nconsistent
        approach rather than each inventing its own. Several SONiC features\nare in
        flight (ACL hardening, BFD, EVPN, static routes, \u2026); without a\nself-enforcing
        model they drift \u2014 adding tables the generator does not\nclassify, which
        silently reintroduces the stale-config bug the ownership model\nexists to
        prevent. This change turns the model from documentation into a CI\ngate: a
        new table that is not classified fails the build with a message\npointing
        at the right list.\n\n(A GitHub issue with the full context and the related
        ownership decisions will\nbe linked here; this PR stands on its own as the
        enforcement mechanism.)\n\n## What\n\nThe generator owns selected `config_db.json`
        tables (dropped and rebuilt every\nregen), but the ownership registry was
        a hand-maintained allowlist with no\nenforcement: a table the generator references
        but forgets to classify falls\ninto the unpoliced pass-through tier and silently
        accumulates stale config. The\nexisting tests only checked relationships between
        the registered constants, so\nthey could not catch an omission, and the model
        lived in a single docstring far\nfrom the helpers that must honour it.\n\n##
        Changes\n\n- **Static guard test.** Parses `config_generator.py` and collects
        every\n  top-level `config_db` table referenced on `config` \u2014 `config[\"X\"]`\n
        \ subscripts, the defensive `config.get/setdefault/pop(\"X\")` accessors (a\n
        \ `.get()` read is a real dependency), and every literal-keyed merge form\n
        \ (`update({...})`, `update(X=...)`, `update(**{...})`, `|=`, `config | {...}`,\n
        \ `{**config, ...}`). The test fails when any referenced table is not\n  classified
        as owned, inherited, or image-consumed, naming the table and the\n  list to
        add it to. Static rather than runtime so it catches tables that emit\n  only
        when NetBox carries their data, which a generate-and-inspect test would\n
        \ miss.\n\n- **Mutation backstop.** A second guard rejects any `config` mutation
        the\n  collector cannot statically read \u2014 an unrecognized method call
        or a\n  reassignment that is not a dict display, a dict-merge, or a whitelisted
        base\n  load \u2014 so coverage cannot erode silently. The one accepted blind
        spot is a\n  dynamic key in a recognized form (`config[var]`, `config.update(name)`),\n
        \ which the scaffold and drop loops rely on.\n\n- **Fourth ownership category,
        `IMAGE_CONSUMED_TABLE_KEYS`.** For tables read\n  from the image base config
        but never modified (read-only inputs that pass\n  through to output). Empty
        for now; the first consumer is the gNMI listen port\n  read from `TELEMETRY`.
        Disjointness invariants complete pairwise across\n  owned / inherited / image-consumed.\n\n-
        **Docstring + comments** rewritten around the four categories\n  (owned /
        inherited / image-consumed / pass-through), with the inherited\n  category
        corrected to \"preserves base content, updates selected fields in\n  place\"
        rather than \"emitted unchanged\".\n\n## Notes\n\n- Verified clean on the
        current tree: all referenced tables classify, the\n  backstop passes, full
        suite green.\n- Several open SONiC PRs add tables that are not yet registered
        (e.g. BFD,\n  EVPN); once this lands they will get a red check pointing at
        the right list\n  rather than shipping latent stale-config data loss.\n\n\U0001F916
        Generated with [Claude Code](https://claude.com/claude-code)"
      change_url: https://github.com/osism/python-osism/pull/2339
      child_jobs: []
      commit_id: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
      event_id: c71fab80-64d1-11f1-8027-244bc1948fd8
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/baa9a9b3c6534acea8b4dc7bf9c17b9d/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/baa9a9b3c6534acea8b4dc7bf9c17b9d/work/logs
        result_data_file: /var/lib/zuul/builds/baa9a9b3c6534acea8b4dc7bf9c17b9d/work/results.json
        src_root: /var/lib/zuul/builds/baa9a9b3c6534acea8b4dc7bf9c17b9d/work/src
        work_root: /var/lib/zuul/builds/baa9a9b3c6534acea8b4dc7bf9c17b9d/work
      include_vars: []
      items:
      - branch: main
        change: '2339'
        change_message: "sonic: Enforce config table ownership statically\n\n## Purpose\n\nThis
          PR establishes a single, enforced ownership model for the SONiC config\ngenerator
          so that all forthcoming PRs touching the generator converge on one\nconsistent
          approach rather than each inventing its own. Several SONiC features\nare
          in flight (ACL hardening, BFD, EVPN, static routes, \u2026); without a\nself-enforcing
          model they drift \u2014 adding tables the generator does not\nclassify,
          which silently reintroduces the stale-config bug the ownership model\nexists
          to prevent. This change turns the model from documentation into a CI\ngate:
          a new table that is not classified fails the build with a message\npointing
          at the right list.\n\n(A GitHub issue with the full context and the related
          ownership decisions will\nbe linked here; this PR stands on its own as the
          enforcement mechanism.)\n\n## What\n\nThe generator owns selected `config_db.json`
          tables (dropped and rebuilt every\nregen), but the ownership registry was
          a hand-maintained allowlist with no\nenforcement: a table the generator
          references but forgets to classify falls\ninto the unpoliced pass-through
          tier and silently accumulates stale config. The\nexisting tests only checked
          relationships between the registered constants, so\nthey could not catch
          an omission, and the model lived in a single docstring far\nfrom the helpers
          that must honour it.\n\n## Changes\n\n- **Static guard test.** Parses `config_generator.py`
          and collects every\n  top-level `config_db` table referenced on `config`
          \u2014 `config[\"X\"]`\n  subscripts, the defensive `config.get/setdefault/pop(\"X\")`
          accessors (a\n  `.get()` read is a real dependency), and every literal-keyed
          merge form\n  (`update({...})`, `update(X=...)`, `update(**{...})`, `|=`,
          `config | {...}`,\n  `{**config, ...}`). The test fails when any referenced
          table is not\n  classified as owned, inherited, or image-consumed, naming
          the table and the\n  list to add it to. Static rather than runtime so it
          catches tables that emit\n  only when NetBox carries their data, which a
          generate-and-inspect test would\n  miss.\n\n- **Mutation backstop.** A second
          guard rejects any `config` mutation the\n  collector cannot statically read
          \u2014 an unrecognized method call or a\n  reassignment that is not a dict
          display, a dict-merge, or a whitelisted base\n  load \u2014 so coverage
          cannot erode silently. The one accepted blind spot is a\n  dynamic key in
          a recognized form (`config[var]`, `config.update(name)`),\n  which the scaffold
          and drop loops rely on.\n\n- **Fourth ownership category, `IMAGE_CONSUMED_TABLE_KEYS`.**
          For tables read\n  from the image base config but never modified (read-only
          inputs that pass\n  through to output). Empty for now; the first consumer
          is the gNMI listen port\n  read from `TELEMETRY`. Disjointness invariants
          complete pairwise across\n  owned / inherited / image-consumed.\n\n- **Docstring
          + comments** rewritten around the four categories\n  (owned / inherited
          / image-consumed / pass-through), with the inherited\n  category corrected
          to \"preserves base content, updates selected fields in\n  place\" rather
          than \"emitted unchanged\".\n\n## Notes\n\n- Verified clean on the current
          tree: all referenced tables classify, the\n  backstop passes, full suite
          green.\n- Several open SONiC PRs add tables that are not yet registered
          (e.g. BFD,\n  EVPN); once this lands they will get a red check pointing
          at the right list\n  rather than shipping latent stale-config data loss.\n\n\U0001F916
          Generated with [Claude Code](https://claude.com/claude-code)"
        change_url: https://github.com/osism/python-osism/pull/2339
        commit_id: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
        patchset: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
        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-osism-unit-tests
      jobtags: []
      max_attempts: 3
      message: c29uaWM6IEVuZm9yY2UgY29uZmlnIHRhYmxlIG93bmVyc2hpcCBzdGF0aWNhbGx5CgojIyBQdXJwb3NlCgpUaGlzIFBSIGVzdGFibGlzaGVzIGEgc2luZ2xlLCBlbmZvcmNlZCBvd25lcnNoaXAgbW9kZWwgZm9yIHRoZSBTT05pQyBjb25maWcKZ2VuZXJhdG9yIHNvIHRoYXQgYWxsIGZvcnRoY29taW5nIFBScyB0b3VjaGluZyB0aGUgZ2VuZXJhdG9yIGNvbnZlcmdlIG9uIG9uZQpjb25zaXN0ZW50IGFwcHJvYWNoIHJhdGhlciB0aGFuIGVhY2ggaW52ZW50aW5nIGl0cyBvd24uIFNldmVyYWwgU09OaUMgZmVhdHVyZXMKYXJlIGluIGZsaWdodCAoQUNMIGhhcmRlbmluZywgQkZELCBFVlBOLCBzdGF0aWMgcm91dGVzLCDigKYpOyB3aXRob3V0IGEKc2VsZi1lbmZvcmNpbmcgbW9kZWwgdGhleSBkcmlmdCDigJQgYWRkaW5nIHRhYmxlcyB0aGUgZ2VuZXJhdG9yIGRvZXMgbm90CmNsYXNzaWZ5LCB3aGljaCBzaWxlbnRseSByZWludHJvZHVjZXMgdGhlIHN0YWxlLWNvbmZpZyBidWcgdGhlIG93bmVyc2hpcCBtb2RlbApleGlzdHMgdG8gcHJldmVudC4gVGhpcyBjaGFuZ2UgdHVybnMgdGhlIG1vZGVsIGZyb20gZG9jdW1lbnRhdGlvbiBpbnRvIGEgQ0kKZ2F0ZTogYSBuZXcgdGFibGUgdGhhdCBpcyBub3QgY2xhc3NpZmllZCBmYWlscyB0aGUgYnVpbGQgd2l0aCBhIG1lc3NhZ2UKcG9pbnRpbmcgYXQgdGhlIHJpZ2h0IGxpc3QuCgooQSBHaXRIdWIgaXNzdWUgd2l0aCB0aGUgZnVsbCBjb250ZXh0IGFuZCB0aGUgcmVsYXRlZCBvd25lcnNoaXAgZGVjaXNpb25zIHdpbGwKYmUgbGlua2VkIGhlcmU7IHRoaXMgUFIgc3RhbmRzIG9uIGl0cyBvd24gYXMgdGhlIGVuZm9yY2VtZW50IG1lY2hhbmlzbS4pCgojIyBXaGF0CgpUaGUgZ2VuZXJhdG9yIG93bnMgc2VsZWN0ZWQgYGNvbmZpZ19kYi5qc29uYCB0YWJsZXMgKGRyb3BwZWQgYW5kIHJlYnVpbHQgZXZlcnkKcmVnZW4pLCBidXQgdGhlIG93bmVyc2hpcCByZWdpc3RyeSB3YXMgYSBoYW5kLW1haW50YWluZWQgYWxsb3dsaXN0IHdpdGggbm8KZW5mb3JjZW1lbnQ6IGEgdGFibGUgdGhlIGdlbmVyYXRvciByZWZlcmVuY2VzIGJ1dCBmb3JnZXRzIHRvIGNsYXNzaWZ5IGZhbGxzCmludG8gdGhlIHVucG9saWNlZCBwYXNzLXRocm91Z2ggdGllciBhbmQgc2lsZW50bHkgYWNjdW11bGF0ZXMgc3RhbGUgY29uZmlnLiBUaGUKZXhpc3RpbmcgdGVzdHMgb25seSBjaGVja2VkIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB0aGUgcmVnaXN0ZXJlZCBjb25zdGFudHMsIHNvCnRoZXkgY291bGQgbm90IGNhdGNoIGFuIG9taXNzaW9uLCBhbmQgdGhlIG1vZGVsIGxpdmVkIGluIGEgc2luZ2xlIGRvY3N0cmluZyBmYXIKZnJvbSB0aGUgaGVscGVycyB0aGF0IG11c3QgaG9ub3VyIGl0LgoKIyMgQ2hhbmdlcwoKLSAqKlN0YXRpYyBndWFyZCB0ZXN0LioqIFBhcnNlcyBgY29uZmlnX2dlbmVyYXRvci5weWAgYW5kIGNvbGxlY3RzIGV2ZXJ5CiAgdG9wLWxldmVsIGBjb25maWdfZGJgIHRhYmxlIHJlZmVyZW5jZWQgb24gYGNvbmZpZ2Ag4oCUIGBjb25maWdbIlgiXWAKICBzdWJzY3JpcHRzLCB0aGUgZGVmZW5zaXZlIGBjb25maWcuZ2V0L3NldGRlZmF1bHQvcG9wKCJYIilgIGFjY2Vzc29ycyAoYQogIGAuZ2V0KClgIHJlYWQgaXMgYSByZWFsIGRlcGVuZGVuY3kpLCBhbmQgZXZlcnkgbGl0ZXJhbC1rZXllZCBtZXJnZSBmb3JtCiAgKGB1cGRhdGUoey4uLn0pYCwgYHVwZGF0ZShYPS4uLilgLCBgdXBkYXRlKCoqey4uLn0pYCwgYHw9YCwgYGNvbmZpZyB8IHsuLi59YCwKICBgeyoqY29uZmlnLCAuLi59YCkuIFRoZSB0ZXN0IGZhaWxzIHdoZW4gYW55IHJlZmVyZW5jZWQgdGFibGUgaXMgbm90CiAgY2xhc3NpZmllZCBhcyBvd25lZCwgaW5oZXJpdGVkLCBvciBpbWFnZS1jb25zdW1lZCwgbmFtaW5nIHRoZSB0YWJsZSBhbmQgdGhlCiAgbGlzdCB0byBhZGQgaXQgdG8uIFN0YXRpYyByYXRoZXIgdGhhbiBydW50aW1lIHNvIGl0IGNhdGNoZXMgdGFibGVzIHRoYXQgZW1pdAogIG9ubHkgd2hlbiBOZXRCb3ggY2FycmllcyB0aGVpciBkYXRhLCB3aGljaCBhIGdlbmVyYXRlLWFuZC1pbnNwZWN0IHRlc3Qgd291bGQKICBtaXNzLgoKLSAqKk11dGF0aW9uIGJhY2tzdG9wLioqIEEgc2Vjb25kIGd1YXJkIHJlamVjdHMgYW55IGBjb25maWdgIG11dGF0aW9uIHRoZQogIGNvbGxlY3RvciBjYW5ub3Qgc3RhdGljYWxseSByZWFkIOKAlCBhbiB1bnJlY29nbml6ZWQgbWV0aG9kIGNhbGwgb3IgYQogIHJlYXNzaWdubWVudCB0aGF0IGlzIG5vdCBhIGRpY3QgZGlzcGxheSwgYSBkaWN0LW1lcmdlLCBvciBhIHdoaXRlbGlzdGVkIGJhc2UKICBsb2FkIOKAlCBzbyBjb3ZlcmFnZSBjYW5ub3QgZXJvZGUgc2lsZW50bHkuIFRoZSBvbmUgYWNjZXB0ZWQgYmxpbmQgc3BvdCBpcyBhCiAgZHluYW1pYyBrZXkgaW4gYSByZWNvZ25pemVkIGZvcm0gKGBjb25maWdbdmFyXWAsIGBjb25maWcudXBkYXRlKG5hbWUpYCksCiAgd2hpY2ggdGhlIHNjYWZmb2xkIGFuZCBkcm9wIGxvb3BzIHJlbHkgb24uCgotICoqRm91cnRoIG93bmVyc2hpcCBjYXRlZ29yeSwgYElNQUdFX0NPTlNVTUVEX1RBQkxFX0tFWVNgLioqIEZvciB0YWJsZXMgcmVhZAogIGZyb20gdGhlIGltYWdlIGJhc2UgY29uZmlnIGJ1dCBuZXZlciBtb2RpZmllZCAocmVhZC1vbmx5IGlucHV0cyB0aGF0IHBhc3MKICB0aHJvdWdoIHRvIG91dHB1dCkuIEVtcHR5IGZvciBub3c7IHRoZSBmaXJzdCBjb25zdW1lciBpcyB0aGUgZ05NSSBsaXN0ZW4gcG9ydAogIHJlYWQgZnJvbSBgVEVMRU1FVFJZYC4gRGlzam9pbnRuZXNzIGludmFyaWFudHMgY29tcGxldGUgcGFpcndpc2UgYWNyb3NzCiAgb3duZWQgLyBpbmhlcml0ZWQgLyBpbWFnZS1jb25zdW1lZC4KCi0gKipEb2NzdHJpbmcgKyBjb21tZW50cyoqIHJld3JpdHRlbiBhcm91bmQgdGhlIGZvdXIgY2F0ZWdvcmllcwogIChvd25lZCAvIGluaGVyaXRlZCAvIGltYWdlLWNvbnN1bWVkIC8gcGFzcy10aHJvdWdoKSwgd2l0aCB0aGUgaW5oZXJpdGVkCiAgY2F0ZWdvcnkgY29ycmVjdGVkIHRvICJwcmVzZXJ2ZXMgYmFzZSBjb250ZW50LCB1cGRhdGVzIHNlbGVjdGVkIGZpZWxkcyBpbgogIHBsYWNlIiByYXRoZXIgdGhhbiAiZW1pdHRlZCB1bmNoYW5nZWQiLgoKIyMgTm90ZXMKCi0gVmVyaWZpZWQgY2xlYW4gb24gdGhlIGN1cnJlbnQgdHJlZTogYWxsIHJlZmVyZW5jZWQgdGFibGVzIGNsYXNzaWZ5LCB0aGUKICBiYWNrc3RvcCBwYXNzZXMsIGZ1bGwgc3VpdGUgZ3JlZW4uCi0gU2V2ZXJhbCBvcGVuIFNPTmlDIFBScyBhZGQgdGFibGVzIHRoYXQgYXJlIG5vdCB5ZXQgcmVnaXN0ZXJlZCAoZS5nLiBCRkQsCiAgRVZQTik7IG9uY2UgdGhpcyBsYW5kcyB0aGV5IHdpbGwgZ2V0IGEgcmVkIGNoZWNrIHBvaW50aW5nIGF0IHRoZSByaWdodCBsaXN0CiAgcmF0aGVyIHRoYW4gc2hpcHBpbmcgbGF0ZW50IHN0YWxlLWNvbmZpZyBkYXRhIGxvc3MuCgrwn6SWIEdlbmVyYXRlZCB3aXRoIFtDbGF1ZGUgQ29kZV0oaHR0cHM6Ly9jbGF1ZGUuY29tL2NsYXVkZS1jb2RlKQ==
      patchset: 0e28d6fa2874487fa78f236ff163d1bbbe9dd311
      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: 0dd2fdecce2beba5aec3eab4f827c7294dc55c7d
          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/test-unit.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: 0dd2fdecce2beba5aec3eab4f827c7294dc55c7d
          name: osism/python-osism
          required: false
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
      ref: refs/pull/2339/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
