all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fef7:507
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 67b58e15-8791-4dc1-951c-e350371381fb
        host_id: df70f2a3f3d0c26428f22685cfc722ebc48099d99e7332c39e017195
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fef7:507
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.7.89
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.192.115
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fef7:507
        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: fbb77e8663044e7597a48beb485610a3
      build_refs:
      - branch: main
        change: '2216'
        change_message: "manage: retry HTTP fetches for image checksum and marker
          URLs\n\n## Problem\n\nFour `osism manage image \u2026` commands (`octavia`,
          `clusterapi`,\n`clusterapi-gardener`, `gardenlinux`) fetch a small text
          file \u2014 a\nmarker like `last-2024.1` or a `.CHECKSUM` / `.sha256` file
          \u2014 from\n`nbg1.your-objectstorage.com` (Hetzner / Ceph RadosGW) using\n`requests.get()`
          with no error handling and no retry. The body is\nparsed directly into a
          checksum or version string.\n\nWhen the bucket transiently returns an XML
          S3 error document instead\nof the expected text, the code parses `<?xml`
          as the checksum and\n`openstack-image-manager` rejects it with\n`'sha256:<?xml'
          is not a valid checksum`. This was the dominant CI\nfailure mode in the
          analysis window 2025-12-14 \u2013 2026-04-27.\n\n## Evidence\n\nAnalysis
          of 295 `.CHECKSUM` fetch events logged across all testbed\ndeploy / upgrade
          / update builds gives the following picture. Timing\nis measured from log
          timestamps (1 s resolution) between the\n`checksum_url:` log line and the
          immediately following `checksum:`\nresult line.\n\n**84 XML failures (28.5
          % of all fetches):**\n\n| Response time | Count | % of failures |\n|---------------|-------|---------------|\n|
          0 s (sub-second) | 66 | 79 % |\n| 1 s | 12 | 14 % |\n| 2 s | 1 | 1 % |\n|
          8 s | 1 | 1 % |\n| 36 s | 1 | 1 % |\n| 41 s | 1 | 1 % |\n| 59 s | 1 | 1
          % |\n| 60 s | 1 | 1 % |\n\n94 % of failures returned in \u2264 2 s (fast
          canned RGW XML response).\nThe remaining 6 % are genuine slow HTTP 503 responses
          \u2014 the server\nconnected and responded, just slowly. Zero failures were\nconnection-level
          errors (ReadError / ConnectTimeout / hang); every\nfailure returned an HTTP
          response.\n\n**211 successful fetches (71.5 % of all fetches):**\n\n| stat
          | value |\n|------|-------|\n| p50  | 0 s |\n| p90  | 1 s |\n| p95  | 1
          s |\n| p99  | 9 s |\n| max  | 53 s |\n\n## Solution\n\nAdd `osism/utils/http.py`
          with a single public function `fetch_text`\nthat wraps `requests.get` with:\n\n-
          Retry on the standard retryable status set `{408, 429} \u222A 5xx`\n- Retry
          on non-`HTTPError` `RequestException` (connection / DNS / TLS)\n- Retry
          when an optional `validate` callback rejects the body\n  (belt-and-suspenders
          against HTTP 200 with unexpected content)\n- Immediate `HTTPError` raise
          on non-retryable 4xx (404, 403, \u2026)\n- Structured `INFO` log lines per
          attempt (`fetch_text url=\u2026 attempt=N/M \u2026`)\n  so retry budget
          consumption is observable in Zuul output\n\nDefault retry schedule: 3 retries
          with 2 s / 4 s / 8 s sleeps (14 s\ntotal sleep budget).\n\nWire all seven
          `requests.get` call sites in `osism/commands/manage.py`\nto `fetch_text`
          with per-command validators:\n\n- `_validate_marker` \u2014 generic `YYYY-MM-DD
          <filename>.qcow2` contract;\n  rejects XML bodies, accepts any `.qcow2`
          name regardless of prefix\n- `_is_sha256` \u2014 requires a 64-char lowercase
          hex first token; matches\n  `sha256sum(1)` output format\n\n## On the timeout
          question\n\nThe distributions of slow failures (8\u201360 s) and slow successes\n(9\u201353
          s) overlap \u2014 a 41 s duration appears as both a failure and a\nsuccess
          in the data. There is no timeout value that cleanly separates\nthe two populations.
          A timeout at 40 s would cut off the 41 s\nsuccess; a timeout safe above
          all observed successes (> 53 s) would\nmiss all but one of the slow failures.\n\nThe
          no-timeout choice is deliberate and backed by the updated latency\ndata.
          The branch still leaves per-attempt duration unbounded and may\nmultiply
          slow 5xx responses, but adding a timeout here would be more\nlikely to introduce
          false positives than fix the observed failure\nmode.\n\n## Testing\n\n34
          unit tests across three new test files:\n\n- `tests/unit/utils/test_http.py`
          \u2014 15 tests covering the retry\n  helper (happy path, retryable statuses,
          RequestException,\n  validate callback, mixed-failure precedence, logging
          contract,\n  fail-fast on non-retryable 4xx)\n- `tests/unit/commands/test_manage_validators.py`
          \u2014 15 tests for\n  `_validate_marker` (M1\u2013M9) and `_is_sha256`
          (S1\u2013S6)\n- `tests/unit/commands/test_manage_wiring.py` \u2014 4 tests
          (W1\u2013W4)\n  asserting validator-to-call-site mapping for all four commands\n\nflake8,
          black, and all unit tests pass locally."
        change_url: https://github.com/osism/python-osism/pull/2216
        commit_id: febe7785fa192ee532bedaedc030ddff7bf20d15
        patchset: febe7785fa192ee532bedaedc030ddff7bf20d15
        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: 36243a1310ce4dd491a807c359fb321a
      buildset_refs:
      - branch: main
        change: '2216'
        change_message: "manage: retry HTTP fetches for image checksum and marker
          URLs\n\n## Problem\n\nFour `osism manage image \u2026` commands (`octavia`,
          `clusterapi`,\n`clusterapi-gardener`, `gardenlinux`) fetch a small text
          file \u2014 a\nmarker like `last-2024.1` or a `.CHECKSUM` / `.sha256` file
          \u2014 from\n`nbg1.your-objectstorage.com` (Hetzner / Ceph RadosGW) using\n`requests.get()`
          with no error handling and no retry. The body is\nparsed directly into a
          checksum or version string.\n\nWhen the bucket transiently returns an XML
          S3 error document instead\nof the expected text, the code parses `<?xml`
          as the checksum and\n`openstack-image-manager` rejects it with\n`'sha256:<?xml'
          is not a valid checksum`. This was the dominant CI\nfailure mode in the
          analysis window 2025-12-14 \u2013 2026-04-27.\n\n## Evidence\n\nAnalysis
          of 295 `.CHECKSUM` fetch events logged across all testbed\ndeploy / upgrade
          / update builds gives the following picture. Timing\nis measured from log
          timestamps (1 s resolution) between the\n`checksum_url:` log line and the
          immediately following `checksum:`\nresult line.\n\n**84 XML failures (28.5
          % of all fetches):**\n\n| Response time | Count | % of failures |\n|---------------|-------|---------------|\n|
          0 s (sub-second) | 66 | 79 % |\n| 1 s | 12 | 14 % |\n| 2 s | 1 | 1 % |\n|
          8 s | 1 | 1 % |\n| 36 s | 1 | 1 % |\n| 41 s | 1 | 1 % |\n| 59 s | 1 | 1
          % |\n| 60 s | 1 | 1 % |\n\n94 % of failures returned in \u2264 2 s (fast
          canned RGW XML response).\nThe remaining 6 % are genuine slow HTTP 503 responses
          \u2014 the server\nconnected and responded, just slowly. Zero failures were\nconnection-level
          errors (ReadError / ConnectTimeout / hang); every\nfailure returned an HTTP
          response.\n\n**211 successful fetches (71.5 % of all fetches):**\n\n| stat
          | value |\n|------|-------|\n| p50  | 0 s |\n| p90  | 1 s |\n| p95  | 1
          s |\n| p99  | 9 s |\n| max  | 53 s |\n\n## Solution\n\nAdd `osism/utils/http.py`
          with a single public function `fetch_text`\nthat wraps `requests.get` with:\n\n-
          Retry on the standard retryable status set `{408, 429} \u222A 5xx`\n- Retry
          on non-`HTTPError` `RequestException` (connection / DNS / TLS)\n- Retry
          when an optional `validate` callback rejects the body\n  (belt-and-suspenders
          against HTTP 200 with unexpected content)\n- Immediate `HTTPError` raise
          on non-retryable 4xx (404, 403, \u2026)\n- Structured `INFO` log lines per
          attempt (`fetch_text url=\u2026 attempt=N/M \u2026`)\n  so retry budget
          consumption is observable in Zuul output\n\nDefault retry schedule: 3 retries
          with 2 s / 4 s / 8 s sleeps (14 s\ntotal sleep budget).\n\nWire all seven
          `requests.get` call sites in `osism/commands/manage.py`\nto `fetch_text`
          with per-command validators:\n\n- `_validate_marker` \u2014 generic `YYYY-MM-DD
          <filename>.qcow2` contract;\n  rejects XML bodies, accepts any `.qcow2`
          name regardless of prefix\n- `_is_sha256` \u2014 requires a 64-char lowercase
          hex first token; matches\n  `sha256sum(1)` output format\n\n## On the timeout
          question\n\nThe distributions of slow failures (8\u201360 s) and slow successes\n(9\u201353
          s) overlap \u2014 a 41 s duration appears as both a failure and a\nsuccess
          in the data. There is no timeout value that cleanly separates\nthe two populations.
          A timeout at 40 s would cut off the 41 s\nsuccess; a timeout safe above
          all observed successes (> 53 s) would\nmiss all but one of the slow failures.\n\nThe
          no-timeout choice is deliberate and backed by the updated latency\ndata.
          The branch still leaves per-attempt duration unbounded and may\nmultiply
          slow 5xx responses, but adding a timeout here would be more\nlikely to introduce
          false positives than fix the observed failure\nmode.\n\n## Testing\n\n34
          unit tests across three new test files:\n\n- `tests/unit/utils/test_http.py`
          \u2014 15 tests covering the retry\n  helper (happy path, retryable statuses,
          RequestException,\n  validate callback, mixed-failure precedence, logging
          contract,\n  fail-fast on non-retryable 4xx)\n- `tests/unit/commands/test_manage_validators.py`
          \u2014 15 tests for\n  `_validate_marker` (M1\u2013M9) and `_is_sha256`
          (S1\u2013S6)\n- `tests/unit/commands/test_manage_wiring.py` \u2014 4 tests
          (W1\u2013W4)\n  asserting validator-to-call-site mapping for all four commands\n\nflake8,
          black, and all unit tests pass locally."
        change_url: https://github.com/osism/python-osism/pull/2216
        commit_id: febe7785fa192ee532bedaedc030ddff7bf20d15
        patchset: febe7785fa192ee532bedaedc030ddff7bf20d15
        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: '2216'
      change_message: "manage: retry HTTP fetches for image checksum and marker URLs\n\n##
        Problem\n\nFour `osism manage image \u2026` commands (`octavia`, `clusterapi`,\n`clusterapi-gardener`,
        `gardenlinux`) fetch a small text file \u2014 a\nmarker like `last-2024.1`
        or a `.CHECKSUM` / `.sha256` file \u2014 from\n`nbg1.your-objectstorage.com`
        (Hetzner / Ceph RadosGW) using\n`requests.get()` with no error handling and
        no retry. The body is\nparsed directly into a checksum or version string.\n\nWhen
        the bucket transiently returns an XML S3 error document instead\nof the expected
        text, the code parses `<?xml` as the checksum and\n`openstack-image-manager`
        rejects it with\n`'sha256:<?xml' is not a valid checksum`. This was the dominant
        CI\nfailure mode in the analysis window 2025-12-14 \u2013 2026-04-27.\n\n##
        Evidence\n\nAnalysis of 295 `.CHECKSUM` fetch events logged across all testbed\ndeploy
        / upgrade / update builds gives the following picture. Timing\nis measured
        from log timestamps (1 s resolution) between the\n`checksum_url:` log line
        and the immediately following `checksum:`\nresult line.\n\n**84 XML failures
        (28.5 % of all fetches):**\n\n| Response time | Count | % of failures |\n|---------------|-------|---------------|\n|
        0 s (sub-second) | 66 | 79 % |\n| 1 s | 12 | 14 % |\n| 2 s | 1 | 1 % |\n|
        8 s | 1 | 1 % |\n| 36 s | 1 | 1 % |\n| 41 s | 1 | 1 % |\n| 59 s | 1 | 1 %
        |\n| 60 s | 1 | 1 % |\n\n94 % of failures returned in \u2264 2 s (fast canned
        RGW XML response).\nThe remaining 6 % are genuine slow HTTP 503 responses
        \u2014 the server\nconnected and responded, just slowly. Zero failures were\nconnection-level
        errors (ReadError / ConnectTimeout / hang); every\nfailure returned an HTTP
        response.\n\n**211 successful fetches (71.5 % of all fetches):**\n\n| stat
        | value |\n|------|-------|\n| p50  | 0 s |\n| p90  | 1 s |\n| p95  | 1 s
        |\n| p99  | 9 s |\n| max  | 53 s |\n\n## Solution\n\nAdd `osism/utils/http.py`
        with a single public function `fetch_text`\nthat wraps `requests.get` with:\n\n-
        Retry on the standard retryable status set `{408, 429} \u222A 5xx`\n- Retry
        on non-`HTTPError` `RequestException` (connection / DNS / TLS)\n- Retry when
        an optional `validate` callback rejects the body\n  (belt-and-suspenders against
        HTTP 200 with unexpected content)\n- Immediate `HTTPError` raise on non-retryable
        4xx (404, 403, \u2026)\n- Structured `INFO` log lines per attempt (`fetch_text
        url=\u2026 attempt=N/M \u2026`)\n  so retry budget consumption is observable
        in Zuul output\n\nDefault retry schedule: 3 retries with 2 s / 4 s / 8 s sleeps
        (14 s\ntotal sleep budget).\n\nWire all seven `requests.get` call sites in
        `osism/commands/manage.py`\nto `fetch_text` with per-command validators:\n\n-
        `_validate_marker` \u2014 generic `YYYY-MM-DD <filename>.qcow2` contract;\n
        \ rejects XML bodies, accepts any `.qcow2` name regardless of prefix\n- `_is_sha256`
        \u2014 requires a 64-char lowercase hex first token; matches\n  `sha256sum(1)`
        output format\n\n## On the timeout question\n\nThe distributions of slow failures
        (8\u201360 s) and slow successes\n(9\u201353 s) overlap \u2014 a 41 s duration
        appears as both a failure and a\nsuccess in the data. There is no timeout
        value that cleanly separates\nthe two populations. A timeout at 40 s would
        cut off the 41 s\nsuccess; a timeout safe above all observed successes (>
        53 s) would\nmiss all but one of the slow failures.\n\nThe no-timeout choice
        is deliberate and backed by the updated latency\ndata. The branch still leaves
        per-attempt duration unbounded and may\nmultiply slow 5xx responses, but adding
        a timeout here would be more\nlikely to introduce false positives than fix
        the observed failure\nmode.\n\n## Testing\n\n34 unit tests across three new
        test files:\n\n- `tests/unit/utils/test_http.py` \u2014 15 tests covering
        the retry\n  helper (happy path, retryable statuses, RequestException,\n  validate
        callback, mixed-failure precedence, logging contract,\n  fail-fast on non-retryable
        4xx)\n- `tests/unit/commands/test_manage_validators.py` \u2014 15 tests for\n
        \ `_validate_marker` (M1\u2013M9) and `_is_sha256` (S1\u2013S6)\n- `tests/unit/commands/test_manage_wiring.py`
        \u2014 4 tests (W1\u2013W4)\n  asserting validator-to-call-site mapping for
        all four commands\n\nflake8, black, and all unit tests pass locally."
      change_url: https://github.com/osism/python-osism/pull/2216
      child_jobs: []
      commit_id: febe7785fa192ee532bedaedc030ddff7bf20d15
      event_id: 86410a80-4237-11f1-8c11-093b9889e665
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/fbb77e8663044e7597a48beb485610a3/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/fbb77e8663044e7597a48beb485610a3/work/logs
        result_data_file: /var/lib/zuul/builds/fbb77e8663044e7597a48beb485610a3/work/results.json
        src_root: /var/lib/zuul/builds/fbb77e8663044e7597a48beb485610a3/work/src
        work_root: /var/lib/zuul/builds/fbb77e8663044e7597a48beb485610a3/work
      include_vars: []
      items:
      - branch: main
        change: '2216'
        change_message: "manage: retry HTTP fetches for image checksum and marker
          URLs\n\n## Problem\n\nFour `osism manage image \u2026` commands (`octavia`,
          `clusterapi`,\n`clusterapi-gardener`, `gardenlinux`) fetch a small text
          file \u2014 a\nmarker like `last-2024.1` or a `.CHECKSUM` / `.sha256` file
          \u2014 from\n`nbg1.your-objectstorage.com` (Hetzner / Ceph RadosGW) using\n`requests.get()`
          with no error handling and no retry. The body is\nparsed directly into a
          checksum or version string.\n\nWhen the bucket transiently returns an XML
          S3 error document instead\nof the expected text, the code parses `<?xml`
          as the checksum and\n`openstack-image-manager` rejects it with\n`'sha256:<?xml'
          is not a valid checksum`. This was the dominant CI\nfailure mode in the
          analysis window 2025-12-14 \u2013 2026-04-27.\n\n## Evidence\n\nAnalysis
          of 295 `.CHECKSUM` fetch events logged across all testbed\ndeploy / upgrade
          / update builds gives the following picture. Timing\nis measured from log
          timestamps (1 s resolution) between the\n`checksum_url:` log line and the
          immediately following `checksum:`\nresult line.\n\n**84 XML failures (28.5
          % of all fetches):**\n\n| Response time | Count | % of failures |\n|---------------|-------|---------------|\n|
          0 s (sub-second) | 66 | 79 % |\n| 1 s | 12 | 14 % |\n| 2 s | 1 | 1 % |\n|
          8 s | 1 | 1 % |\n| 36 s | 1 | 1 % |\n| 41 s | 1 | 1 % |\n| 59 s | 1 | 1
          % |\n| 60 s | 1 | 1 % |\n\n94 % of failures returned in \u2264 2 s (fast
          canned RGW XML response).\nThe remaining 6 % are genuine slow HTTP 503 responses
          \u2014 the server\nconnected and responded, just slowly. Zero failures were\nconnection-level
          errors (ReadError / ConnectTimeout / hang); every\nfailure returned an HTTP
          response.\n\n**211 successful fetches (71.5 % of all fetches):**\n\n| stat
          | value |\n|------|-------|\n| p50  | 0 s |\n| p90  | 1 s |\n| p95  | 1
          s |\n| p99  | 9 s |\n| max  | 53 s |\n\n## Solution\n\nAdd `osism/utils/http.py`
          with a single public function `fetch_text`\nthat wraps `requests.get` with:\n\n-
          Retry on the standard retryable status set `{408, 429} \u222A 5xx`\n- Retry
          on non-`HTTPError` `RequestException` (connection / DNS / TLS)\n- Retry
          when an optional `validate` callback rejects the body\n  (belt-and-suspenders
          against HTTP 200 with unexpected content)\n- Immediate `HTTPError` raise
          on non-retryable 4xx (404, 403, \u2026)\n- Structured `INFO` log lines per
          attempt (`fetch_text url=\u2026 attempt=N/M \u2026`)\n  so retry budget
          consumption is observable in Zuul output\n\nDefault retry schedule: 3 retries
          with 2 s / 4 s / 8 s sleeps (14 s\ntotal sleep budget).\n\nWire all seven
          `requests.get` call sites in `osism/commands/manage.py`\nto `fetch_text`
          with per-command validators:\n\n- `_validate_marker` \u2014 generic `YYYY-MM-DD
          <filename>.qcow2` contract;\n  rejects XML bodies, accepts any `.qcow2`
          name regardless of prefix\n- `_is_sha256` \u2014 requires a 64-char lowercase
          hex first token; matches\n  `sha256sum(1)` output format\n\n## On the timeout
          question\n\nThe distributions of slow failures (8\u201360 s) and slow successes\n(9\u201353
          s) overlap \u2014 a 41 s duration appears as both a failure and a\nsuccess
          in the data. There is no timeout value that cleanly separates\nthe two populations.
          A timeout at 40 s would cut off the 41 s\nsuccess; a timeout safe above
          all observed successes (> 53 s) would\nmiss all but one of the slow failures.\n\nThe
          no-timeout choice is deliberate and backed by the updated latency\ndata.
          The branch still leaves per-attempt duration unbounded and may\nmultiply
          slow 5xx responses, but adding a timeout here would be more\nlikely to introduce
          false positives than fix the observed failure\nmode.\n\n## Testing\n\n34
          unit tests across three new test files:\n\n- `tests/unit/utils/test_http.py`
          \u2014 15 tests covering the retry\n  helper (happy path, retryable statuses,
          RequestException,\n  validate callback, mixed-failure precedence, logging
          contract,\n  fail-fast on non-retryable 4xx)\n- `tests/unit/commands/test_manage_validators.py`
          \u2014 15 tests for\n  `_validate_marker` (M1\u2013M9) and `_is_sha256`
          (S1\u2013S6)\n- `tests/unit/commands/test_manage_wiring.py` \u2014 4 tests
          (W1\u2013W4)\n  asserting validator-to-call-site mapping for all four commands\n\nflake8,
          black, and all unit tests pass locally."
        change_url: https://github.com/osism/python-osism/pull/2216
        commit_id: febe7785fa192ee532bedaedc030ddff7bf20d15
        patchset: febe7785fa192ee532bedaedc030ddff7bf20d15
        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: bWFuYWdlOiByZXRyeSBIVFRQIGZldGNoZXMgZm9yIGltYWdlIGNoZWNrc3VtIGFuZCBtYXJrZXIgVVJMcwoKIyMgUHJvYmxlbQoKRm91ciBgb3Npc20gbWFuYWdlIGltYWdlIOKApmAgY29tbWFuZHMgKGBvY3RhdmlhYCwgYGNsdXN0ZXJhcGlgLApgY2x1c3RlcmFwaS1nYXJkZW5lcmAsIGBnYXJkZW5saW51eGApIGZldGNoIGEgc21hbGwgdGV4dCBmaWxlIOKAlCBhCm1hcmtlciBsaWtlIGBsYXN0LTIwMjQuMWAgb3IgYSBgLkNIRUNLU1VNYCAvIGAuc2hhMjU2YCBmaWxlIOKAlCBmcm9tCmBuYmcxLnlvdXItb2JqZWN0c3RvcmFnZS5jb21gIChIZXR6bmVyIC8gQ2VwaCBSYWRvc0dXKSB1c2luZwpgcmVxdWVzdHMuZ2V0KClgIHdpdGggbm8gZXJyb3IgaGFuZGxpbmcgYW5kIG5vIHJldHJ5LiBUaGUgYm9keSBpcwpwYXJzZWQgZGlyZWN0bHkgaW50byBhIGNoZWNrc3VtIG9yIHZlcnNpb24gc3RyaW5nLgoKV2hlbiB0aGUgYnVja2V0IHRyYW5zaWVudGx5IHJldHVybnMgYW4gWE1MIFMzIGVycm9yIGRvY3VtZW50IGluc3RlYWQKb2YgdGhlIGV4cGVjdGVkIHRleHQsIHRoZSBjb2RlIHBhcnNlcyBgPD94bWxgIGFzIHRoZSBjaGVja3N1bSBhbmQKYG9wZW5zdGFjay1pbWFnZS1tYW5hZ2VyYCByZWplY3RzIGl0IHdpdGgKYCdzaGEyNTY6PD94bWwnIGlzIG5vdCBhIHZhbGlkIGNoZWNrc3VtYC4gVGhpcyB3YXMgdGhlIGRvbWluYW50IENJCmZhaWx1cmUgbW9kZSBpbiB0aGUgYW5hbHlzaXMgd2luZG93IDIwMjUtMTItMTQg4oCTIDIwMjYtMDQtMjcuCgojIyBFdmlkZW5jZQoKQW5hbHlzaXMgb2YgMjk1IGAuQ0hFQ0tTVU1gIGZldGNoIGV2ZW50cyBsb2dnZWQgYWNyb3NzIGFsbCB0ZXN0YmVkCmRlcGxveSAvIHVwZ3JhZGUgLyB1cGRhdGUgYnVpbGRzIGdpdmVzIHRoZSBmb2xsb3dpbmcgcGljdHVyZS4gVGltaW5nCmlzIG1lYXN1cmVkIGZyb20gbG9nIHRpbWVzdGFtcHMgKDEgcyByZXNvbHV0aW9uKSBiZXR3ZWVuIHRoZQpgY2hlY2tzdW1fdXJsOmAgbG9nIGxpbmUgYW5kIHRoZSBpbW1lZGlhdGVseSBmb2xsb3dpbmcgYGNoZWNrc3VtOmAKcmVzdWx0IGxpbmUuCgoqKjg0IFhNTCBmYWlsdXJlcyAoMjguNSAlIG9mIGFsbCBmZXRjaGVzKToqKgoKfCBSZXNwb25zZSB0aW1lIHwgQ291bnQgfCAlIG9mIGZhaWx1cmVzIHwKfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tfC0tLS0tLS0tLS0tLS0tLXwKfCAwIHMgKHN1Yi1zZWNvbmQpIHwgNjYgfCA3OSAlIHwKfCAxIHMgfCAxMiB8IDE0ICUgfAp8IDIgcyB8IDEgfCAxICUgfAp8IDggcyB8IDEgfCAxICUgfAp8IDM2IHMgfCAxIHwgMSAlIHwKfCA0MSBzIHwgMSB8IDEgJSB8CnwgNTkgcyB8IDEgfCAxICUgfAp8IDYwIHMgfCAxIHwgMSAlIHwKCjk0ICUgb2YgZmFpbHVyZXMgcmV0dXJuZWQgaW4g4omkIDIgcyAoZmFzdCBjYW5uZWQgUkdXIFhNTCByZXNwb25zZSkuClRoZSByZW1haW5pbmcgNiAlIGFyZSBnZW51aW5lIHNsb3cgSFRUUCA1MDMgcmVzcG9uc2VzIOKAlCB0aGUgc2VydmVyCmNvbm5lY3RlZCBhbmQgcmVzcG9uZGVkLCBqdXN0IHNsb3dseS4gWmVybyBmYWlsdXJlcyB3ZXJlCmNvbm5lY3Rpb24tbGV2ZWwgZXJyb3JzIChSZWFkRXJyb3IgLyBDb25uZWN0VGltZW91dCAvIGhhbmcpOyBldmVyeQpmYWlsdXJlIHJldHVybmVkIGFuIEhUVFAgcmVzcG9uc2UuCgoqKjIxMSBzdWNjZXNzZnVsIGZldGNoZXMgKDcxLjUgJSBvZiBhbGwgZmV0Y2hlcyk6KioKCnwgc3RhdCB8IHZhbHVlIHwKfC0tLS0tLXwtLS0tLS0tfAp8IHA1MCAgfCAwIHMgfAp8IHA5MCAgfCAxIHMgfAp8IHA5NSAgfCAxIHMgfAp8IHA5OSAgfCA5IHMgfAp8IG1heCAgfCA1MyBzIHwKCiMjIFNvbHV0aW9uCgpBZGQgYG9zaXNtL3V0aWxzL2h0dHAucHlgIHdpdGggYSBzaW5nbGUgcHVibGljIGZ1bmN0aW9uIGBmZXRjaF90ZXh0YAp0aGF0IHdyYXBzIGByZXF1ZXN0cy5nZXRgIHdpdGg6CgotIFJldHJ5IG9uIHRoZSBzdGFuZGFyZCByZXRyeWFibGUgc3RhdHVzIHNldCBgezQwOCwgNDI5fSDiiKogNXh4YAotIFJldHJ5IG9uIG5vbi1gSFRUUEVycm9yYCBgUmVxdWVzdEV4Y2VwdGlvbmAgKGNvbm5lY3Rpb24gLyBETlMgLyBUTFMpCi0gUmV0cnkgd2hlbiBhbiBvcHRpb25hbCBgdmFsaWRhdGVgIGNhbGxiYWNrIHJlamVjdHMgdGhlIGJvZHkKICAoYmVsdC1hbmQtc3VzcGVuZGVycyBhZ2FpbnN0IEhUVFAgMjAwIHdpdGggdW5leHBlY3RlZCBjb250ZW50KQotIEltbWVkaWF0ZSBgSFRUUEVycm9yYCByYWlzZSBvbiBub24tcmV0cnlhYmxlIDR4eCAoNDA0LCA0MDMsIOKApikKLSBTdHJ1Y3R1cmVkIGBJTkZPYCBsb2cgbGluZXMgcGVyIGF0dGVtcHQgKGBmZXRjaF90ZXh0IHVybD3igKYgYXR0ZW1wdD1OL00g4oCmYCkKICBzbyByZXRyeSBidWRnZXQgY29uc3VtcHRpb24gaXMgb2JzZXJ2YWJsZSBpbiBadXVsIG91dHB1dAoKRGVmYXVsdCByZXRyeSBzY2hlZHVsZTogMyByZXRyaWVzIHdpdGggMiBzIC8gNCBzIC8gOCBzIHNsZWVwcyAoMTQgcwp0b3RhbCBzbGVlcCBidWRnZXQpLgoKV2lyZSBhbGwgc2V2ZW4gYHJlcXVlc3RzLmdldGAgY2FsbCBzaXRlcyBpbiBgb3Npc20vY29tbWFuZHMvbWFuYWdlLnB5YAp0byBgZmV0Y2hfdGV4dGAgd2l0aCBwZXItY29tbWFuZCB2YWxpZGF0b3JzOgoKLSBgX3ZhbGlkYXRlX21hcmtlcmAg4oCUIGdlbmVyaWMgYFlZWVktTU0tREQgPGZpbGVuYW1lPi5xY293MmAgY29udHJhY3Q7CiAgcmVqZWN0cyBYTUwgYm9kaWVzLCBhY2NlcHRzIGFueSBgLnFjb3cyYCBuYW1lIHJlZ2FyZGxlc3Mgb2YgcHJlZml4Ci0gYF9pc19zaGEyNTZgIOKAlCByZXF1aXJlcyBhIDY0LWNoYXIgbG93ZXJjYXNlIGhleCBmaXJzdCB0b2tlbjsgbWF0Y2hlcwogIGBzaGEyNTZzdW0oMSlgIG91dHB1dCBmb3JtYXQKCiMjIE9uIHRoZSB0aW1lb3V0IHF1ZXN0aW9uCgpUaGUgZGlzdHJpYnV0aW9ucyBvZiBzbG93IGZhaWx1cmVzICg44oCTNjAgcykgYW5kIHNsb3cgc3VjY2Vzc2VzCig54oCTNTMgcykgb3ZlcmxhcCDigJQgYSA0MSBzIGR1cmF0aW9uIGFwcGVhcnMgYXMgYm90aCBhIGZhaWx1cmUgYW5kIGEKc3VjY2VzcyBpbiB0aGUgZGF0YS4gVGhlcmUgaXMgbm8gdGltZW91dCB2YWx1ZSB0aGF0IGNsZWFubHkgc2VwYXJhdGVzCnRoZSB0d28gcG9wdWxhdGlvbnMuIEEgdGltZW91dCBhdCA0MCBzIHdvdWxkIGN1dCBvZmYgdGhlIDQxIHMKc3VjY2VzczsgYSB0aW1lb3V0IHNhZmUgYWJvdmUgYWxsIG9ic2VydmVkIHN1Y2Nlc3NlcyAoPiA1MyBzKSB3b3VsZAptaXNzIGFsbCBidXQgb25lIG9mIHRoZSBzbG93IGZhaWx1cmVzLgoKVGhlIG5vLXRpbWVvdXQgY2hvaWNlIGlzIGRlbGliZXJhdGUgYW5kIGJhY2tlZCBieSB0aGUgdXBkYXRlZCBsYXRlbmN5CmRhdGEuIFRoZSBicmFuY2ggc3RpbGwgbGVhdmVzIHBlci1hdHRlbXB0IGR1cmF0aW9uIHVuYm91bmRlZCBhbmQgbWF5Cm11bHRpcGx5IHNsb3cgNXh4IHJlc3BvbnNlcywgYnV0IGFkZGluZyBhIHRpbWVvdXQgaGVyZSB3b3VsZCBiZSBtb3JlCmxpa2VseSB0byBpbnRyb2R1Y2UgZmFsc2UgcG9zaXRpdmVzIHRoYW4gZml4IHRoZSBvYnNlcnZlZCBmYWlsdXJlCm1vZGUuCgojIyBUZXN0aW5nCgozNCB1bml0IHRlc3RzIGFjcm9zcyB0aHJlZSBuZXcgdGVzdCBmaWxlczoKCi0gYHRlc3RzL3VuaXQvdXRpbHMvdGVzdF9odHRwLnB5YCDigJQgMTUgdGVzdHMgY292ZXJpbmcgdGhlIHJldHJ5CiAgaGVscGVyIChoYXBweSBwYXRoLCByZXRyeWFibGUgc3RhdHVzZXMsIFJlcXVlc3RFeGNlcHRpb24sCiAgdmFsaWRhdGUgY2FsbGJhY2ssIG1peGVkLWZhaWx1cmUgcHJlY2VkZW5jZSwgbG9nZ2luZyBjb250cmFjdCwKICBmYWlsLWZhc3Qgb24gbm9uLXJldHJ5YWJsZSA0eHgpCi0gYHRlc3RzL3VuaXQvY29tbWFuZHMvdGVzdF9tYW5hZ2VfdmFsaWRhdG9ycy5weWAg4oCUIDE1IHRlc3RzIGZvcgogIGBfdmFsaWRhdGVfbWFya2VyYCAoTTHigJNNOSkgYW5kIGBfaXNfc2hhMjU2YCAoUzHigJNTNikKLSBgdGVzdHMvdW5pdC9jb21tYW5kcy90ZXN0X21hbmFnZV93aXJpbmcucHlgIOKAlCA0IHRlc3RzIChXMeKAk1c0KQogIGFzc2VydGluZyB2YWxpZGF0b3ItdG8tY2FsbC1zaXRlIG1hcHBpbmcgZm9yIGFsbCBmb3VyIGNvbW1hbmRzCgpmbGFrZTgsIGJsYWNrLCBhbmQgYWxsIHVuaXQgdGVzdHMgcGFzcyBsb2NhbGx5Lg==
      patchset: febe7785fa192ee532bedaedc030ddff7bf20d15
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 69987497b92a6fd27b27eac0fffd3d2d5411103c
          trusted/project_1/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 397240f42127868e42e86e6aeb120c2cb092d117
          untrusted/project_0/github.com/osism/python-osism:
            canonical_name: github.com/osism/python-osism
            checkout: main
            commit: 39770be7b0f913ab5fd9438be538eb1467fe220f
          untrusted/project_1/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 69987497b92a6fd27b27eac0fffd3d2d5411103c
          untrusted/project_2/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 397240f42127868e42e86e6aeb120c2cb092d117
        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
      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: 39770be7b0f913ab5fd9438be538eb1467fe220f
          name: osism/python-osism
          required: false
          short_name: python-osism
          src_dir: src/github.com/osism/python-osism
      ref: refs/pull/2216/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
