diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml new file mode 100644 index 000000000..9f9cc8403 --- /dev/null +++ b/.github/workflows/add-to-project.yml @@ -0,0 +1,14 @@ +name: Add Issue or PR to Project + +on: + issues: + types: [opened] + # For testing purposes changed pull_request_target to pull_request + pull_request: + types: [opened, ready_for_review, converted_to_draft] + +jobs: + add-to-project: + name: Add issue or pull request to project + uses: arielswalker/cFS/.github/workflows/add-to-project-reusable.yml@test-cfs/workflows122 + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/code-coverage-eds.yml b/.github/workflows/code-coverage-eds.yml new file mode 100644 index 000000000..e7644c8de --- /dev/null +++ b/.github/workflows/code-coverage-eds.yml @@ -0,0 +1,52 @@ +name: "Code Coverage Analysis, EDS enabled" + +on: + push: + branches: + - dev + - main + pull_request: + types: + - opened + - reopened + - synchronize + workflow_dispatch: + schedule: + # 11:00 PM UTC every Sunday + - cron: '0 23 * * 0' + +env: + SIMULATION: native + ENABLE_UNIT_TESTS: true + OMIT_DEPRECATED: false + CFE_EDS_ENABLED: true + BUILDTYPE: debug + +jobs: + + Execute-Unit-Tests: + name: Build and Execute CFE unit tests + runs-on: ubuntu-22.04 + container: ghcr.io/core-flight-system/cfsbuildenv-linux:latest + timeout-minutes: 15 + + steps: + - name: Checkout CFE + uses: actions/checkout@v4 + with: + path: cfe + + - name: Set up Dependencies + uses: ./cfe/.github/actions/setup-cfe + with: + source-dir: . + preferred-ref: ${{ github.head_ref }} + org: nasa + + - name: Execute coverage testing + uses: ./cfe/.github/actions/code-coverage + with: + module-list: config core_api core_private es evs fs resourceid sb sbr tbl time + allowed-missed-branches: 22 + allowed-missed-lines: 14 + allowed-missed-functions: 0 \ No newline at end of file diff --git a/.github/workflows/functional-test-eds.yml b/.github/workflows/functional-test-eds.yml new file mode 100644 index 000000000..1f3298c67 --- /dev/null +++ b/.github/workflows/functional-test-eds.yml @@ -0,0 +1,189 @@ +name: "Internal Functional Test, EDS enabled" + +on: + push: + branches: + - dev + - main + pull_request: + types: + - opened + - reopened + - synchronize + workflow_dispatch: + schedule: + # 11:45 PM UTC every Sunday + - cron: '45 23 * * 0' + +env: + SIMULATION: native + ENABLE_UNIT_TESTS: false + OMIT_DEPRECATED: true + CFE_EDS_ENABLED: true + BUILDTYPE: debug + # jphfix should be release + +jobs: + + Local-Test-Build: + name: Build CFE + runs-on: ubuntu-22.04 + container: ghcr.io/core-flight-system/cfsbuildenv-linux:latest + timeout-minutes: 15 + + steps: + - name: Checkout CFE + uses: actions/checkout@v4 + with: + path: cfe + + - name: Set up Dependencies + uses: ./cfe/.github/actions/setup-cfe + with: + source-dir: . + preferred-ref: ${{ github.head_ref }} + org: nasa + + # Setup the build system + - name: Set up for build + run: make prep + + - name: Build CFE + run: make install + + - name: Generate Startup Link + run: ln -s core-cpu1 ./build/exe/cpu1/container-start + + - name: List cpu1 + run: ls build/exe/cpu1/ + + - name: Archive binaries + run: | + cd $GITHUB_WORKSPACE/build/exe + find -maxdepth 1 -mindepth 1 -type d | while read dir + do + inst=$(basename ${dir}) + tar Jcv -f $GITHUB_WORKSPACE/${inst}-bin.tar.xz -C ${inst} . + done + + - name: Upload all artifacts + uses: actions/upload-artifact@v4 + with: + name: functional-test-eds-bin + path: ./*.tar.xz + + Execute-Test: + name: Execute Functional Test + permissions: + contents: read + actions: read + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_HOST: developer.nasa.gov + GH_REPO: cFS/cFE + runs-on: ubuntu-22.04 + needs: Local-Test-Build + timeout-minutes: 15 + + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: functional-test-eds-bin + path: functional-test-eds-bin + + - name: Unpack artifacts + run: | + for i in cpu1 host + do + mkdir -p "$i" + tar Jxv -C "$i" -f "$GITHUB_WORKSPACE/functional-test-eds-bin/$i-bin.tar.xz" + done + + - name: List Files + run: ls -lR . + + - name: Start CPU1 container + id: start-cpu1 + uses: nasa/cFS/actions/start-cfs-container@dev + with: + binary-dir: ${{ github.workspace }}/cpu1 + exec-image: ghcr.io/core-flight-system/cfsbuildenv-linux:latest + + - name: Check CPU1 container + id: check-cpu1 + uses: nasa/cFS/actions/healthcheck-logs@dev + with: + container-id: ${{ steps.start-cpu1.outputs.container-id }} + healthcheck-regex: 'CFE_ES_Main entering OPERATIONAL state$' + + - name: Execute No-Op Check + working-directory: ./host + run: | + ./cmd_send -v --host=${{ steps.check-cpu1.outputs.ip-addr }} --endian=EDS --pktid=CFE_ES/Application/CMD --cmdcode=NoopCmd + sleep 2 + docker logs "${{ steps.start-cpu1.outputs.container-id }}" | grep -A 2 'CFE_ES 3: No-op command' + + - name: Launch Functional Test + working-directory: ./host + run: | + ./cmd_send -v --host=${{ steps.check-cpu1.outputs.ip-addr }} --endian=EDS --pktid=CFE_ES/Application/CMD --cmdcode=StartAppCmd Application="CFE_TEST" AppEntryPoint="CFE_TestMain" AppFileName="cfe_testcase" StackSize=16384 Priority=100 + sleep 10 + docker logs "${{ steps.start-cpu1.outputs.container-id }}" + + - name: Wait for Functional Test + working-directory: ./cpu1 + run: | + counter=0 + stuck=0 + + while [ ! -f cf/cfe_test.log ] + do + temp=$(grep -c "BEGIN" cf/cfe_test.tmp) + if [ $temp -eq $counter ] + then + stuck=$(($stuck + 1)) + else + stuck=0 + fi + + if [ $stuck -ge 3 ] + then + echo "Test is frozen. Quitting" + break + fi + + counter=$(grep -c "BEGIN" cf/cfe_test.tmp) + echo "Waiting for CFE Tests" + sleep 30 + done + + - name: Shut down CFE + if: ${{ always() && steps.check-cpu1.outputs.ip-addr != '' }} + working-directory: ./host + run: | + ./cmd_send -v --host=${{ steps.check-cpu1.outputs.ip-addr }} --endian=EDS --pktid=CFE_ES/Application/CMD --cmdcode=RestartCmd RestartType=2 + sleep 1 + + - name: Stop CPU1 Container + if: ${{ always() && steps.start-cpu1.outputs.container-id != '' }} + uses: nasa/cFS/actions/stop-cfs-container@dev + with: + container-id: ${{ steps.start-cpu1.outputs.container-id }} + + - name: Archive cFS Startup Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: cFS-startup-log-deprecate-true-release + path: cpu1/cf/cfe_test.log + + - name: Check for cFS Warnings + run: | + if [[ -z $(grep -i "SUMMARY.*FAIL::0.*TSF::0.*TTF::0" cf/cfe_test.log) ]]; then + echo "Must resolve Test Failures in cFS Test App before submitting a pull request" + echo "" + grep -i '\[ FAIL]\|\[ TSF]\|\[ TTF]' cf/cfe_test.log + exit -1 + fi + working-directory: ./cpu1/ \ No newline at end of file diff --git a/.github/workflows/mcdc.yml b/.github/workflows/mcdc.yml new file mode 100644 index 000000000..a8b601fe5 --- /dev/null +++ b/.github/workflows/mcdc.yml @@ -0,0 +1,209 @@ +name: MCDC Analysis + +on: + push: + branches: + - dev + - main + pull_request: + types: + - opened + - reopened + - synchronize + workflow_dispatch: + +# Force bash to apply pipefail option so pipeline failures aren't masked +defaults: + run: + shell: bash + +env: + SIMULATION: native + ENABLE_UNIT_TESTS: true + OMIT_DEPRECATED: false + BUILDTYPE: debug + TESTS_RAN: false + +jobs: + mcdc: + name: Build and Run MCDC + runs-on: ubuntu-22.04 + container: ghcr.io/core-flight-system/mcdc:latest + + steps: + - name: Checkout CFE + uses: actions/checkout@v4 + with: + path: cfe + + - name: Set up Dependencies + uses: ./cfe/.github/actions/setup-cfe + with: + source-dir: . + preferred-ref: ${{ github.head_ref }} + org: nasa + + - name: Checkout MCDC Script + uses: actions/checkout@v4 + with: + repository: arielswalker/cFS + path: mcdc + ref: test-cfs/workflows122 + + - name: Modify osal to include coverage flags + run: | + mkdir -p sample_defs/cpu1 + echo "target_compile_options(ut_coverage_compile INTERFACE -fcondition-coverage -fprofile-abs-path)" >> sample_defs/cpu1/install_custom.cmake + + # Setup the build system + - name: Set up for build + run: make prep + + - name: Build CFE + run: make install + + - name: Build + run: | + make -C build/native/default_cpu1/config + make -C build/native/default_cpu1/core_api + make -C build/native/default_cpu1/core_private + make -C build/native/default_cpu1/es + make -C build/native/default_cpu1/evs + make -C build/native/default_cpu1/fs + make -C build/native/default_cpu1/msg + make -C build/native/default_cpu1/resourceid + make -C build/native/default_cpu1/sb + make -C build/native/default_cpu1/sbr + make -C build/native/default_cpu1/tbl + make -C build/native/default_cpu1/time + + - name: Test + run: | + (cd build/native/default_cpu1/config && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/core_api && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/core_private && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/es && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/evs && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/fs && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/msg && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/resourceid && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/sb && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/sbr && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/tbl && ctest --output-on-failure || true) | tee -a test_results.txt + (cd build/native/default_cpu1/time && ctest --output-on-failure || true) | tee -a test_results.txt + echo "TESTS_RAN=true" >> $GITHUB_ENV + + - name: Grab test modules + if: ${{ env.TESTS_RAN == 'true' }} + run: | + echo "MODULES=$(grep -oP 'Test\s+#\d+: \K[\w\-\_]+(?= )' test_results.txt | tr '\n' ' ' | sed 's/ $//')" >> $GITHUB_ENV + grep -oP 'Test #\d+: \K[\w\-\_]+' test_results.txt | tr '\n' ' ' | sed 's/ $//' >> modules.txt + + - name: Run mcdc analysis + if: ${{ env.TESTS_RAN == 'true' }} + run: bash mcdc/.github/scripts/mcdc-analyze.sh + + - name: Save PR number + if: github.event_name == 'pull_request' && always() + env: + PR_NUMBER: ${{ github.event.number }} + run: echo $PR_NUMBER > pr_number + + - name: Archive unit test results + # Upload if success or failure which supports skipping, unlike always() + if: ${{ env.TESTS_RAN == 'true' }} + uses: actions/upload-artifact@v4 + with: + name: Unit test results + path: | + test_results.txt + + - name: Archive mcdc results + # Upload if success or failure which supports skipping, unlike always() + if: ${{ env.TESTS_RAN == 'true' }} + uses: actions/upload-artifact@v4 + with: + name: MCDC results + path: | + **/*.gcov.json.gz + mcdc_results.txt + pr_number + modules.txt + + summary-mcdc: + needs: mcdc + if: github.event_name == 'pull_request' + name: Generate MCDC Comparison Summary + runs-on: ubuntu-22.04 + + steps: + - name: Checkout MCDC Script + uses: actions/checkout@v4 + with: + repository: arielswalker/cFS + path: mcdc + ref: test-cfs/workflows122 + + - name: Download latest main branch artifact + continue-on-error: true + uses: dawidd6/action-download-artifact@v2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + workflow: mcdc-internal.yml + search_artifacts: true + branch: dev + name: MCDC results + path: ./main-branch-results + + - uses: actions/download-artifact@v4 + with: + name: MCDC results + + - name: Compare main and PR artifacts + run: | + if [ -f "main-branch-results/mcdc_results.txt" ]; then + echo "Main branch artifact found. Running comparison." + bash mcdc/.github/scripts/mcdc-compare.sh main-branch-results/mcdc_results.txt mcdc_results.txt main-branch-results/modules.txt + else + echo "Main branch artifact not found. Skipping comparison step." + fi + + - name: Output summary to workflow + run: | + if [ -s "mcdc_comment.txt" ]; then + echo "### MC/DC Results (Comparison with dev branch)" >> $GITHUB_STEP_SUMMARY + echo '```plaintext' >> $GITHUB_STEP_SUMMARY + cat mcdc_comment.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + elif [ -s "mcdc_results.txt" ]; then + echo "### MC/DC Results (Current PR)" >> $GITHUB_STEP_SUMMARY + echo '```plaintext' >> $GITHUB_STEP_SUMMARY + cat mcdc_results.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + else + echo "No MCDC results found." >> $GITHUB_STEP_SUMMARY + fi + + # Output uncovered branches if the file exists and is not empty + if [ -s "uncovered.json" ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "Click to view uncovered branches (uncovered.json)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo '```json' >> $GITHUB_STEP_SUMMARY + cat uncovered.json >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "
" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + fi + + - name: Archive mcdc comparison + # Upload if success or failure which supports skipping, unlike always() + if: success() || failure() + uses: actions/upload-artifact@v4 + with: + name: MCDC main branch comparison + path: | + mcdc_comment.txt + mcdc_compare.txt \ No newline at end of file