Skip to content

Add basic U-mode support with ecall-based syscalls #105

Add basic U-mode support with ecall-based syscalls

Add basic U-mode support with ecall-based syscalls #105

Workflow file for this run

name: Linmo CI
on:
push:
branches:
- main
pull_request:
branches:
- main
# Cancel in-progress runs for the same PR/branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Least-privilege permissions
permissions:
contents: read
actions: write # Required for actions/cache@v4 to save/restore cache
jobs:
# Fast-running lint job to catch formatting issues early
lint:
runs-on: ubuntu-24.04
name: Code Quality Checks
timeout-minutes: 10
env:
CLANG_FORMAT_VERSION: 18
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install linting tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends clang-format-${{ env.CLANG_FORMAT_VERSION }} shfmt
- name: Check code formatting
run: .ci/check-format.sh
- name: Check newline at end of files
run: .ci/check-newline.sh
# Build and test matrix - runs in parallel after lint passes
# NOTE: LLVM toolchain performs build-only validation (no runtime tests)
# to verify cross-toolchain compilation compatibility. GNU toolchain
# runs the full test suite including application and functional tests.
matrix-tests:
runs-on: ubuntu-24.04
name: Test on ${{ matrix.toolchain }} toolchain
needs: lint
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
toolchain: [gnu, llvm]
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cache toolchain
uses: actions/cache@v4
id: cache-toolchain
with:
path: riscv
key: ${{ runner.os }}-${{ matrix.toolchain }}-toolchain-${{ hashFiles('.ci/setup-toolchain.sh') }}
restore-keys: |
${{ runner.os }}-${{ matrix.toolchain }}-toolchain-
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends build-essential qemu-system-riscv32 wget
- name: Setup ${{ matrix.toolchain }} toolchain
if: steps.cache-toolchain.outputs.cache-hit != 'true'
run: .ci/setup-toolchain.sh ${{ matrix.toolchain }}
- name: Configure toolchain environment
if: steps.cache-toolchain.outputs.cache-hit == 'true'
run: |
echo "$PWD/riscv/bin" >> "$GITHUB_PATH"
echo "CROSS_COMPILE=riscv32-unknown-elf-" >> "$GITHUB_ENV"
echo "TOOLCHAIN_TYPE=${{ matrix.toolchain }}" >> "$GITHUB_ENV"
- name: Verify toolchain installation
run: |
if [ "${{ matrix.toolchain }}" = "gnu" ]; then
riscv32-unknown-elf-gcc --version
else
# LLVM toolchain fallback: try system llvm-objdump
riscv32-unknown-elf-clang --version || clang --version
riscv32-unknown-elf-llvm-objdump --version || llvm-objdump --version
fi
qemu-system-riscv32 --version
- name: Build Kernel
run: |
set -euo pipefail
make clean
make -j$(nproc)
env:
TOOLCHAIN_TYPE: ${{ matrix.toolchain }}
- name: Run All Apps
id: test
continue-on-error: true
if: matrix.toolchain == 'gnu'
run: |
set -euo pipefail
output=$(.ci/run-app-tests.sh 2>&1) || true
echo "TEST_OUTPUT<<EOF" >> $GITHUB_OUTPUT
echo "$output" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
env:
TOOLCHAIN_TYPE: ${{ matrix.toolchain }}
- name: Run Functional Tests
id: functional_test
continue-on-error: true
if: matrix.toolchain == 'gnu'
run: |
set -euo pipefail
output=$(.ci/run-functional-tests.sh 2>&1) || true
echo "FUNCTIONAL_TEST_OUTPUT<<EOF" >> $GITHUB_OUTPUT
echo "$output" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
env:
TOOLCHAIN_TYPE: ${{ matrix.toolchain }}
- name: Collect Test Data
if: always()
run: |
set -euo pipefail
COMMIT_SHA="${{ github.sha }}"
COMMIT_SHORT=$(git rev-parse --short HEAD 2>/dev/null || echo "${{ github.sha }}" | cut -c1-7)
GITHUB_REPO="${{ github.repository }}"
if [ "${{ matrix.toolchain }}" = "llvm" ]; then
# LLVM: Build-only validation, skip tests
mkdir -p test-results
echo "${{ matrix.toolchain }}" > test-results/toolchain
echo "$COMMIT_SHA" > test-results/commit_sha
echo "$COMMIT_SHORT" > test-results/commit_short
echo "$GITHUB_REPO" > test-results/github_repo
echo "skipped" > test-results/crash_exit_code
echo "skipped" > test-results/functional_exit_code
# Generate skipped status for all apps
apps=$(find app/ -name "*.c" -exec basename {} .c \; | sort)
for app in $apps; do
echo "$app=skipped" >> test-results/apps_data
done
# Generate skipped status for functional tests
echo "mutex=skipped" > test-results/functional_data
echo "semaphore=skipped" >> test-results/functional_data
# Generate skipped status for functional test criteria
echo "mutex:fairness=skipped" > test-results/functional_criteria_data
echo "mutex:mutual_exclusion=skipped" >> test-results/functional_criteria_data
echo "mutex:data_consistency=skipped" >> test-results/functional_criteria_data
echo "mutex:overall=skipped" >> test-results/functional_criteria_data
echo "semaphore:overall=skipped" >> test-results/functional_criteria_data
echo "LLVM toolchain: Build validation only (tests skipped)"
else
# GNU: Full test suite
.ci/ci-tools.sh collect-data "${{ matrix.toolchain }}" "$COMMIT_SHA" "$COMMIT_SHORT" "$GITHUB_REPO" "${{ steps.test.outputs.TEST_OUTPUT }}" "${{ steps.functional_test.outputs.FUNCTIONAL_TEST_OUTPUT }}"
fi
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.toolchain }}
path: test-results/
retention-days: 3
if-no-files-found: warn
# Comprehensive test summary with detailed reporting
test-summary:
runs-on: ubuntu-24.04
needs: [lint, matrix-tests]
if: always()
timeout-minutes: 15
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Download Test Results
uses: actions/download-artifact@v4
with:
pattern: test-results-*
path: all-test-results/
- name: Generate Test Summary
id: generate_summary
continue-on-error: true
run: |
echo "Aggregating test results..."
.ci/ci-tools.sh aggregate all-test-results test-summary.toml
if [ -f test-summary.toml ]; then
echo "summary_generated=true" >> $GITHUB_OUTPUT
echo "Test Summary:"
cat test-summary.toml
else
echo "summary_generated=false" >> $GITHUB_OUTPUT
echo "⚠️ Warning: test-summary.toml not generated"
fi
- name: Upload Test Summary
if: always() && steps.generate_summary.outputs.summary_generated == 'true'
uses: actions/upload-artifact@v4
with:
name: test-summary
path: test-summary.toml
retention-days: 30
if-no-files-found: error
- name: Comment PR with Formatted Summary
if: always() && github.event_name == 'pull_request' && steps.generate_summary.outputs.summary_generated == 'true'
continue-on-error: true
run: |
echo "Posting summary to PR #${{ github.event.number }}..."
.ci/ci-tools.sh post-comment test-summary.toml ${{ github.event.number }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Final Status Check
run: |
set -euo pipefail
echo "=== Final CI Status Check ==="
if [ ! -f test-summary.toml ]; then
echo "❌ Error: test-summary.toml not found"
echo "CI infrastructure issue - check test aggregation step"
exit 1
fi
overall_status=$(grep -A 1 '^\[summary\]' test-summary.toml | grep 'status =' | cut -d'"' -f2)
echo "Overall test status: $overall_status"
# Extract failure details if available
if [ "$overall_status" != "passed" ]; then
echo ""
echo "=== Failure Details ==="
grep -E '(failed|error|skipped)' test-summary.toml || true
fi
if [ "$overall_status" = "passed" ]; then
echo ""
echo "✅ All tests passed successfully"
exit 0
else
echo ""
echo "❌ Tests failed - see details above"
exit 1
fi