diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..0b53fd1 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,50 @@ +name: tests +on: [push, pull_request] + +env: + RUN: docker run --rm body /bin/bash -c + PERSIST: docker run --name body body /bin/sh -c + BUILD: | + docker pull $(grep -ioP '(?<=^from)\s+\S+' Dockerfile) || true + docker pull ghcr.io/commaai/body:latest || true + docker build --cache-from ghcr.io/commaai/body:latest -t body -f Dockerfile . + +jobs: + docker_push: + name: docker push + runs-on: ubuntu-20.04 + timeout-minutes: 20 + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/body' + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Login to dockerhub + run: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} + - name: Tag image + run: docker tag body ghcr.io/commaai/body:latest + - name: Push image + run: docker push ghcr.io/commaai/body:latest + + build: + name: build + runs-on: ubuntu-20.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Build firmware + run: $RUN "cd /tmp/openpilot/body && scons" + + python_linter: + name: python linter + runs-on: ubuntu-20.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Run static analysis + run: | + $RUN "cd /tmp/openpilot/body && git init && git add -A && pre-commit run --all" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..11c4b28 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-ast + - id: check-yaml + - id: check-merge-conflict + - id: check-symlinks +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.971 + hooks: + - id: mypy + additional_dependencies: ['git+https://github.com/numpy/numpy-stubs', 'types-requests', 'types-atomicwrites', + 'types-pycurl'] +- repo: https://github.com/PyCQA/flake8 + rev: 5.0.4 + hooks: + - id: flake8 + args: + - --select=F,E112,E113,E304,E501,E502,E701,E702,E703,E71,E72,E731,W191,W6 + - --max-line-length=160 + - --statistics +- repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + args: + - --disable=C,R,W0613,W0511,W0212,W0201,W0311,W0106,W0603,W0621,W0703,E1136 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b86ebfc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +FROM ubuntu:20.04 +ENV PYTHONUNBUFFERED 1 +ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + ca-certificates \ + clang \ + curl \ + g++ \ + gcc-arm-none-eabi libnewlib-arm-none-eabi \ + git \ + libtool \ + libssl-dev \ + libsqlite3-dev \ + locales \ + make \ + patch \ + pkg-config \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" + +COPY requirements.txt /tmp/ +RUN pyenv install 3.8.10 && \ + pyenv global 3.8.10 && \ + pyenv rehash && \ + pip install --no-cache-dir -r /tmp/requirements.txt + +COPY . /tmp/openpilot/body +RUN rm -rf /tmp/openpilot/body/.git diff --git a/board/canloader.py b/board/canloader.py index 661cd3f..b9ea11a 100755 --- a/board/canloader.py +++ b/board/canloader.py @@ -2,8 +2,8 @@ import time import argparse import _thread -from panda import Panda, MCU_TYPE_F4 -from panda.tests.pedal.canhandle import CanHandle +from panda import Panda, MCU_TYPE_F4 # pylint: disable=import-error +from panda.tests.pedal.canhandle import CanHandle # pylint: disable=import-error def heartbeat_thread(p): diff --git a/crypto/sign.py b/crypto/sign.py index e199a6b..fe188e5 100755 --- a/crypto/sign.py +++ b/crypto/sign.py @@ -9,28 +9,30 @@ # increment this to make new hardware not run old versions VERSION = 2 -rsa = RSA.importKey(open(sys.argv[3]).read()) +if __name__ == "__main__": + with open(sys.argv[3], encoding='utf8') as k: + rsa = RSA.importKey(k.read()) -with open(sys.argv[1], "rb") as f: - dat = f.read() + with open(sys.argv[1], "rb") as f: + dat = f.read() -print("signing", len(dat), "bytes") + print("signing", len(dat), "bytes") -with open(sys.argv[2], "wb") as f: - if os.getenv("SETLEN") is not None: - # add the version at the end - dat += b"VERS" + struct.pack("I", VERSION) - # add the length at the beginning - x = struct.pack("I", len(dat)) + dat[4:] - # mock signature of dat[4:] - dd = hashlib.sha1(dat[4:]).digest() - else: - x = dat - dd = hashlib.sha1(dat).digest() + with open(sys.argv[2], "wb") as f: + if os.getenv("SETLEN") is not None: + # add the version at the end + dat += b"VERS" + struct.pack("I", VERSION) + # add the length at the beginning + x = struct.pack("I", len(dat)) + dat[4:] + # mock signature of dat[4:] + dd = hashlib.sha1(dat[4:]).digest() + else: + x = dat + dd = hashlib.sha1(dat).digest() - print("hash:", str(binascii.hexlify(dd), "utf-8")) - dd = b"\x00\x01" + b"\xff" * 0x69 + b"\x00" + dd - rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa.d, rsa.n) - sig = (hex(rsa_out)[2:].rjust(0x100, '0')) - x += binascii.unhexlify(sig) - f.write(x) + print("hash:", str(binascii.hexlify(dd), "utf-8")) + dd = b"\x00\x01" + b"\xff" * 0x69 + b"\x00" + dd + rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa.d, rsa.n) + sig = (hex(rsa_out)[2:].rjust(0x100, '0')) + x += binascii.unhexlify(sig) + f.write(x) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1a57441 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +cffi +scons +pylint +pre-commit +pycryptodome==3.9.8