Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3d220bd
feat: Add 'casp reproduce project' command
hunsche Nov 18, 2025
8e57006
feat: Add --os-version flag to 'casp reproduce project' command
hunsche Nov 18, 2025
3d6cebc
Merge branch 'master' into fix/casp-reproduce-tool
hunsche Nov 19, 2025
8377a2d
casp: Update reproduce project command with correct Docker images
hunsche Nov 19, 2025
a2d6936
casp: Refactor Docker image logic to be dynamic
hunsche Nov 19, 2025
1214949
casp: Remove --non-dry-run option for reproduce project command
hunsche Nov 19, 2025
3d31fbe
casp: Align reproduce project command with reproduce testcase pattern
hunsche Nov 19, 2025
aef7ef9
casp: Rename --project to --environment (-e)
hunsche Nov 19, 2025
212a7dd
casp: Update reproduce project log message
hunsche Nov 19, 2025
9ac971d
casp: Set default parallelism to 10 and add reproduction summary
hunsche Nov 19, 2025
530fc41
casp: Skip unreproducible testcases in reproduce project
hunsche Nov 19, 2025
e31f8d3
casp: Consolidate initial testcase count messages
hunsche Nov 19, 2025
909a100
Update testcase skipping logic to include one-time crashers
hunsche Nov 19, 2025
28b5065
feat(casp): Adjust reproduction summary for clarity
hunsche Nov 21, 2025
9f3e261
feat(casp): Enhance testcase handling and logging in reproduction pro…
hunsche Nov 21, 2025
2403fe7
feat: Add oss-migration script and local build/testcase filtering to …
hunsche Nov 25, 2025
906bbf5
feat: enhance local build combo isolation with persistent directories…
hunsche Nov 25, 2025
3b7fc60
feat: Add signal handlers for graceful subprocess termination, standa…
hunsche Nov 25, 2025
2521dde
feat: Add scripts for Ubuntu 24.04 migration PR creation, batch proce…
hunsche Dec 1, 2025
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
50 changes: 50 additions & 0 deletions batch-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env python3
import json
import os
import subprocess
import sys

def main():
# 1. Use existing top 100 projects list
output_file = '/usr/local/google/home/matheushunsche/projects/top_100_projects.json'
if not os.path.exists(output_file):
print(f"Error: {output_file} not found. Please run count_testcases_async.py first or provide the file.")
sys.exit(1)

with open(output_file, 'r') as f:
projects_data = json.load(f)

projects = [p['project'] for p in projects_data]
# projects.reverse() # Run projects with fewer test cases first
total = len(projects)
print(f"Found {total} projects to process (running in descending order of test cases).")

# 2. Run oss-migration.py for each project
for i, project in enumerate(projects, 1):
print(f"\n[{i}/{total}] Processing project: {project}")
print("=" * 40)

# Check if project already has a successful result
summary_log = f'/usr/local/google/home/matheushunsche/projects/oss-migration/{project}/results/summary.log'
if os.path.exists(summary_log):
with open(summary_log, 'r') as f:
content = f.read()
if "✅ Success: Results meet criteria for PR." in content:
print(f"Skipping {project} as it already has a successful result.")
print("=" * 40)
continue

cmd = [sys.executable, 'oss-migration.py', project, '--use-batch', '--gcs-bucket', 'clusterfuzz-external-casp-temp', '--rebuild']
# Add other flags if needed, e.g., --use-batch, --gcs-bucket
# For now, keep it simple as requested (just build and test)

try:
subprocess.run(cmd, check=False) # Don't check=True to allow continuing on failure
except Exception as e:
print(f"Error running migration for {project}: {e}")

print(f"Finished processing {project}")
print("=" * 40)

if __name__ == '__main__':
main()
29 changes: 20 additions & 9 deletions cli/casp/src/casp/commands/reproduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is is "AS IS" BASIS,
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Expand All @@ -20,18 +20,25 @@
from casp.utils import docker_utils
import click

from . import reproduce_project

@click.command(
name='reproduce',

@click.group(name='reproduce', help='Reproduces a testcase locally')
def cli():
"""Reproduces a testcase locally"""


@cli.command(
name='testcase',
help=('Reproduces a testcase locally. '
' WARN: This essentially runs untrusted code '
'in your local environment. '
'Please acknowledge the testcase (mainly input and build) '
'before running this command.'))
@click.option(
'--project',
'-p',
help='The ClusterFuzz project to use.',
'--environment',
'-e',
help='The ClusterFuzz environment to use.',
required=True,
type=click.Choice(
docker_utils.PROJECT_TO_IMAGE.keys(), case_sensitive=False),
Expand All @@ -46,11 +53,12 @@
)
@click.option(
'--testcase-id', required=True, help='The ID of the testcase to reproduce.')
def cli(project: str, config_dir: str, testcase_id: str) -> None:
def reproduce_testcase(environment: str, config_dir: str,
testcase_id: str) -> None:
"""Reproduces a testcase locally by running a Docker container.

Args:
project: The ClusterFuzz project name.
environment: The ClusterFuzz environment name.
config_dir: The default configuration directory path within the container.
testcase_id: The ID of the testcase to be reproduced.
"""
Expand All @@ -69,6 +77,9 @@ def cli(project: str, config_dir: str, testcase_id: str) -> None:
command,
volumes,
privileged=True,
image=docker_utils.PROJECT_TO_IMAGE[project],
image=docker_utils.PROJECT_TO_IMAGE[environment],
):
sys.exit(1)


cli.add_command(reproduce_project.cli)
Loading
Loading