Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/required-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Required CI

on:
pull_request:
branches:
- "develop"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow_ref }}-${{ github.ref }}
cancel-in-progress: true

jobs:
required-checks:
runs-on: ubuntu-latest
timeout-minutes: 8
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5.4
with:
enable-cache: true
prune-cache: false
python-version: "3.13"
version: "0.9.1"
cache-suffix: required-ci

- name: Install Python dependencies
run: uv sync --frozen

- name: Run required checks
run: |
uv run pytest \
-n auto \
--timeout 15 \
tests/unit/cli/commands \
tests/unit/sdk/codebase/test_rust_backend.py \
tests/unit/sdk/codebase/test_rust_rewrite_readiness.py \
-q
176 changes: 4 additions & 172 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,99 +1,29 @@
name: Tests
name: Legacy Tests

on:
push:
branches:
- "develop"
pull_request_target:
types: [opened, synchronize, reopened, labeled]
branches:
- "develop"
workflow_dispatch:

jobs:
access-check:
runs-on: ubuntu-latest
steps:
- name: Check if bot account
id: bot-check
run: |
actor="${{ github.triggering_actor }}"
echo "Checking actor: $actor"
if [[ "$actor" == *"[bot]" ]] || [[ "$actor" == "renovate" ]] || [[ "$actor" == "dependabot" ]]; then
echo "is_bot=true" >> $GITHUB_OUTPUT
echo "Detected bot account: $actor - skipping permission check"
exit 0
else
echo "is_bot=false" >> $GITHUB_OUTPUT
echo "Detected human account: $actor"
fi
- name: Check user permissions
if: steps.bot-check.outputs.is_bot == 'false'
uses: actions-cool/check-user-permission@v2
with:
require: write
username: ${{ github.triggering_actor }}
error-if-missing: true

