# https://circleci.com/docs/2.0/

version: 2
workflows:
  version: 2
  ci:
    jobs:
      # Platforms
      - "debian-9"
      - "debian-8":
          requires:
            - "debian-9"

      - "ubuntu-18.04"
      - "ubuntu-16.04":
          requires:
            - "ubuntu-18.04"

      - "fedora-29"
      - "fedora-28":
          requires:
            - "fedora-29"

      - "centos-7"

      - "slackware-14.2"

      # Other assorted tasks and configurations
      - "lint"
      - "deprecations"
      - "c-locale"
      # Any locale other than C or UTF-8.
      - "another-locale"

      - "integration":
          requires:
            # If the unit test suite doesn't pass, don't bother running the
            # integration tests.
            - "debian-9"

  images:
    # Build the Docker images used by the ci jobs.  This makes the ci jobs
    # faster and takes various spurious failures out of the critical path.
    triggers:
      # Build once a day
      - schedule:
          cron: "0 0 * * *"
          filters:
            branches:
              only:
                - "master"

    jobs:
      - "build-image-debian-8"
      - "build-image-debian-9"
      - "build-image-ubuntu-16.04"
      - "build-image-ubuntu-18.04"
      - "build-image-fedora-28"
      - "build-image-fedora-29"
      - "build-image-centos-7"
      - "build-image-slackware-14.2"


