Skip to content

Repository audit: fix CI, restore broken examples, remove committed artifacts and PII - #178

Merged
gautammanak1 merged 21 commits into
mainfrom
chore/repo-audit-cleanup
Aug 13, 2026
Merged

Repository audit: fix CI, restore broken examples, remove committed artifacts and PII#178
gautammanak1 merged 21 commits into
mainfrom
chore/repo-audit-cleanup

Conversation

@gautammanak1

Copy link
Copy Markdown
Collaborator

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 test job reported "No test files found" on every run since it was added. The cause:

if find . -name "test_*.py" ... | grep -q .; then

grep -q exits as soon as it matches, find then dies with SIGPIPE, and set -o pipefail turns that into a failing pipeline — so the else branch ran even though tests existed. Replaced with .github/scripts/run-example-tests.sh.

The script builds a virtualenv per example, because a single root pytest cannot work here: ag2-agents needs a2a-sdk<0.4 while Claude Agent SDK needs a newer one, and the root Dockerfile only installs uagents. 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-required only triggered on push-style PR events, so it stayed red after a maintainer approved. Moved to review-required.yml with a pull_request_review trigger, and it now uses each reviewer's latest state so CHANGES_REQUESTED correctly overrides an earlier approval.
  • lint/format/typecheck passed deleted files to ruff/mypy (any PR removing a .py file failed), and mypy aborted with "Duplicate module" whenever a PR touched two files sharing a basename — tests/conftest.py in two examples was enough.
  • ruff.toml at the root pins the rule selection. CI installs the latest ruff, and ruff's defaults have grown well past the E4/E7/E9/F set 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:

Example Break
ag2-agents/* ag2 1.0 removed the autogen module; a2a-sdk 0.4 removed a2a.types.TextPart; uagents-adapter dropped SingleA2AAdapter
mcp-agents/ticketlens-agent mcp 2.0 renamed streamablehttp_client

Pinned to the last compatible line rather than rewriting the examples.

Separately, twitch-growth-agent's integration tests call os._exit(0), which terminates pytest mid-run with a success code and silently drops the other 28 tests. Deselected by default via pytest.ini; still runnable with pytest -m integration.

Committed artifacts and PII

  • A 5,310-file Python virtualenv under frontend-integration/venv/, plus 2,265 __pycache__ entries, 15 .DS_Store files, and uAgents runtime state (*.sqlite, agent1q*_data.json).
  • .gitignore had a blanket *.json rule 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-agent shipped real passenger PII: full names, fetch.ai email addresses, phone numbers, dates of birth and a passport number, in a KNOWN_PASSENGERS map. 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.example defined LINKEDLN_AUTH_CONFIG_ID; 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 a ../requirements.txt that does not exist.
  • The root examples index pointed at advance-agent-examples/, renamed to google-adk/, and omitted five directories.
  • contributors/README.md linked a gemini-research-agent/ that does not exist and omitted the two community agents that do.
  • Seven relative links in example READMEs pointed at the wrong directory depth.
  • .github/BRANCH_PROTECTION.md listed contributor-path-check as 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 --check and mypy are 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.py keeps 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

- 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).
@github-actions github-actions Bot added documentation Improvements or additions to documentation gssoc26 GirlScript Summer of Code 2026 contribution level1 GSSoC level 1 - beginner friendly (lowest points) labels Aug 13, 2026
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.
@gautammanak1 gautammanak1 removed gssoc26 GirlScript Summer of Code 2026 contribution level1 GSSoC level 1 - beginner friendly (lowest points) labels Aug 13, 2026
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.
@github-actions github-actions Bot added gssoc26 GirlScript Summer of Code 2026 contribution level1 GSSoC level 1 - beginner friendly (lowest points) labels Aug 13, 2026
gautammanak1 and others added 9 commits August 14, 2026 03:27
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.
@gautammanak1
gautammanak1 merged commit 931b448 into main Aug 13, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation gssoc26 GirlScript Summer of Code 2026 contribution level1 GSSoC level 1 - beginner friendly (lowest points)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong path: Missing README references for some example folders

1 participant