Ejemplo n.º 1
0
def render(run, report_dir):
    temporary_report_dir = litani.get_report_data_dir() / str(uuid.uuid4())
    temporary_report_dir.mkdir(parents=True)
    old_report_dir_path = litani.get_report_dir().resolve()
    old_report_dir = litani.ExpireableDirectory(old_report_dir_path)

    artifact_dir = temporary_report_dir / "artifacts"
    shutil.copytree(litani.get_artifacts_dir(), artifact_dir)

    render_artifact_indexes(artifact_dir)

    template_dir = pathlib.Path(__file__).parent.parent / "templates"
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(str(template_dir)))

    svgs = render_runtimes(run, env, temporary_report_dir)

    litani_report_archive_path = os.getenv("LITANI_REPORT_ARCHIVE_PATH")

    dash_templ = env.get_template("dashboard.jinja.html")
    page = dash_templ.render(
        run=run,
        svgs=svgs,
        litani_hash=get_git_hash(),
        litani_version=litani.VERSION,
        litani_report_archive_path=litani_report_archive_path)
    with litani.atomic_write(temporary_report_dir / "index.html") as handle:
        print(page, file=handle)

    with litani.atomic_write(temporary_report_dir / litani.RUN_FILE) as handle:
        print(json.dumps(run, indent=2), file=handle)

    pipe_templ = env.get_template("pipeline.jinja.html")
    for pipe in run["pipelines"]:
        page = pipe_templ.render(run=run, pipe=pipe)
        with litani.atomic_write(temporary_report_dir / pipe["url"]) as handle:
            print(page, file=handle)

    temp_symlink_dir = report_dir.with_name(report_dir.name +
                                            str(uuid.uuid4()))
    os.symlink(temporary_report_dir, temp_symlink_dir)
    os.rename(temp_symlink_dir, report_dir)

    # Release lock so that other processes can read from this directory
    new_report_dir = litani.LockableDirectory(report_dir.resolve())
    new_report_dir.release()

    if old_report_dir_path.exists():
        old_report_dir.expire()
    litani.unlink_expired()
def render_artifact_indexes(artifact_dir, env):
    def dirs_needing_indexes():
        for root, dirs, fyles in os.walk(artifact_dir):
            if "index.html" not in fyles:
                yield pathlib.Path(root), dirs, fyles

    index_templ = env.get_template("file-list.jinja.html")
    for dyr, dirs, files in dirs_needing_indexes():
        page = index_templ.render(file_list=sorted(files),
                                  dir_list=sorted(dirs),
                                  root=str(dyr))
        with litani.atomic_write(dyr / "index.html") as handle:
            print(page, file=handle)
Ejemplo n.º 3
0
def render(run, report_dir):
    artifacts_dst = report_dir / "artifacts"
    if artifacts_dst.exists():
        shutil.rmtree(report_dir / "artifacts")
    shutil.copytree(litani.get_artifacts_dir(), report_dir / "artifacts")
    render_artifact_indexes(artifacts_dst)

    template_dir = pathlib.Path(__file__).parent.parent / "templates"
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(str(template_dir)))

    svgs = render_runtimes(run, env, report_dir)

    dash_templ = env.get_template("dashboard.jinja.html")
    page = dash_templ.render(run=run, svgs=svgs)
    with litani.atomic_write(report_dir / "index.html") as handle:
        print(page, file=handle)

    pipe_templ = env.get_template("pipeline.jinja.html")
    for pipe in run["pipelines"]:
        page = pipe_templ.render(run=run, pipe=pipe)
        with litani.atomic_write(report_dir / pipe["url"]) as handle:
            print(page, file=handle)
Ejemplo n.º 4
0
def render_artifact_indexes(artifact_dir):
    def dirs_needing_indexes():
        for root, dirs, fyles in os.walk(artifact_dir):
            if "index.html" not in fyles:
                yield pathlib.Path(root), dirs, fyles

    template_dir = pathlib.Path(__file__).parent.parent / "templates"
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(str(template_dir)))
    index_templ = env.get_template("file-list.jinja.html")
    for dyr, dirs, files in dirs_needing_indexes():
        page = index_templ.render(file_list=sorted(files),
                                  dir_list=sorted(dirs),
                                  root=str(dyr))
        with litani.atomic_write(dyr / "index.html") as handle:
            print(page, file=handle)
