Skip to content

CI

CI #81

Workflow file for this run

name: CI
on:
push:
branches:
- main
pull_request:
types: [opened, reopened, synchronize]
# Allow manual triggers
workflow_dispatch: {}
jobs:
pre-commit:
runs-on: ubuntu-24.04
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
# actions/setup-python v6.3.0
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
- name: Install pre-commit
run: python -m pip install pre-commit
- name: Show installed Python packages
run: python -m pip freeze --local
- name: Cache pre-commit environments
# actions/cache v6.1.0
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: ~/.cache/pre-commit
key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit
run: pre-commit run --show-diff-on-failure --color=always --all-files
bazel-oss-docker-image:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
# docker/setup-buildx-action v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5
- name: Build and load public Docker image
# docker/build-push-action v7.2.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: false
load: true
tags: bedrock-rtl-dev:${{ github.sha }}
labels: |
org.opencontainers.image.revision=${{ github.sha }}
cache-from: type=gha,scope=bedrock-rtl-dev-docker
# PR builds write to their PR-scoped GitHub Actions cache; this does
# not publish an image or write anything to GHCR.
cache-to: type=gha,mode=max,scope=bedrock-rtl-dev-docker
- name: Export public Docker image
run: docker save bedrock-rtl-dev:${{ github.sha }} --output /tmp/bedrock-rtl-dev.tar
- name: Upload public Docker image
# actions/upload-artifact v7.0.1
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: bedrock-rtl-dev-image-${{ github.sha }}
path: /tmp/bedrock-rtl-dev.tar
compression-level: 0
retention-days: 1
bazel-oss-tool-test-shard:
name: bazel-oss-tool-test-shard (${{ matrix.name }})
runs-on: ubuntu-24.04
needs: bazel-oss-docker-image
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- name: python-stardoc
suite: python-stardoc
shard_index: 0
shard_count: 1
- name: slang-1-of-4
suite: slang
shard_index: 0
shard_count: 4
- name: slang-2-of-4
suite: slang
shard_index: 1
shard_count: 4
- name: slang-3-of-4
suite: slang
shard_index: 2
shard_count: 4
- name: slang-4-of-4
suite: slang
shard_index: 3
shard_count: 4
- name: verilator-1-of-8
suite: verilator
shard_index: 0
shard_count: 8
- name: verilator-2-of-8
suite: verilator
shard_index: 1
shard_count: 8
- name: verilator-3-of-8
suite: verilator
shard_index: 2
shard_count: 8
- name: verilator-4-of-8
suite: verilator
shard_index: 3
shard_count: 8
- name: verilator-5-of-8
suite: verilator
shard_index: 4
shard_count: 8
- name: verilator-6-of-8
suite: verilator
shard_index: 5
shard_count: 8
- name: verilator-7-of-8
suite: verilator
shard_index: 6
shard_count: 8
- name: verilator-8-of-8
suite: verilator
shard_index: 7
shard_count: 8
- name: coverage-1-of-4
suite: coverage
shard_index: 0
shard_count: 4
- name: coverage-2-of-4
suite: coverage
shard_index: 1
shard_count: 4
- name: coverage-3-of-4
suite: coverage
shard_index: 2
shard_count: 4
- name: coverage-4-of-4
suite: coverage
shard_index: 3
shard_count: 4
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
# bazel-contrib/setup-bazel v0.19.0
- name: Set up Bazel caches
uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86
with:
bazelisk-cache: true
# A stable partition gets a stable cache. Including the shard count
# prevents incompatible partitions from sharing an Actions cache.
disk-cache: ${{ github.workflow }}-oss-${{ matrix.suite }}-${{ matrix.shard_index }}-of-${{ matrix.shard_count }}
repository-cache: true
# Save PR-local caches so repeated pushes to the same PR can reuse
# Bazel outputs. GitHub scopes pull_request caches to the PR merge
# ref; this does not make them shared main-branch caches.
cache-save: true
output-base: ${{ runner.temp }}/bazel-output
- name: Configure public Bazel environment
run: |
# setup-bazel restores these paths on a cache hit. Create them on a
# miss so Docker can bind-mount the same host paths below.
mkdir -p \
"${HOME}/.cache/bazel" \
"${HOME}/.cache/bazelisk" \
"${HOME}/.cache/bazel-disk" \
"${HOME}/.cache/bazel-repo" \
"${RUNNER_TEMP}/bazel-output"
# The Slang plugin executes $SLANG_PATH directly rather than looking
# up `slang` on PATH. The public Docker image installs it here.
echo 'common --action_env=SLANG_PATH=/usr/local/bin/slang' > ci.bazelrc
- name: Download public Docker image
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: bedrock-rtl-dev-image-${{ github.sha }}
path: /tmp
- name: Load public Docker image
run: docker load --input /tmp/bedrock-rtl-dev.tar
# Do not use `bazel test //...` with a tag filter here. Bazel would still
# analyze targets that need proprietary verilog_runner plugins.
- name: Run public Bazel test shard
continue-on-error: true
run: |
# Keep stdin attached so `bash -s` receives the heredoc below. The
# hosted runner UID is not present in the image's passwd file, so set
# USER explicitly while retaining that UID for cache writes.
docker run --rm -i \
--user "$(id -u):$(id -g)" \
--env USER=user \
--env HOME="${HOME}" \
--env CI_SUITE="${{ matrix.suite }}" \
--env CI_SHARD_INDEX="${{ matrix.shard_index }}" \
--env CI_SHARD_COUNT="${{ matrix.shard_count }}" \
--workdir "${GITHUB_WORKSPACE}" \
--volume "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}" \
--volume "${HOME}/.bazelrc:${HOME}/.bazelrc:ro" \
--volume "${HOME}/.cache/bazel:${HOME}/.cache/bazel" \
--volume "${HOME}/.cache/bazelisk:${HOME}/.cache/bazelisk" \
--volume "${HOME}/.cache/bazel-disk:${HOME}/.cache/bazel-disk" \
--volume "${HOME}/.cache/bazel-repo:${HOME}/.cache/bazel-repo" \
--volume "${RUNNER_TEMP}/bazel-output:${RUNNER_TEMP}/bazel-output" \
bedrock-rtl-dev:${{ github.sha }} \
bash -s <<'EOF'
set +e
BAZEL_FLAGS=(
--action_env=PATH
--noshow_loading_progress
--test_output=errors
--disk_cache=/home/runner/.cache/bazel-disk
--repository_cache=/home/runner/.cache/bazel-repo
--experimental_disk_cache_gc_max_size=256M
--experimental_disk_cache_gc_max_age=7d
)
HELPER=python/ci/bazel_oss_sharding.py
RESULTS_DIR="bazel-oss-results/${CI_SUITE}-${CI_SHARD_INDEX}-of-${CI_SHARD_COUNT}"
mkdir -p "$RESULTS_DIR"
run_discovered_suite() {
local suite="$1"
local shard_index="$2"
local shard_count="$3"
local discovered="$4"
local result="$RESULTS_DIR/result-${suite}-${shard_index}-of-${shard_count}.json"
local targets="$RESULTS_DIR/targets-${suite}-${shard_index}-of-${shard_count}.txt"
local log="/tmp/bazel-${suite}-${shard_index}-of-${shard_count}.log"
python3.12 "$HELPER" partition \
--suite "$suite" \
--shard-index "$shard_index" \
--shard-count "$shard_count" \
--input "$discovered" \
--output-dir "$RESULTS_DIR"
local partition_exit_code=$?
if [ "$partition_exit_code" -ne 0 ]; then
return "$partition_exit_code"
fi
# Save timestamp of bazel test invocation for testreport generation purpose
echo $(date -d "today" +"%Y-%m-%d-%H-%M-%S") > $RESULTS_DIR/timestamp-${suite}-${shard_index}-of-${shard_count}.txt
# A target-pattern file guarantees one Bazel invocation even when
# thousands of labels would exceed the shell argument limit.
if [[ "$suite" == "coverage" ]]; then
bazel build "${BAZEL_FLAGS[@]}" \
--target_pattern_file="$targets" 2>&1 | tee "$log"
else
bazel test "${BAZEL_FLAGS[@]}" \
--target_pattern_file="$targets" 2>&1 | tee "$log"
fi
local bazel_exit_code=${PIPESTATUS[0]}
python3.12 "$HELPER" finalize \
--result "$result" \
--log "$log" \
--exit-code "$bazel_exit_code"
cp $log $RESULTS_DIR/
mv $(readlink -f ./bazel-testlogs) ./$RESULTS_DIR/testlogs-${suite}-${shard_index}-of-${shard_count}
}
query_and_run_suite() {
local suite="$1"
local shard_index="$2"
local shard_count="$3"
local query_expression="$4"
local discovered="/tmp/discovered-${suite}-${shard_index}-of-${shard_count}.txt"
local result="$RESULTS_DIR/result-${suite}-${shard_index}-of-${shard_count}.json"
bazel query --noshow_progress "$query_expression" > "$discovered"
local query_exit_code=$?
if [ "$query_exit_code" -ne 0 ]; then
python3.12 "$HELPER" partition \
--suite "$suite" \
--shard-index "$shard_index" \
--shard-count "$shard_count" \
--input "$discovered" \
--output-dir "$RESULTS_DIR"
python3.12 "$HELPER" discovery-failure \
--result "$result" \
--exit-code "$query_exit_code" \
--message "Bazel query failed"
return "$query_exit_code"
fi
run_discovered_suite "$suite" "$shard_index" "$shard_count" "$discovered"
}
case "$CI_SUITE" in
python-stardoc)
query_and_run_suite python 0 1 \
'tests(//python/...) union tests(//ecc/rtl/secded_codegen/...)'
printf '%s\n' \
//bazel:verilog_rules_diff_test \
> /tmp/discovered-stardoc.txt
run_discovered_suite stardoc 0 1 /tmp/discovered-stardoc.txt
;;
slang)
query_and_run_suite slang "$CI_SHARD_INDEX" "$CI_SHARD_COUNT" \
'(tests(//...) intersect attr(tags, "slang", //...)) except attr(tags, "manual", //...)'
;;
verilator)
query_and_run_suite verilator "$CI_SHARD_INDEX" "$CI_SHARD_COUNT" \
'tests(//...) intersect attr(tags, "verilator", //...) intersect attr(tags, "sim", //...)'
;;
coverage)
query_and_run_suite coverage "$CI_SHARD_INDEX" "$CI_SHARD_COUNT" \
'kind(".*_coverage_data", //...)'
;;
*)
echo "Unknown public suite: $CI_SUITE" >&2
exit 4
;;
esac
check_args=(--results-dir "$RESULTS_DIR")
if [ "$CI_SUITE" = python-stardoc ]; then
check_args+=(--expected-suite python --expected-suite stardoc)
else
check_args+=(--expected-suite "$CI_SUITE")
fi
python3.12 "$HELPER" check "${check_args[@]}"
EOF
- name: Upload public shard result
if: ${{ always() }}
# actions/upload-artifact v7.0.1
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: bazel-oss-result-${{ matrix.name }}
path: |
bazel-oss-results/${{ matrix.suite }}-${{ matrix.shard_index }}-of-${{ matrix.shard_count }}
bazel-oss-results/bazel-${{ matrix.suite }}-${{ matrix.shard_index }}-of-${{ matrix.shard_count }}.log
bazel-oss-results/testlogs-${{ matrix.suite }}-${{ matrix.shard_index }}-of-${{ matrix.shard_count }}
bazel-oss-results/timestamp-${{ matrix.suite }}-${{ matrix.shard_index }}-of-${{ matrix.shard_count }}.txt
if-no-files-found: error
retention-days: 1
- name: Check public shard result
if: ${{ always() }}
run: |
check_args=(
--results-dir "bazel-oss-results/${{ matrix.suite }}-${{ matrix.shard_index }}-of-${{ matrix.shard_count }}"
)
if [ "${{ matrix.suite }}" = python-stardoc ]; then
check_args+=(--expected-suite python --expected-suite stardoc)
else
check_args+=(--expected-suite "${{ matrix.suite }}")
fi
python3.12 python/ci/bazel_oss_sharding.py check "${check_args[@]}"
bazel-oss-verilator-coverage:
runs-on: ubuntu-24.04
needs: bazel-oss-tool-test-shard
if: ${{ always() }}
permissions:
contents: read
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
# bazel-contrib/setup-bazel v0.19.0
- name: Set up Bazel caches
uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86
with:
bazelisk-cache: true
# Save the merged cache produced after restoring the coverage shards.
disk-cache: ${{ github.workflow }}-oss-coverage-aggregate
repository-cache: true
cache-save: true
output-base: ${{ runner.temp }}/bazel-output
- name: Configure public Bazel environment
run: |
# setup-bazel restores these paths on a cache hit. Create them on a
# miss so Docker can bind-mount the same host paths below.
mkdir -p \
"${HOME}/.cache/bazel" \
"${HOME}/.cache/bazelisk" \
"${HOME}/.cache/bazel-disk" \
"${HOME}/.cache/bazel-repo" \
"${RUNNER_TEMP}/bazel-output"
# The Slang plugin executes $SLANG_PATH directly rather than looking
# up `slang` on PATH. The public Docker image installs it here.
echo 'common --action_env=SLANG_PATH=/usr/local/bin/slang' > ci.bazelrc
- name: Restore public coverage shard 1 Bazel disk cache
# actions/cache v6.1.0
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: /home/runner/.cache/bazel-disk
key: setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-0-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
restore-keys: |
setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-0-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
- name: Restore public coverage shard 2 Bazel disk cache
# actions/cache v6.1.0
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: /home/runner/.cache/bazel-disk
key: setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-1-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
restore-keys: |
setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-1-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
- name: Restore public coverage shard 3 Bazel disk cache
# actions/cache v6.1.0
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: /home/runner/.cache/bazel-disk
key: setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-2-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
restore-keys: |
setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-2-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
- name: Restore public coverage shard 4 Bazel disk cache
# actions/cache v6.1.0
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: /home/runner/.cache/bazel-disk
key: setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-3-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
restore-keys: |
setup-bazel-1-linux-x64-disk-${{ github.workflow }}-oss-coverage-3-of-4-${{ hashFiles('MODULE.bazel', '**/BUILD.bazel') }}
- name: Download public Docker image
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: bedrock-rtl-dev-image-${{ github.sha }}
path: /tmp
- name: Load public Docker image
run: docker load --input /tmp/bedrock-rtl-dev.tar
- name: Build public Verilator coverage archive
run: |
# Keep stdin attached so `bash -s` receives the heredoc below. The
# hosted runner UID is not present in the image's passwd file, so set
# USER explicitly while retaining that UID for cache writes.
docker run --rm -i \
--user "$(id -u):$(id -g)" \
--env USER=user \
--env HOME="${HOME}" \
--workdir "${GITHUB_WORKSPACE}" \
--volume "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}" \
--volume "${HOME}/.bazelrc:${HOME}/.bazelrc:ro" \
--volume "${HOME}/.cache/bazel:${HOME}/.cache/bazel" \
--volume "${HOME}/.cache/bazelisk:${HOME}/.cache/bazelisk" \
--volume "${HOME}/.cache/bazel-disk:${HOME}/.cache/bazel-disk" \
--volume "${HOME}/.cache/bazel-repo:${HOME}/.cache/bazel-repo" \
--volume "${RUNNER_TEMP}/bazel-output:${RUNNER_TEMP}/bazel-output" \
bedrock-rtl-dev:${{ github.sha }} \
bash -s <<'EOF'
set -euo pipefail
BAZEL_FLAGS=(
--action_env=PATH
--noshow_loading_progress
--disk_cache=/home/runner/.cache/bazel-disk
--repository_cache=/home/runner/.cache/bazel-repo
--experimental_disk_cache_gc_max_size=256M
--experimental_disk_cache_gc_max_age=7d
)
bazel run "${BAZEL_FLAGS[@]}" //:br_verilator_coverage
EOF
mkdir -p dashboard-build
cp bazel-bin/br_verilator_coverage_run.zip dashboard-build/br_verilator_coverage.zip
test -s dashboard-build/br_verilator_coverage.zip
- name: Upload public Verilator coverage archive
# actions/upload-artifact v7.0.1
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: br-verilator-coverage-${{ github.sha }}
path: dashboard-build/br_verilator_coverage.zip
if-no-files-found: error
retention-days: 1
# This stable aggregate check is the public branch-protection, badge, and
# image-publication interface; individual shards remain visible underneath it.
bazel-oss-tool-test:
runs-on: ubuntu-24.04
needs: bazel-oss-tool-test-shard
if: ${{ always() }}
permissions:
contents: read
outputs:
image-tag: ${{ steps.image-metadata.outputs.tag }}
python_total_tests: ${{ steps.results.outputs.python_total_tests }}
python_passing_tests: ${{ steps.results.outputs.python_passing_tests }}
python_exit_code: ${{ steps.results.outputs.python_exit_code }}
stardoc_total_tests: ${{ steps.results.outputs.stardoc_total_tests }}
stardoc_passing_tests: ${{ steps.results.outputs.stardoc_passing_tests }}
stardoc_exit_code: ${{ steps.results.outputs.stardoc_exit_code }}
slang_total_tests: ${{ steps.results.outputs.slang_total_tests }}
slang_passing_tests: ${{ steps.results.outputs.slang_passing_tests }}
slang_exit_code: ${{ steps.results.outputs.slang_exit_code }}
verilator_total_tests: ${{ steps.results.outputs.verilator_total_tests }}
verilator_passing_tests: ${{ steps.results.outputs.verilator_passing_tests }}
verilator_exit_code: ${{ steps.results.outputs.verilator_exit_code }}
coverage_total_tests: ${{ steps.results.outputs.coverage_total_tests }}
coverage_passing_tests: ${{ steps.results.outputs.coverage_passing_tests }}
coverage_exit_code: ${{ steps.results.outputs.coverage_exit_code }}
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Set YYYY-MM-DD-SHA image tag
id: image-metadata
run: |
commit_timestamp="$(git show --no-patch --format=%ct "${GITHUB_SHA}")"
commit_date="$(date --utc --date="@${commit_timestamp}" +%F)"
echo "tag=${commit_date}-${GITHUB_SHA}" >> "${GITHUB_OUTPUT}"
- name: Download public shard results
continue-on-error: true
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
pattern: bazel-oss-result-*
path: bazel-oss-aggregate
merge-multiple: true
- name: Aggregate public shard results
id: results
continue-on-error: true
run: |
python3.12 python/ci/bazel_oss_sharding.py aggregate \
--results-dir bazel-oss-aggregate \
--expected python=1 \
--expected stardoc=1 \
--expected slang=4 \
--expected verilator=8 \
--expected coverage=4 \
--github-output "$GITHUB_OUTPUT" \
--step-summary "$GITHUB_STEP_SUMMARY"
- name: Check public Bazel test suite results
run: |
if [ "${{ needs.bazel-oss-tool-test-shard.result }}" != success ]; then
echo "::error title=Public Bazel shard failed::One or more matrix jobs failed"
exit 1
fi
if [ "${{ steps.results.outcome }}" != success ]; then
echo "::error title=Public Bazel aggregation failed::Shard results were incomplete or failed validation"
exit 1
fi
generate-and-publish-test-results:
runs-on: ubuntu-24.04
needs: [bazel-oss-tool-test-shard, bazel-oss-verilator-coverage]
if: ${{ always() }}
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Download public Verilator coverage archive
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: br-verilator-coverage-${{ github.sha }}
path: dashboard-build
- name: Check out Coverview
# actions/checkout v7.0.0
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
with:
repository: antmicro/coverview
ref: main
path: coverview
persist-credentials: false
- name: Set up Node.js
# actions/setup-node v7.0.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: 24
cache: npm
cache-dependency-path: coverview/package-lock.json
- name: Build embedded Coverview page
working-directory: coverview
run: |
set -euo pipefail
npm ci
npm run build
python3 embed.py --inject-data ../dashboard-build/br_verilator_coverage.zip
test -f dist/index.html
grep -q 'embeddedZipArchive = "' dist/index.html
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Download public Docker image
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: bedrock-rtl-dev-image-${{ github.sha }}
path: /tmp
- name: Load public Docker image
run: docker load --input /tmp/bedrock-rtl-dev.tar
- name: Download public shard results
continue-on-error: true
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
pattern: bazel-oss-result-*
path: bazel-oss-aggregate
merge-multiple: false
- name: Generate report
id: report_generation
run: |
# Keep stdin attached so `bash -s` receives the heredoc below. The
# hosted runner UID is not present in the image's passwd file, so set
# USER explicitly while retaining that UID for cache writes.
docker run --rm -i \
--user "$(id -u):$(id -g)" \
--env USER=user \
--env HOME="${HOME}" \
--workdir "${GITHUB_WORKSPACE}" \
--volume "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}" \
bedrock-rtl-dev:${{ github.sha }} \
bash -s <<'EOF'
pushd scripts
test_categories=("verilator" "stardoc" "slang")
concat_shards () {
search_dir=$(realpath $1)
out_dir=$(realpath $2)
aggregate_from_dir () {
category_name=$1
dir_path=$2
ls -la $dir_path
cat $dir_path/*/*$category_name*.log >> $out_dir/$category_name/$category_name.log.concat
cp -r $dir_path/*/*testlogs*$category_name*/* $out_dir/$category_name/testlogs_$category_name/
}
for category_name in "${@:3}"
do
mkdir -p $out_dir/$category_name/testlogs_$category_name/
echo "Searching for $category_name in $search_dir directory"
ls -la "$search_dir"
for dir in $(realpath $search_dir)/*; do
echo "Checking $dir"
if [[ "$dir" =~ .*"$category_name".* ]] && [ -d $dir ]; then
echo "Found $dir, aggregating"
aggregate_from_dir $category_name $dir
fi
done
done
}
testplan_generate () {
test_category=$1
export BAZEL_TEST_LOGS_PATH="$(pwd)/concat_shards_out/$test_category/$test_category.log.concat"
# Timestamp here won't be accurate, we concat every shard of the same type.
# Sticking to timestamp of running this script
export BAZEL_TEST_TIMESTAMP="$(date -d "today" +"%Y-%m-%d-%H-%M-%S")"
export BEDROCK_RTL_SOURCE_URL_PREFIX="https://github.com/antmicro/bedrock-rtl"
export TESTLOGS_PATH="$(pwd)/concat_shards_out/$test_category/testlogs_$test_category"
export BEDROCK_RTL_PROJECT_ROOT=../
export TEST_SUMMARY_OUTPUT_DIR="${BEDROCK_RTL_PROJECT_ROOT}/testresult_out"
export TEST_CATEGORY="$test_category"
./generate_test_summary.sh
}
concat_shards ../bazel-oss-aggregate/ ./concat_shards_out "${test_categories[@]}"
for category in ${test_categories[@]}; do
testplan_generate $category
done
testplanner ./testplans/*.hjson -s ./testreports/*.hjson -ot ${TEST_SUMMARY_OUTPUT_DIR}/generated/testplan.md \
-os ${TEST_SUMMARY_OUTPUT_DIR}/sim-res --output-summary-title "Bedrock-RTL tests" \
--output-summary ${TEST_SUMMARY_OUTPUT_DIR}/sim-res/index.html \
--project-root ${BEDROCK_RTL_PROJECT_ROOT} --source-url-prefix ${BEDROCK_RTL_SOURCE_URL_PREFIX} \
--coverage-report-url https://antmicro.github.io/bedrock-rtl/coverage
popd
EOF
- name: Combine testplan with coverage dashboard
run: cp coverview/dist testplan_out/sim-res/coverage
- name: Upload Pages artifact
# actions/upload-pages-artifact v5.0.0
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9
with:
path: testresult_out/sim-res
- name: Deploy coverage dashboard
id: deployment
# if: github.ref == 'refs/heads/main'
# actions/deploy-pages v5.0.0
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128
docker-image-publish:
runs-on: ubuntu-24.04
needs: bazel-oss-tool-test
# GitHub only permits users with repository write access to use workflow_dispatch.
if: >-
needs.bazel-oss-tool-test.result == 'success' &&
(github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/main'))
permissions:
# Allows checkout to read the repository contents.
contents: read
# Allows GitHub to issue the OIDC token used to sign the provenance attestation.
id-token: write
# Allows the job to persist the signed provenance attestation with GitHub.
attestations: write
# Allows the job credential to publish the image to GHCR.
packages: write
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Download public Docker image
# actions/download-artifact v8.0.1
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: bedrock-rtl-dev-image-${{ github.sha }}
path: /tmp
- name: Load public Docker image
run: docker load --input /tmp/bedrock-rtl-dev.tar
- name: Log in to GHCR
# docker/login-action v4.2.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Tag tested Docker image
env:
IMAGE_TAG: ${{ needs.bazel-oss-tool-test.outputs.image-tag }}
run: docker tag "bedrock-rtl-dev:${GITHUB_SHA}" "ghcr.io/xlsynth/bedrock-rtl-dev:${IMAGE_TAG}"
- name: Push tested Docker image
id: publish
env:
IMAGE_TAG: ${{ needs.bazel-oss-tool-test.outputs.image-tag }}
run: |
image="ghcr.io/xlsynth/bedrock-rtl-dev:${IMAGE_TAG}"
docker push "${image}"
digest="$(docker image inspect --format='{{index .RepoDigests 0}}' "${image}" | sed 's/.*@//')"
echo "digest=${digest}" >> "${GITHUB_OUTPUT}"
- name: Attest Docker image provenance
# actions/attest v4.1.1
uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763
with:
subject-name: ghcr.io/xlsynth/bedrock-rtl-dev
subject-digest: ${{ steps.publish.outputs.digest }}
# Keep the signed attestation in GitHub's attestation store without
# publishing a second sha256-* OCI artifact into GHCR.
push-to-registry: false
create-storage-record: false
# Keep proprietary tools and their logs exclusively on the private runner.
bazel-build-and-proprietary-tool-test:
runs-on: self-hosted
env:
# TODO(xiyu): Temporary workaround until CI provides a container-local EDA setup script.
# The current CI plugins invoke tools by bare command name, and Bazel 9 uses
# a sanitized action PATH unless PATH is passed explicitly.
TMP_HACK_BAZEL_CI_FLAGS: --action_env=PATH
outputs:
verific_total_tests: ${{ steps.verific.outputs.total_tests }}
verific_passing_tests: ${{ steps.verific.outputs.passing_tests }}
verific_exit_code: ${{ steps.verific.outputs.exit_code }}
ascentlint_total_tests: ${{ steps.ascentlint.outputs.total_tests }}
ascentlint_passing_tests: ${{ steps.ascentlint.outputs.passing_tests }}
ascentlint_exit_code: ${{ steps.ascentlint.outputs.exit_code }}
vcs_total_tests: ${{ steps.vcs.outputs.total_tests }}
vcs_passing_tests: ${{ steps.vcs.outputs.passing_tests }}
vcs_exit_code: ${{ steps.vcs.outputs.exit_code }}
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
# TODO(xiyu): Create a CI-container-local EDA setup script and point
# VERILOG_RUNNER_EDA_TOOLS_ENV_SETUP at it from the copied ci.bazelrc.
- name: Copy ci.bazelrc
working-directory: ${{ github.workspace }}
run: cp /home/gh-actions/bedrock-infra/ci.bazelrc ci.bazelrc
- name: Build
id: build
run: |
set +e
bazel build $TMP_HACK_BAZEL_CI_FLAGS --noshow_loading_progress //...
echo "exit_code=$?" >> $GITHUB_OUTPUT
- name: Verilog elaboration tests (using Verific tclmain)
id: verific
# Use --test_output=summary to suppress log output, even on failure (proprietary EDA tool output may be sensitive).
run: |
set +e
bazel test $TMP_HACK_BAZEL_CI_FLAGS --noshow_loading_progress --test_output=summary //... --test_tag_filters=verific 2>&1 | tee .bazel-test-verific.log
BAZEL_EXIT_CODE=${PIPESTATUS[0]}
TOTAL_TESTS=$(grep -Po '(?<=out of )\d+(?= test)' .bazel-test-verific.log)
PASSING_TESTS=$(grep -Po '\d+(?= test passes?\.| tests pass)' .bazel-test-verific.log)
echo "total_tests=$TOTAL_TESTS" >> $GITHUB_OUTPUT
echo "passing_tests=$PASSING_TESTS" >> $GITHUB_OUTPUT
echo "exit_code=$BAZEL_EXIT_CODE" >> $GITHUB_OUTPUT
# Keep AscentLint after the elaboration suites.
- name: Verilog lint tests (using RealIntent AscentLint)
id: ascentlint
# Use --test_output=summary to suppress log output, even on failure (proprietary EDA tool output may be sensitive).
run: |
set +e
bazel test $TMP_HACK_BAZEL_CI_FLAGS --noshow_loading_progress --test_output=summary //... --test_tag_filters=ascentlint 2>&1 | tee .bazel-test-ascentlint.log
BAZEL_EXIT_CODE=${PIPESTATUS[0]}
TOTAL_TESTS=$(grep -Po '(?<=out of )\d+(?= test)' .bazel-test-ascentlint.log)
PASSING_TESTS=$(grep -Po '\d+(?= test passes?\.| tests pass)' .bazel-test-ascentlint.log)
echo "total_tests=$TOTAL_TESTS" >> $GITHUB_OUTPUT
echo "passing_tests=$PASSING_TESTS" >> $GITHUB_OUTPUT
echo "exit_code=$BAZEL_EXIT_CODE" >> $GITHUB_OUTPUT
- name: Verilog sim tests (using Synopsys VCS)
id: vcs
# Use --test_output=summary to suppress log output, even on failure (proprietary EDA tool output may be sensitive).
run: |
set +e
bazel test $TMP_HACK_BAZEL_CI_FLAGS --noshow_loading_progress --test_output=summary //... --test_tag_filters=vcs 2>&1 | tee .bazel-test-vcs.log
BAZEL_EXIT_CODE=${PIPESTATUS[0]}
TOTAL_TESTS=$(grep -Po '(?<=out of )\d+(?= test)' .bazel-test-vcs.log)
PASSING_TESTS=$(grep -Po '\d+(?= test passes?\.| tests pass)' .bazel-test-vcs.log)
echo "total_tests=$TOTAL_TESTS" >> $GITHUB_OUTPUT
echo "passing_tests=$PASSING_TESTS" >> $GITHUB_OUTPUT
echo "exit_code=$BAZEL_EXIT_CODE" >> $GITHUB_OUTPUT
- name: Check proprietary Bazel build and test suite results
run: |
failed_suites=()
check_suite() {
local suite="$1"
local exit_code="$2"
if [ "$exit_code" != "0" ]; then
echo "::error title=Bazel suite failed::$suite exited with code ${exit_code:-missing}"
failed_suites+=("$suite")
fi
}
check_suite "build" "${{ steps.build.outputs.exit_code }}"
check_suite "verific" "${{ steps.verific.outputs.exit_code }}"
check_suite "ascentlint" "${{ steps.ascentlint.outputs.exit_code }}"
check_suite "vcs" "${{ steps.vcs.outputs.exit_code }}"
if [ "${#failed_suites[@]}" -ne 0 ]; then
echo "Failed Bazel suites:"
printf ' - %s\n' "${failed_suites[@]}"
exit 1
fi
##########################################
##########################################
##########################################
#
# BADGES
#
##########################################
##########################################
##########################################
rtl-files-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Count RTL files
run: |
NUM_RTL_FILES=$(find . -type d -name rtl -exec find {} -type f -name "*.sv" \; | wc -l)
echo "NUM_RTL_FILES=$NUM_RTL_FILES" >> $GITHUB_ENV
- name: Create RTL files badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: rtl.json
label: "rtl files"
message: ${{ env.NUM_RTL_FILES }}
color: "purple"
python-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-oss-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create python badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: python.json
label: "python"
message: ${{ needs.bazel-oss-tool-test.outputs.python_passing_tests }} of ${{ needs.bazel-oss-tool-test.outputs.python_total_tests }} passing
color: ${{ needs.bazel-oss-tool-test.outputs.python_exit_code == '0' && 'brightgreen' || 'red' }}
stardoc-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-oss-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create stardoc badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: stardoc.json
label: "stardoc"
message: ${{ needs.bazel-oss-tool-test.outputs.stardoc_passing_tests }} of ${{ needs.bazel-oss-tool-test.outputs.stardoc_total_tests }} passing
color: ${{ needs.bazel-oss-tool-test.outputs.stardoc_exit_code == '0' && 'brightgreen' || 'red' }}
verific-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-build-and-proprietary-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create verific badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: verific.json
label: "verific"
message: ${{ needs.bazel-build-and-proprietary-tool-test.outputs.verific_passing_tests }} of ${{ needs.bazel-build-and-proprietary-tool-test.outputs.verific_total_tests }} passing
color: ${{ needs.bazel-build-and-proprietary-tool-test.outputs.verific_exit_code == '0' && 'brightgreen' || 'red' }}
slang-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-oss-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create slang badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: slang.json
label: "slang"
message: ${{ needs.bazel-oss-tool-test.outputs.slang_passing_tests }} of ${{ needs.bazel-oss-tool-test.outputs.slang_total_tests }} passing
color: ${{ needs.bazel-oss-tool-test.outputs.slang_exit_code == '0' && 'brightgreen' || 'red' }}
ascentlint-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-build-and-proprietary-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create ascentlint badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: ascentlint.json
label: "ascentlint"
message: ${{ needs.bazel-build-and-proprietary-tool-test.outputs.ascentlint_passing_tests }} of ${{ needs.bazel-build-and-proprietary-tool-test.outputs.ascentlint_total_tests }} passing
color: ${{ needs.bazel-build-and-proprietary-tool-test.outputs.ascentlint_exit_code == '0' && 'brightgreen' || 'red' }}
vcs-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-build-and-proprietary-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create vcs badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: vcs.json
label: "vcs"
message: ${{ needs.bazel-build-and-proprietary-tool-test.outputs.vcs_passing_tests }} of ${{ needs.bazel-build-and-proprietary-tool-test.outputs.vcs_total_tests }} passing
color: ${{ needs.bazel-build-and-proprietary-tool-test.outputs.vcs_exit_code == '0' && 'brightgreen' || 'red' }}
verilator-badge:
runs-on: ubuntu-24.04
environment: ci-badge-publishing
needs: bazel-oss-tool-test
if: ${{ always() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Create verilator badge
# schneegans/dynamic-badges-action v1.7.0
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483
with:
auth: ${{ secrets.MGOTTSCHO_GISTS_SECRET }}
gistID: c66dc2ddc0e513ba06ce338620977b26
filename: verilator.json
label: "verilator"
message: ${{ needs.bazel-oss-tool-test.outputs.verilator_passing_tests }} of ${{ needs.bazel-oss-tool-test.outputs.verilator_total_tests }} passing
color: ${{ needs.bazel-oss-tool-test.outputs.verilator_exit_code == '0' && 'brightgreen' || 'red' }}