fix(aw): Issue Arborist - re-apply curl REST API workaround for DIFC proxy#8573
Conversation
The gh issue list invocation still fails under the DIFC proxy even with gh-aw-mcpg v0.3.17 (the version was supposed to resolve the /meta block per githubnext/agentics#339). The failed run at https://github.com/microsoft/testfx/actions/runs/26406407163 surfaced a different but related `malformed version:` error, so re-apply the curl + REST API workaround that was introduced in #8185 / #8507 and reverted in #8550. Fixes #8571. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Re-applies the Issue Arborist “curl + GitHub Search REST API” workaround to fetch recent open issues without using gh issue list, avoiding DIFC proxy–related failures that are still occurring despite newer gh-aw-mcpg versions.
Changes:
- Replace
gh issue listwith acurlcall to${{ github.api_url }}/search/issues, normalizing the REST payload viajqto match the expectedgh --jsonshape. - Add
GH_AW_ORIGINAL_GITHUB_API_URLenv var to preserve the real API URL for the REST call. - Regenerate the compiled workflow lock file (
--strict) to reflect the updated source workflow.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/issue-arborist.md | Switches issue prefetching from gh to curl + REST search and normalizes output JSON for the agent prompt. |
| .github/workflows/issue-arborist.lock.yml | Regenerated compiled workflow reflecting the updated fetch step and environment variables. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 1
| "${GH_AW_ORIGINAL_GITHUB_API_URL}/search/issues" \ | ||
| | jq '.items // [] | map({ | ||
| number: .number, |
Evangelink
left a comment
There was a problem hiding this comment.
Expert Review Summary
This PR re-applies a curl/REST API workaround for the Issue Arborist workflow to work around DIFC proxy compatibility issues with gh issue list.
| # | Dimension | Verdict |
|---|---|---|
| 1 | Algorithmic Correctness | 🔴 1 MAJOR |
| 8 | Defensive Coding at Boundaries | 🔴 1 MAJOR |
✅ 19/21 dimensions clean.
Issues Found
- Algorithmic Correctness — Semantic mismatch:
-parent-issue:*≠-is:sub-issue. The new query will include child issues that should be excluded, breaking the workflow's filtering contract. - Defensive Coding — Pipeline error handling: the
|| echo '[]'fallback only applies to curl, not the entirecurl | jqpipeline. If jq fails (malformed JSON, HTML error page), the fallback doesn't execute and the workflow crashes.
Dimensions Not Applicable
The following dimensions were evaluated but do not apply to this workflow configuration change:
- Threading & Concurrency (no shared mutable state)
- Public API & Binary Compatibility (workflow files only)
- Performance & Allocations (workflow execution, not hot path)
- Cross-TFM Compatibility (no multi-targeting)
- Resource & IDisposable Management (no .NET resources)
- Localization & Resources (no user-facing strings)
- Test Isolation, Assertion Quality, Flakiness, Test Completeness, Data-Driven Coverage (no test changes)
- Naming & Conventions (bash/YAML, not C#)
- Documentation Accuracy (extensive comments present)
- Analyzer & Code Fix Quality (no analyzer changes)
- IPC Wire Compatibility (no serialization protocol changes)
Clean Dimensions
- ✅ Security & IPC Contract Safety — All inputs properly escaped, credentials handled securely, no injection vectors
- ✅ Code Structure & Simplification — Appropriate structure for curl + jq pipeline
- ✅ Build Infrastructure — Isolated workflow fix, no impact on build/test/release
- ✅ Scope & PR Discipline — Single-purpose change, excellent cross-referencing (5+ related issues/PRs)
Note: The two MAJOR issues require fixes before merge. The semantic query mismatch could cause the arborist to process issues incorrectly, and the incomplete error handling will cause obscure failures when the API returns malformed responses.
Generated by Expert Code Review (on open) for issue #8573 · ● 3.3M
| -H "Authorization: Bearer ${GITHUB_TOKEN}" \ | ||
| -H "Accept: application/vnd.github+json" \ | ||
| --get \ | ||
| --data-urlencode "q=repo:${GH_AW_GITHUB_REPOSITORY} is:issue is:open -is:sub-issue" \ |
There was a problem hiding this comment.
[MAJOR] Algorithmic Correctness
Semantic mismatch in issue filtering query
The old query uses -parent-issue:* which excludes issues that have a parent-issue: custom field (i.e., issues that are children in a parent-child relationship).
The new query uses -is:sub-issue which excludes issues marked by GitHub's native sub-issue feature.
These are not equivalent.
Concrete failing scenario:
- Repository has Issue DeploymentItem should be implemented via Fx extensibility #100 (parent issue)
- Issue Removed Attribute from the namespace for DynamicDataAttribute #200 is linked as a child via the custom
parent-issue: #100field - Old query (
-parent-issue:*) → excludes Removed Attribute from the namespace for DynamicDataAttribute #200 (has parent) - New query (
-is:sub-issue) → includes Removed Attribute from the namespace for DynamicDataAttribute #200 (not marked as native sub-issue) - The arborist now incorrectly processes Issue Removed Attribute from the namespace for DynamicDataAttribute #200 as a candidate for linking
Impact: Child issues that should be excluded will now be included, breaking the workflow's core filtering logic. The arborist may attempt to re-link issues that are already children, or create duplicate parent-child relationships.
Recommendation:
The search query should match the original intent. Options:
- Use
NOT "parent-issue" in:bodyif the parent relationship is tracked in issue bodies - Switch to GitHub's native sub-issue feature consistently (document the migration)
- Use the GitHub GraphQL API directly with the same query structure as
gh issue list
Note: The comment states this "re-applies the exact same workaround" from #8185 and #8507, but if those PRs had the same query mismatch, the filtering bug has been present since the original workaround.
| milestone: (if .milestone != null then {title: .milestone.title} else null end), | ||
| assignees: [.assignees[] | {login: .login}] | ||
| })' \ | ||
| > /tmp/gh-aw/issues-data/issues.json \ |
There was a problem hiding this comment.
[MAJOR] Defensive Coding at Boundaries
jq parse failure not caught by fallback
The || echo '[]' fallback is chained only to curl, not to the entire curl | jq pipeline. If jq fails to parse the response (malformed JSON, HTML error page, network corruption), the fallback does NOT execute.
Concrete failing scenario:
- GitHub API returns HTTP 500 with an HTML error page (service outage, proxy error)
curlsucceeds (exit 0) and writes HTML to stdoutjqattempts to parse HTML → parse error, exits 1- The
|| echo '[]'fallback does not execute (it's only attached to curl) /tmp/gh-aw/issues-data/issues.jsonis empty or truncated- The next line runs
jq 'length' /tmp/gh-aw/issues-data/issues.json→ crashes with parse error - Workflow fails with obscure error instead of graceful degradation
Proof:
# Simulate malformed JSON
echo "not json" | jq '.items // []' > output.json || echo '[]' > output.json
# jq exits 1, but the || fallback doesn't fire because it's not part of the piped commandRecommendation:
The fallback must apply to the entire pipeline:
curl -s \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
--get \
--data-urlencode "q=repo:${GH_AW_GITHUB_REPOSITORY} is:issue is:open -is:sub-issue" \
--data-urlencode "sort=created" \
--data-urlencode "order=desc" \
--data-urlencode "per_page=100" \
"${GH_AW_ORIGINAL_GITHUB_API_URL}/search/issues" \
| jq '.items // [] | map({
number: .number,
title: .title,
author: {login: .user.login},
createdAt: .created_at,
state: (.state | ascii_upcase),
url: .html_url,
body: .body,
labels: [.labels[] | {name: .name}],
updatedAt: .updated_at,
closedAt: .closed_at,
milestone: (if .milestone != null then {title: .milestone.title} else null end),
assignees: [.assignees[] | {login: .login}]
})' > /tmp/gh-aw/issues-data/issues.json \
|| echo '[]' > /tmp/gh-aw/issues-data/issues.jsonMove the || echo '[]' to the end of the entire pipeline so it catches both curl and jq failures.
Fixes #8571.
The
Fetch issues datastep in.github/workflows/issue-arborist.mdstill fails under the DIFC proxy even withgh-aw-mcpg v0.3.17— the version that was supposed to resolve the/metablock per githubnext/agentics#339.The most recent failed run (https://github.com/microsoft/testfx/actions/runs/26406407163) surfaced a different, but still
gh CLI-induced, error:So PR #8550 (which reverted #8507's workaround in anticipation of the upstream mcpg fix) was premature. This PR re-applies the exact same
curl + REST APIworkaround that was previously introduced in #8185 and re-applied in #8507. The compiled.lock.ymlis regenerated withgh aw v0.75.0 compile --strict.The agent prompt is unchanged because the curl pipeline normalizes the JSON shape to match what
gh issue list --jsonwould return (uppercasedstateetc.), so downstreamjqqueries in the prompt continue to work as-is.