Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nix support #275

Merged
merged 23 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/test-import-using-nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
on:
workflow_dispatch: # allow manual execution
push:
pull_request:
schedule:
# run on the 3rd each month at 10:00am
- cron: '0 10 3 * *'

jobs:
nix-check-and-import:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v11
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
with:
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/20.09.tar.gz
install_url: https://github.com/numtide/nix-flakes-installer/releases/download/nix-3.0pre20201007_5257a25/install
extra_nix_config: |
experimental-features = nix-command flakes
- name: run checks & test import
run: |
cd etc/nix
nix --print-build-logs flake check
./test-import-using-nix.sh alpine
37 changes: 36 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,41 @@ When not running in development mode, an environment variable named
is to use the code Django includes for this purpose:
``SECRET_KEY=$(python -c "from django.core.management import utils; print(utils.get_random_secret_key())")``.

Using Nix
~~~~~~~~~

You can install VulnerableCode with `Nix <https://nixos.org/download.html>`__ (`Flake <https://nixos.wiki/wiki/Flakes>`__ support is needed).

::

cd etc/nix
nix --print-build-logs flake check # build & run tests

There are several options to use the Nix version

::

# Enter an interactive environment with all dependencies set up.
cd etc/nix
nix develop
> ../../manage.py ... # invoke the local checkout
> vulnerablecode-manage.py ... # invoke manage.py as installed in the nix store

# Test the import prodecure using the Nix version.
etc/nix/test-import-using-nix.sh --all # import everything
# Test the import using the local checkout.
INSTALL_DIR=. etc/nix/test-import-using-nix.sh ruby # import ruby only


**Keeping the Nix setup in sync**

The Nix installation uses `mach-nix <https://github.com/DavHau/mach-nix>`__ to handle Python dependencies because some dependencies are currently not available as Nix packages.
All Python dependencies are automatically fetched from ``./requirements.txt``.
If the ``mach-nix``-based installation fails, you might need to update ``mach-nix`` itself and the `pypi-deps-db <https://github.com/DavHau/pypi-deps-db>`_ version in use (see ``etc/nix/flake.nix:inputs.machnix`` and ``machnixFor.pypiDataRev``).

Non-Python dependencies are curated in ``etc/nix/flake.nix:vulnerablecode.propagatedBuildInputs``.


Tests
-----

Expand Down Expand Up @@ -227,4 +262,4 @@ For full documentation about API endpoints.
.. |Gitter chat| image:: https://badges.gitter.im/gitterHQ/gitter.png
:target: https://gitter.im/aboutcode-org/vulnerablecode
.. |PRs Welcome| image:: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
:target: http://makeapullrequest.com
:target: http://makeapullrequest.com
4 changes: 4 additions & 0 deletions etc/nix/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(import (fetchTarball
"https://github.com/edolstra/flake-compat/archive/master.tar.gz") {
src = ./.;
}).defaultNix
96 changes: 96 additions & 0 deletions etc/nix/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

