Skip to content

feat(0024): CODEOWNERS + GitHub App approval matrix#40

Merged
ralphbean merged 7 commits into
mainfrom
0024-codeowners-app-matrix
Jul 14, 2026
Merged

feat(0024): CODEOWNERS + GitHub App approval matrix#40
ralphbean merged 7 commits into
mainfrom
0024-codeowners-app-matrix

Conversation

@ralphbean

Copy link
Copy Markdown
Member

Summary

  • Adds experiment 0024: empirical validation of how GitHub CODEOWNERS blank-owner entries interact with GitHub App approvals under branch protection
  • Tested 6 scenarios using two throwaway GitHub Apps (contents: read vs contents: write) against a purpose-built repo with CODEOWNERS and branch protection
  • All six hypotheses confirmed — validates the assumptions in the auto-merge ADR PR and the CODEOWNERS blank-owner PR

Key findings

Scenario Result
contents: read app approval Ignored by branch protection (403 on merge)
contents: write app + owned file Approval counts, but CODEOWNERS blocks
contents: write app + blank-owner file Merged successfully
Either app + mixed files CODEOWNERS blocks on owned files

Test plan

  • Experiment ran and results recorded
  • Pre-commit hooks pass
  • Test infrastructure cleaned up with teardown.sh

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@ralphbean ralphbean requested a review from a team as a code owner July 13, 2026 19:13
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 13, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:14 PM UTC · Completed 7:18 PM UTC
Commit: 6bc76ea · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Experiment 0024: CODEOWNERS blank owners vs GitHub App approvals

✨ Enhancement 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add experiment 0024 to empirically test CODEOWNERS blank-owner behavior under branch protection.
• Provide scripts to provision a lab repo, generate matrix PRs, and clean up resources.
• Add a Python harness to approve PRs as GitHub Apps and record mergeability outcomes.
Diagram