jobs:
  lint:
    docker:
      - image: "circleci/python:2"

    steps:
      - "checkout"

      - run:
          name: "Install tox"
          command: |
            pip install --user tox

      - run:
          name: "Static-ish code checks"
          command: |
            ~/.local/bin/tox -e codechecks

  debian-9: &DEBIAN
    docker:
      - image: "tahoelafsci/debian:9"
        user: "nobody"

    environment: &UTF_8_ENVIRONMENT
      # Tell Hypothesis which configuration we want it to use.
      TAHOE_LAFS_HYPOTHESIS_PROFILE: "ci"
      # Tell the C runtime things about character encoding (mainly to do with
      # filenames and argv).
      LANG: "en_US.UTF-8"
      # Select a tox environment to run for this job.
      TAHOE_LAFS_TOX_ENVIRONMENT: "coverage"
      # Additional arguments to pass to tox.
      TAHOE_LAFS_TOX_ARGS: ""
      # The path in which test artifacts will be placed.
      ARTIFACTS_OUTPUT_PATH: "/tmp/artifacts"
      # Convince all of our pip invocations to look at the cached wheelhouse
      # we maintain.
      WHEELHOUSE_PATH: &WHEELHOUSE_PATH "/tmp/wheelhouse"
      PIP_FIND_LINKS: "file:///tmp/wheelhouse"

    # pip cannot install packages if the working directory is not readable.
    # We want to run a lot of steps as nobody instead of as root.
    working_directory: "/tmp/project"

    steps:
      - "checkout"
      - run: &SETUP_VIRTUALENV
          name: "Setup virtualenv"
          command: |
            /tmp/project/.circleci/setup-virtualenv.sh \
                "/tmp/venv" \
                "/tmp/project" \
                "${WHEELHOUSE_PATH}" \
                "${TAHOE_LAFS_TOX_ENVIRONMENT}" \
                "${TAHOE_LAFS_TOX_ARGS}"

      - run: &RUN_TESTS
          name: "Run test suite"
          command: |
            /tmp/project/.circleci/run-tests.sh \
                "/tmp/venv" \
                "/tmp/project" \
                "${ARTIFACTS_OUTPUT_PATH}" \
                "${TAHOE_LAFS_TOX_ENVIRONMENT}" \
                "${TAHOE_LAFS_TOX_ARGS}"
          # trial output gets directed straight to a log.  avoid the circleci
          # timeout while the test suite runs.
          no_output_timeout: "20m"

      - store_test_results: &STORE_TEST_RESULTS
          path: "/tmp/artifacts/junit"

      - store_artifacts: &STORE_TEST_LOG
          # Despite passing --workdir /tmp to tox above, it still runs trial
          # in the project source checkout.
          path: "/tmp/project/_trial_temp/test.log"

      - store_artifacts: &STORE_OTHER_ARTIFACTS
          # Store any other artifacts, too.  This is handy to allow other jobs
          # sharing most of the definition of this one to be able to
          # contribute artifacts easily.
          path: "/tmp/artifacts"

      - run: &SUBMIT_COVERAGE
          name: "Submit coverage results"
          command: |
            /tmp/venv/bin/codecov


  debian-8:
    <<: *DEBIAN
    docker:
      - image: "tahoelafsci/debian:8"
        user: "nobody"


  c-locale:
    <<: *DEBIAN

    environment:
      <<: *UTF_8_ENVIRONMENT
      LANG: "C"


  another-locale:
    <<: *DEBIAN

    environment:
      <<: *UTF_8_ENVIRONMENT
      # aka "Latin 1"
      LANG: "en_US.ISO-8859-1"


  deprecations:
    <<: *DEBIAN

    environment:
      <<: *UTF_8_ENVIRONMENT
      # Select the deprecations tox environments.
      TAHOE_LAFS_TOX_ENVIRONMENT: "deprecations,upcoming-deprecations"
      # Put the logs somewhere we can report them.
      TAHOE_LAFS_WARNINGS_LOG: "/tmp/artifacts/deprecation-warnings.log"


  integration:
    <<: *DEBIAN

    environment:
      <<: *UTF_8_ENVIRONMENT
      # Select the integration tests tox environments.
      TAHOE_LAFS_TOX_ENVIRONMENT: "integration"
      # Disable artifact collection because py.test can't produce any.
      ARTIFACTS_OUTPUT_PATH: ""

    steps:
      - "checkout"
      # DRY, YAML-style.  See the debian-9 steps.
      - run: *SETUP_VIRTUALENV
      - run: *RUN_TESTS


  ubuntu-16.04:
    <<: *DEBIAN
    docker:
      - image: "tahoelafsci/ubuntu:16.04"
        user: "nobody"


  ubuntu-18.04:
    <<: *DEBIAN
    docker:
      - image: "tahoelafsci/ubuntu:18.04"
        user: "nobody"


  centos-7: &RHEL_DERIV
    docker:
      - image: "tahoelafsci/centos:7"
        user: "nobody"

    environment: *UTF_8_ENVIRONMENT

    # pip cannot install packages if the working directory is not readable.
    # We want to run a lot of steps as nobody instead of as root.
    working_directory: "/tmp/project"

    steps:
      - "checkout"
      - run: *SETUP_VIRTUALENV
      - run: *RUN_TESTS
      - store_test_results: *STORE_TEST_RESULTS
      - store_artifacts: *STORE_TEST_LOG
      - store_artifacts: *STORE_OTHER_ARTIFACTS
      - run: *SUBMIT_COVERAGE


  fedora-28:
    <<: *RHEL_DERIV
    docker:
      - image: "tahoelafsci/fedora:28"
        user: "nobody"


  fedora-29:
    <<: *RHEL_DERIV
    docker:
      - image: "tahoelafsci/fedora:29"
        user: "nobody"


  slackware-14.2:
    docker:
      - image: "tahoelafsci/slackware:14.2"
        user: "nobody"

    environment: *UTF_8_ENVIRONMENT

    # pip cannot install packages if the working directory is not readable.
    # We want to run a lot of steps as nobody instead of as root.
    working_directory: "/tmp/project"

    steps:
      - "checkout"
      - run: *SETUP_VIRTUALENV
      - run: *RUN_TESTS
      - store_test_results: *STORE_TEST_RESULTS
      - store_artifacts: *STORE_TEST_LOG
      - store_artifacts: *STORE_OTHER_ARTIFACTS
      - run: *SUBMIT_COVERAGE

  build-image: &BUILD_IMAGE
    # This is a template for a job to build a Docker image that has as much of
    # the setup as we can manage already done and baked in.  This cuts down on
    # the per-job setup time the actual testing jobs have to perform - by
    # perhaps 10% - 20%.
    #
    # https://circleci.com/blog/how-to-build-a-docker-image-on-circleci-2-0/
    docker:
      - image: "docker:17.05.0-ce-git"

    environment:
      DISTRO: "tahoelafsci/<DISTRO>:foo"
      TAG: "tahoelafsci/distro:<TAG>"

    steps:
      - "checkout"
      - "setup_remote_docker"
      - run:
          name: "Get openssl"
          command: |
            apk add --no-cache openssl
      - run:
          name: "Get Dockerhub secrets"
          command: |
            # If you create an encryption key like this:
            #
            #   openssl enc -aes-256-cbc -k secret -P -md sha256

            # From the output that looks like:
            #
            #  salt=...
            #  key=...
            #  iv =...
            #
            # extract just the value for ``key``.

            # then you can re-generate ``secret-env-cipher`` locally using the
            # command:
            #
            #   openssl aes-256-cbc -e -md sha256 -in secret-env-plain -out .circleci/secret-env-cipher -pass env:KEY
            #
            # Make sure the key is set as the KEY environment variable in the
            # CircleCI web interface.  You can do this by visiting
            # <https://circleci.com/gh/tahoe-lafs/tahoe-lafs/edit#env-vars>
            # after logging in to CircleCI with an account in the tahoe-lafs
            # CircleCI team.
            #
            # Then you can recover the environment plaintext (for example, to
            # change and re-encrypt it) like just like CircleCI recovers it
            # here:
            #
            openssl aes-256-cbc -d -md sha256 -in .circleci/secret-env-cipher -pass env:KEY >> ~/.env
      - run:
          name: "Log in to Dockerhub"
          command: |
            . ~/.env
            # TAHOELAFSCI_PASSWORD come from the secret env.
            docker login -u tahoelafsci -p ${TAHOELAFSCI_PASSWORD}
      - run:
          name: "Build image"
          command: |
            docker \
                build \
                --build-arg TAG=${TAG} \
                -t tahoelafsci/${DISTRO}:${TAG} \
                -f ~/project/.circleci/Dockerfile.${DISTRO} \
                ~/project/
      - run:
          name: "Push image"
          command: |
            docker push tahoelafsci/${DISTRO}:${TAG}


  build-image-debian-8:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "debian"
      TAG: "8"


  build-image-debian-9:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "debian"
      TAG: "9"


  build-image-ubuntu-16.04:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "ubuntu"
      TAG: "16.04"


  build-image-ubuntu-18.04:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "ubuntu"
      TAG: "18.04"


  build-image-centos-7:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "centos"
      TAG: "7"


  build-image-fedora-28:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "fedora"
      TAG: "28"


  build-image-fedora-29:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "fedora"
      TAG: "29"


  build-image-slackware-14.2:
    <<: *BUILD_IMAGE

    environment:
      DISTRO: "slackware"
      TAG: "14.2"