153 changes: 153 additions & 0 deletions etc/nix/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
{
description =
"Vulnerablecode - A free and open vulnerabilities database and the packages they impact.";

inputs.nixpkgs = {
type = "github";
owner = "NixOS";
repo = "nixpkgs";
ref = "20.09";
};

inputs.machnix = {
type = "github";
owner = "DavHau";
repo = "mach-nix";
ref = "3.1.1";
};

outputs = { self, nixpkgs, machnix }:
let

vulnerablecode-src = ./../..;

# Extract version from setup.py.
version = builtins.head (builtins.match ''.*version=["']?([^"',]+).*''
(builtins.readFile (vulnerablecode-src + "/setup.py")));

# Common shell code.
libSh = ./lib.sh;

# System types to support.
supportedSystems = [ "x86_64-linux" ];

# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
forAllSystems = f:
nixpkgs.lib.genAttrs supportedSystems (system: f system);

# Nixpkgs instantiated for supported system types.
nixpkgsFor = forAllSystems (system:
import nixpkgs {
inherit system;
overlays = [ self.overlay ];
});

# mach-nix instantiated for supported system types.
machnixFor = forAllSystems (system:
import machnix {
pkgs = (nixpkgsFor.${system}).pkgs;
python = "python38";

# Pin pypi repo to a specific commit which includes all necessary
# Python deps. The default version is updated with every mach-nix
# release might be be sufficient for newer releases.
# The corresponding sha256 hash can be obtained with:
# $ nix-prefetch-url --unpack https://github.com/DavHau/pypi-deps-db/tarball/<pypiDataRev>
pypiDataRev = "c86b4490a7d838bd54a2d82730455e96c6e4eb14";
pypiDataSha256 =
"0al490gi0qda1nkb9289z2msgpc633rv5hn3w5qihkl1rh88dmjd";
});

in {

# A Nixpkgs overlay.
overlay = final: prev:
with final.pkgs; {

pythonEnv = machnixFor.${system}.mkPython {
requirements =
builtins.readFile (vulnerablecode-src + "/requirements.txt");
};

vulnerablecode = stdenv.mkDerivation {
inherit version;
name = "vulnerablecode-${version}";
src = vulnerablecode-src;
dontConfigure = true; # do not use ./configure
propagatedBuildInputs = [ pythonEnv postgresql ];

postPatch = ''
# Make sure the pycodestyle binary in $PATH is used.
substituteInPlace vulnerabilities/tests/test_basics.py \
--replace 'join(bin_dir, "pycodestyle")' '"pycodestyle"'
'';

installPhase = ''
cp -r . $out
'';
};

};

# Provide a nix-shell env to work with vulnerablecode.
devShell = forAllSystems (system:
with nixpkgsFor.${system};
mkShell {
# will be available as env var in `nix develop` / `nix-shell`.
VULNERABLECODE_INSTALL_DIR = vulnerablecode;
buildInputs = [ vulnerablecode ];
shellHook = ''
alias vulnerablecode-manage.py=${vulnerablecode}/manage.py
'';
});

# Provide some packages for selected system types.
packages = forAllSystems
(system: { inherit (nixpkgsFor.${system}) vulnerablecode; });

# The default package for 'nix build'.
defaultPackage =
forAllSystems (system: self.packages.${system}.vulnerablecode);

# Tests run by 'nix flake check' and by Hydra.
checks = forAllSystems (system: {
inherit (self.packages.${system}) vulnerablecode;

vulnerablecode-test = with nixpkgsFor.${system};
stdenv.mkDerivation {
name = "${vulnerablecode.name}-test";

buildInputs = [ wget vulnerablecode ];

# Used by pygit2.
# See https://github.com/NixOS/nixpkgs/pull/72544#issuecomment-582674047.
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";

unpackPhase = "true";

buildPhase = ''
source ${libSh}
initPostgres $(pwd)
export DJANGO_DEV=1
${vulnerablecode}/manage.py migrate
'';

doCheck = true;
checkPhase = ''
# Run pytest on the installed version. A running postgres
# database server is needed.
(cd ${vulnerablecode} && pytest)

# Launch the webserver and call the API.
${vulnerablecode}/manage.py runserver &
sleep 2
wget http://127.0.0.1:8000/api/
kill %1 # kill background task (i.e. webserver)
'';

installPhase =
"mkdir -p $out"; # make this derivation return success
};
});
};
}
18 changes: 18 additions & 0 deletions etc/nix/lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

# Setup postgres; see the README for the latest instructions.
#
# $RUNDIR is used to prevent postgres from accessings its default run dir at
# /run/postgresql. See
# https://github.com/NixOS/nixpkgs/issues/83770#issuecomment-607992517
function initPostgres() {
ROOTDIR=$1
DATADIR=$ROOTDIR/pgdata
RUNDIR=$ROOTDIR/run
ENCODING="UTF-8"
mkdir -p "$RUNDIR"
initdb -D "$DATADIR" -E $ENCODING
pg_ctl -D "$DATADIR" -o "-k $RUNDIR" -l "$DATADIR/logfile" start
createuser --host "$RUNDIR" --no-createrole --no-superuser --login --inherit --createdb vulnerablecode
createdb --host "$RUNDIR" -E $ENCODING --owner=vulnerablecode --user=vulnerablecode --port=5432 vulnerablecode
}
3 changes: 3 additions & 0 deletions etc/nix/shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(import (fetchTarball https://github.com/edolstra/flake-compat/archive/master.tar.gz) {
src = ./.;
}).shellNix
29 changes: 29 additions & 0 deletions etc/nix/test-import-using-nix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash

# Populate a test database using either the Nix installation or the local
# checkout.

set -e

THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
DEFAULT_INSTALL_DIR=$VULNERABLECODE_INSTALL_DIR # in the Nix store, see flake.nix
INSTALL_DIR=${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}
ARGS=$(if [ $# -eq 0 ]; then echo "--all"; else echo "$@"; fi)
export DJANGO_DEV=${DJANGO_DEV:-1}
TEMPDIR=$(mktemp -d -p "$THIS_DIR")
export TEMPDIR

source "$THIS_DIR/lib.sh"

cleanup() {
pg_ctl -D "$DATADIR" stop
rm -rf "$TEMPDIR"
}

trap cleanup EXIT

initPostgres "$TEMPDIR"

"$INSTALL_DIR/manage.py" migrate
"$INSTALL_DIR/manage.py" import $ARGS