Ejemplo n.º 5
0
async def add_job(job_dict):
    cache_file = litani.get_cache_dir() / litani.CACHE_FILE
    with open(cache_file) as handle:
        cache_contents = json.load(handle)
    if job_dict["ci_stage"] not in cache_contents["stages"]:
        valid_stages = "', '".join(cache_contents["stages"])
        logging.error(
            "Invalid stage name '%s' was provided, possible "
            "stage names are: '%s'", job_dict["ci_stage"], valid_stages)
        sys.exit(1)

    jobs_dir = litani.get_cache_dir() / litani.JOBS_DIR
    jobs_dir.mkdir(exist_ok=True, parents=True)

    if job_dict["phony_outputs"]:
        if not job_dict["outputs"]:
            job_dict["outputs"] = job_dict["phony_outputs"]
        else:
            for phony_output in job_dict["phony_outputs"]:
                if phony_output not in job_dict["outputs"]:
                    job_dict["outputs"].append(phony_output)

    if "func" in job_dict:
        job_dict.pop("func")

    job_id = str(uuid.uuid4())
    job_dict["job_id"] = job_id
    job_dict["status_file"] = str(
        litani.get_status_dir() / ("%s.json" % job_id))

    logging.debug("Adding job: %s", json.dumps(job_dict, indent=2))

    for key in _PRIVATE_JOB_FIELDS:
        if key not in job_dict:
            raise AssertionError(f"Key {key} missing from job definition")

    with litani.atomic_write(jobs_dir / ("%s.json" % job_id)) as handle:
        print(json.dumps(job_dict, indent=2), file=handle)
    def render(self, gnu_file, out_file=None):
        if not self.should_render():
            raise UserWarning(
                "Should not call Gnuplot.render() if should_render() is False")

        cmd = ["gnuplot"]
        with subprocess.Popen(cmd,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.DEVNULL,
                              text=True) as proc:
            out, _ = proc.communicate(input=gnu_file)
        if proc.returncode:
            logging.error("Failed to render gnuplot file:")
            logging.error(gnu_file)
            self._should_render = False
            return

        lines = [l for l in out.splitlines() if "<?xml version" not in l]
        if out_file:
            with litani.atomic_write(out_file) as handle:
                print("\n".join(lines), file=handle)
        return lines
def render(run, report_dir, pipeline_depgraph_renderer):
    temporary_report_dir = litani.get_report_data_dir() / str(uuid.uuid4())
    temporary_report_dir.mkdir(parents=True)
    old_report_dir_path = litani.get_report_dir().resolve()
    old_report_dir = litani.ExpireableDirectory(old_report_dir_path)

    artifact_dir = temporary_report_dir / "artifacts"
    shutil.copytree(litani.get_artifacts_dir(), artifact_dir)

    template_dir = pathlib.Path(__file__).parent.parent / "templates"
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(str(template_dir)),
                             autoescape=jinja2.select_autoescape(
                                 enabled_extensions=('html'),
                                 default_for_string=True))

    render_artifact_indexes(artifact_dir, env)

    gnuplot = Gnuplot()
    svgs = get_dashboard_svgs(run, env, gnuplot)

    litani_report_archive_path = os.getenv("LITANI_REPORT_ARCHIVE_PATH")

    dash_templ = env.get_template("dashboard.jinja.html")
    page = dash_templ.render(
        run=run,
        svgs=svgs,
        litani_hash=get_git_hash(),
        litani_version=litani.VERSION,
        litani_report_archive_path=litani_report_archive_path,
        summary=get_summary(run))
    with litani.atomic_write(temporary_report_dir / "index.html") as handle:
        print(page, file=handle)

    with litani.atomic_write(temporary_report_dir / litani.RUN_FILE) as handle:
        print(json.dumps(run, indent=2), file=handle)

    pipe_templ = env.get_template("pipeline.jinja.html")
    for pipe in run["pipelines"]:
        pipeline_depgraph_renderer.render(render_root=temporary_report_dir,
                                          pipe_url=pathlib.Path(pipe["url"]),
                                          pipe=pipe)
        for stage in pipe["ci_stages"]:
            for job in stage["jobs"]:
                if JobOutcomeTableRenderer.should_render(job):
                    JobOutcomeTableRenderer.render(
                        temporary_report_dir / pipe["url"], env, job)
                if MemoryTraceRenderer.should_render(job):
                    MemoryTraceRenderer.render(
                        temporary_report_dir / pipe["url"], env, job, gnuplot)

        pipe_page = pipe_templ.render(run=run, pipe=pipe)
        with litani.atomic_write(temporary_report_dir / pipe["url"] /
                                 "index.html") as handle:
            print(pipe_page, file=handle)

    temp_symlink_dir = report_dir.with_name(report_dir.name +
                                            str(uuid.uuid4()))
    os.symlink(temporary_report_dir, temp_symlink_dir)
    os.rename(temp_symlink_dir, report_dir)

    # Release lock so that other processes can read from this directory
    new_report_dir = litani.LockableDirectory(report_dir.resolve())
    new_report_dir.release()

    if old_report_dir_path.exists():
        old_report_dir.expire()
    litani.unlink_expired()
