diff --git a/infra/gcb/badge_images/building.png b/infra/gcb/badge_images/building.png new file mode 100644 index 000000000..9e7e73447 Binary files /dev/null and b/infra/gcb/badge_images/building.png differ diff --git a/infra/gcb/badge_images/building.svg b/infra/gcb/badge_images/building.svg new file mode 100644 index 000000000..19f28d7fb --- /dev/null +++ b/infra/gcb/badge_images/building.svg @@ -0,0 +1 @@ + oss-fuzzoss-fuzzfuzzingfuzzing \ No newline at end of file diff --git a/infra/gcb/badge_images/coverage_failing.png b/infra/gcb/badge_images/coverage_failing.png new file mode 100644 index 000000000..85abe2352 Binary files /dev/null and b/infra/gcb/badge_images/coverage_failing.png differ diff --git a/infra/gcb/badge_images/coverage_failing.svg b/infra/gcb/badge_images/coverage_failing.svg new file mode 100644 index 000000000..dc7b72e39 --- /dev/null +++ b/infra/gcb/badge_images/coverage_failing.svg @@ -0,0 +1 @@ + oss-fuzzoss-fuzzcoverage failingcoverage failing \ No newline at end of file diff --git a/infra/gcb/badge_images/failing.png b/infra/gcb/badge_images/failing.png new file mode 100644 index 000000000..0d2bb4701 Binary files /dev/null and b/infra/gcb/badge_images/failing.png differ diff --git a/infra/gcb/badge_images/failing.svg b/infra/gcb/badge_images/failing.svg new file mode 100644 index 000000000..ed0f8621e --- /dev/null +++ b/infra/gcb/badge_images/failing.svg @@ -0,0 +1 @@ + oss-fuzzoss-fuzzbuild failingbuild failing \ No newline at end of file diff --git a/infra/gcb/builds_status.py b/infra/gcb/builds_status.py index 0b2fe15ef..eb98ac166 100755 --- a/infra/gcb/builds_status.py +++ b/infra/gcb/builds_status.py @@ -20,6 +20,7 @@ import build_project STATUS_BUCKET = 'oss-fuzz-build-logs' SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +BADGE_DIR = 'badges/' RETRY_COUNT = 3 RETRY_WAIT = 5 MAX_BUILD_RESULTS = 2000 @@ -173,6 +174,45 @@ def update_build_status( upload_status(successes, failures, status_filename) +def update_build_badges(builds, projects, build_tag, coverage_tag): + for project in projects: + last_build = find_last_build(builds, project, build_tag) + last_coverage_build = find_last_build(builds, project, coverage_tag) + if not last_build or not last_coverage_build: + continue + + badge = 'building' + if not is_build_successful(last_coverage_build): + badge = 'coverage_failing' + if not is_build_successful(last_build): + badge = 'failing' + + print("[badge] {}: {}".format(project, badge)) + + storage_client = storage.Client() + status_bucket = storage_client.get_bucket(STATUS_BUCKET) + + # Supported image types for badges + image_types = { + 'svg': 'image/svg+xml', + 'png': 'image/png' + } + for extension, mime_type in image_types.items(): + badge_name = '{badge}.{extension}'.format( + badge=badge, extension=extension) + # Retrieve the image relative to this script's location + badge_file = os.path.join( + SCRIPT_DIR, 'badge_images', image_directory, badge_name) + + # The uploaded blob name should look like `badges/project.png` + blob_name = '{badge_dir}{project_name}.{extension}'.format( + badge_dir=BADGE_DIR, project_name=project, + extension=extension) + + badge_blob = status_bucket.blob(blob_name) + badge_blob.upload_from_filename(badge_file, content_type=mime_type) + + def main(): if len(sys.argv) != 2: usage() @@ -190,6 +230,10 @@ def main(): build_and_run_coverage.COVERAGE_BUILD_TAG, status_filename='status-coverage.json') + update_build_badges(builds, projects, + build_tag=build_project.FUZZING_BUILD_TAG, + coverage_tag=build_and_run_coverage.COVERAGE_BUILD_TAG) + if __name__ == '__main__': main()