186 lines
7.1 KiB
YAML
186 lines
7.1 KiB
YAML
---
|
|
# DESCRIPTION: Github actions config
|
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
|
|
name: reusable-test
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
archive:
|
|
description: "Name of the repository archive artifact from reusable-build"
|
|
required: true
|
|
type: string
|
|
cc:
|
|
description: "Compiler to use: 'gcc' or 'clang'"
|
|
required: true
|
|
type: string
|
|
dev-gcov:
|
|
description: "Collect gcov coverage data from the test run"
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
reloc:
|
|
description: "Relocate the installation before testing"
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
runs-on:
|
|
description: "Runner to test on, e.g. ubuntu-24.04"
|
|
required: true
|
|
type: string
|
|
suite:
|
|
description: "Test suite to run, e.g. dist-vlt-0"
|
|
required: true
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
actions: read
|
|
|
|
env:
|
|
CCACHE_COMPILERCHECK: content
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
CXX: ${{ inputs.cc == 'clang' && 'clang++' || 'g++' }}
|
|
GH_TOKEN: ${{ github.token }}
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
working-directory: repo
|
|
|
|
jobs:
|
|
|
|
test:
|
|
runs-on: ${{ inputs.runs-on }}
|
|
name: Test
|
|
steps:
|
|
|
|
- name: Download repository archive
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: ${{ inputs.archive }}
|
|
path: ${{ github.workspace }}
|
|
|
|
- name: Unpack repository archive
|
|
working-directory: ${{ github.workspace }}
|
|
run: |
|
|
tar --zstd -x -f ${{ inputs.archive }}
|
|
ls -lsha
|
|
|
|
# Test-job ccache is stored as an artifact, not actions/cache
|
|
# - pull_request: restore this PR's own previous run; if none, fall back to the PR's target branch.
|
|
# - branch push: restore that branch's own cache
|
|
# Artifact names are a global, unauthenticated namespace, so a PR could
|
|
# upload a "-branch-<x>" artifact impersonating a branch. Branch-scoped
|
|
# restores are therefore provenance-checked below (must come from a same-repo
|
|
# push to that branch); the pr-<N> scope is not (a PR can only affect its own
|
|
# unmerged cache).
|
|
- name: Compute ccache artifact name
|
|
# Pass github refs via env, not ${{ }} interpolation, so a branch name
|
|
# containing shell metacharacters can't break or inject into the script.
|
|
env:
|
|
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
REF_NAME: ${{ github.ref_name }}
|
|
run: |
|
|
base="ccache-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ inputs.suite }}"
|
|
sanitize() { printf '%s' "$1" | tr '/' '_'; } # artifact names cannot contain '/'
|
|
if [ "${{ github.event_name }}" = pull_request ]; then
|
|
echo "CCACHE_ARTIFACT=${base}-pr-${{ github.event.pull_request.number }}" >> "$GITHUB_ENV"
|
|
echo "CCACHE_ARTIFACT_BRANCH=" >> "$GITHUB_ENV"
|
|
echo "CCACHE_FALLBACK=${base}-branch-$(sanitize "$BASE_REF")" >> "$GITHUB_ENV"
|
|
echo "CCACHE_FALLBACK_BRANCH=${BASE_REF}" >> "$GITHUB_ENV"
|
|
else
|
|
echo "CCACHE_ARTIFACT=${base}-branch-$(sanitize "$REF_NAME")" >> "$GITHUB_ENV"
|
|
echo "CCACHE_ARTIFACT_BRANCH=${REF_NAME}" >> "$GITHUB_ENV"
|
|
fi
|
|
|
|
- name: Restore ccache from artifact
|
|
continue-on-error: true # a cold start is fine; never fail the job here
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p "$CCACHE_DIR"
|
|
# Return newest non-expired artifact named $1 (empty if none). When
|
|
# $2 (branch) is non-empty, require provenance: the artifact must come from
|
|
# a same-repo run (head_repository_id == repository_id) whose head branch
|
|
# is $2, so a fork PR cannot forge a branch-scoped artifact.
|
|
newest_run_id() {
|
|
want="$1" br="$2" gh api \
|
|
"/repos/$GITHUB_REPOSITORY/actions/artifacts?name=$1&per_page=100" \
|
|
--jq '.artifacts[]
|
|
| select(.expired == false and .name == env.want)
|
|
| select(env.br == ""
|
|
or (.workflow_run.head_branch == env.br
|
|
and .workflow_run.head_repository_id == .workflow_run.repository_id))
|
|
| [.created_at, (.workflow_run.id | tostring)] | @tsv' \
|
|
| sort | tail -n1 | cut -f2
|
|
}
|
|
restore() { # $1=name $2=branch(empty ok); returns 0 on a successful restore
|
|
local name="$1" br="$2" rid tarball
|
|
[ -n "$name" ] || return 1
|
|
rid="$(newest_run_id "$name" "$br")" || return 1
|
|
[ -n "$rid" ] || return 1
|
|
echo "Restoring ccache from '$name' (run $rid)"
|
|
gh run download "$rid" --name "$name" --dir "$RUNNER_TEMP/ccache-dl" || return 1
|
|
tarball="$(find "$RUNNER_TEMP/ccache-dl" -name ccache.tar.zst -print -quit)"
|
|
[ -n "$tarball" ] || return 1
|
|
tar -I zstd -x -f "$tarball" -C "$CCACHE_DIR"
|
|
}
|
|
if restore "${CCACHE_ARTIFACT:-}" "${CCACHE_ARTIFACT_BRANCH:-}"; then
|
|
echo "Restored primary ccache"
|
|
exit 0
|
|
fi
|
|
if restore "${CCACHE_FALLBACK:-}" "${CCACHE_FALLBACK_BRANCH:-}"; then
|
|
echo "Restored fallback ccache"
|
|
exit 0
|
|
fi
|
|
echo "No ccache artifact found; starting cold"
|
|
|
|
- name: Install test dependencies
|
|
run: |
|
|
./ci/ci-install.bash test
|
|
make venv
|
|
|
|
- name: Test
|
|
id: run-test
|
|
continue-on-error: true
|
|
run: |
|
|
source .venv/bin/activate
|
|
./ci/ci-test.bash \
|
|
--suite ${{ inputs.suite }} \
|
|
${{ inputs.reloc && format('--reloc {0}/reloc', github.workspace) || '' }}
|
|
|
|
- name: Combine code coverage data
|
|
if: ${{ inputs.dev-gcov }}
|
|
run: |
|
|
make coverage-combine
|
|
mv obj_coverage/verilator.info obj_coverage/verilator-${{ inputs.suite }}.info
|
|
ls -lsha obj_coverage
|
|
|
|
- name: Upload code coverage data
|
|
if: ${{ inputs.dev-gcov }}
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
path: ${{ github.workspace }}/repo/obj_coverage/verilator-${{ inputs.suite }}.info
|
|
name: code-coverage-${{ inputs.suite }}
|
|
|
|
- name: Pack ccache
|
|
if: ${{ !cancelled() && env.CCACHE_ARTIFACT != '' }}
|
|
run: tar -I 'zstd -T0' -cf "$GITHUB_WORKSPACE/ccache.tar.zst" -C "$CCACHE_DIR" .
|
|
|
|
- name: Save ccache artifact
|
|
if: ${{ !cancelled() && env.CCACHE_ARTIFACT != '' }}
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: ${{ env.CCACHE_ARTIFACT }}
|
|
path: ${{ github.workspace }}/ccache.tar.zst
|
|
retention-days: 3
|
|
overwrite: true
|
|
compression-level: 0
|
|
|
|
- name: Fail job if a test failed
|
|
if: ${{ steps.run-test.outcome == 'failure' && !cancelled() }}
|
|
run: |-
|
|
echo "Click on '> Tests' arrow above (or on other steps), to expand it, and see the failure reasons"
|
|
exit 1
|