diff --git a/.dockerignore b/.dockerignore index 0ddbf08..14d189a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ -node_modules -target -ui-dist +/server/target +/ui/dist +/ui/node_modules +/ui/yarn-error.log diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1e24ad..dc240f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - target + server/target key: ${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Install dependencies run: sudo apt-get update && sudo apt-get install libavcodec-dev libavformat-dev libavutil-dev libncurses-dev libsqlite3-dev pkgconf @@ -38,7 +38,7 @@ jobs: toolchain: ${{ matrix.rust }} override: true - name: Test - run: cargo test ${{ matrix.extra_args }} --all + run: cd server && cargo test ${{ matrix.extra_args }} --all js: name: Build and lint Javascript frontend runs-on: ubuntu-20.04 @@ -57,6 +57,6 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - - run: yarn install - - run: yarn build - - run: yarn lint + - run: cd ui && yarn install + - run: cd ui && yarn build + - run: cd ui && yarn lint diff --git a/.gitignore b/.gitignore index cbc053a..a965172 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ .DS_Store *.swp -*.sublime-workspace -node_modules -prep.config -db/schema.rs -target -ui-dist -yarn-error.log +/server/target +/ui/dist +/ui/node_modules +/ui/yarn-error.log diff --git a/docker/Dockerfile b/docker/Dockerfile index f085924..0e4154b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,39 +3,51 @@ # See documentation here: # https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md -# Moonfire NVR development environment, using the build platform. -FROM --platform=$BUILDPLATFORM ubuntu:20.04 AS dev +# "dev-common" is the portion of "dev" (see below) which isn't specific to the +# target arch. It's sufficient for building the non-arch-specific webpack. +FROM --platform=$BUILDPLATFORM ubuntu:20.04 AS dev-common LABEL maintainer="slamb@slamb.org" -ARG TARGETARCH -ARG BUILDARCH ARG BUILD_UID=1000 ARG BUILD_GID=1000 -LABEL maintainer="slamb@slamb.org" ENV LC_ALL=C.UTF-8 +COPY docker/dev-common.bash / +RUN /dev-common.bash +CMD [ "/bin/bash", "--login" ] + +# "dev" is a full development environment, suitable for shelling into or +# using with the VS Code container plugin. +FROM --platform=$BUILDPLATFORM dev-common AS dev +ARG BUILDARCH +ARG TARGETARCH +LABEL maintainer="slamb@slamb.org" COPY docker/dev.bash / RUN /dev.bash USER moonfire-nvr:moonfire-nvr WORKDIR /var/lib/moonfire-nvr -CMD [ "/bin/bash", "--login" ] -# Build the webpack with node_modules and ui-dist outside the src dir. -FROM dev AS build-webpack +# Build the UI with node_modules and ui-dist outside the src dir. +FROM --platform=$BUILDPLATFORM dev-common AS build-ui LABEL maintainer="slamb@slamb.org" -RUN --mount=type=bind,target=/var/lib/moonfire-nvr/src,readonly \ - ln -s src/package.json src/yarn.lock src/ui-src src/webpack . && \ - yarn install && yarn build && rm -rf node_modules +WORKDIR /var/lib/moonfire-nvr/src/ui +COPY ui /var/lib/moonfire-nvr/src/ui +RUN --mount=type=cache,target=/var/lib/moonfire-nvr/src/ui/node_modules,sharing=locked,mode=1777 \ + yarn install && yarn build # Build the Rust components. Note that dev.sh set up an environment variable # in .buildrc that similarly changes the target dir path. -FROM dev AS build-server +FROM --platform=$BUILDPLATFORM dev AS build-server LABEL maintainer="slamb@slamb.org" -RUN --mount=type=bind,target=/var/lib/moonfire-nvr/src,readonly \ - bash -c 'set -o xtrace && source ~/.buildrc && cd src && cargo test && cargo build --release' +RUN --mount=type=cache,id=target,target=/var/lib/moonfire-nvr/target,sharing=locked,mode=1777 \ + --mount=type=bind,source=server,target=/var/lib/moonfire-nvr/src/server,readonly \ + bash -c 'set -o xtrace && \ + source ~/.buildrc && \ + cd src/server && \ + cargo test && \ + cargo build --release && \ + sudo install -m 755 ~/moonfire-nvr /usr/local/bin/moonfire-nvr' # Deployment environment, now in the target platform. FROM --platform=$TARGETPLATFORM ubuntu:20.04 AS deploy -ARG DEPLOY_UID=10000 -ARG DEPLOY_GID=10000 LABEL maintainer="slamb@slamb.org" ENV LC_ALL=C.UTF-8 RUN export DEBIAN_FRONTEND=noninteractive && \ @@ -51,21 +63,12 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ vim-nox && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ - groupadd \ - --gid="${DEPLOY_GID}" \ - moonfire-nvr && \ - useradd \ - --no-log-init \ - --home-dir=/var/lib/moonfire-nvr \ - --uid="${DEPLOY_UID}" \ - --gid=moonfire-nvr \ - --shell=/bin/bash \ - --create-home \ - moonfire-nvr && \ ln -s moonfire-nvr /usr/local/bin/nvr -COPY --from=build-server /var/lib/moonfire-nvr/moonfire-nvr /usr/local/bin/moonfire-nvr -COPY --from=build-webpack /var/lib/moonfire-nvr/ui-dist /usr/local/lib/moonfire-nvr/ui +COPY --from=build-server /usr/local/bin/moonfire-nvr /usr/local/bin/moonfire-nvr +COPY --from=build-ui /var/lib/moonfire-nvr/ui/dist /usr/local/lib/moonfire-nvr/ui -USER moonfire-nvr:moonfire-nvr +# The install instructions say to use --user in the docker run commandline. +# Specify a non-root user just in case someone forgets. +USER 10000:10000 WORKDIR /var/lib/moonfire-nvr ENTRYPOINT [ "/usr/local/bin/moonfire-nvr" ] diff --git a/docker/dev-common.bash b/docker/dev-common.bash new file mode 100755 index 0000000..0bd1ff0 --- /dev/null +++ b/docker/dev-common.bash @@ -0,0 +1,68 @@ +#!/bin/bash +# Build the "dev" target. See Dockerfile. + +set -o errexit +set -o pipefail +set -o xtrace + +export DEBIAN_FRONTEND=noninteractive + +packages=() + +apt-get update + +# Add yarn repository. +apt-get --assume-yes --no-install-recommends install curl gnupg ca-certificates +curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" \ + >> /etc/apt/sources.list.d/yarn.list + +# Install all packages necessary for building (and some for testing/debugging). +packages+=( + build-essential + pkgconf + locales + nodejs + sudo + sqlite3 + tzdata + vim-nox + yarn +) +apt-get update +apt-get install --assume-yes --no-install-recommends "${packages[@]}" +apt-get clean +rm -rf /var/lib/apt/lists/* + +# Create the user. On the dev environment, allow sudo. +groupadd \ + --gid="${BUILD_GID}" \ + moonfire-nvr +useradd \ + --no-log-init \ + --home-dir=/var/lib/moonfire-nvr \ + --uid="${BUILD_UID}" \ + --gid=moonfire-nvr \ + --shell=/bin/bash \ + --create-home \ + moonfire-nvr +echo 'moonfire-nvr ALL=(ALL) NOPASSWD: ALL' >>/etc/sudoers + +# Install Rust. Note curl was already installed for yarn above. +su moonfire-nvr -lc "curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs | + sh -s - -y" + +# Put configuration for the Rust build into a new ".buildrc" which is used +# both (1) interactively from ~/.bashrc when logging into the dev container +# and (2) from a build-server RUN command. In particular, the latter can't +# use ~/.bashrc because that script immediately exits when run from a +# non-interactive shell. +echo 'source $HOME/.buildrc' >> /var/lib/moonfire-nvr/.bashrc +cat >> /var/lib/moonfire-nvr/.buildrc <> /etc/apt/sources.list.d/yarn.list - -# Install all packages necessary for building (and some for testing/debugging). +# Install the packages for the target architecture. packages+=( - build-essential - pkgconf ffmpeg"${apt_target_suffix}" libavcodec-dev"${apt_target_suffix}" libavformat-dev"${apt_target_suffix}" libavutil-dev"${apt_target_suffix}" libncurses-dev"${apt_target_suffix}" libsqlite3-dev"${apt_target_suffix}" - locales - nodejs - sudo - sqlite3 - tzdata - vim-nox - yarn ) apt-get update apt-get install --assume-yes --no-install-recommends "${packages[@]}" apt-get clean rm -rf /var/lib/apt/lists/* -# Create the user. On the dev environment, allow sudo. -groupadd \ - --gid="${BUILD_GID}" \ - moonfire-nvr -useradd \ - --no-log-init \ - --home-dir=/var/lib/moonfire-nvr \ - --uid="${BUILD_UID}" \ - --gid=moonfire-nvr \ - --shell=/bin/bash \ - --create-home \ - moonfire-nvr -echo 'moonfire-nvr ALL=(ALL) NOPASSWD: ALL' >>/etc/sudoers - -# Install Rust. Note curl was already installed for yarn above. -su moonfire-nvr -lc "curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs | - sh -s - -y" - -# Put configuration for the Rust build into a new ".buildrc" which is used -# both (1) interactively from ~/.bashrc when logging into the dev container -# and (2) from a build-server RUN command. In particular, the latter can't -# use ~/.bashrc because that script immediately exits when run from a -# non-interactive shell. -echo 'source $HOME/.buildrc' >> /var/lib/moonfire-nvr/.bashrc -cat >> /var/lib/moonfire-nvr/.buildrc <