Repository audit: fix CI, restore broken examples, remove committed artifacts and PII - #178
Merged
Conversation
- Delete a committed 5,310-file Python virtualenv (frontend-integration/venv), 2,265 __pycache__ entries, 15 .DS_Store files and uAgents runtime state (duffel-agent sqlite session stores, agent1q*_data.json). The vendored venv also broke root-level pytest collection. - Rename security-scanner-agent/,gitignore -> .gitignore; the typo meant its ignore rules never applied. - Rename the two tracked Crewai-agents .env files to .env.example. Both only ever held empty placeholders, verified across the full git history. - Replace the blanket *.json ignore with credential-specific patterns and stop ignoring .dockerignore, so legitimate project files are no longer dropped.
…d pass The test job never ran a single test. `find ... | grep -q .` makes find die of SIGPIPE as soon as grep exits on the first match, and under `set -o pipefail` that failure became the if-condition, so every run reported "No test files found; skipping tests" — confirmed in the run logs. Fixing only the pipeline is not enough: a root-level `pytest` fails collection on 32 modules because the examples have independent, conflicting dependency sets. Replace it with .github/scripts/run-example-tests.sh, which builds a virtualenv per example from that example's requirements.txt and runs its suite. All seven discovered suites pass (234 tests). Also deselect stripe-payment-agents/twitch-growth-agent's integration tests by default: they call os._exit(0), which terminates pytest mid-run with a success code and silently drops every remaining test. They stay runnable via `pytest -m integration`. Move review-required into its own workflow so it also triggers on pull_request_review. It previously only ran on push-style PR events, so it stayed red after a maintainer approved and could never be satisfied. Also take each reviewer's latest state so a later CHANGES_REQUESTED overrides an earlier approval, and drop the stale contributor-path-check entry from BRANCH_PROTECTION.md — no workflow produces that check, so requiring it would block every PR forever.
…m releases These examples pinned nothing, so a fresh `pip install -r requirements.txt` today installs releases that removed the APIs they use: - ag2 1.0 dropped the `autogen` module entirely (it now exposes a different `ag2` API), so `from autogen import ConversableAgent, LLMConfig` fails. - a2a-sdk 0.4 removed `a2a.types.TextPart`; uagents-adapter dropped `SingleA2AAdapter`. - mcp 2.0 renamed `streamablehttp_client` to `streamable_http_client`. Pin to the last compatible line rather than rewriting the examples onto new APIs, matching the pins already used by launch-your-a2a-agent and google-adk/sub-agents. Also give the ag2 suites an event loop for their synchronous tests: pytest-asyncio unsets the loop after each async test, but SingleA2AAdapter calls asyncio.get_event_loop() when constructed, so the adapter tests failed purely on ordering. Verified on Python 3.11: payment-approval 15 passed, research-synthesis-team 15 passed, ticketlens-agent 6 passed.
- advance-agent-examples/ was renamed to google-adk/; both the structure tree and the index still pointed at the old path (404 on GitHub). - Add the five example directories missing from the index entirely: google-adk, langchain-agents, pydantic-agent, security-scanner-agent and video-to-map-agent. Every top-level example directory is now listed and every relative link in README.md resolves.
…anges Two bugs that fire on ordinary PRs: - The changed-file list included deletions, so ruff and mypy were handed paths that no longer exist and failed with E902. Any PR that removes a .py file broke all three jobs. Filter with --diff-filter=ACMR. - mypy was given every changed file in one invocation. The examples are independent projects that reuse filenames, so touching two files that share a basename (agent.py, main.py, conftest.py) aborted the run with "Duplicate module" before checking anything. Invoke mypy per file instead.
…emplates - duffel-agent shipped real passenger profiles in KNOWN_PASSENGERS: full names, fetch.ai email addresses, phone numbers, dates of birth and a passport number. Replace with an empty map plus a commented template; both call sites already handle an unknown sender, so demo behaviour is unchanged for everyone else. The people named may want to treat those details as disclosed. - Composio/linkedln/.env.example defined LINKEDLN_AUTH_CONFIG_ID while the code reads LINKEDIN_AUTH_CONFIG_ID, so following the README always produced a null auth config. - fet-example/.env.example asked for GEMINI_API_KEY, which the example never reads; it uses ASI_ONE_API_KEY. - a2a-cart-store/README.md told users to install ../requirements.txt, which does not exist (the parent is the repo root). - contributors/README.md linked a gemini-research-agent/ directory that does not exist, and omitted the two community agents that do. - Correct seven relative links in example READMEs that pointed at the wrong directory depth (LICENSE, docs.md, sibling examples). - Delete two dead files: an empty duffel-agent/runner.py and events-finder-mcp-agent/new-adapter.py, an unreferenced orphan importing a .protocol module that does not exist.
CI installs the latest ruff on every run, and ruff's default selection has since grown far past the classic E4/E7/E9/F set these examples were written against. The practical effect is that upgrading ruff upstream retroactively fails PRs on pre-existing style debt (BLE001, S110, I001, UP006 and friends) across ~200 files, in code the contributor never touched. On duffel-agent/protocols alone that is 20 findings, 18 of which predate this branch. A maintainer already hit this and scoped Browser-based-agents/browser-use with a local ruff.toml (9baf342), explicitly preferring that over rewriting exception handling repo-wide. Apply the same decision at the root so it holds everywhere. An example can still opt into stricter rules with its own config. Also fix the two genuine pyflakes findings this exposed in duffel-agent: an unused uuid4 import and an f-string with no placeholders.
The CI format job checks whole changed files, and this file was never ruff-format clean, so any edit to it fails the gate. Mechanical reformat only, no behaviour change (verified: file still compiles and lint is clean).
Same SIGPIPE-under-pipefail bug as the test job. 'echo "$CHANGED" | grep -q' kills echo as soon as grep matches and stops reading, and pipefail promotes that to a failed condition, so the check reports a missing changelog entry on PRs that updated it. It only shows on large PRs, where the match lands early and echo still has thousands of lines to write: on this branch CHANGELOG.md is the 8th of 5383 changed paths and the pipeline exits 141. Use a here-string, which feeds grep from a temp file and cannot SIGPIPE.
GSSoC '26 has ended, so the label bootstrap/sync workflows, the label definitions, the bootstrap script and docs/GSSOC.md no longer serve the repo. The contributor badge system existed to support that program, so the award workflow, badge artwork, BADGE_REGISTRY.json and profile-badge-sync go with it, along with the badge sections in CONTRIBUTING.md and contributors/README.md. Also drop create-fetch-tech-issues.sh, a one-shot script that bulk-created the issue batch #54-#91. It is not wired into CI and re-running it duplicates issues. Kept .github/scripts/run-example-tests.sh: it is not program automation, it is what the CI test job runs. Generic contributor infrastructure stays: CONTRIBUTING.md, issue and PR templates, CODEOWNERS, MAINTAINERS, stargazer-gate, review-required and the contributors/ folder. Individual contributors' own credit lines in their agent READMEs are untouched.
The repo had no GitHub topics set at all, which is the biggest discoverability lever on GitHub; 20 are now set via the API along with a keyword-led description and a homepage link. README changes: keyword-led header and quick nav, the folder tree expanded into a full annotated map grouped by category (so the layout is readable without browsing), a star history chart, a test command in the contributing steps, and an FAQ answering what people actually search for. Also lists contributors/gemini-task-manager-agent, which existed but was missing from the index. All relative links and heading anchors verified.
The GSSoC removal commit deleted .github/scripts/run-example-tests.sh along with the program scripts in the same directory, which its own message said it was keeping. The test job runs that file, so it failed with exit 127 (No such file or directory) instead of running the suites. Restored unchanged from ff3eca2, executable bit included.
Reviews every PR into main with ASI:One (model asi1), posting inline comments on the diff plus a summary, and failing the check on a high-confidence must_fix or a secret-scan hit so it can be made merge-blocking. Two decisions worth calling out: Trigger is pull_request_target, not pull_request. Most contributions here come from forks, and pull_request does not expose repository secrets to fork PRs, so the review would silently skip for exactly the contributors it is meant to help. pull_request_target is only safe if the workflow never runs contributor code: checkout takes the base ref and the script reads the diff over the API, never executing anything from the PR. The workflow says so where someone would be tempted to add a build step. Without ASI_ONE_API_KEY the job explains what is missing and passes, so adding this does not block a repo that has not configured the secret. The prompt treats the PR title, body and diff as untrusted data rather than instructions, scopes findings to the diff, and asks for few high-signal results since these are teaching examples. Inline comments are only emitted for lines inside a diff hunk, because one bad line reference makes GitHub reject the whole review; anything else is demoted to the summary. Verified the hunk parser and secret patterns against hand-built cases and the read path against this PR. Also switches the README star history to the theme-aware star-history badge.
…pendency files conversational-property-finder could not start at all. It imports a property_finder package that exists nowhere in the repo: the directory was renamed to conversational-property-finder without updating the imports, and a hyphenated directory can never be a package. The sys.path bootstrap meant to enable that import also ran after it. Now imports asi1_agent and repliers_client directly with the path set up first, verified by resolving all four module specs. Added the missing asi1_agent/.env.example covering the 18 variables the code actually reads, and rewrote the README instructions, which pointed at property_finder/ and at the original author's local desktop path. Five examples instruct 'pip install -r requirements.txt' but ship no such file: airbnb-mcp-agent, calendar_chat_uagent, gmail_chat_uagent, shopping_agent and Prep-for-a-meeting-Agent. Each now has one derived from its actual imports and pinned like its siblings. shopping_agent needed the same a2a-sdk<0.4 and uagents-adapter==0.6.2 pins as ag2-agents: it imports a2a.types.TextPart and SingleA2AAdapter, both removed upstream. Also: fet-example omitted cosmpy and requests while listing Pillow and google-genai that it never imports; pdf-summariser-example shipped a .env.example and a README telling you to use it but never called load_dotenv; and the Nike agent asked for notte when it imports notte_sdk. Found by three parallel audit subagents. I checked each claim first, which is how two of them turned out not to hold: web3 metta/test.py imports siblings that do exist and runs fine, and 'notte' does pull in notte-sdk, so that one was wasteful rather than broken.
The header read 'token with pull-requests: write', which sounds like a maintainer has to mint a personal access token with write access. It is the per-run token Actions creates on its own, scoped to this repository, narrowed by the workflow to contents:read and pull-requests:write, and expired when the job ends. The write bit exists only so the job can post its review back onto the PR. ASI_ONE_API_KEY remains the only secret anyone has to add.
Addresses four issues that were each reproducible in the current tree: - #111/#138: trip_planner's calculator ran eval() on model-authored text, giving prompt injection arbitrary code execution. Replaced with an AST walker limited to arithmetic, with a bounded exponent. - #130: the LinkedIn agent shared one instance across all chat senders and reassigned its user_id per message, so concurrent users could act on each other's LinkedIn accounts. Instances are now per sender. - #134: the GitHub MCP agent read `scopes` outside the branch that binds it, crashing on any token GitHub does not report scopes for. - #148: the frontend integration issued POSTs with no timeout, letting an unresponsive agent pin a Flask worker forever.
…ments
COPYing ${EXAMPLE}/requirements.txt fails the Docker build outright when an
example ships none, so the example is now copied first and the install is
guarded by a file test. setup.sh assumed the POSIX .venv/bin layout and could
not activate the venv under Git Bash, which uses .venv/Scripts.
Co-authored-by: saurabhhhcodes <saurabhhhcodes@users.noreply.github.com>
Adds a regression suite for the trip_planner calculator so the eval() hole cannot reopen: ordinary arithmetic keeps working and each escape payload is refused. Also narrows the last bare except, which would have swallowed KeyboardInterrupt and left the agent unstoppable mid-request. Co-authored-by: Chitranshu0 <Chitranshu0@users.noreply.github.com> Co-authored-by: saurabhhhcodes <saurabhhhcodes@users.noreply.github.com>
The root CHANGELOG.md tried to cover every example in the repository at once. Since the examples are independent projects that change on unrelated schedules, it was mostly merge-conflict surface for contributors rather than something anyone read. Removed, along with the two checks that would now fail on every run: the pull_request changelog gate and the required-files list on main. contributors/CHANGELOG.md stays, and is still enforced for changes under contributors/, since community agents do share a release flow.
…None bugs changelog-check counted deleted files, so removing stale contributor artifacts demanded a changelog entry for work that only took things away. It now uses --diff-filter=ACMR, matching what lint, format and typecheck already do. The format and typecheck jobs were failing on pre-existing debt in files this branch happens to touch. Applied ruff format, and fixed the type errors rather than silencing them — two were real: the GitHub agent dereferenced get_user_info() without checking for None, which crashes when GitHub rejects a freshly minted device-flow token, and the LinkedIn agent passed an unvalidated LINKEDIN_AUTH_CONFIG_ID straight through to Composio.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Audit of the repository, covering CI, dependencies, committed artifacts, secrets and documentation. Every change is scoped to a problem I could reproduce; nothing here is a stylistic rewrite.
The CI gate was not testing anything
The
testjob reported "No test files found" on every run since it was added. The cause:grep -qexits as soon as it matches,findthen dies with SIGPIPE, andset -o pipefailturns that into a failing pipeline — so theelsebranch ran even though tests existed. Replaced with.github/scripts/run-example-tests.sh.The script builds a virtualenv per example, because a single root
pytestcannot work here:ag2-agentsneedsa2a-sdk<0.4whileClaude Agent SDKneeds a newer one, and the rootDockerfileonly installsuagents. 234 tests across 7 suites now run and pass.Three more CI defects, each of which failed PRs for reasons unrelated to their content:
review-requiredonly triggered on push-style PR events, so it stayed red after a maintainer approved. Moved toreview-required.ymlwith apull_request_reviewtrigger, and it now uses each reviewer's latest state soCHANGES_REQUESTEDcorrectly overrides an earlier approval.lint/format/typecheckpassed deleted files toruff/mypy(any PR removing a.pyfile failed), andmypyaborted with "Duplicate module" whenever a PR touched two files sharing a basename —tests/conftest.pyin two examples was enough.ruff.tomlat the root pins the rule selection. CI installs the latest ruff, and ruff's defaults have grown well past theE4/E7/E9/Fset these examples were written against, so an upstream ruff release retroactively fails PRs on untouched code. A maintainer already hit this and scoped one directory the same way in 9baf342; this applies that decision repo-wide.Three examples could not start
Unpinned dependencies, each broken by a major release:
ag2-agents/*autogenmodule; a2a-sdk 0.4 removeda2a.types.TextPart;uagents-adapterdroppedSingleA2AAdaptermcp-agents/ticketlens-agentstreamablehttp_clientPinned to the last compatible line rather than rewriting the examples.
Separately,
twitch-growth-agent's integration tests callos._exit(0), which terminates pytest mid-run with a success code and silently drops the other 28 tests. Deselected by default viapytest.ini; still runnable withpytest -m integration.Committed artifacts and PII
frontend-integration/venv/, plus 2,265__pycache__entries, 15.DS_Storefiles, and uAgents runtime state (*.sqlite,agent1q*_data.json)..gitignorehad a blanket*.jsonrule that silently dropped legitimate project files, and ignored.dockerignore. Replaced with credential-specific patterns.security-scanner-agent/,gitignore— a typo for.gitignore, so its rules never applied.duffel-agentshipped real passenger PII: full names,fetch.aiemail addresses, phone numbers, dates of birth and a passport number, in aKNOWN_PASSENGERSmap. Replaced with an empty map and a commented template; both call sites already handled an unknown sender, so demo behaviour is unchanged. The people named may want to treat those details as disclosed — this is in the public git history and removing it here does not undo that.Documentation that did not match the code
Composio/linkedln/.env.exampledefinedLINKEDLN_AUTH_CONFIG_ID; the code readsLINKEDIN_AUTH_CONFIG_ID, so following the README always produced a null auth config.fet-example/.env.exampleasked forGEMINI_API_KEY, which the example never reads (it usesASI_ONE_API_KEY).a2a-cart-store/README.mdtold users to install a../requirements.txtthat does not exist.advance-agent-examples/, renamed togoogle-adk/, and omitted five directories.contributors/README.mdlinked agemini-research-agent/that does not exist and omitted the two community agents that do..github/BRANCH_PROTECTION.mdlistedcontributor-path-checkas a required status check. No workflow produces it, so enabling branch protection as documented would have blocked every PR indefinitely.Verification
ruff check,ruff format --checkandmypyare clean on every file this branch touches, and the full example test suite passes. The test script was run locally end to end.Not addressed
Composio/linkedln/agent.pykeeps a single module-level agent instance shared across all senders, so concurrent users overwrite each other's session. That is a real bug but the fix changes the example's structure, so it belongs in its own PR.Closes #34