graph TD
  U["Operator"] --> S["setup_repo.sh"] --> R["codeowners-lab repo"] --> C["create_prs.sh"] --> P["6 test PRs"] --> H["run_matrix.py"] --> G["GitHub REST API"] --> D["results.json + 0024 README"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. GitHub Actions workflow to run the matrix
  • ➕ Fully reproducible runs without local environment drift
  • ➕ Easy to attach artifacts (results.json) and logs to a run
  • ➕ Can be scheduled or rerun on-demand with consistent inputs
  • ➖ Harder to safely manage App private keys/secrets for an ephemeral experiment
  • ➖ More setup overhead than a local one-off harness
  • ➖ Still requires creating/tearing down a dedicated lab repo/org resources
2. Use only the mergeability endpoint (no merge attempt)
  • ➕ Less destructive (no actual merges needed)
  • ➕ Fewer permissions required; clearer separation of 'mergeable' vs 'can merge'
  • ➖ May miss real-world failures only surfaced by merge attempts (e.g., 403/405 behavior differences)
  • ➖ mergeable_state timing can be flaky; may require more polling logic
3. GraphQL-based checks for required reviews/codeowner state
  • ➕ Potentially richer, more direct branch-protection/review requirement signals
  • ➕ Can reduce multiple REST calls per PR
  • ➖ Higher complexity for a small experiment
  • ➖ Requires GraphQL schema familiarity; not clearly better for simple validation

Recommendation: Current approach (REST-based approve + merge attempt) is appropriate for an empirical validation because it tests the exact failure modes that matter (403 integration access vs 405 codeowner gating). If this needs to be rerun periodically, consider adding an optional GitHub Actions workflow wrapper, but keep the local scripts as the primary path to avoid secret-management complexity.

Files changed (7) +587 / -0

Enhancement (2) +357 / -0
create_prs.shScript to create the 6 scenario PRs via GitHub API +100/-0

Script to create the 6 scenario PRs via GitHub API

• Adds a gh CLI script that creates branches, modifies one or two files per scenario using the contents API, and opens PRs against main. Encodes file contents as base64 to match the GitHub contents API contract and skips scenarios if the branch already exists.

0024-codeowners-app-matrix/create_prs.sh

run_matrix.pyPython harness to approve PRs as Apps and attempt merges +257/-0

Python harness to approve PRs as Apps and attempt merges

• Implements GitHub App JWT auth, exchanges for installation tokens, posts APPROVE reviews, and checks/attempts merges for each PR in the matrix. Writes a structured results.json capturing mergeable state, review list, HTTP status codes, and error messages.

0024-codeowners-app-matrix/run_matrix.py

Documentation (2) +106 / -0
README.mdDocument hypotheses, matrix design, and observed results +105/-0

Document hypotheses, matrix design, and observed results

• Adds the full experiment write-up: hypotheses H1–H6, lab repo/app setup, the 6-PR test matrix, and the measured outcomes including HTTP error modes. Concludes that only a contents:write app on blank-owner-only changes is mergeable under codeowner-required branch protection.

0024-codeowners-app-matrix/README.md

README.mdRegister experiment 0024 in the experiments index +1/-0

Register experiment 0024 in the experiments index

• Adds a new row linking to the 0024 CODEOWNERS + GitHub App approval matrix experiment and marks it Concluded.

README.md

Other (3) +124 / -0
requirements.txtPin Python dependencies for GitHub App auth + API calls +3/-0

Pin Python dependencies for GitHub App auth + API calls

• Adds dependencies needed by the harness: PyJWT/cryptography for RS256 app JWTs and requests for REST API calls.

0024-codeowners-app-matrix/requirements.txt

setup_repo.shProvision a dedicated lab repo with CODEOWNERS and branch protection +106/-0

Provision a dedicated lab repo with CODEOWNERS and branch protection

• Adds a gh-based setup script to create a team and repo, seed main.go/go.mod/go.sum and CODEOWNERS (including blank-owner entries), and configure branch protection requiring 1 approval plus codeowner review. Designed to be idempotent when rerun.

0024-codeowners-app-matrix/setup_repo.sh

teardown.shCleanup script for the lab repo and team +15/-0

Cleanup script for the lab repo and team

• Adds a teardown script that deletes the test repo and team and reminds the operator to manually delete the throwaway GitHub Apps.

0024-codeowners-app-matrix/teardown.sh

@qodo-code-review

qodo-code-review Bot commented Jul 13, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Context used
✅ Compliance rules (platform): 19 rules
✅ Skills: writing-how-to

Grey Divider


Action required

1. READ_BOT_PEM has default path ✓ Resolved 📜 Skill insight ⛨ Security
Description
run_matrix.py hardcodes default values for secret-related environment variables
(READ_BOT_PEM/WRITE_BOT_PEM) by falling back to local PEM key paths. This can lead to accidental
use/commit of sensitive credentials and violates the no-defaults requirement for secret environment
variables.
Code

0024-codeowners-app-matrix/run_matrix.py[R149-152]

+    read_app_id = os.environ.get("READ_BOT_APP_ID")
+    read_pem = os.environ.get("READ_BOT_PEM", "./read-bot.pem")
+    write_app_id = os.environ.get("WRITE_BOT_APP_ID")
+    write_pem = os.environ.get("WRITE_BOT_PEM", "./write-bot.pem")
Relevance

⭐⭐ Medium

Repo shows strong secret-safety reviews, but no specific precedent about forbidding default secret
env var paths.

PR-#10

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1062127 prohibits hardcoded default values for secret environment variables. The
new code sets default PEM key paths for READ_BOT_PEM and WRITE_BOT_PEM, which are used to load
GitHub App private keys.

0024-codeowners-app-matrix/run_matrix.py[149-152]
Skill: writing-how-to

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

## Issue description
`READ_BOT_PEM` and `WRITE_BOT_PEM` (paths to GitHub App private keys) currently have hardcoded default values (`./read-bot.pem`, `./write-bot.pem`). This violates the requirement to never provide defaults for secret environment variables.

## Issue Context
These PEM files contain private keys and should be supplied explicitly (via required env vars or explicit CLI args) to avoid insecure implicit behavior.

## Fix Focus Areas
- 0024-codeowners-app-matrix/run_matrix.py[149-158]

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



Remediation recommended

2. Token prefix logged ✓ Resolved 🐞 Bug ⛨ Security
Description
run_matrix.py prints the first 12 characters of each GitHub App installation token, which exposes
sensitive credential material in stdout (often captured by CI/logging systems). This conflicts with
the repo’s “don’t handle tokens unsafely” guidance and is unnecessary for the experiment to run.
Code

0024-codeowners-app-matrix/run_matrix.py[R161-170]

+    print("Authenticating read-bot...")
+    read_jwt = make_jwt(read_app_id, read_pem)
+    read_token = get_installation_token(read_jwt)
+    print(f"  read-bot token: {read_token[:12]}...")
+
+    print("Authenticating write-bot...")
+    write_jwt = make_jwt(write_app_id, write_pem)
+    write_token = get_installation_token(write_jwt)
+    print(f"  write-bot token: {write_token[:12]}...")
+
Relevance

⭐⭐⭐ High

Team previously accepted changes to reduce token/secret exposure in scripts (redaction and GH_TOKEN
scoping).

PR-#10

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The harness explicitly prints token prefixes, and the repository guidance explicitly calls out
tokens as secrets that should not be exposed.

0024-codeowners-app-matrix/run_matrix.py[161-170]
AGENTS.md[69-72]

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

## Issue description
`0024-codeowners-app-matrix/run_matrix.py` prints installation token prefixes to stdout. Even truncated token material is sensitive and can end up in CI logs, shared terminals, or log aggregation.

## Issue Context
The script only needs the token to authenticate API calls; it doesn’t need to reveal any part of it for correct behavior.

## Fix Focus Areas
- 0024-codeowners-app-matrix/run_matrix.py[161-170]
- (optional supporting context) AGENTS.md[69-72]

## Suggested fix
- Remove the two `print(f"  ... token: {token[:12]}...")` lines.
- Replace with a non-secret confirmation message (e.g., `print("  read-bot token acquired")`).
- If correlation is needed, print non-secret metadata (e.g., installation id) or a one-way hash of the token instead of the token prefix.

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


3. Unchecked API responses ✗ Dismissed 🐞 Bug ☼ Reliability
Description
approve_pr() and check_merge_status() assume GitHub API calls succeed and return the expected JSON
shapes, so expected error outcomes (like 403/405 in the experiment) can raise JSON decode/type/key
errors or record misleading data. This makes the matrix harness fragile and can prevent producing
results.json reliably.
Code

0024-codeowners-app-matrix/run_matrix.py[R100-145]

+def approve_pr(token: str, pr_number: int, bot_name: str) -> dict:
+    """Submit an APPROVE review on a PR."""
+    resp = requests.post(
+        f"{API}/repos/{ORG}/{REPO}/pulls/{pr_number}/reviews",
+        headers={**HEADERS, "Authorization": f"Bearer {token}"},
+        json={
+            "event": "APPROVE",
+            "body": f"Approved by {bot_name} (experiment)",
+        },
+        timeout=60,
+    )
+    return {"status": resp.status_code, "body": resp.json()}
+
+
+def check_merge_status(token: str, pr_number: int) -> dict:
+    """Check PR mergeability and attempt a squash merge."""
+    pr_resp = requests.get(
+        f"{API}/repos/{ORG}/{REPO}/pulls/{pr_number}",
+        headers={**HEADERS, "Authorization": f"Bearer {token}"},
+        timeout=60,
+    )
+    pr_data = pr_resp.json()
+
+    reviews_resp = requests.get(
+        f"{API}/repos/{ORG}/{REPO}/pulls/{pr_number}/reviews",
+        headers={**HEADERS, "Authorization": f"Bearer {token}"},
+        timeout=60,
+    )
+    reviews = [
+        {"user": r["user"]["login"], "state": r["state"]} for r in reviews_resp.json()
+    ]
+
+    merge_resp = requests.put(
+        f"{API}/repos/{ORG}/{REPO}/pulls/{pr_number}/merge",
+        headers={**HEADERS, "Authorization": f"Bearer {token}"},
+        json={"merge_method": "squash"},
+        timeout=60,
+    )
+
+    return {
+        "mergeable": pr_data.get("mergeable"),
+        "mergeable_state": pr_data.get("mergeable_state"),
+        "reviews": reviews,
+        "merge_status": merge_resp.status_code,
+        "merge_body": merge_resp.json(),
+    }
Relevance

⭐⭐ Medium

No direct historical evidence on checking API status before resp.json(); reliability practices not
clearly enforced here.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The code parses JSON and indexes response fields without status checks, while the experiment’s own
results table shows 403/405 responses are expected in some scenarios, making these failure modes
likely during normal runs.

0024-codeowners-app-matrix/run_matrix.py[100-145]
0024-codeowners-app-matrix/README.md[78-85]

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

## Issue description
Several requests in `run_matrix.py` call `.json()` and then index fields without checking status codes or validating the returned JSON type. When GitHub returns an error payload (often a dict) instead of the expected list/object, the harness can crash (TypeError/KeyError/JSONDecodeError) or produce incomplete/incorrect recorded results.

## Issue Context
The experiment itself documents 403 and 405 outcomes as expected signals, so the harness should treat non-2xx responses as structured outcomes rather than as unexpected shapes.

## Fix Focus Areas
- 0024-codeowners-app-matrix/run_matrix.py[100-145]
- 0024-codeowners-app-matrix/README.md[78-85]

## Suggested fix
- For every request in `approve_pr()` / `check_merge_status()`:
 - Capture `status_code` and `text`.
 - Attempt JSON parsing only when appropriate (wrap `resp.json()` in try/except).
 - When status is non-2xx, return a structured error object (e.g., `{status, error_body}`) instead of iterating/indexing.
- Specifically guard `reviews_resp.json()` to ensure it is a list before list-comprehension, and guard `merge_resp.json()` for empty/non-JSON responses.

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


Grey Divider

Qodo Logo

Comment thread 0024-codeowners-app-matrix/run_matrix.py Outdated
Comment thread 0024-codeowners-app-matrix/run_matrix.py
Comment thread 0024-codeowners-app-matrix/run_matrix.py
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review — ✅ Approve

PR: #40
Title: feat(0024): CODEOWNERS + GitHub App approval matrix
Author: ralphbean (MEMBER)
Head SHA: 06fc521537ba25f064c6e54b4b6489d00fd1a79c
Re-review: Prior SHA 6bc76eabdf44417db52cc837f33ce9f3aed4e1ee → current SHA 06fc521537ba25f064c6e54b4b6489d00fd1a79c (1 commit delta)

Delta since prior review

Single commit modifying run_matrix.py only:

  • Fixed prior finding: Removed token prefix logging (read_token[:12], write_token[:12]) — replaced with generic "authenticated" message. This directly addresses the low-severity finding from the prior review.
  • Improved env var validation: All 4 required env vars (READ_BOT_APP_ID, READ_BOT_PEM, WRITE_BOT_APP_ID, WRITE_BOT_PEM) are now validated with a clear error message listing missing vars. Previously only the two APP_ID vars were checked, and PEM vars had default paths (./read-bot.pem, ./write-bot.pem) — a latent risk if the defaults didn't exist.

Dimension analysis

Correctness ✅

  • The env var validation improvement is correct — validates all 4 required vars and reports the specific missing ones.
  • Shell scripts (create_prs.sh, setup_repo.sh, teardown.sh) are idempotent with proper existence checks.
  • run_matrix.py properly handles API responses throughout, recording status codes rather than crashing.
  • The results table in README.md is internally consistent with the test matrix and hypotheses.
  • No production test suite expected for concluded experiment tooling.

Security ✅

  • Prior finding resolved: Token prefix logging removed. No sensitive data is logged.
  • .gitignore properly excludes *.pem, .env, and results.json.
  • No hardcoded secrets or credentials.
  • All env vars now require explicit setting — no default paths for PEM files, eliminating the risk of accidentally using stale keys.
  • Shell scripts use only hardcoded org/repo names (appdumpster/codeowners-lab) — no user-controlled input in command construction.

Intent & coherence ✅

  • The experiment validates assumptions from the auto-merge ADR PR and CODEOWNERS blank-owner PR — clear purpose and documented motivation.
  • Self-contained within 0024-codeowners-app-matrix/ with no cross-experiment dependencies.
  • No linked issue, but experiments in this repo are self-authorizing per AGENTS.md.
  • Correct numbering (0024 follows 0023).

Style & conventions ✅

  • Directory naming: 0024-codeowners-app-matrix/
  • Frontmatter: title, status, topics all present ✓
  • Title format: "24. CODEOWNERS + GitHub App approval matrix" — no leading zeros ✓
  • H1 heading matches frontmatter title ✓
  • Status: Concluded — appropriate for completed experiment ✓
  • Root README.md index updated ✓
  • Shell scripts: #!/usr/bin/env bash and set -euo pipefail
  • PR title follows conventional commits: feat(0024): ...

Documentation currency ✅

  • Experiment README thoroughly documents hypotheses, approach, test infrastructure, results, and conclusions.
  • Root README.md index is in sync with the experiment on disk.
  • No staleness introduced by the delta.

Cross-repo contracts ✅

  • No exported interfaces, schemas, or public APIs affected. Self-contained experiment against throwaway test org.

Findings

No findings at or above the reporting threshold. The prior review's sole finding (token prefix logging) has been addressed.

Previous run

Review — ✅ Approve

PR: #40
Title: feat(0024): CODEOWNERS + GitHub App approval matrix
Author: ralphbean (MEMBER)
Head SHA: 6bc76eabdf44417db52cc837f33ce9f3aed4e1ee

Summary

This PR adds experiment 0024 — an empirical validation of how GitHub CODEOWNERS blank-owner entries interact with GitHub App approvals under branch protection. The experiment is well-structured, self-contained, and follows all repo conventions. Results are clearly documented and all six hypotheses were confirmed. The test infrastructure was purpose-built in a throwaway org (appdumpster) and cleaned up via teardown.sh.

Dimension analysis

Correctness ✅

  • The experiment scripts (create_prs.sh, setup_repo.sh, run_matrix.py, teardown.sh) are logically sound. They follow a clear setup → execute → measure → teardown lifecycle.
  • run_matrix.py properly validates required environment variables before proceeding and handles all API responses (including failures) by recording status codes rather than crashing — appropriate for an experiment harness.
  • The results table in README.md is internally consistent with the test matrix and the hypotheses are properly evaluated against the observed outcomes.
  • No production test suite expected for concluded experiment tooling.

Security ✅

  • .gitignore properly excludes *.pem, .env, and results.json — the three categories of sensitive files this experiment produces.
  • No hardcoded secrets, API keys, or credentials found in any file.
  • Low-severity note: run_matrix.py logs the first 12 characters of installation access tokens (lines 170–171). GitHub installation tokens follow the ghs_-prefix format, so this reveals 8 meaningful characters. Since these are short-lived tokens (~1 hour) in throwaway test infrastructure, this is not exploitable in practice, but the pattern shouldn't be copied into production code.

Intent & coherence ✅

  • The experiment is properly scoped to validate assumptions from the auto-merge ADR PR and the CODEOWNERS blank-owner PR. The results directly inform those design decisions.
  • No unauthorized scope expansion — the PR only adds the experiment directory and updates the root README index.

Style & conventions ✅

  • Directory naming: 0024-codeowners-app-matrix/ ✓ (zero-padded 4-digit)
  • Frontmatter: title, status, topics all present ✓
  • Title format: "24. CODEOWNERS + GitHub App approval matrix" — no leading zeros in title ✓
  • H1 heading matches frontmatter title ✓
  • Status: Concluded — appropriate for a completed experiment with documented results ✓
  • Root README.md index updated with experiment entry ✓
  • Shell scripts use #!/usr/bin/env bash and set -euo pipefail
  • PR title follows conventional commits: feat(0024): ...

Documentation currency ✅

  • Experiment README.md is thorough: hypotheses, approach, test infrastructure, repo layout, branch protection config, test matrix, measurement methodology, results table, key observations, and conclusions.
  • Root README.md index is in sync with the new experiment on disk.

Cross-repo contracts ✅

  • No cross-repo APIs, schemas, or interfaces affected. The experiment is self-contained and operates against a throwaway test org.

Findings

Severity File Description
low 0024-codeowners-app-matrix/run_matrix.py Token prefix logging (lines 170–171) prints first 12 chars of ghs_-prefixed installation tokens. Not exploitable with short-lived throwaway tokens, but avoid copying this pattern.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Jul 13, 2026
- Remove default PEM paths — all four env vars are now required
- Replace token prefix logging with non-revealing confirmation messages

Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 13, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:31 PM UTC · Completed 7:37 PM UTC
Commit: 06fc521 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed ready-for-merge All reviewers approved — ready to merge labels Jul 13, 2026

@ben-alkov ben-alkov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@ralphbean ralphbean added this pull request to the merge queue Jul 14, 2026
Merged via the queue into main with commit cd6df4e Jul 14, 2026
8 checks passed
@ralphbean ralphbean deleted the 0024-codeowners-app-matrix branch July 14, 2026 00:08
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jul 14, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 12:09 AM UTC · Completed 12:16 AM UTC
Commit: 06fc521 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

PR #40 added experiment 0024 (CODEOWNERS + GitHub App approval matrix) — a human-authored PR by ralphbean with Claude Opus 4.6 assistance. The workflow was efficient: two review bots (fullsend-ai-review and qodo) reviewed in parallel, identified overlapping and complementary security findings, and the author fixed two of three flagged issues in a single follow-up commit. A second human reviewer approved with LGTM. Total time to merge was ~5 hours with only 1 rework iteration. One notable review quality gap: the fullsend-ai-review agent missed default PEM path values on secret-related env vars that qodo correctly flagged. Two proposals filed.

Proposals filed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants