Skip to content

Commit

Permalink
Extend CI to automatically run tests on select MSI platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
arturkow2000 committed Nov 14, 2023
1 parent fd4ea51 commit aa8072e
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 1 deletion.
57 changes: 56 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
strategy:
matrix:
vendor: [ msi ]
model: [ ms7d25_ddr4, ms7d25_ddr5, ms7e06_ddr4, ms7e06_ddr5 ]
model: [ ms7d25_ddr5 ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand All @@ -62,12 +62,17 @@ jobs:
cp configs/config.${{ matrix.vendor }}_${{ matrix.model }} .config
make olddefconfig
make
- name: Create patched binary with pre-enabled serial output
run: |
cp build/coreboot.rom build/coreboot_serial_enabled.rom
build/util/cbfstool/cbfstool build/coreboot_serial_enabled.rom write -r SMMSTORE -f ci/smmstore-serial-enabled
- name: Save artifacts
uses: actions/upload-artifact@v2
with:
name: "dasharo-${{ matrix.vendor }}-${{ matrix.model }}-${{ matrix.build }}"
path: |
build/coreboot.rom
build/coreboot_serial_enabled.rom
retention-days: 30
build_protectli:
environment: Protectli
Expand Down Expand Up @@ -100,3 +105,53 @@ jobs:
- name: Build Dasharo
run: |
./build.sh ${{ matrix.model }}
test_msi:
runs-on: self-hosted
strategy:
matrix:
vendor: [ msi ]
model: [ ms7d25_ddr5 ]
needs: [build_msi]
steps:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.11'

- name: Fetch CI script
uses: actions/checkout@v4
with:
sparse-checkout: ci
sparse-checkout-cone-mode: false

- name: Checkout test repository
uses: actions/checkout@v4
with:
repository: Dasharo/open-source-firmware-validation
path: validation
submodules: true

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r validation/requirements.txt
- name: Fetch latest firmware
uses: actions/download-artifact@v3
with:
name: dasharo-${{ matrix.vendor }}-${{ matrix.model }}-${{ matrix.build }}
path: firmware

- name: Flash firmware
shell: bash
run: ./ci/ci.sh -r validation -v "${{ matrix.vendor }}" -m "${{ matrix.model }}" -f firmware/coreboot_serial_enabled.rom flash

- name: Run tests
shell: bash
run: ./ci/ci.sh -r validation -v "${{ matrix.vendor }}" -m "${{ matrix.model }}" -f firmware/coreboot_serial_enabled.rom test

- name: Upload test results
uses: actions/upload-artifact@v3
with:
name: test-results-${{ matrix.vendor }}-${{ matrix.model }}
if: always()
131 changes: 131 additions & 0 deletions ci/ci.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env bash

set -euo pipefail

script_dir="$(dirname "${BASH_SOURCE[0]}")"

vendor=""
model=""

usage() {
echo "Usage: ci.sh -v vendor -m model -f firmware command" 1>&2
exit 1
}

while getopts "r:v:m:f:" o; do
case "${o}" in
r) root="${OPTARG}" ;;
v) vendor="${OPTARG}" ;;
m) model="${OPTARG}" ;;
f) fw_file="${OPTARG}" ;;
*) usage ;;
esac
done
shift $((OPTIND-1))

[ -n "$vendor" ] || usage
[ -n "$model" ] || usage
[ $# -eq 1 ] || usage

command="$1"
[[ "$command" =~ ^(flash|test)$ ]] || usage
shift 1

options=(
-L TRACE
-v snipeit:none
)

compatibility_tests=()
performance_tests=()
security_tests=()
stability_tests=()

case "$vendor" in
msi)
case "$model" in
ms7d25_ddr5)
device_ip="192.168.10.93"
rte_ip="192.168.10.188"
pikvm_ip="192.168.10.45"
config="msi-pro-z690-a-ddr5"
;;
*)
echo unknown board: $model
exit 1
;;
esac
;;
*)
echo unknown vendor: $vendor
exit 1
;;
esac

options+=(
-v device_ip:$device_ip
-v rte_ip:$rte_ip
-v pikvm_ip:$pikvm_ip
-v config:$config
-v snipeit:no
)

if [ "$command" == "flash" ]; then
"$script_dir/scp.py" "$rte_ip" "$fw_file" /tmp/dasharo.rom
"$script_dir/ssh.py" "$rte_ip" /home/root/flash.sh /tmp/dasharo.rom
exit 0
fi

case "$vendor" in
msi)
case "$model" in
ms7d25_ddr5)
compatibility_tests+=(
custom-boot-menu-key
)

security_tests+=(
me-neuter
)
;;
*)
echo unknown board: $model
exit 1
;;
esac
;;
*)
echo unknown vendor: $vendor
exit 1
;;
esac

mkdir -p "test-results-$vendor-$model"

run_robot() {
local category="$1"
local test="$2"

robot -l "test-results-$vendor-$model/dasharo-${category}.log.html" \
-r "test-results-$vendor-$model/dasharo-${category}.html" \
-o "test-results-$vendor-$model/dasharo-${category}.xml" \
${options[@]} "$root/dasharo-${category}/$test.robot"
}

if [ "$command" == "test" ]; then
for test in "${compatibility_tests[@]}"; do
run_robot compatibility "$test"
done

for test in "${performance_tests[@]}"; do
run_robot performance "$test"
done

for test in "${security_tests[@]}"; do
run_robot security "$test"
done

for test in "${stability_tests[@]}"; do
run_robot stability "$test"
done
fi
22 changes: 22 additions & 0 deletions ci/scp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python3

from argparse import ArgumentParser
import paramiko

def main():
parser = ArgumentParser()
parser.add_argument("host")
parser.add_argument("local")
parser.add_argument("remote")
args = parser.parse_args()

client = paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(args.host, username="root", password="meta-rte")

ftp = client.open_sftp()
ftp.put(args.local, args.remote)
ftp.close()

if __name__ == '__main__':
main()
Binary file added ci/smmstore-serial-enabled
Binary file not shown.
42 changes: 42 additions & 0 deletions ci/ssh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python3

from argparse import ArgumentParser, REMAINDER
from select import select
import paramiko
import sys
import os

def main():
parser = ArgumentParser()
parser.add_argument("host")
parser.add_argument("command")
parser.add_argument("args", nargs=REMAINDER)
args = parser.parse_args()

client = paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(args.host, username="root", password="meta-rte")

cmd = f"{args.command} "
for arg in args.args:
cmd += f'\'{arg}\' '

transport = client.get_transport()
channel = transport.open_session()
channel.exec_command(cmd)

while True:
if channel.exit_status_ready():
break
rl, _wl, _xl = select([channel], [], [])
if len(rl) > 0:
if channel.recv_ready():
data = channel.recv(1024)
os.write(sys.stdout.fileno(), data)

if channel.recv_stderr_ready():
data = channel.recv_stderr(1024)
os.write(sys.stderr.fileno(), data)

if __name__ == '__main__':
main()

0 comments on commit aa8072e

Please sign in to comment.