## Building Nim projects on commercial CI systems

Building your code on CI is useful to check regressions against the master and devel branches of Nim.
Same for your code documentation.

There are 3 most common ways to install Nim:

* Pulling the Debian packages: fastest; requires keeping the .deb file URL up to date
* Using a Docker image: slower but requires little maintenance
* Using choosenim: slow when compiling Nim from sources

The Nim docker image contains the latest version.

Use this .circleci/config.yml

[source,yaml]
----
version: 2
jobs:
  build:
    docker:
      - image: nimlang/nim
    steps:
      - run: echo 'export PATH=~/.nimble/bin:$PATH' >> $BASH_ENV
      - checkout
      # Reuse cached directories
      - restore_cache:
          key: nim-0000
      - run:
          command: |
            # Example: adding OS libraries
            apt-get update
            apt-get install -y --no-install-recommends libsodium23
      - save_cache:
          key: nim-0000
          paths:
            - .nimble
      - run: nimble build -y
      - run: nim c -r <mytest.nim>
      - store_artifacts:
          path: test-reports/
          destination: tr1
      - store_test_results:
          path: test-reports/
----

## Building Nim projects on Circle CI v2.0 with Docker

On Circle CI 2.0 you can use Docker containers to perform builds. The following example is taken from the following guide and builds against the current Nim version on both Ubuntu and Alpine Linux: https://www.euantorano.co.uk/posts/nim-circle-ci/[Continuous Integration for Nim using Circle CI]

[source,yaml]
----
version: 2
jobs:
  build:
    working_directory: /usr/src/dotenv
    docker:
      - image: nimlang/nim
    branches:
      only:
        - master
    steps:
      - checkout
      - run:
          name: test
          command: nim c -r tests/main.nim
  build_alpine:
    working_directory: /usr/src/dotenv
    docker:
      - image: nimlang/nim:alpine
    branches:
      only:
        - master
    steps:
      - checkout
      - run:
          name: test
          command: nim c -r tests/main.nim
workflows:
  version: 2
  build_and_test:
    jobs:
      - build
      - build_alpine
----

## Building Nim projects on Travis CI

### Using Docker
[source,yaml]
----
sudo: required
services:
  - docker
before_install:
  - docker pull nimlang/nim
script:
  - docker run nimlang/nim nim --version
  - docker run -v "$(pwd):/project" -w /project nimlang/nim sh -c "nimble install -dy && nimble test"
#  - docker run -v "$(pwd):/project" -w /project nimlang/nim sh -c "find src/ -name '*.nim' -type f -exec nim doc {} \;"
----

Uncomment the last line to test embedded `runnableExamples` blocks.

### Using choosenim

[source,yaml]
----
language: c

cache: ccache
cache:
  directories:
  - .cache

matrix:
  include:
    # Build and test against the master (stable) and devel branches of Nim
    - os: linux
      env: CHANNEL=stable
      compiler: gcc

    - os: linux
      env: CHANNEL=devel
      compiler: gcc

    # On OSX we only test against clang (gcc is mapped to clang by default)
    - os: osx
      env: CHANNEL=stable
      compiler: clang

  allow_failures:
    # Ignore failures when building against the devel Nim branch
    # Also ignore OSX, due to very long build queue
    - env: CHANNEL=devel
    - os: osx
  fast_finish: true

## BEGIN: Assuming you rely on external dependencies
addons: # This will only be executed on Linux
  apt:
    packages:
      - libyourdependency

before_install:
  # If you want to install an OSX Homebrew dependency
  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update          ; fi
  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libyourdependency; fi
## END: Assuming you rely on external dependencies

install:
  - export CHOOSENIM_NO_ANALYTICS=1
  - curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh
  - sh init.sh -y
  - export PATH=~/.nimble/bin:$PATH
  - echo "export PATH=~/.nimble/bin:$PATH" >> ~/.profile
  - choosenim $CHANNEL

script:
    - nimble refresh
    - nimble test

branches:
  except:
    - gh-pages
---- 

### Devel branches

Building your code on Travis CI is useful to check regressions against the master and devel branches of Nim.
Same for your code documentation.

Detailed guide, which the following example originates from: +
http://blaxpirit.com/blog/22/advanced-uses-of-travis-ci-with-nim.html[Advanced uses of Travis CI with Nim]

[source,yaml]
----
# Copied from https://github.com/nim-lang/Nim/wiki/TravisCI
language: c
env:
  # Build and test against the master and devel branches of Nim
  - BRANCH=master
  - BRANCH=devel
compiler:
  # Build and test using both gcc and clang
  - gcc
  - clang
matrix:
  allow_failures:
    # Ignore failures when building against the devel Nim branch
    - env: BRANCH=devel
  fast_finish: true
install:
  - |
    if [ ! -x nim-$BRANCH/bin/nim ]; then
      git clone -b $BRANCH --depth 1 git://github.com/nim-lang/nim nim-$BRANCH/
      cd nim-$BRANCH
      git clone --depth 1 git://github.com/nim-lang/csources csources/
      cd csources
      sh build.sh
      cd ..
      rm -rf csources
      bin/nim c koch
      ./koch boot -d:release
    else
      cd nim-$BRANCH
      git fetch origin
      if ! git merge FETCH_HEAD | grep "Already up-to-date"; then
        bin/nim c koch
        ./koch boot -d:release
      fi
    fi
    cd ..
before_script:
    - export PATH="nim-$BRANCH/bin${PATH:+:$PATH}"
script:
    # Replace uppercase strings!
    - nim c --cc:$CC --verbosity:0 -r MYFILE.nim
    # Optional: build docs. 
    - nim doc --docSeeSrcUrl:https://github.com/AUTHOR/MYPROJECT/blob/master --project MYFILE.nim
cache:
  directories:
    - nim-master
    - nim-devel
branches:
  except:
    - gh-pages

----

## Appveyor

Create .appveyor.yml 

[source,yaml]
----
version: '{build}'

cache:
- nim-0.16.0_x64.zip
- x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z

matrix:
  fast_finish: true

environment:
  matrix:
    - MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
      MINGW_DIR: mingw64
      MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z/download
      NIM_ARCHIVE: nim-0.16.0_x64.zip
      NIM_DIR: nim-0.16.0
      NIM_URL: https://nim-lang.org/download/nim-0.16.0_x64.zip
      platform: x64

install:
  - MKDIR %CD%\tools_tmp
  - IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%"
  - 7z x -y "%MINGW_ARCHIVE%" -o"%CD%\tools_tmp"> nul
  - IF not exist "%NIM_ARCHIVE%" appveyor DownloadFile "%NIM_URL%" -FileName "%NIM_ARCHIVE%"
  - 7z x -y "%NIM_ARCHIVE%" -o"%CD%\tools_tmp"> nul
  - SET PATH=%CD%\tools_tmp\%NIM_DIR%\bin;%CD%\tools_tmp\%MINGW_DIR%\bin;%PATH%

build_script:
  - nimble.exe install CHANGEME -y
  - nim.exe c -p:. ./tests/CHANGEME.nim

test_script:
  - ./tests/CHANGEME

deploy: off
----

You may encounter an issue with Sourceforge download and download just a webpage. In that case replace the generic URL by a direct link into a mirror like 'https://ayera.dl.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z'
