Skip to content

feat(RELEASE-2479): add collect_index_images.py script#851

Open
johnbieren wants to merge 1 commit into
konflux-ci:mainfrom
johnbieren:release2479
Open

feat(RELEASE-2479): add collect_index_images.py script#851
johnbieren wants to merge 1 commit into
konflux-ci:mainfrom
johnbieren:release2479

Conversation

@johnbieren

Copy link
Copy Markdown
Collaborator

This commit adds a python script to replicate the functionality of the inline bash script in the collect-index-images managed task in the catalog repo. The task will be updated to use this python module instead.

Assisted-By: Cursor

@codecov-commenter

codecov-commenter commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.70%. Comparing base (a0c68a7) to head (8896c96).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #851      +/-   ##
==========================================
+ Coverage   95.51%   95.70%   +0.18%     
==========================================
  Files          69       72       +3     
  Lines        6893     7192     +299     
==========================================
+ Hits         6584     6883     +299     
  Misses        309      309              
Flag Coverage Δ
unit-tests 95.70% <100.00%> (+0.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
scripts/python/helpers/image_ref.py 100.00% <100.00%> (ø)
...ripts/python/tasks/managed/collect_index_images.py 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a0c68a7...8896c96. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@johnbieren

Copy link
Copy Markdown
Collaborator Author

/agentic_review

1 similar comment
@johnbieren

Copy link
Copy Markdown
Collaborator Author

/agentic_review

@qodo-app-for-konflux-ci

qodo-app-for-konflux-ci Bot commented Jun 25, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 25 rules

Grey Divider


Action required

1. run_collect_index_images() hardcodes I/O calls ✗ Dismissed 📘 Rule violation ▣ Testability
Description
The new task logic directly calls filesystem and environment dependencies (file.load_json_dict,
Path.write_text, tekton.require_env) without providing overridable callable keyword-argument
injections. This reduces testability and violates the requirement to inject side-effectful
dependencies with production-safe defaults.
Code

scripts/python/tasks/managed/collect_index_images.py[R145-182]

+def run_collect_index_images(
+    *,
+    data_dir: Path,
+    internal_request_results_file: Path,
+    build_timestamp: str,
+    snapshot_path: Path,
+    index_image_snapshot_result_path: Path,
+) -> None:
+    """Load results, build the snapshot JSON, and write Tekton outputs."""
+    results_path = data_dir / internal_request_results_file
+    if not results_path.is_file():
+        msg = f"internal request results file not found: {results_path}"
+        raise FileNotFoundError(msg)
+
+    logger.info("Loading internal request results from %s", results_path)
+    results = file.load_json_dict(results_path)
+    snapshot = collect_index_image_components(results, build_timestamp)
+
+    snapshot_path.parent.mkdir(parents=True, exist_ok=True)
+    snapshot_path.write_text(json.dumps(snapshot) + "\n", encoding="utf-8")
+    index_image_snapshot_result_path.write_text(SNAPSHOT_FILENAME, encoding="utf-8")
+    logger.info("Wrote index image snapshot to %s", snapshot_path)
+
+
+def main() -> int:
+    """Run the collect-index-images workflow."""
+    data_dir = Path(tekton.require_env("PARAM_DATA_DIR"))
+    run_collect_index_images(
+        data_dir=data_dir,
+        internal_request_results_file=Path(
+            tekton.require_env("PARAM_INTERNAL_REQUEST_RESULTS_FILE"),
+        ),
+        build_timestamp=tekton.require_env("PARAM_BUILD_TIMESTAMP"),
+        snapshot_path=data_dir / SNAPSHOT_FILENAME,
+        index_image_snapshot_result_path=tekton.result_paths_from_env(
+            "RESULT_INDEX_IMAGE_SNAPSHOT_PATH",
+        )[0],
+    )
Evidence
PR Compliance ID 906 requires side-effectful dependencies (I/O, env reads) to be injected as
callable keyword arguments with production-ready defaults. The new managed task script calls these
dependencies directly in run_collect_index_images() and main() without any injectable *_fn
keyword parameters.

Rule 906: Inject dependencies as overridable callable keyword arguments with production-safe defaults
scripts/python/tasks/managed/collect_index_images.py[145-182]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/python/tasks/managed/collect_index_images.py` performs side-effectful operations (env reads + file I/O) via hardcoded module/method calls. Per compliance, these dependencies must be injected as overridable callable keyword arguments with production-safe defaults.

## Issue Context
This affects `run_collect_index_images()` and `main()`, which currently call `tekton.require_env`, `file.load_json_dict`, and `Path.write_text` directly.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[145-182]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Unstripped index values 🐞 Bug ≡ Correctness
Description
collect_index_image_components() validates target_index/index_image_resolved using .strip() but then
continues processing the unstripped strings, so leading/trailing whitespace can prevent
delivery-repo translation and cause build_tags() to miss bare OCP version tags.
Code

scripts/python/tasks/managed/collect_index_images.py[R101-111]

+        target_index = row.get("target_index")
+        source_index = row.get("index_image_resolved")
+        if not isinstance(target_index, str) or not target_index.strip():
+            msg = f"components[{index}].target_index must be a non-empty string"
+            raise ValueError(msg)
+        if not isinstance(source_index, str) or not source_index.strip():
+            msg = f"components[{index}].index_image_resolved must be a non-empty string"
+            raise ValueError(msg)
+
+        repository, tag = split_target_index(target_index)
+        tags = build_tags(tag, build_timestamp)
Evidence
The task validates stripped values but proceeds with the original strings; both tag matching and
delivery-repo prefix matching are whitespace-sensitive.

scripts/python/tasks/managed/collect_index_images.py[101-125]
scripts/python/tasks/managed/collect_index_images.py[29-34]
scripts/python/helpers/image_ref.py[22-33]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`collect_index_image_components()` checks `target_index.strip()` / `source_index.strip()` for non-emptiness, but then passes the original variables into `split_target_index()`, `build_tags()`, and `translate_delivery_repo()`. If the JSON contains whitespace (common when values come from templating or manual edits), tag parsing and translation can silently fail.

## Issue Context
- `build_tags()` uses a strict `fullmatch()` on the tag string.
- `translate_delivery_repo()` uses `startswith()` against exact prefixes.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[101-123]
- scripts/python/helpers/image_ref.py[22-33]

## Suggested fix
1) In `collect_index_image_components()`, after the type/emptiness checks, normalize:
```py
assert isinstance(target_index, str)
assert isinstance(source_index, str)
target_index = target_index.strip()
source_index = source_index.strip()
```
Then use the normalized variables for `split_target_index()`, logging, and `translate_delivery_repo()`.

2) Optionally harden `translate_delivery_repo()` itself:
- Replace `normalized = repo.replace(...)` with `repo = repo.strip(); normalized = repo.replace(...)` so callers don’t need to remember to trim.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Bad colon tag stripping 🐞 Bug ≡ Correctness
Description
translation_repo_url() removes a tag by splitting on the first ':', which will truncate valid
registry references that include a host port (e.g. registry:5000/repo:tag), yielding an incorrect
rh-registry-repo/registry-access-repo value.
Code

scripts/python/tasks/managed/collect_index_images.py[R37-45]

+def translation_repo_url(translated: list[dict[str, Any]], repo_key: str) -> str:
+    """Return the host/path portion of a translated delivery-repo URL."""
+    for entry in translated:
+        if entry.get("repo") != repo_key:
+            continue
+        url = entry.get("url")
+        if not isinstance(url, str) or not url:
+            return ""
+        return url.split(":", 1)[0]
Evidence
The PR implementation strips tags via a first-colon split, which will truncate host:port references;
existing repo code uses last-colon splitting to avoid this.

scripts/python/tasks/managed/collect_index_images.py[37-46]
scripts/python/helpers/authentication.py[229-240]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`translation_repo_url()` currently returns `url.split(":", 1)[0]`, which drops everything after the *first* colon. For registry references that contain a port (e.g. `registry:5000/ns/repo:tag`), this returns only `registry`, corrupting the computed `rh-registry-repo` / `registry-access-repo`.

## Issue Context
Other code in this repo already uses `rsplit(':', 1)` to remove tag suffixes while preserving host:port.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[37-46]

## Suggested fix
Replace the naive split with parsing that removes a tag only when the colon appears after the last `/`, and strip digests safely:
- Start with `ref = url.split("@", 1)[0]` (drop digest if present)
- Find `last_slash = ref.rfind("/")` and `last_colon = ref.rfind(":")`
- If `last_colon > last_slash`, return `ref[:last_colon]` else return `ref`
This preserves `registry:5000/...` while still stripping `...:tag`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

4. Non-CheckStepError raises in collect_index_images 📘 Rule violation ≡ Correctness ⭐ New
Description
The managed Tekton task script raises ValueError/FileNotFoundError for expected step-failure
conditions instead of raising tekton.CheckStepError. This can break standardized Tekton failure
handling and result reporting expected by the shared helpers.
Code

scripts/python/tasks/managed/collect_index_images.py[R154-157]

+    results_path = data_dir / internal_request_results_file
+    if not results_path.is_file():
+        msg = f"internal request results file not found: {results_path}"
+        raise FileNotFoundError(msg)
Relevance

⭐ Low

Managed tasks intentionally let generic exceptions propagate; recent merged managed scripts raise
FileNotFoundError/ValueError without CheckStepError.

PR-#841
PR-#813

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 904 requires signaling expected Tekton step failures via
helpers.tekton.CheckStepError (imported here as tekton) rather than ad-hoc exceptions/exits. The
new managed task code raises ValueError and FileNotFoundError directly for validation and
missing-input conditions, which are typical step-failure paths.

Rule 904: Use helpers.tekton.CheckStepError for Tekton step failures
scripts/python/tasks/managed/collect_index_images.py[20-26]
scripts/python/tasks/managed/collect_index_images.py[154-157]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/python/tasks/managed/collect_index_images.py` signals expected Tekton step failures by raising `ValueError` / `FileNotFoundError` directly. Per the checklist, expected step-failure conditions in Tekton scripts should use `tekton.CheckStepError` so failures are standardized and can be rendered consistently into Tekton results.

## Issue Context
Examples of expected failures here include invalid `target_index` formatting and missing internal-results input files.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[20-26]
- scripts/python/tasks/managed/collect_index_images.py[154-157]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit bbf98f2

Results up to commit 5a0ab16


🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. run_collect_index_images() hardcodes I/O calls ✗ Dismissed 📘 Rule violation ▣ Testability
Description
The new task logic directly calls filesystem and environment dependencies (file.load_json_dict,
Path.write_text, tekton.require_env) without providing overridable callable keyword-argument
injections. This reduces testability and violates the requirement to inject side-effectful
dependencies with production-safe defaults.
Code

scripts/python/tasks/managed/collect_index_images.py[R145-182]

+def run_collect_index_images(
+    *,
+    data_dir: Path,
+    internal_request_results_file: Path,
+    build_timestamp: str,
+    snapshot_path: Path,
+    index_image_snapshot_result_path: Path,
+) -> None:
+    """Load results, build the snapshot JSON, and write Tekton outputs."""
+    results_path = data_dir / internal_request_results_file
+    if not results_path.is_file():
+        msg = f"internal request results file not found: {results_path}"
+        raise FileNotFoundError(msg)
+
+    logger.info("Loading internal request results from %s", results_path)
+    results = file.load_json_dict(results_path)
+    snapshot = collect_index_image_components(results, build_timestamp)
+
+    snapshot_path.parent.mkdir(parents=True, exist_ok=True)
+    snapshot_path.write_text(json.dumps(snapshot) + "\n", encoding="utf-8")
+    index_image_snapshot_result_path.write_text(SNAPSHOT_FILENAME, encoding="utf-8")
+    logger.info("Wrote index image snapshot to %s", snapshot_path)
+
+
+def main() -> int:
+    """Run the collect-index-images workflow."""
+    data_dir = Path(tekton.require_env("PARAM_DATA_DIR"))
+    run_collect_index_images(
+        data_dir=data_dir,
+        internal_request_results_file=Path(
+            tekton.require_env("PARAM_INTERNAL_REQUEST_RESULTS_FILE"),
+        ),
+        build_timestamp=tekton.require_env("PARAM_BUILD_TIMESTAMP"),
+        snapshot_path=data_dir / SNAPSHOT_FILENAME,
+        index_image_snapshot_result_path=tekton.result_paths_from_env(
+            "RESULT_INDEX_IMAGE_SNAPSHOT_PATH",
+        )[0],
+    )
Evidence
PR Compliance ID 906 requires side-effectful dependencies (I/O, env reads) to be injected as
callable keyword arguments with production-ready defaults. The new managed task script calls these
dependencies directly in run_collect_index_images() and main() without any injectable *_fn
keyword parameters.

Rule 906: Inject dependencies as overridable callable keyword arguments with production-safe defaults
scripts/python/tasks/managed/collect_index_images.py[145-182]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/python/tasks/managed/collect_index_images.py` performs side-effectful operations (env reads + file I/O) via hardcoded module/method calls. Per compliance, these dependencies must be injected as overridable callable keyword arguments with production-safe defaults.

## Issue Context
This affects `run_collect_index_images()` and `main()`, which currently call `tekton.require_env`, `file.load_json_dict`, and `Path.write_text` directly.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[145-182]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. Bad colon tag stripping 🐞 Bug ≡ Correctness
Description
translation_repo_url() removes a tag by splitting on the first ':', which will truncate valid
registry references that include a host port (e.g. registry:5000/repo:tag), yielding an incorrect
rh-registry-repo/registry-access-repo value.
Code

scripts/python/tasks/managed/collect_index_images.py[R37-45]

+def translation_repo_url(translated: list[dict[str, Any]], repo_key: str) -> str:
+    """Return the host/path portion of a translated delivery-repo URL."""
+    for entry in translated:
+        if entry.get("repo") != repo_key:
+            continue
+        url = entry.get("url")
+        if not isinstance(url, str) or not url:
+            return ""
+        return url.split(":", 1)[0]
Evidence
The PR implementation strips tags via a first-colon split, which will truncate host:port references;
existing repo code uses last-colon splitting to avoid this.

scripts/python/tasks/managed/collect_index_images.py[37-46]
scripts/python/helpers/authentication.py[229-240]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`translation_repo_url()` currently returns `url.split(":", 1)[0]`, which drops everything after the *first* colon. For registry references that contain a port (e.g. `registry:5000/ns/repo:tag`), this returns only `registry`, corrupting the computed `rh-registry-repo` / `registry-access-repo`.

## Issue Context
Other code in this repo already uses `rsplit(':', 1)` to remove tag suffixes while preserving host:port.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[37-46]

## Suggested fix
Replace the naive split with parsing that removes a tag only when the colon appears after the last `/`, and strip digests safely:
- Start with `ref = url.split("@", 1)[0]` (drop digest if present)
- Find `last_slash = ref.rfind("/")` and `last_colon = ref.rfind(":")`
- If `last_colon > last_slash`, return `ref[:last_colon]` else return `ref`
This preserves `registry:5000/...` while still stripping `...:tag`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unstripped index values 🐞 Bug ≡ Correctness
Description
collect_index_image_components() validates target_index/index_image_resolved using .strip() but then
continues processing the unstripped strings, so leading/trailing whitespace can prevent
delivery-repo translation and cause build_tags() to miss bare OCP version tags.
Code

scripts/python/tasks/managed/collect_index_images.py[R101-111]

+        target_index = row.get("target_index")
+        source_index = row.get("index_image_resolved")
+        if not isinstance(target_index, str) or not target_index.strip():
+            msg = f"components[{index}].target_index must be a non-empty string"
+            raise ValueError(msg)
+        if not isinstance(source_index, str) or not source_index.strip():
+            msg = f"components[{index}].index_image_resolved must be a non-empty string"
+            raise ValueError(msg)
+
+        repository, tag = split_target_index(target_index)
+        tags = build_tags(tag, build_timestamp)
Evidence
The task validates stripped values but proceeds with the original strings; both tag matching and
delivery-repo prefix matching are whitespace-sensitive.

scripts/python/tasks/managed/collect_index_images.py[101-125]
scripts/python/tasks/managed/collect_index_images.py[29-34]
scripts/python/helpers/image_ref.py[22-33]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`collect_index_image_components()` checks `target_index.strip()` / `source_index.strip()` for non-emptiness, but then passes the original variables into `split_target_index()`, `build_tags()`, and `translate_delivery_repo()`. If the JSON contains whitespace (common when values come from templating or manual edits), tag parsing and translation can silently fail.

## Issue Context
- `build_tags()` uses a strict `fullmatch()` on the tag string.
- `translate_delivery_repo()` uses `startswith()` against exact prefixes.

## Fix Focus Areas
- scripts/python/tasks/managed/collect_index_images.py[101-123]
- scripts/python/helpers/image_ref.py[22-33]

## Suggested fix
1) In `collect_index_image_components()`, after the type/emptiness checks, normalize:
```py
assert isinstance(target_index, str)
assert isinstance(source_index, str)
target_index = target_index.strip()
source_index = source_index.strip()
```
Then use the normalized variables for `split_target_index()`, logging, and `translate_delivery_repo()`.

2) Optionally harden `translate_delivery_repo()` itself:
- Replace `normalized = repo.replace(...)` with `repo = repo.strip(); normalized = repo.replace(...)` so callers don’t need to remember to trim.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

@johnbieren

Copy link
Copy Markdown
Collaborator Author

/agentic_review

@johnbieren

Copy link
Copy Markdown
Collaborator Author

/agentic_review

3 similar comments
@johnbieren

Copy link
Copy Markdown
Collaborator Author

/agentic_review

@johnbieren

Copy link
Copy Markdown
Collaborator Author

/agentic_review

@seanconroy2021

Copy link
Copy Markdown
Member

/agentic_review

Comment thread scripts/python/tasks/managed/collect_index_images.py
@johnbieren johnbieren marked this pull request as ready for review June 25, 2026 18:44
@qodo-app-for-konflux-ci

Copy link
Copy Markdown

PR Summary by Qodo

Add collect_index_images managed task and delivery-repo translation helper
✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

Description

• Add a Python collect-index-images managed task to generate Pyxis snapshot JSON.
• Translate Quay delivery-repo image references to public registry URLs.
• Add unit tests covering translation rules, tagging behavior, and snapshot generation.
Diagram

graph TD
  A["Tekton params/env"] --> B["collect_index_images.py"] --> C[("Internal results JSON")]
  B --> D["image_ref.translate_delivery_repo"]
  B --> E[("index_image_snapshot.json")]
  B --> F[("Tekton result file")]
Loading
High-Level Assessment

The PR’s approach (porting bash task logic to a typed, unit-tested Python module and reusing a shared translation helper) is the most maintainable option for managed tasks. Keeping the logic in inline bash would reduce reuse and make validation/testing harder; no materially better architectural alternative stands out for this scope.

Files changed (4) +695 / -0

Enhancement (2) +242 / -0
image_ref.pyAdd delivery-repo to public-registry translation helper +55/-0

Add delivery-repo to public-registry translation helper

• Introduces translate_delivery_repo() to map Quay delivery-repo references (including flatpaks and stage/prod) into corresponding registry.redhat.io and registry.access.* URLs. Emits a warning and passes through unknown formats while leaving access URL blank.

scripts/python/helpers/image_ref.py

collect_index_images.pyAdd managed task to build index-image snapshot from internal-request results +187/-0

Add managed task to build index-image snapshot from internal-request results

• Implements a Tekton-invoked script that loads internal-request results, validates schema, derives snapshot tags (including timestamp suffix for bare vX.Y tags), translates delivery repos, and writes index_image_snapshot.json plus a Tekton result containing the snapshot filename.

scripts/python/tasks/managed/collect_index_images.py

Tests (2) +453 / -0
test_image_ref.pyAdd unit tests for delivery-repo translation rules +86/-0

Add unit tests for delivery-repo translation rules

• Adds pytest coverage for translate_delivery_repo() across prod/pending, flatpaks stage/prod, index-image style references, empty input, and unknown-format warning behavior.

scripts/python/helpers/test_image_ref.py

test_collect_index_images.pyAdd unit tests for snapshot generation and Tekton I/O behavior +367/-0

Add unit tests for snapshot generation and Tekton I/O behavior

• Adds comprehensive tests for tag derivation, target_index parsing, delivery-repo field population, imageDigests propagation/defaulting, input validation failures, and run/main behaviors including missing input file handling.

scripts/python/tasks/managed/test_collect_index_images.py

@qodo-app-for-konflux-ci

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit bbf98f2

Comment thread scripts/python/tasks/managed/collect_index_images.py
Comment thread scripts/python/helpers/image_ref.py Outdated
Comment thread scripts/python/helpers/image_ref.py
Comment thread scripts/python/tasks/managed/collect_index_images.py Outdated

@FilipNikolovski FilipNikolovski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm once @querti comments are resolved.

This commit adds a python script to replicate the functionality of the
inline bash script in the collect-index-images managed task in the
catalog repo. The task will be updated to use this python module
instead.

Assisted-By: Cursor

Signed-off-by: Johnny Bieren <jbieren@redhat.com>
@johnbieren

Copy link
Copy Markdown
Collaborator Author

/retest

@johnbieren

Copy link
Copy Markdown
Collaborator Author

/retest

@johnbieren johnbieren requested a review from twaugh June 30, 2026 18:11

@ach912 ach912 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ach912

ach912 commented Jul 1, 2026

Copy link
Copy Markdown

Production Approval Record

Field Value
Action APPROVED
Reviewer @ach912
Timestamp 2026-07-01T07:24:32.895Z

Approved

@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 1, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 2, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 2, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 2, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 2, 2026
@johnbieren johnbieren added this pull request to the merge queue Jul 3, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants