File: ci-pages.bash

package info (click to toggle)
verilator 5.042-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 61,876 kB
  • sloc: cpp: 149,079; python: 21,943; ansic: 10,559; yacc: 6,019; lex: 1,971; makefile: 1,384; sh: 603; perl: 302; fortran: 22
file content (171 lines) | stat: -rwxr-xr-x 5,741 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!/usr/bin/env bash
# DESCRIPTION: Verilator: CI script for 'pages.yml', builds the GitHub Pages
#
# Copyright 2025 by Geza Lore. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
#
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

# This scipt build the content of the GitHub Pages for the repository.
# Currently this only hosts code coverage reports, but it would be possible to
# add any other contents to the page in parallel here.

# Developer note: You should be able to run this script in your local checkout
# if you have GitHub CLI (command 'gh') setup, authenticated ('gh auth login'),
# and have set a default repository ('gh repo set-default').

# Create pages root directory. The contents of this directory will be deployed
# and served via GitHubPages
readonly PAGES_ROOT=pages
mkdir -p ${PAGES_ROOT}

# Get the current repo URL - might differ on a fork
readonly REPO_URL=$(gh repo view --json url --jq .url)

# Set GITHUB_OUTPUT when run locally for testing
if [[ -z "$GITHUB_OUTPUT" ]]; then
  GITHUB_OUTPUT=github-output.txt
fi

# Populates ${PAGES_ROOT}/coverage-reports
compile_coverage_reports() {
  # We will process all runs up to and including this date. This is chosen to be
  # slightly less than the artifact retention period for simplicity.
  local OLDEST=$(date --date="28 days ago" --iso-8601=date)

  # Gather all coverage workflow runs within the time window
  gh run list -w coverage.yml --limit 1000 --created ">=${OLDEST}" --json "databaseId,event,status,conclusion,createdAt,number" > recentRuns.json
  echo @@@ Recent runs:
  jq "." recentRuns.json

  # Select completd runs that were not cancelled or skipped, sort by descending run number
  jq 'sort_by(-.number) | map(select(.status == "completed" and (.conclusion == "success" or .conclusion == "failure")))' recentRuns.json > completedRuns.json
  echo @@@ Completed with success or failure:
  jq "." completedRuns.json

  # Create artifacts root directory
  local ARTIFACTS_ROOT=artifacts
  mkdir -p ${ARTIFACTS_ROOT}

  # Create coverage reports root directory
  local COVERAGE_ROOT=${PAGES_ROOT}/coverage-reports
  mkdir -p ${COVERAGE_ROOT}

  # Create index page contents fragment
  local CONTENTS=contents.tmp
  echo > ${CONTENTS}

  # Run IDs of PR jobs processed
  local PR_RUN_IDS=""

  # Iterate over all unique event types that triggered the workflows
  for EVENT in $(jq -r 'map(.event) | sort | unique | .[]' completedRuns.json); do
    echo "@@@ Processing '${EVENT}' runs"

    # Emit section header if a report exists with this event type
    EMIT_SECTION_HEADER=1

    # For each worfklow run that was triggered by this event type
    for RUN_ID in $(jq ".[] | select(.event == \"${EVENT}\") |.databaseId" completedRuns.json); do
      echo "@@@ Processing run ${RUN_ID}"

      # Extract the info of this run
      jq ".[] | select(.databaseId == $RUN_ID)" completedRuns.json > workflow.json
      jq "." workflow.json

      # Record run ID of PR job
      if [[ $EVENT == "pull_request" ]]; then
        if [[ -z "$PR_RUN_IDS" ]]; then
          PR_RUN_IDS="$RUN_ID"
        else
          PR_RUN_IDS="$PR_RUN_IDS,$RUN_ID"
        fi
      fi

      # Create workflow artifacts directory
      local ARTIFACTS_DIR=${ARTIFACTS_ROOT}/${RUN_ID}
      mkdir -p ${ARTIFACTS_DIR}

      # Download artifacts of this run, if exists
      gh run download ${RUN_ID} --name coverage-report --dir ${ARTIFACTS_DIR} || true
      ls -lsha ${ARTIFACTS_DIR}

      # Move on if no coverage report is available
      if [ ! -d ${ARTIFACTS_DIR}/report ]; then
        echo "No coverage report found"
        continue
      fi
      echo "Coverage report found"

      # Emit section header
      if [[ -n $EMIT_SECTION_HEADER ]]; then
        unset EMIT_SECTION_HEADER
        if [[ $EVENT == "pull_request" ]]; then
          echo "<h4>Patch coverage reports for '${EVENT}' runs:</h4>" >> ${CONTENTS}
        else
          echo "<h4>Code coverage reports for '${EVENT}' runs:</h4>" >> ${CONTENTS}
        fi
      fi

      # Create pages subdirectory
      mv ${ARTIFACTS_DIR}/report ${COVERAGE_ROOT}/${RUN_ID}

      # Add index page content
      local WORKFLOW_CREATED=$(jq -r '.createdAt' workflow.json)
      local WOFKRLOW_NUMBER=$(jq -r '.number' workflow.json)
      cat >> ${CONTENTS} <<CONTENTS_TEMPLATE
        Run <a href="${RUN_ID}/index.html">#${WOFKRLOW_NUMBER}</a>
        | GitHub: <a href="${REPO_URL}/actions/runs/${RUN_ID}">${RUN_ID}</a>
        | started at: ${WORKFLOW_CREATED}
CONTENTS_TEMPLATE
      if [ -e ${ARTIFACTS_DIR}/pr-number.txt ]; then
        local PRNUMBER=$(cat ${ARTIFACTS_DIR}/pr-number.txt)
        echo " | Pull request: <a href=\"${REPO_URL}/pull/${PRNUMBER}\">#${PRNUMBER}</a>" >> ${CONTENTS}
      fi
      echo "<br>" >> ${CONTENTS}
    done

    # Section break
    if [[ -z "$EMIT_SECTION_HEADER" ]]; then
      echo "<hr>" >> ${CONTENTS}
    fi
  done

  # Write coverage report index.html
  cat > ${COVERAGE_ROOT}/index.html  <<INDEX_TEMPLATE
  <html>

  <head>
    <title>Verilator CI coverage reports</title>
    <style>
    body {
      font-family: courier, serif;
      background-color: #f3f3f3;
      a {
        color: #008fd7;
      }
    }
    </style>
  </head>

  <body>
  $(cat ${CONTENTS})
  <h4>Assembled $(date --iso-8601=minutes --utc)</h1>
  <body>

  </html>
INDEX_TEMPLATE

  # Report size
  du -shc ${COVERAGE_ROOT}/*

  # Set output
  echo "coverage-pr-run-ids=${PR_RUN_IDS}" >> $GITHUB_OUTPUT
}

# Compilie coverage reports
compile_coverage_reports;

# You can build any other content here to be put under ${PAGES_ROOT}