diff --git a/.codechecker.yml b/.codechecker.yml index d00e66ca4f7..62b939df771 100644 --- a/.codechecker.yml +++ b/.codechecker.yml @@ -17,5 +17,16 @@ analyzer: - --disable=clang-diagnostic-reserved-identifier - --disable=clang-diagnostic-reserved-macro-identifier + # userspace includes c files + - --disable=bugprone-suspicious-include + + - --disable=clang-diagnostic-unused-parameter + - --disable=bugprone-narrowing-conversions + + # LOG_ macros + - --disable=alpha.core.SizeofPtr + - --disable=bugprone-sizeof-expression + - --disable=performance-no-int-to-ptr + # Cleanup - --clean diff --git a/.github/codechecker/skipfile b/.github/codechecker/skipfile new file mode 100644 index 00000000000..a861faf04ae --- /dev/null +++ b/.github/codechecker/skipfile @@ -0,0 +1 @@ +-lib/libc/picolibc/* diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 2f3efb49505..8be474050d2 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -16,7 +16,7 @@ jobs: clang-build: if: github.repository_owner == 'zephyrproject-rtos' runs-on: - group: zephyr-runner-v2-linux-x64-4xlarge + group: test-runner-v2-linux-x64-4xlarge container: image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.27.4.20241026 options: '--entrypoint /bin/bash' diff --git a/.github/workflows/codechecker.yml b/.github/workflows/codechecker.yml new file mode 100644 index 00000000000..5d7f71aa960 --- /dev/null +++ b/.github/workflows/codechecker.yml @@ -0,0 +1,122 @@ +name: Codechecker +on: + push: + branches: + - main + - v*-branch + - collab-* +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + Codechecker: + if: github.repository_owner == 'zephyrproject-rtos' + runs-on: + group: zephyr-runner-v2-linux-x64-4xlarge + container: + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.27.4.20241026 + options: '--entrypoint /bin/bash' + env: + CCACHE_DIR: /node-cache/ccache-zephyr + CCACHE_REMOTE_STORAGE: "redis://cache-*.keydb-cache.svc.cluster.local|shards=1,2,3" + CCACHE_REMOTE_ONLY: "true" + CCACHE_IGNOREOPTIONS: '-specs=* --specs=*' + LLVM_TOOLCHAIN_PATH: /usr/lib/llvm-16 + BASE_REF: ${{ github.base_ref }} + permissions: + security-events: write + steps: + - name: Apply container owner mismatch workaround + run: | + # FIXME: The owner UID of the GITHUB_WORKSPACE directory may not + # match the container user UID because of the way GitHub + # Actions runner is implemented. Remove this workaround when + # GitHub comes up with a fundamental fix for this problem. + git config --global --add safe.directory ${GITHUB_WORKSPACE} + + - name: Print cloud service information + run: | + echo "ZEPHYR_RUNNER_CLOUD_PROVIDER = ${ZEPHYR_RUNNER_CLOUD_PROVIDER}" + echo "ZEPHYR_RUNNER_CLOUD_NODE = ${ZEPHYR_RUNNER_CLOUD_NODE}" + echo "ZEPHYR_RUNNER_CLOUD_POD = ${ZEPHYR_RUNNER_CLOUD_POD}" + + - name: Clone cached Zephyr repository + continue-on-error: true + run: | + git clone --shared /repo-cache/zephyrproject/zephyr . + git remote set-url origin ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} + + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Environment Setup + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + git config --global user.email "bot@zephyrproject.org" + git config --global user.name "Zephyr Bot" + rm -fr ".git/rebase-apply" + rm -fr ".git/rebase-merge" + git clean -f -d + git log --pretty=oneline | head -n 10 + west init -l . || true + west config --global update.narrow true + west config manifest.group-filter -- +ci,-optional + # In some cases modules are left in a state where they can't be + # updated (i.e. when we cancel a job and the builder is killed), + # So first retry to update, if that does not work, remove all modules + # and start over. (Workaround until we implement more robust module + # west caching). + west update --path-cache /repo-cache/zephyrproject 2>&1 1> west.log || west update --path-cache /repo-cache/zephyrproject 2>&1 1> west2.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /repo-cache/zephyrproject) + + echo "ZEPHYR_SDK_INSTALL_DIR=/opt/toolchains/zephyr-sdk-$( cat SDK_VERSION )" >> $GITHUB_ENV + + - name: Check Environment + run: | + cmake --version + ${LLVM_TOOLCHAIN_PATH}/bin/clang --version + gcc --version + ls -la + + - name: Run Tests with Twister + id: twister + run: | + export ZEPHYR_BASE=${PWD} + export ZEPHYR_TOOLCHAIN_VARIANT=zephyr + export ZEPHYR_SCA_VARIANT=codechecker + export CODECHECKER_CONFIG_FILE=$ZEPHYR_BASE/.codechecker.yml + export CODECHECKER_CLEANUP=y + export CODECHECKER_EXPORT=sarif + export CODECHECKER_SKIP_FILE=$ZEPHYR_BASE/.github/codechecker/skipfile + + pip install codechecker==v6.25.1 cppcheck sarif-tools jq + sudo apt-get update + sudo apt-get install -y jq + export PATH=/usr/lib/llvm-16/bin/:$PATH + + ./scripts/twister -i --force-color -N -v --build-only --timeout-multiplier 2 -p qemu_x86 -T tests/kernel/threads -T tests/lib/heap + + #sarif copy --output results.sarif $(find twister-out -name "codechecker.sarif") + jq -s '{ "$schema": "https://json.schemastore.org/sarif-2.1.0", "version": "2.1.0", "runs": map(.runs) | add }' $(find twister-out -name "codechecker.sarif") > results.sarif + + - name: Upload SARIF as artifact + if: always() + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + with: + name: sarif + if-no-files-found: ignore + path: | + build/sca/codechecker/codechecker.sarif + results.sarif + + - name: Upload Analysis Results + if: always() + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9374cbf787e..ea250b4eed6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,9 +2,18 @@ name: "CodeQL" on: push: - branches: ["main"] + branches: + - main + - v*-branch + - collab-* schedule: - cron: '34 16 * * 3' + pull_request: + branches: + - main + - v*-branch + - collab-* + permissions: contents: read jobs: diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 559e315d587..5b02bf46a23 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -1,18 +1,23 @@ name: Compliance Checks on: - pull_request: - types: - - edited - - opened - - reopened - - synchronize + workflow_call: permissions: contents: read jobs: + check_compliance_push: + if: github.event_name == 'push' + runs-on: ubuntu-22.04 + name: Run compliance checks on patch series (PR) + steps: + - name: Do nothing + run: | + echo "Doing nothing" + check_compliance: + if: github.event_name == 'pull_request' runs-on: ubuntu-22.04 name: Run compliance checks on patch series (PR) steps: @@ -65,14 +70,6 @@ jobs: west config manifest.group-filter -- +ci,-optional west update -o=--depth=1 -n 2>&1 1> west.update.log || west update -o=--depth=1 -n 2>&1 1> west.update2.log - - name: Check for PR description - if: ${{ github.event.pull_request.body == '' }} - continue-on-error: true - id: pr_description - run: | - echo "Pull request description cannot be empty." - exit 1 - - name: Run Compliance Tests continue-on-error: true id: compliance @@ -96,6 +93,8 @@ jobs: path: compliance.xml - name: check-warns + id: check-warns + continue-on-error: true run: | if [[ ! -s "compliance.xml" ]]; then exit 1; @@ -124,10 +123,12 @@ jobs: if [ "${exit}" == "1" ]; then echo "Compliance error, check for error messages in the \"Run Compliance Tests\" step" echo "You can run this step locally with the ./scripts/ci/check_compliance.py script." + echo "exit_code=${exit}" >> $GITHUB_OUTPUT exit 1; fi - - if [ "${{ steps.pr_description.outcome }}" == "failure" ]; then - echo "PR description cannot be empty" - exit 1; - fi + - name: resolve + if: | + steps.check-warns.outputs.exit_code != 0 && + ! contains(github.event.pull_request.labels.*.name, 'Compliance: False Positive') + run: | + exit ${{ steps.check-warns.outputs.exit_code }} diff --git a/.github/workflows/compliance_compat.yml b/.github/workflows/compliance_compat.yml new file mode 100644 index 00000000000..86c73f02ddf --- /dev/null +++ b/.github/workflows/compliance_compat.yml @@ -0,0 +1,19 @@ +name: Compliance Checks (Compatibility mode) + +on: + pull_request: + types: + - edited + - opened + - reopened + - synchronize + +jobs: + check_compliance: + runs-on: ubuntu-22.04 + name: Run compliance checks on patch series (PR) + steps: + - name: do nothing + run: | + echo "do nothing" + exit 0 diff --git a/.github/workflows/do_not_merge.yml b/.github/workflows/pr_metadata_check.yml similarity index 64% rename from .github/workflows/do_not_merge.yml rename to .github/workflows/pr_metadata_check.yml index 39275a03f11..2c450efc7d6 100644 --- a/.github/workflows/do_not_merge.yml +++ b/.github/workflows/pr_metadata_check.yml @@ -1,8 +1,14 @@ -name: Do Not Merge +name: PR Metadata Check on: pull_request: - types: [synchronize, opened, reopened, labeled, unlabeled] + types: + - synchronize + - opened + - reopened + - labeled + - unlabeled + - edited permissions: contents: read @@ -22,3 +28,13 @@ jobs: echo "Pull request is labeled as 'DNM', 'TSC', 'Architecture Review' or 'dev-review'." echo "This workflow fails so that the pull request cannot be merged." exit 1 + + empty_pr_description: + if: ${{ github.event.pull_request.body == '' }} + name: PR Description + runs-on: ubuntu-22.04 + steps: + - name: Check for PR description + run: | + echo "Pull request description cannot be empty." + exit 1 diff --git a/.github/workflows/twister-prep.yaml b/.github/workflows/twister-prep.yaml index 5ea135ddde4..c630ed7e063 100644 --- a/.github/workflows/twister-prep.yaml +++ b/.github/workflows/twister-prep.yaml @@ -18,9 +18,9 @@ permissions: jobs: prep_pr: - if: github.repository_owner == 'zephyrproject-rtos' && github.event_name == 'pull_request_target' + if: github.repository_owner == 'zephyrproject-rtos' && github.event_name == 'pull_request' runs-on: - group: zephyr-runner-v2-linux-x64-4xlarge + group: test-runner-v2-linux-x64-4xlarge container: image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.27.4.20241026 options: '--entrypoint /bin/bash' diff --git a/.github/workflows/twister-publish.yaml b/.github/workflows/twister-publish.yaml index 63433d7569b..a46df8a977b 100644 --- a/.github/workflows/twister-publish.yaml +++ b/.github/workflows/twister-publish.yaml @@ -15,7 +15,7 @@ jobs: upload-to-elasticsearch: if: | github.repository == 'zephyrproject-rtos/zephyr' && - github.event.workflow_run.event != 'pull_request_target' + github.event.workflow_run.event != 'pull_request' env: ELASTICSEARCH_KEY: ${{ secrets.ELASTICSEARCH_KEY }} ELASTICSEARCH_SERVER: "https://elasticsearch.zephyrproject.io:443" diff --git a/.github/workflows/twister.yaml b/.github/workflows/twister.yaml index 04f687888b2..331754023a6 100644 --- a/.github/workflows/twister.yaml +++ b/.github/workflows/twister.yaml @@ -6,7 +6,7 @@ on: - main - v*-branch - collab-* - pull_request_target: + pull_request: branches: - main - v*-branch @@ -23,12 +23,16 @@ concurrency: cancel-in-progress: true jobs: + compliance-check: + uses: ./.github/workflows/compliance.yml + twister-build-prep: + needs: compliance-check uses: ./.github/workflows/twister-prep.yaml twister-build: runs-on: - group: zephyr-runner-v2-linux-x64-4xlarge + group: test-runner-v2-linux-x64-4xlarge needs: twister-build-prep if: needs.twister-build-prep.outputs.size != 0 container: @@ -84,7 +88,7 @@ jobs: - name: Environment Setup run: | - if [ "${{github.event_name}}" = "pull_request_target" ]; then + if [ "${{github.event_name}}" = "pull_request" ]; then git config --global user.email "bot@zephyrproject.org" git config --global user.name "Zephyr Builder" rm -fr ".git/rebase-apply" @@ -146,7 +150,7 @@ jobs: fi fi - - if: github.event_name == 'pull_request_target' + - if: github.event_name == 'pull_request' name: Run Tests with Twister (Pull Request) id: run_twister_pr run: | @@ -219,7 +223,7 @@ jobs: permissions: checks: write # to create the check run entry with Twister test results # the build-and-test job might be skipped, we don't need to run this job then - if: success() || failure() + if: (success() || failure()) && needs.twister-build.result != 'skipped' steps: - name: Check out source code @@ -236,6 +240,7 @@ jobs: path: artifacts - name: Merge Test Results + if: needs.twister-build.result != 'skipped' run: | pip install junitparser junit2html junitparser merge artifacts/*/*/twister.xml junit.xml @@ -280,6 +285,7 @@ jobs: if: always() name: "Check Twister Status" needs: + - compliance-check - twister-build-prep - twister-build uses: ./.github/workflows/ready-to-merge.yml diff --git a/cmake/sca/codechecker/sca.cmake b/cmake/sca/codechecker/sca.cmake index 7c69c836d6d..09fe20dcde9 100644 --- a/cmake/sca/codechecker/sca.cmake +++ b/cmake/sca/codechecker/sca.cmake @@ -15,6 +15,7 @@ zephyr_get(CODECHECKER_ANALYZE_JOBS) zephyr_get(CODECHECKER_ANALYZE_OPTS) zephyr_get(CODECHECKER_CLEANUP) zephyr_get(CODECHECKER_CONFIG_FILE) +zephyr_get(CODECHECKER_SKIP_FILE) zephyr_get(CODECHECKER_EXPORT) zephyr_get(CODECHECKER_NAME) zephyr_get(CODECHECKER_PARSE_EXIT_STATUS) @@ -47,6 +48,10 @@ if(CODECHECKER_CONFIG_FILE) set(CODECHECKER_CONFIG_FILE "--config;${CODECHECKER_CONFIG_FILE}") endif() +if(CODECHECKER_SKIP_FILE) + set(CODECHECKER_SKIP_FILE "--skip;${CODECHECKER_SKIP_FILE}") +endif() + if(CODECHECKER_STORE_TAG) set(CODECHECKER_STORE_TAG "--tag;${CODECHECKER_STORE_TAG}") else() diff --git a/test.py b/test.py new file mode 100755 index 00000000000..52ae2b47b47 --- /dev/null +++ b/test.py @@ -0,0 +1,107 @@ +# Copyright (c) 2023, Bjarki Arge Andreasen +# SPDX-License-Identifier: Apache-2.0 + +import socket +import threading +import select +import time +import copy + +class TEUDPReceiveSession(): + def __init__(self, address, timeout = 1): + self.address = address + self.last_packet_received_at = time.monotonic() + self.timeout = timeout + self.packets_received = 0 + self.packets_dropped = 0 + + def get_address(self): + return self.address + + def on_packet_received(self, data): + if self._validate_packet_(data): + self.packets_received += 1 + else: + self.packets_dropped += 1 + + self.last_packet_received_at = time.monotonic() + + def update(self): + if (time.monotonic() - self.last_packet_received_at) > self.timeout: + return (self.packets_received, self.packets_dropped) + return None + + def _validate_packet_(self, data: bytes) -> bool: + prng_state = 1234 + for b in data: + prng_state = ((1103515245 * prng_state) + 12345) % (1 << 31) + if prng_state & 0xFF != b: + return False + return True + +class TEUDPReceive(): + def __init__(self): + self.running = True + self.thread = threading.Thread(target=self._target_) + self.sessions = [] + + def start(self): + self.thread.start() + + def stop(self): + self.running = False + self.thread.join(1) + + def _target_(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setblocking(False) + sock.bind(('0.0.0.0', 7781)) + + while self.running: + try: + ready_to_read, _, _ = select.select([sock], [sock], [], 0.5) + + if not ready_to_read: + self._update_sessions_(sock) + continue + + data, address = sock.recvfrom(4096) + + print(f'udp received {len(data)} bytes -> {address[0]}:{address[1]}') + + session = self._get_session_by_address_(address) + session.on_packet_received(data) + + except Exception as e: + print(e) + break + + sock.close() + + def _get_session_by_address_(self, address) -> TEUDPReceiveSession: + # Search for existing session + for session in self.sessions: + if session.get_address() == address: + return session + + # Create and return new session + print(f'Created session for {address[0]}:{address[1]}') + self.sessions.append(TEUDPReceiveSession(address, 2)) + return self.sessions[-1] + + def _update_sessions_(self, sock): + sessions = copy.copy(self.sessions) + + for session in sessions: + result = session.update() + + if result is None: + continue + + response = bytes([result[0], result[1]]) + + print(f'Sending result {response} to address {session.get_address()}') + sock.sendto(response, session.get_address()) + + print(f'Removing session for address {session.get_address()}') + self.sessions.remove(session) diff --git a/west.yml b/west.yml index b1ecbb2b408..f79f48eaeff 100644 --- a/west.yml +++ b/west.yml @@ -320,6 +320,8 @@ manifest: - name: nrf_hw_models revision: b84bd7314a239f818e78f6927f5673247816df53 path: modules/bsim_hw_models/nrf_hw_models + groups: + - hal - name: nrf_wifi revision: 662ed74dce955e6c243f91c45a66768f5971e3cb path: modules/lib/nrf_wifi