legacy-test-scope:
needs: access-check
runs-on: ubuntu-latest
outputs:
run_legacy_tests: ${{ steps.scope.outputs.run_legacy_tests }}
steps:
- name: Detect changes requiring legacy tests
id: scope
env:
GH_TOKEN: ${{ github.token }}
GH_EVENT_NAME: ${{ github.event_name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPOSITORY: ${{ github.repository }}
run: |
if [[ "$GH_EVENT_NAME" != "pull_request_target" ]]; then
echo "run_legacy_tests=true" >> "$GITHUB_OUTPUT"
exit 0
fi

run_legacy_tests=false
while IFS= read -r file; do
case "$file" in
.codegen/*|.github/actions/*|.github/workflows/test.yml|Cargo.lock|Cargo.toml|Dockerfile|hatch.toml|mypy.ini|pyproject.toml|ruff.toml|uv.lock|crates/*|examples/*|rust-rewrite/tools/*|scripts/*|src/*|tests/*)
run_legacy_tests=true
;;
esac
done < <(gh api --paginate "repos/$REPOSITORY/pulls/$PR_NUMBER/files" --jq '.[].filename')

echo "run_legacy_tests=$run_legacy_tests" >> "$GITHUB_OUTPUT"
if [[ "$run_legacy_tests" == "true" ]]; then
echo "Code, package, test, or workflow files changed; running legacy tests."
else
echo "Only docs/site/planning files changed; skipping expensive legacy tests."
fi
permissions:
contents: read

jobs:
unit-tests:
needs: [access-check, legacy-test-scope]
runs-on: ubuntu-latest
strategy:
matrix:
group: [1, 2, 3, 4, 5, 6, 7, 8]

steps:
- name: Skip legacy unit tests
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests != 'true' }}
run: echo "Only docs/site/planning files changed; skipping legacy unit test shard ${{ matrix.group }}."

- uses: actions/checkout@v4
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup environment
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
uses: ./.github/actions/setup-environment

- name: Test with pytest
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
timeout-minutes: 5
run: |
uv run pytest \
Expand All @@ -105,61 +35,14 @@ jobs:
tests/unit

- uses: ./.github/actions/report
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
with:
flag: unit-tests
codecov_token: ${{ secrets.CODECOV_TOKEN }}

codemod-tests:
needs: access-check
# TODO: re-enable when this check is a develop required check
if: false
runs-on: ubuntu-latest
strategy:
matrix:
sync_graph: [true, false]
size: [small, large]
exclude:
# Exclude large codemod tests when not needed
- size: ${{(contains(github.event.pull_request.labels.*.name, 'big-codemod-tests') || github.event_name == 'push' || github.event_name == 'workflow_dispatch') && 'kevin' || 'large'}}
- size: large
sync_graph: true
concurrency:
group: ${{ github.workflow }}-${{github.ref}}-${{matrix.sync_graph}}-${{matrix.size}}-${{github.event_name == 'push'&& github.sha}}
cancel-in-progress: true
name: "Codemod tests ${{matrix.size}}: Sync Graph=${{matrix.sync_graph}}"
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup environment
uses: ./.github/actions/setup-environment

- name: Cache oss-repos
uses: ./.github/actions/setup-oss-repos

- name: Run ATS and Tests
uses: ./.github/actions/run-ats
timeout-minutes: 15
with:
default_tests: "tests/integration/codemod/test_codemods.py"
codecov_static_token: ${{ secrets.CODECOV_STATIC_TOKEN }}
codecov_token: ${{ secrets.CODECOV_TOKEN }}
collect_args: "--size=${{matrix.size}} --sync-graph=${{matrix.sync_graph}}"
ats_collect_args: "--size=${{matrix.size}},--sync-graph=${{matrix.sync_graph}},"
codecov_flags: codemod-tests-${{matrix.size}}-${{matrix.sync_graph}}
env:
GITHUB_WORKSPACE: $GITHUB_WORKSPACE

parse-tests:
needs: access-check
if: contains(github.event.pull_request.labels.*.name, 'parse-tests') || github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup environment
uses: ./.github/actions/setup-environment
Expand Down Expand Up @@ -187,65 +70,15 @@ jobs:
flag: no-flag
codecov_token: ${{ secrets.CODECOV_TOKEN }}

- name: Notify parse tests failure
uses: slackapi/slack-github-action@v2.1.1
if: failure() && github.event_name == 'push' && false
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "❌ Parse Tests Failed",
"emoji": true
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Branch:* ${{ github.ref_name }}\n*Triggered by:* <${{ github.server_url }}/${{ github.actor }}|@${{ github.actor }}>\n\n*Details:*\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View workflow run>"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Failed at <!date^${{ github.event.head_commit.timestamp }}^{date_num} {time}|just now>"
}
]
}
]
}

integration-tests:
needs: [access-check, legacy-test-scope]
# The rust-rewrite baseline PR keeps protected checks focused on local unit,
# Rust, wheel, docs, and large-repo proof. These legacy integration tests push
# branches to an external fixture repo and require a writable PAT.
if: ${{ github.event_name != 'pull_request_target' || github.event.pull_request.head.ref != 'rust-rewrite' }}
runs-on: ubuntu-latest
steps:
- name: Skip legacy integration tests
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests != 'true' }}
run: echo "Only docs/site/planning files changed; skipping legacy integration tests."

- uses: actions/checkout@v4
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
with:
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup environment
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
uses: ./.github/actions/setup-environment

- name: Test with pytest
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
timeout-minutes: 5
env:
GITHUB_WORKSPACE: $GITHUB_WORKSPACE
Expand All @@ -257,7 +90,6 @@ jobs:
tests/integration/codegen

- uses: ./.github/actions/report
if: ${{ needs.legacy-test-scope.outputs.run_legacy_tests == 'true' }}
with:
flag: integration-tests
codecov_token: ${{ secrets.CODECOV_TOKEN }}
4 changes: 4 additions & 0 deletions rust-rewrite/tools/check_cli_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ cd "$ROOT"

CLI_FILES=(
src/graph_sitter/cli/cli.py
src/graph_sitter/cli/commands/diagnose/main.py
src/graph_sitter/cli/commands/doctor/main.py
src/graph_sitter/cli/commands/parse/main.py
src/graph_sitter/cli/commands/run/main.py
src/graph_sitter/cli/commands/run/run_local.py
src/graph_sitter/cli/commands/transform/main.py
tests/unit/cli/commands/diagnose/test_diagnose.py
tests/unit/cli/commands/parse/test_parse.py
tests/unit/cli/commands/run/test_run.py
tests/unit/cli/commands/transform/test_transform.py
Expand All @@ -20,13 +22,15 @@ uv run ruff check "${CLI_FILES[@]}"
uv run python -m py_compile "${CLI_FILES[@]}"

uv run graph-sitter --help >/dev/null
uv run graph-sitter diagnose --help >/dev/null
uv run graph-sitter doctor --help >/dev/null
uv run graph-sitter doctor --json >/dev/null
uv run graph-sitter parse --help >/dev/null
uv run graph-sitter run --help >/dev/null
uv run graph-sitter transform --help >/dev/null

uv run pytest \
tests/unit/cli/commands/diagnose/test_diagnose.py \
tests/unit/cli/commands/parse/test_parse.py \
tests/unit/cli/commands/run/test_run.py \
tests/unit/cli/commands/transform/test_transform.py \
Expand Down
2 changes: 1 addition & 1 deletion src/graph_sitter/cli/commands/diagnose/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def _memory_payload(samples: list[dict[str, float | str]]) -> dict[str, float |
start_rss = float(samples[0]["rss_mb"])
after_parse_rss = float(samples[1]["rss_mb"])
after_stats_rss = float(samples[-1]["rss_mb"])
peak_rss = max(float(sample["max_rss_mb"]) for sample in samples)
peak_rss = max(max(float(sample["rss_mb"]), float(sample["max_rss_mb"])) for sample in samples)
return {
"rss_start_mb": round(start_rss, 3),
"rss_after_parse_mb": round(after_parse_rss, 3),
Expand Down
Loading