diff --git a/.circleci/config.yml b/.circleci/config.yml index 3fe7c7630832fb9e47fb8a214723f72827f9b9e2..8c393e1ad5d65dac119855647901edd1aab24377 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -49,30 +49,103 @@ jobs: tests: docker: - - image: "circleci/python:2.7" + # Run in a highly Nix-capable environment. + - image: "nixorg/nix:circleci" environment: - PIP_REQUIREMENTS: "-r requirements.txt -r requirements-tests.txt" - ZKAPAUTHORIZER_HYPOTHESIS_PROFILE: "ci" + CODECOV_TOKEN: "cc6e4697-4337-4506-88af-92b8f8ca6b22" + # Specify a revision of NixOS/nixpkgs to run against. This essentially + # pins the majority of the software involved in the build. This + # revision is selected arbitrarily. It's somewhat current as of the + # time of this comment. We can bump it to a newer version when that + # makes sense. Meanwhile, the platform won't shift around beneath us + # unexpectedly. + NIXPKGS_REV: "5d5cd70516001e79516d2ade8bcf31df208a4ef3" steps: + - run: + # Get NIX_PATH set for the rest of the job so that the revision of + # nixpkgs we selected will be used everywhere Nix pulls in software. + # There is no way to set an environment variable containing the + # value of another environment variable on CircleCI except to use + # the `BASE_ENV` feature as we do here. + name: "Setup NIX_PATH Environment Variable" + command: | + echo "export NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/$NIXPKGS_REV.tar.gz" >> $BASH_ENV + - "checkout" - - <<: *PREPARE_VIRTUALENV + - "run": + # CircleCI won't let us interpolate NIXPKGS_REV into a cache key. + # Only CircleCI's own environment variables or variables set via the + # web interface in a "context" can be interpolated into cache keys. + # However, we can interpolate the checksum of a file... Since we + # don't care about the exact revision, we just care that a new + # revision gives us a new string, we can write the revision to a + # file and then put the checksum of that file into the cache key. + # This way, we don't have to maintain the nixpkgs revision in two + # places and risk having them desynchronize. + name: "Prepare For Cache Key" + command: | + echo "${NIXPKGS_REV}" > nixpkgs.rev + + - restore_cache: + # Get all of Nix's state relating to the particular revision of + # nixpkgs we're using. It will always be the same. CircleCI + # artifacts and nixpkgs store objects are probably mostly hosted in + # the same place (S3) so there's not a lot of difference for + # anything that's pre-built. For anything we end up building + # ourselves, though, this saves us all of the build time (less the + # download time). + # + # Read about caching dependencies: https://circleci.com/docs/2.0/caching/ + name: "Restore Nix Store Paths" + keys: + # Construct cache keys that allow sharing as long as nixpkgs + # revision is unchanged. + # + # If nixpkgs changes then potentially a lot of cached packages for + # the base system will be invalidated so we may as well drop them + # and make a new cache with the new packages. + - zkapauthorizer-nix-store-v1-{{ checksum "nixpkgs.rev" }} + - zkapauthorizer-nix-store-v1- - run: name: "Run Test Suite" command: | - . venv/bin/activate - pip install . - coverage run -m twisted.trial _zkapauthorizer + # Building the package has, as a side effect, running the test + # suite. If the test suite fails, so does the build. + # + # Pass in a couple args here to control how the test suite is run + # - configure Hypothesis so it can behave appropriately in a CI + # environment (where resources are scarce, competetion with other + # tenants is high, etc) and collect coverage information. + # + # Further, we want the "doc" output built as well because that's + # where the coverage data ends up. + nix-build --argstr hypothesisProfile ci --arg collectCoverage true --attr doc - run: - name: "Report Coverage" + name: "Cache codecov" command: | - . venv/bin/activate - CODECOV_TOKEN="cc6e4697-4337-4506-88af-92b8f8ca6b22" codecov + # Build codecov and any dependencies here, before we save the + # cache, so that they make it in to the cache too. Turns out + # there is a python-cryptography dependency here that is expensive + # to build that doesn't get built earlier. This saves us a couple + # minutes. + nix-build --expr '(import <nixpkgs> { }).python.withPackages (ps: [ ps.codecov ])' + + - save_cache: + name: "Cache Nix Store Paths" + key: zkapauthorizer-nix-store-v1-{{ checksum "nixpkgs.rev" }} + paths: + - "/nix" + - run: + name: "Report Coverage" + command: | + nix-shell -p 'python.withPackages (ps: [ ps.codecov ])' --keep CODECOV_TOKEN --run \ + 'codecov --file ./result-doc/share/doc/*/.coverage' workflows: version: 2 diff --git a/autobahn.nix b/autobahn.nix index 3cc1df2138e783f7bb212b50ba09435773233b88..df026096799d6b65bf34ad7700b6a726e9252f68 100644 --- a/autobahn.nix +++ b/autobahn.nix @@ -1,6 +1,7 @@ { lib, buildPythonPackage, fetchFromGitHub, isPy3k, six, txaio, twisted, zope_interface, cffi, trollius, futures, cryptography, - mock, pytest + mock, pytest, + supportAsyncio ? false }: buildPythonPackage rec { pname = "autobahn"; @@ -14,7 +15,9 @@ buildPythonPackage rec { }; propagatedBuildInputs = [ six txaio twisted zope_interface cffi cryptography ] ++ - (lib.optionals (!isPy3k) [ trollius futures ]); + (lib.optionals (!isPy3k) [ futures ]) ++ + (lib.optionals (supportAsyncio && !isPy3k) [ trollius ]) + ; checkInputs = [ mock pytest ]; checkPhase = '' diff --git a/default.nix b/default.nix index f1c5e37ea433eb5add61f81b6c9ed3c4b359ce25..04af35d91986bd58cdc708b9bddc31c6aa1d50d4 100644 --- a/default.nix +++ b/default.nix @@ -1,2 +1,2 @@ -{ pkgs ? import ./nixpkgs.nix { } }: -pkgs.python27Packages.callPackage ./zkapauthorizer.nix { } +{ pkgs ? import ./nixpkgs.nix { }, hypothesisProfile ? null, collectCoverage ? false }: +pkgs.python27Packages.callPackage ./zkapauthorizer.nix { inherit hypothesisProfile collectCoverage; } diff --git a/zkapauthorizer.nix b/zkapauthorizer.nix index 0b311a4868fcec93729afe25b028ab4dcd336126..ae7453630fde5af7ae11afb728cdd9563f109f8c 100644 --- a/zkapauthorizer.nix +++ b/zkapauthorizer.nix @@ -1,6 +1,8 @@ { buildPythonPackage, sphinx, circleci-cli , attrs, zope_interface, twisted, tahoe-lafs, privacypass , fixtures, testtools, hypothesis, pyflakes, treq, coverage +, hypothesisProfile ? null +, collectCoverage ? false }: buildPythonPackage rec { version = "0.0"; @@ -8,7 +10,7 @@ buildPythonPackage rec { name = "${pname}-${version}"; src = ./.; - outputs = [ "out" "doc" ]; + outputs = [ "out" ] ++ (if collectCoverage then [ "doc" ] else [ ]); depsBuildBuild = [ sphinx @@ -35,13 +37,18 @@ buildPythonPackage rec { checkPhase = '' runHook preCheck "${pyflakes}/bin/pyflakes" src/_zkapauthorizer - python -m coverage run --branch --source _zkapauthorizer,twisted.plugins.zkapauthorizer --module twisted.trial _zkapauthorizer + python -m ${if collectCoverage + then "coverage run --branch --source _zkapauthorizer,twisted.plugins.zkapauthorizer --module" + else "" + } twisted.trial _zkapauthorizer runHook postCheck ''; - postCheck = '' + postCheck = if collectCoverage + then '' python -m coverage html mkdir -p "$doc/share/doc/${name}" cp -vr .coverage htmlcov "$doc/share/doc/${name}" - ''; + '' + else ""; }