Ejemplo n.º 8
0
    def __call__(self, run):
        temporary_report_dir = litani.get_report_data_dir() / str(uuid.uuid4())
        temporary_report_dir.mkdir(parents=True)
        old_report_dir_path = litani.get_report_dir().resolve()
        old_report_dir = litani.ExpireableDirectory(old_report_dir_path)

        artifact_dir = temporary_report_dir / "artifacts"
        shutil.copytree(litani.get_artifacts_dir(), artifact_dir)

        template_dir = pathlib.Path(__file__).parent.parent / "templates"
        env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(str(template_dir)),
            autoescape=jinja2.select_autoescape(enabled_extensions=('html'),
                                                default_for_string=True))

        render_artifact_indexes(artifact_dir, env)

        gnuplot = Gnuplot()
        svgs = get_dashboard_svgs(run, env, gnuplot)

        litani_report_archive_path = os.getenv("LITANI_REPORT_ARCHIVE_PATH")

        with litani.atomic_write(temporary_report_dir /
                                 litani.RUN_FILE) as handle:
            print(json.dumps(run, indent=2), file=handle)

        front_page_outputs = {}
        pipe_templ = env.get_template("pipeline.jinja.html")
        for pipe in run["pipelines"]:
            self.pipeline_depgraph_renderer.render(
                render_root=temporary_report_dir,
                pipe_url=pathlib.Path(pipe["url"]),
                pipe=pipe)
            for stage in pipe["ci_stages"]:
                for job in stage["jobs"]:
                    if JobOutcomeTableRenderer.should_render(job):
                        JobOutcomeTableRenderer.render(
                            temporary_report_dir / pipe["url"], env, job)
                    if MemoryTraceRenderer.should_render(job):
                        MemoryTraceRenderer.render(
                            temporary_report_dir / pipe["url"], env, job,
                            gnuplot)

                    tags = job["wrapper_arguments"]["tags"]
                    description = job["wrapper_arguments"]["description"]
                    if tags and "front-page-text" in tags:
                        if "stdout" in job and job["stdout"]:
                            front_page_outputs[description] = job

            pipe_page = pipe_templ.render(run=run, pipe=pipe)
            with litani.atomic_write(temporary_report_dir / pipe["url"] /
                                     "index.html") as handle:
                print(pipe_page, file=handle)

        if "end_time" in run:
            s = datetime.datetime.strptime(run["start_time"],
                                           litani.TIME_FORMAT_R)
            e = datetime.datetime.strptime(run["end_time"],
                                           litani.TIME_FORMAT_R)
            runtime = (e - s).seconds
            run["__duration_str"] = s_to_hhmmss(runtime)

        dash_templ = env.get_template("dashboard.jinja.html")
        page = dash_templ.render(
            run=run,
            svgs=svgs,
            litani_version=litani.VERSION,
            litani_report_archive_path=litani_report_archive_path,
            summary=get_summary(run),
            front_page_outputs=front_page_outputs)

        with litani.atomic_write(temporary_report_dir /
                                 "index.html") as handle:
            print(page, file=handle)

        locked_dir = litani.LockableDirectory(temporary_report_dir)

        temp_symlink_dir = self.report_dir.with_name(self.report_dir.name +
                                                     str(uuid.uuid4()))
        os.symlink(temporary_report_dir, temp_symlink_dir)
        os.rename(temp_symlink_dir, self.report_dir)

        locked_dir.release()

        try:
            old_report_dir.expire()
        except FileNotFoundError:
            pass

        litani.unlink_expired()