Skip to content

Add PTODSL A5 DSL ST coverage #3386

Add PTODSL A5 DSL ST coverage

Add PTODSL A5 DSL ST coverage #3386

Workflow file for this run

name: CI
concurrency:
group: ci-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
on:
pull_request:
# Nightly remote-board validation (GitHub cron is UTC).
# 22:00 CST (UTC+8) == 14:00 UTC.
schedule:
- cron: "0 14 * * *"
workflow_dispatch:
inputs:
stage:
description: "Validation stage (build|run)"
type: choice
options: [build, run]
default: run
run_mode:
description: "Run mode passed to generated CMake (sim|npu)"
type: choice
options: [npu, sim]
default: npu
soc_version:
description: "Ascend SoC version (e.g. Ascend910B1)"
type: string
default: Ascend910
device_id:
description: "TaskQueue device selector (`auto` or physical device id)"
type: string
# NOTE: Shared A3 hosts now require task-submit queueing to obtain
# temporary device access. Use `auto` by default so the queue picks an
# allowed device and exposes it to the validation command.
default: "auto"
skip_cases:
description: "Comma/space separated testcase names to skip (e.g. scatter,mrgsort)"
type: string
default: "mix_kernel,vadd_validshape,vadd_validshape_dynamic,print,storefp"
run_only_cases:
description: "Comma/space separated testcase names to run (empty = run all)"
type: string
default: ""
pto_isa_repo:
description: "pto-isa repo URL on remote"
type: string
default: https://gitcode.com/cann/pto-isa.git
pto_isa_commit:
description: "pto-isa ref (commit/tag/branch; empty = repo-pinned weekly commit)"
type: string
# NOTE: Pin a known-good GitCode commit for deterministic runs.
default: 7e879c4198939b506571f8769326b5a61e88da25
remote_host:
description: "SSH host/IP for the NPU machine"
type: string
default: 101.245.68.6
remote_user:
description: "SSH user for the NPU machine"
type: string
default: zhongxuan
remote_port:
description: "SSH port"
type: string
default: "22"
permissions:
contents: read
actions: write
pull-requests: read
jobs:
license-header-check:
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Check PR386 license headers
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
python3 .github/scripts/check_license_headers.py \
--repo "${{ github.repository }}" \
--event-name "${{ github.event_name }}" \
--pr-number "${{ github.event.pull_request.number || '' }}" \
--base-sha "${{ github.event.pull_request.base.sha || github.event.before || '' }}" \
--head-sha "${{ github.event.pull_request.head.sha || github.sha }}" \
--github-token "${GITHUB_TOKEN}"
build-and-test:
runs-on: ubuntu-22.04
env:
PTOAS_CLANG_MAJOR: "15"
LLVM_REPO: https://github.com/vpto-dev/llvm-project.git
LLVM_REF: feature-vpto-llvm21
LLVM_BUILD_DIR: ${{ github.workspace }}/llvm-project/llvm/build-assert
LLVM_DIR: ${{ github.workspace }}/llvm-project/llvm/build-assert
PTO_BUILD_DIR: ${{ github.workspace }}/build-assert
PTO_INSTALL_DIR: ${{ github.workspace }}/install-assert
MLIR_PYTHONPATH: ${{ github.workspace }}/llvm-project/llvm/build-assert/tools/mlir/python_packages/mlir_core
LLVM_CACHE_FLAVOR: llvm21-assert-shared-mlirpy-hardening-v1
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
- name: Install dependencies
run: |
# GitHub-hosted runners may include Microsoft apt sources unrelated to
# PTOAS; these can intermittently return 403 and break apt-get update.
sudo rm -f \
/etc/apt/sources.list.d/azure-cli*.list \
/etc/apt/sources.list.d/azure-cli*.sources \
/etc/apt/sources.list.d/microsoft-prod*.list \
/etc/apt/sources.list.d/microsoft-prod*.sources \
/etc/apt/sources.list.d/packages-microsoft-prod*.list \
/etc/apt/sources.list.d/packages-microsoft-prod*.sources
sudo apt-get update
sudo apt-get install -y \
cmake git ninja-build \
python3 python3-pip python3-venv \
clang-${PTOAS_CLANG_MAJOR} lld-${PTOAS_CLANG_MAJOR} \
libedit-dev zlib1g-dev libxml2-dev libzstd-dev
python3 -m pip install --upgrade pip
# LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x.
python3 -m pip install setuptools wheel 'pybind11<3' nanobind numpy
- name: Define payload paths
shell: bash
run: |
set -euo pipefail
# NOTE: Some GitHub/GHES versions don't allow using `${{ runner.temp }}` in
# `jobs.<job>.env`. Use the runtime env var instead.
tmp_root="${RUNNER_TEMP:-${GITHUB_WORKSPACE}/.tmp}"
echo "PAYLOAD_DIR=${tmp_root}/ptoas_payload" >> "${GITHUB_ENV}"
echo "PAYLOAD_TGZ=${tmp_root}/ptoas_payload.tgz" >> "${GITHUB_ENV}"
- name: Prepare payload dir
shell: bash
run: |
set -euo pipefail
rm -rf "${PAYLOAD_DIR}" "${PAYLOAD_TGZ}"
mkdir -p "${PAYLOAD_DIR}/test/samples"
mkdir -p "${PAYLOAD_DIR}/test/npu_validation/scripts"
mkdir -p "${PAYLOAD_DIR}/test/npu_validation/templates"
- name: Resolve clang-${{ env.PTOAS_CLANG_MAJOR }} toolchain
shell: bash
run: |
set -euo pipefail
clang_c="$(command -v "clang-${PTOAS_CLANG_MAJOR}")"
clang_cxx="$(command -v "clang++-${PTOAS_CLANG_MAJOR}")"
echo "PTOAS_CMAKE_C_COMPILER=${clang_c}" >> "${GITHUB_ENV}"
echo "PTOAS_CMAKE_CXX_COMPILER=${clang_cxx}" >> "${GITHUB_ENV}"
"${clang_c}" --version | head -n 1
"${clang_cxx}" --version | head -n 1
- name: Resolve LLVM source SHA
shell: bash
run: |
set -euo pipefail
LLVM_SOURCE_SHA="$(git ls-remote "${LLVM_REPO}" "refs/heads/${LLVM_REF}" | awk '{print $1}')"
[[ -n "${LLVM_SOURCE_SHA}" ]] || {
echo "ERROR: failed to resolve ${LLVM_REPO} ${LLVM_REF}" >&2
exit 1
}
echo "LLVM_SOURCE_SHA=${LLVM_SOURCE_SHA}" >> "${GITHUB_ENV}"
# 先恢复 LLVM build 缓存
- name: Restore LLVM build cache
id: cache-llvm
uses: actions/cache/restore@v4
with:
path: |
llvm-project/llvm/build-assert
key: llvm-${{ runner.os }}-clang${{ env.PTOAS_CLANG_MAJOR }}-${{ env.LLVM_SOURCE_SHA }}-${{ env.LLVM_CACHE_FLAVOR }}
- name: Prepare LLVM source (no rebuild)
run: |
mkdir -p llvm-project
cd llvm-project
# cache 只保存 build 目录,这里补一个最小 git repo 供 cmake/ninja 使用
if [ ! -d .git ]; then
git init
git remote add origin "${LLVM_REPO}"
fi
git remote set-url origin "${LLVM_REPO}"
git fetch --depth 1 origin "${LLVM_REF}"
git checkout --force FETCH_HEAD
- name: Build LLVM/MLIR (only if cache miss)
if: steps.cache-llvm.outputs.cache-hit != 'true'
run: |
cd llvm-project
cmake -C "${GITHUB_WORKSPACE}/cmake/LinuxHardeningCache.cmake" -G Ninja -S llvm -B "${LLVM_BUILD_DIR}" \
-DLLVM_ENABLE_PROJECTS="mlir;clang" \
-DBUILD_SHARED_LIBS=ON \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DMLIR_ENABLE_BINDINGS_PYTHON=ON \
-DPython3_EXECUTABLE=python3 \
-DPython_EXECUTABLE=python3 \
-Dpybind11_DIR="$(python3 -m pybind11 --cmakedir)" \
-Dnanobind_DIR="$(python3 -m nanobind --cmake_dir)" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER="${PTOAS_CMAKE_C_COMPILER}" \
-DCMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \
-DLLVM_TARGETS_TO_BUILD="host"
ninja -C "${LLVM_BUILD_DIR}"
# LLVM build 完成后立即保存缓存,避免后续测试影响缓存内容
- name: Save LLVM build cache
if: steps.cache-llvm.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
llvm-project/llvm/build-assert
key: llvm-${{ runner.os }}-clang${{ env.PTOAS_CLANG_MAJOR }}-${{ env.LLVM_SOURCE_SHA }}-${{ env.LLVM_CACHE_FLAVOR }}
- name: Validate strict CMake 4 configure
shell: bash
run: |
set -euo pipefail
cmake4_pkg="${RUNNER_TEMP:-${GITHUB_WORKSPACE}/.tmp}/cmake-4.1.3-pkg"
cmake4_build="${RUNNER_TEMP:-${GITHUB_WORKSPACE}/.tmp}/ptoas-cmake4-strict"
rm -rf "${cmake4_pkg}" "${cmake4_build}"
python3 -m pip install --target "${cmake4_pkg}" "cmake==4.1.3"
cmake4_bin="$(
PYTHONPATH="${cmake4_pkg}" python3 -c 'import cmake; from pathlib import Path; print(Path(cmake.__file__).resolve().parent / "data" / "bin" / "cmake")'
)"
"${cmake4_bin}" --version
"${cmake4_bin}" -C "${GITHUB_WORKSPACE}/cmake/LinuxHardeningCache.cmake" \
-G Ninja \
-S "${GITHUB_WORKSPACE}" \
-B "${cmake4_build}" \
-DLLVM_DIR="${LLVM_DIR}/lib/cmake/llvm" \
-DMLIR_DIR="${LLVM_DIR}/lib/cmake/mlir" \
-DPython3_EXECUTABLE="$(command -v python3)" \
-DPython3_FIND_STRATEGY=LOCATION \
-Dpybind11_DIR="$(python3 -m pybind11 --cmakedir)" \
-DMLIR_ENABLE_BINDINGS_PYTHON=ON \
-DMLIR_PYTHON_PACKAGE_DIR="${MLIR_PYTHONPATH}" \
-DPTO_ENABLE_PYTHON_BINDING=ON \
-DPTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT=ON \
-DPTOAS_ENABLE_WERROR=OFF \
-DBUILD_TESTING=ON \
-DCMAKE_C_COMPILER="${PTOAS_CMAKE_C_COMPILER}" \
-DCMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \
-Werror=dev
- name: Build PTOAS
run: |
rm -rf "${PTO_BUILD_DIR}"
rm -rf "${PTO_INSTALL_DIR}"
# LLVM_BUILD_DIR is the env var read by the build backend (_ptoas_build_backend.py).
LLVM_BUILD_DIR="${LLVM_DIR}" \
CMAKE_C_COMPILER="${PTOAS_CMAKE_C_COMPILER}" \
CMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \
PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" \
python3 -m pip install . --no-build-isolation --no-deps --ignore-installed --prefix "${PTO_INSTALL_DIR}"
- name: Run PTODSL Python tests
shell: bash
env:
LLVM_DIR: ${{ env.LLVM_DIR }}
PTO_INSTALL_DIR: ${{ env.PTO_INSTALL_DIR }}
MLIR_PYTHONPATH: ${{ env.MLIR_PYTHONPATH }}
run: |
PTOAS_PYTHON_SITE="$(PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" python3 -c 'import os, sysconfig; prefix = os.environ["PTO_INSTALL_DIR"]; print(sysconfig.get_path("purelib", vars={"base": prefix, "platbase": prefix}))')"
export PATH="${LLVM_DIR}/bin:${PTO_INSTALL_DIR}/bin:${PATH}"
export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}"
export PYTHONPATH="${PTOAS_PYTHON_SITE}:${PTO_INSTALL_DIR}:${MLIR_PYTHONPATH}:${PYTHONPATH:-}"
ctest --test-dir "${PTO_BUILD_DIR}" --output-on-failure -L PTODSL
- name: Run lit tests
shell: bash
env:
LLVM_DIR: ${{ env.LLVM_DIR }}
PTO_INSTALL_DIR: ${{ env.PTO_INSTALL_DIR }}
MLIR_PYTHONPATH: ${{ env.MLIR_PYTHONPATH }}
run: |
PTOAS_PYTHON_SITE="$(PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" python3 -c 'import os, sysconfig; prefix = os.environ["PTO_INSTALL_DIR"]; print(sysconfig.get_path("purelib", vars={"base": prefix, "platbase": prefix}))')"
export PATH="${LLVM_DIR}/bin:${PTO_INSTALL_DIR}/bin:${PATH}"
export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}"
export PYTHONPATH="${PTOAS_PYTHON_SITE}:${PTO_INSTALL_DIR}:${MLIR_PYTHONPATH}:${PYTHONPATH:-}"
ninja -C "${PTO_BUILD_DIR}" check-pto
- name: Run sample tests (py -> pto -> cpp)
shell: bash
env:
CI_EVENT_NAME: ${{ github.event_name }}
WORKFLOW_SOC_VERSION: ${{ github.event.inputs.soc_version || 'Ascend910' }}
PTOAS_BIN: ${{ env.PTO_BUILD_DIR }}/tools/ptoas/ptoas
PTOBC_BIN: ${{ env.PTO_BUILD_DIR }}/tools/ptobc/ptobc
PTO_BUILD_DIR: ${{ env.PTO_BUILD_DIR }}
PYTHON_BIN: /usr/bin/python3
MLIR_PYTHON_ROOT: ${{ env.MLIR_PYTHONPATH }}
PTO_INSTALL_DIR: ${{ env.PTO_INSTALL_DIR }}
run: |
set -euo pipefail
PTOAS_PYTHON_SITE="$(PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" python3 -c 'import os, sysconfig; prefix = os.environ["PTO_INSTALL_DIR"]; print(sysconfig.get_path("purelib", vars={"base": prefix, "platbase": prefix}))')"
export PATH="${PTO_INSTALL_DIR}/bin:${PATH}"
export PYTHONPATH="${PTOAS_PYTHON_SITE}:${PTO_INSTALL_DIR}:${MLIR_PYTHON_ROOT}:${PYTHONPATH:-}"
export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}"
export PTOAS_OUT_DIR="${PAYLOAD_DIR}/test/samples"
if [[ "${CI_EVENT_NAME}" == "workflow_dispatch" || "${CI_EVENT_NAME}" == "schedule" ]]; then
# Board-validation payloads must only contain the arch-matching
# direct .pto samples. Some A3/A5 qwen decode cases intentionally
# share the same testcase basename, so SKIP_CASES cannot
# distinguish them later once the payload is built.
SOC_VERSION="${WORKFLOW_SOC_VERSION}" bash test/samples/runop.sh --enablebc all
else
bash test/samples/runop.sh --enablebc all
fi
- name: Build payload artifact
if: >-
${{
github.event_name == 'workflow_dispatch' ||
github.event_name == 'schedule'
}}
shell: bash
run: |
set -euo pipefail
cp test/npu_validation/scripts/generate_testcase.py "${PAYLOAD_DIR}/test/npu_validation/scripts/"
cp test/npu_validation/scripts/run_remote_npu_validation.sh "${PAYLOAD_DIR}/test/npu_validation/scripts/"
cp test/npu_validation/templates/* "${PAYLOAD_DIR}/test/npu_validation/templates/"
chmod +x "${PAYLOAD_DIR}/test/npu_validation/scripts/run_remote_npu_validation.sh"
tar -czf "${PAYLOAD_TGZ}" -C "${PAYLOAD_DIR}" .
- name: Upload payload artifact
if: >-
${{
github.event_name == 'workflow_dispatch' ||
github.event_name == 'schedule'
}}
uses: actions/upload-artifact@v4
with:
name: ptoas_payload
path: ${{ env.PAYLOAD_TGZ }}
if-no-files-found: error
remote-npu-validation:
needs: build-and-test
runs-on: ubuntu-22.04
timeout-minutes: 180
concurrency:
group: remote-npu-validation
cancel-in-progress: false
# Ordering: `needs: build-and-test` enforces "CI -> remote".
if: >-
${{
(github.event_name == 'workflow_dispatch' ||
github.event_name == 'schedule')
}}
env:
PAYLOAD_DOWNLOAD_DIR: ${{ github.workspace }}/_payload
PAYLOAD_TGZ: ${{ github.workspace }}/_payload/ptoas_payload.tgz
# Temporary CI gate: skip cases that still error/flap on the remote NPU.
# Update this list as we fix the underlying issues.
DEFAULT_SKIP_CASES: >-
mix_kernel,vadd_validshape,vadd_validshape_dynamic,print,storefp
steps:
- name: Resolve validation parameters
shell: bash
env:
STAGE: ${{ github.event.inputs.stage || 'run' }}
RUN_MODE: ${{ github.event.inputs.run_mode || 'npu' }}
SOC_VERSION: ${{ github.event.inputs.soc_version || 'Ascend910' }}
DEVICE_ID: ${{ github.event.inputs.device_id || 'auto' }}
SKIP_CASES: ${{ github.event.inputs.skip_cases || '' }}
RUN_ONLY_CASES: ${{ github.event.inputs.run_only_cases || '' }}
PTO_ISA_REPO: ${{ github.event.inputs.pto_isa_repo || 'https://gitcode.com/cann/pto-isa.git' }}
PTO_ISA_COMMIT: ${{ github.event.inputs.pto_isa_commit || '7e879c4198939b506571f8769326b5a61e88da25' }}
REMOTE_HOST: ${{ github.event.inputs.remote_host || '101.245.68.6' }}
REMOTE_USER: ${{ github.event.inputs.remote_user || 'zhongxuan' }}
REMOTE_PORT: ${{ github.event.inputs.remote_port || '22' }}
run: |
set -euo pipefail
# For scheduled runs, default to DEFAULT_SKIP_CASES (known-bad/flaky).
# For workflow_dispatch runs, honor the user's input (the UI default
# is pre-filled but can be edited to run everything).
if [[ "${GITHUB_EVENT_NAME}" != "workflow_dispatch" ]]; then
if [[ -z "${SKIP_CASES}" ]]; then
SKIP_CASES="${DEFAULT_SKIP_CASES}"
fi
fi
# Some validation samples are arch-specific due to stricter pto-isa
# static checks and A5-only tile layouts. Always skip the
# non-matching variant based on SOC_VERSION, even for explicit
# RUN_ONLY_CASES requests, so remote validation does not try to force
# A5-only cases through an A3 flow or vice versa.
A3_ONLY_CASES="partition5d,partition5d_dynamic,mrgsort,tmatmulk_autosync"
A5_ONLY_CASES="partition5d_a5,partition5d_dynamic_a5,mrgsort_a5,tmatmulk_autosync_a5,tpack,matmul_mx_low_precision,gemvmx,tquant_mx"
sv_lc="$(printf '%s' "${SOC_VERSION}" | tr '[:upper:]' '[:lower:]')"
is_a5=0
if [[ "${sv_lc}" == *"950"* || "${sv_lc}" == *"a5"* ]]; then
is_a5=1
fi
if [[ ${is_a5} -eq 1 ]]; then
SKIP_CASES="${SKIP_CASES:+${SKIP_CASES},}${A3_ONLY_CASES}"
else
SKIP_CASES="${SKIP_CASES:+${SKIP_CASES},}${A5_ONLY_CASES}"
fi
echo "STAGE=${STAGE}" >> "${GITHUB_ENV}"
echo "RUN_MODE=${RUN_MODE}" >> "${GITHUB_ENV}"
echo "SOC_VERSION=${SOC_VERSION}" >> "${GITHUB_ENV}"
echo "DEVICE_ID=${DEVICE_ID}" >> "${GITHUB_ENV}"
echo "SKIP_CASES=${SKIP_CASES}" >> "${GITHUB_ENV}"
echo "RUN_ONLY_CASES=${RUN_ONLY_CASES}" >> "${GITHUB_ENV}"
echo "PTO_ISA_REPO=${PTO_ISA_REPO}" >> "${GITHUB_ENV}"
echo "PTO_ISA_COMMIT=${PTO_ISA_COMMIT}" >> "${GITHUB_ENV}"
echo "REMOTE_HOST=${REMOTE_HOST}" >> "${GITHUB_ENV}"
echo "REMOTE_USER=${REMOTE_USER}" >> "${GITHUB_ENV}"
echo "REMOTE_PORT=${REMOTE_PORT}" >> "${GITHUB_ENV}"
- name: Setup SSH
shell: bash
env:
SSH_KEY: ${{ secrets.SSH_KEY }}
SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
run: |
set -euo pipefail
if [[ -z "${SSH_KEY}" ]]; then
echo "ERROR: secrets.SSH_KEY is not set"
exit 1
fi
if [[ -z "${SSH_KNOWN_HOSTS}" ]]; then
echo "ERROR: secrets.SSH_KNOWN_HOSTS is not set"
exit 1
fi
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "${SSH_KEY}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%s\n' "${SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: Download payload artifact
uses: actions/download-artifact@v4
with:
name: ptoas_payload
path: ${{ env.PAYLOAD_DOWNLOAD_DIR }}
- name: Vendor pto-isa into payload (offline remote)
shell: bash
run: |
set -euo pipefail
tmp_root="${RUNNER_TEMP:-${GITHUB_WORKSPACE}/.tmp}"
work="$(mktemp -d "${tmp_root}/ptoas_payload_unpack.XXXXXX")"
tar -xzf "${PAYLOAD_TGZ}" -C "${work}"
rm -rf "${work}/pto-isa"
git clone "${PTO_ISA_REPO}" "${work}/pto-isa"
if [[ -n "${PTO_ISA_COMMIT}" ]]; then
git -C "${work}/pto-isa" checkout -f "${PTO_ISA_COMMIT}"
else
git -C "${work}/pto-isa" checkout -f origin/HEAD || true
fi
# Ship a working tree only; remote should not need outbound network.
rm -rf "${work}/pto-isa/.git"
tar -czf "${PAYLOAD_TGZ}" -C "${work}" .
- name: Copy payload to remote
shell: bash
run: |
set -euo pipefail
if [[ ! -f "${PAYLOAD_TGZ}" ]]; then
echo "ERROR: payload tarball not found: ${PAYLOAD_TGZ}"
exit 1
fi
REMOTE_DIR="/tmp/ptoas_npu_validation/${GITHUB_REPOSITORY}/${GITHUB_RUN_ID}"
echo "REMOTE_DIR=${REMOTE_DIR}" >> "${GITHUB_ENV}"
ssh -p "${REMOTE_PORT}" "${REMOTE_USER}@${REMOTE_HOST}" "rm -rf '${REMOTE_DIR}' && mkdir -p '${REMOTE_DIR}'"
scp -P "${REMOTE_PORT}" "${PAYLOAD_TGZ}" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/payload.tgz"
- name: Run remote validation
shell: bash
run: |
set -euo pipefail
if [[ -z "${DEVICE_ID}" ]]; then
DEVICE_ID="auto"
fi
ssh -p "${REMOTE_PORT}" "${REMOTE_USER}@${REMOTE_HOST}" \
"set -euo pipefail; \
cd '${REMOTE_DIR}'; \
tar -xzf payload.tgz; \
command -v task-submit >/dev/null 2>&1 || { echo 'ERROR: task-submit not found on remote host'; exit 1; }; \
task-submit --device '${DEVICE_ID}' --timeout 0 --max-time 0 \
--run \"cd '${REMOTE_DIR}' && STAGE='${STAGE}' RUN_MODE='${RUN_MODE}' SOC_VERSION='${SOC_VERSION}' PTO_ISA_REPO='${PTO_ISA_REPO}' PTO_ISA_COMMIT='${PTO_ISA_COMMIT}' DEVICE_ID=\\\${TASK_DEVICE:-${DEVICE_ID}} SKIP_CASES='${SKIP_CASES}' RUN_ONLY_CASES='${RUN_ONLY_CASES}' bash ./test/npu_validation/scripts/run_remote_npu_validation.sh\""
- name: Fetch results
if: always()
shell: bash
run: |
set -euo pipefail
if [[ -z "${REMOTE_DIR:-}" ]]; then
echo "REMOTE_DIR is not set; skipping results fetch."
exit 0
fi
scp -P "${REMOTE_PORT}" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/remote_npu_validation_results.tsv" ./remote_npu_validation_results.tsv || true
- name: Upload results artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: remote_npu_validation_results
path: remote_npu_validation_results.tsv
if-no-files-found: warn
- name: Cleanup remote
if: always()
shell: bash
run: |
set -euo pipefail
if [[ -n "${REMOTE_DIR:-}" ]]; then
ssh -p "${REMOTE_PORT}" "${REMOTE_USER}@${REMOTE_HOST}" "rm -rf '${REMOTE_DIR}'" || true
fi