├── .appveyor.yml ├── .azure-pipelines.yml ├── .circleci └── config.yml ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitlab-ci.yml ├── .travis.yml ├── LICENCE.md ├── NOTICE.md ├── README.md ├── bitbucket-pipelines.yml ├── ci-utils-features.asd ├── ci-utils.asd ├── config-examples ├── .appveyor.yml ├── .azure-pipelines.yml ├── .circleci │ └── config.yml ├── .github │ └── workflows │ │ └── ci.yml ├── .gitlab-ci.yml ├── .travis.yml └── bitbucket-pipelines.yml ├── docs ├── Comparison-of-CI-platforms.md ├── Introduction-to-CI.md ├── Other-Resources.md └── _config.yml ├── generate-API-docs.ros ├── roswell ├── asdf-register-project.ros └── run-fiveam.ros ├── src ├── ci-utils.lisp ├── coveralls.lisp └── features.lisp └── t └── tests.lisp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2022 2 | 3 | platform: 4 | - x64 5 | 6 | clone_folder: c:\Users\appveyor\.roswell\local-projects\ci-utils\ 7 | 8 | environment: 9 | BIT: 64 10 | COMPILER: msys2 11 | ROSWELL_ZIP: https://ci.appveyor.com/api/projects/snmsts/roswell-en89n/artifacts/Roswell-x86_64.zip?branch=master&job=Environment%3A%20MSYS2_ARCH%3Dx86_64,%20MSYS2_BITS%3D64,%20MSYSTEM%3DMINGW64,%20METHOD%3Dcross 12 | MSYS2_ARCH: x86_64 13 | MSYS2_DIR: msys64 14 | MSYSTEM: MINGW64 15 | PATH: c:\msys64\usr\bin;c:\msys64\mingw64\bin;%USERPROFILE%\roswell;%PATH% 16 | PLATFORM: x64 17 | matrix: 18 | - LISP: sbcl-bin 19 | 20 | install: 21 | - bash -lc 'pacman -Sy --noconfirm mingw64/mingw-w64-x86_64-zeromq mingw32/mingw-w64-i686-zeromq' 22 | - ps: appveyor DownloadFile $Env:ROSWELL_ZIP -FileName Roswell.zip 23 | - 7z x -o%USERPROFILE% Roswell.zip 24 | - ros install %LISP% 25 | - ros config 26 | 27 | build: off 28 | 29 | test_script: 30 | - ros -Q -- c:\Users\appveyor\.roswell\local-projects\ci-utils\roswell\run-fiveam.ros -l ci-utils/test :appveyor-tests :base-tests :noncoveralls-tests 31 | -------------------------------------------------------------------------------- /.azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # based on https://github.com/realark/cl-sample-game/blob/master/azure-pipelines.yaml 2 | 3 | trigger: 4 | - master 5 | 6 | variables: 7 | LISP: sbcl-bin 8 | 9 | 10 | jobs: 11 | - job: 'Test' 12 | strategy: 13 | matrix: 14 | win: 15 | target: 'x86_64-windows-10' 16 | imageName: 'windows-latest' 17 | pool: 18 | vmImage: $(imageName) 19 | steps: 20 | - powershell: | 21 | iex "& {$(irm get.scoop.sh)} -RunAsAdmin" 22 | scoop install roswell 23 | ros install %LISP% 24 | ros config 25 | mkdir "$Env:LOCALAPPDATA\config\common-lisp\source-registry.conf.d\" 26 | # $Env:dir = "%AGENT_BUILDDIRECTORY:\=/%" 27 | Set-Content -Path "$Env:LOCALAPPDATA\config\common-lisp\source-registry.conf.d\ci.conf" -Value "(:tree ""$Env:AGENT_BUILDDIRECTORY"")" 28 | displayName: Install and configure Rowswell 29 | 30 | - powershell: | 31 | ros -Q -- roswell/run-fiveam.ros -l ci-utils/test :azure-pipelines-tests :base-tests :noncoveralls-tests 32 | displayName: Run tests 33 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | docker: 6 | - image: circleci/buildpack-deps:stretch-curl 7 | environment: 8 | LISP: sbcl-bin 9 | steps: 10 | - checkout 11 | - run: PATH=~/.roswell/bin:$PATH 12 | - run: curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 13 | - run: echo "(:tree \"$CIRCLE_WORKING_DIRECTORY/\")" > "$HOME/.config/common-lisp/source-registry.conf.d/ci.conf" 14 | - run: roswell/run-fiveam.ros -l ci-utils/test :circleci-tests :noncoveralls-tests :base-tests 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * autocrlf=input 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | schedule: 8 | - cron: 0 0 1 * * 9 | 10 | jobs: 11 | test: 12 | name: ${{ matrix.lisp }} on ${{ matrix.os }} 13 | runs-on: ${{ matrix.os }} 14 | env: 15 | BUILD_DOCS: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.os == 'ubuntu-latest' && matrix.lisp == 'sbcl-bin' }} 16 | strategy: 17 | matrix: 18 | lisp: [sbcl-bin, ccl-bin] 19 | os: [windows-latest, ubuntu-latest, macOS-latest] 20 | 21 | steps: 22 | - name: Logging 23 | run: | 24 | echo BUILD_DOCS ${{env.BUILD_DOCS}} 25 | echo ${{ github.event_name == 'push' }} ${{ github.ref == 'refs/heads/master' }} ${{ matrix.os == 'ubuntu-latest' }} ${{ matrix.lisp == 'sbcl-bin' }} 26 | - uses: actions/checkout@v2 27 | - name: Set LISP env var 28 | run: echo "LISP=${{ matrix.lisp }}" >> $GITHUB_ENV 29 | - uses: 40ants/setup-lisp@v2 30 | - name: Run tests (Non-Windows) 31 | if: runner.os != 'Windows' 32 | shell: bash 33 | run: roswell/run-fiveam.ros -l ci-utils/test :github-actions-tests :noncoveralls-tests :base-tests 34 | - name: Run tests (Windows) 35 | if: runner.os == 'Windows' 36 | shell: msys2 {0} 37 | run: roswell/run-fiveam.ros -l ci-utils/test :github-actions-tests :noncoveralls-tests :base-tests 38 | 39 | - name: Build Docs 40 | if: github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.os == 'ubuntu-latest' && matrix.lisp == 'sbcl-bin' 41 | run: | 42 | ros install neil-lindquist/doc-site-generator 43 | copy-site-base docs docs-bin 44 | echo 'The documentation page for the CI-Utils Common Lisp library.' | make-gh-page README.md docs-bin/index.md 45 | ./generate-API-docs.ros 46 | 47 | - name: Deploy Docs 48 | if: github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.os == 'ubuntu-latest' && matrix.lisp == 'sbcl-bin' 49 | uses: crazy-max/ghaction-github-pages@v3 50 | with: 51 | target_branch: gh-pages 52 | build_dir: docs-bin 53 | env: 54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 55 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | LISP: sbcl-bin 3 | 4 | before_script: 5 | - PATH=~/.roswell/bin:$PATH 6 | - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 7 | - echo "(:tree \"$CI_PROJECT_DIR/\")" > "$HOME/.config/common-lisp/source-registry.conf.d/ci.conf" 8 | 9 | test: 10 | script: 11 | - roswell/run-fiveam.ros -l ci-utils/test :gitlab-ci-tests :noncoveralls-tests :base-tests 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | #from https://github.com/roswell/roswell/wiki/Travis-CI 4 | 5 | addons: 6 | homebrew: 7 | update: true 8 | packages: 9 | - roswell 10 | apt: 11 | packages: 12 | - libc6-i386 13 | - default-jre 14 | 15 | env: 16 | global: 17 | - PATH=~/.roswell/bin:$PATH 18 | - ROSWELL_INSTALL_DIR=$HOME/.roswell 19 | jobs: 20 | - LISP=sbcl-bin DOCS=true 21 | COVERALLS_TEST=:noncoveralls-tests 22 | # CL-coveralls is temporaraly broken 23 | # - LISP=sbcl-bin COVERALLS=true COVERAGE_EXCLUDE=t:test-launcher.txt 24 | # COVERALLS_TEST=:coveralls-tests COVERALLS_REPO_TOKEN=ignore 25 | - LISP=abcl 26 | COVERALLS_TEST=:noncoveralls-tests 27 | - LISP=ecl 28 | COVERALLS_TEST=:noncoveralls-tests 29 | - LISP=alisp 30 | COVERALLS_TEST=:noncoveralls-tests 31 | - LISP=ccl-bin 32 | COVERALLS_TEST=:noncoveralls-tests 33 | - LISP=cmucl 34 | COVERALLS_TEST=:noncoveralls-tests 35 | 36 | jobs: 37 | include: 38 | - os: osx 39 | env: LISP=sbcl-bin 40 | osx_image: xcode12.2 41 | - os: osx 42 | env: LISP=ccl-bin 43 | osx_image: xcode12.2 44 | 45 | cache: 46 | directories: 47 | - $HOME/.roswell 48 | - $HOME/.config/common-lisp 49 | 50 | install: 51 | - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh 52 | - ros install neil-lindquist/doc-site-generator 53 | 54 | script: 55 | - roswell/run-fiveam.ros -l ci-utils/test :travis-tests $COVERALLS_TEST :base-tests 56 | 57 | 58 | before_deploy: 59 | - copy-site-base docs docs-bin 60 | - echo "The documentation page for the CI-Utils Common Lisp library." | make-gh-page README.md docs-bin/index.md 61 | - ./generate-API-docs.ros 62 | 63 | deploy: 64 | provider: pages 65 | skip_cleanup: true 66 | token: $GITHUB_TOKEN 67 | keep_history: true 68 | local_dir: docs-bin 69 | on: 70 | branch: master 71 | condition: $DOCS = true 72 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Neil Lindquist 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /NOTICE.md: -------------------------------------------------------------------------------- 1 | ## Copied Code Licenses 2 | A few code snippets have been taken verbatim or nearly verbatim from other authors, and are licensed under various licenses, as described in the files with such code. 3 | In compliance with those libraries, the text of those licenses is below. 4 | 5 | ### 2-Clause BSD License 6 | > Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | > 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | > 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | > 10 | > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | 12 | ### MIT License 13 | > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | > 15 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | > 17 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## CI-Utils 2 | 3 | [![Travis Status](https://img.shields.io/badge/Build-Disabled-inactive?logo=Travis)](https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing) 4 | [![CircleCI Status](https://img.shields.io/circleci/build/github/neil-lindquist/CI-Utils/master?logo=CircleCI)](https://circleci.com/gh/neil-lindquist/CI-Utils) 5 | [![Appveyor Status](https://ci.appveyor.com/api/projects/status/mm1swvm28hpp2oc5/branch/master?svg=true)](https://ci.appveyor.com/project/neil-lindquist/ci-utils/branch/master) 6 | [![Gitlab CI Status](https://img.shields.io/gitlab/pipeline/neil-lindquist/CI-Utils/master?logo=Gitlab)](https://gitlab.com/neil-lindquist/CI-Utils/pipelines) 7 | [![Bitbucket pipelines status](https://img.shields.io/bitbucket/pipelines/nlindqu1/ci-utils/master?logo=bitbucket)](https://bitbucket.org/nlindqu1/ci-utils/addon/pipelines/home#!/) 8 | [![Azure Pipelines Status](https://img.shields.io/azure-devops/build/archer1mail/archer1mail/1/master?logo=azure%20pipelines)](https://dev.azure.com/archer1mail/archer1mail/_build?definitionId=1&_a=summary) 9 | [![Github Actions Status](https://img.shields.io/github/actions/workflow/status/neil-lindquist/CI-Utils/ci.yml?logo=github)](https://github.com/neil-lindquist/CI-Utils/actions/workflows/ci.yml) 10 | 11 | [![Coveralls coverage](https://img.shields.io/coveralls/github/neil-lindquist/CI-Utils?logo=coveralls)](https://coveralls.io/github/neil-lindquist/CI-Utils) 12 | 13 | ![MIT License](https://img.shields.io/github/license/neil-lindquist/linear-programming.svg?color=informational) 14 | [![Current documentation](https://img.shields.io/badge/docs-current-informational.svg)](https://neil-lindquist.github.io/CI-Utils/) 15 | 16 | CI-Utils is a set of utilities and examples for working on continuous integration platforms, including a run script for the Fiveam test library. 17 | 18 | ### Example CI Configurations 19 | Example configurations for the CI platforms supported by CI-Utils can be found in the [`config-examples`](https://github.com/neil-lindquist/CI-Utils/tree/master/config-examples) directory. 20 | These examples are intended to jump start using CI to test Common Lisp projects. 21 | Basic usage should just require replacing `foo` with the name of the system, possibly adjusting the testing framework, and moving the file (or directory in a few cases) to the project root. 22 | 23 | 24 | ### Installation 25 | If you are using Roswell, run `ros install ci-utils`. 26 | This will download the code where ASDF can find it and place `run-fiveam` in the roswell bin directory. 27 | If you are not using Roswell, either run `(ql:quickload :ci-utils)` or manually download the contents of this repository somewhere that ASDF can find it. 28 | 29 | ### Usage 30 | 31 | See [neil-lindquist.github.io/CI-Utils/API](https://neil-lindquist.github.io/CI-Utils/API) for documentation of the API. 32 | 33 | #### run-fiveam 34 | 35 | The `run-fiveam` Roswell script is designed to make running Fiveam tests simple. 36 | It has the form `run-fiveam [options] `. 37 | The test and suite names are read as symbols after loading any requested systems. 38 | The `--quicklisp ` and `-l ` options load a system using quicklisp. 39 | Note that any root systems in the project directory are automatically loaded. 40 | The `--exclude ` and `-e ` options mark a path for exclusion when measuring code coverage. 41 | Additionally, there are two environmental variables that directly affect run-fiveam. 42 | `COVERALLS` enables measuring code coverage using [cl-coveralls](https://github.com/fukamachi/cl-coveralls/). 43 | `COVERAGE_EXCLUDE` is a colon separated list of paths to exclude from code coverage measurements, in addition to those passed as arguments. 44 | See `run-fiveam --help` for more information. 45 | 46 | #### Platform Features 47 | 48 | CI-Utils adds a few values to `*FEATURES*` that describe the current platform. 49 | First, `:CI` is added if the `CI` environmental variable is set or the system is otherwise recognized as a known CI platform. 50 | Known CI platforms have their name added (listed in the table below). 51 | If `CI` is set but the system is not a recognized CI platform, then `:UNKNOWN-CI` is added. 52 | Finally, if the `COVERALLS` environmental variable is set, then `:COVERALLS` is added. 53 | Note that when the `:COVERALLS` feature is added, CI-Utils replaces the platform inspection in cl-coverall with it's own functions in order to extend platform support. 54 | 55 | | Platform | Symbol Name | 56 | |:---------:|:------------:| 57 | | Travis CI | `:TRAVIS-CI` | 58 | | Circle CI | `:CIRCLECI` | 59 | | Appveyor | `:APPVEYOR` | 60 | | GitLab CI | `:GITLAB-CI` | 61 | | Bitbucket Pipelines | `:BITBUCKET-PIPELINES` | 62 | | Azure Pipelines | `:AZURE-PIPELINES` | 63 | | Github Actions | `:GITHUB-ACTIONS` | 64 | -------------------------------------------------------------------------------- /bitbucket-pipelines.yml: -------------------------------------------------------------------------------- 1 | # bitbucket's default image doesn't contain the needed tools for the roswell installation 2 | image: circleci/buildpack-deps:stretch-curl 3 | 4 | pipelines: 5 | default: 6 | - step: 7 | name: Build and test 8 | script: 9 | - PATH=~/.roswell/bin:$PATH 10 | - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 11 | - echo "(:tree \"$BITBUCKET_CLONE_DIR/\")" > "$HOME/.config/common-lisp/source-registry.conf.d/ci.conf" 12 | - roswell/run-fiveam.ros -l ci-utils/test :bitbucket-pipelines-tests :noncoveralls-tests :base-tests 13 | -------------------------------------------------------------------------------- /ci-utils-features.asd: -------------------------------------------------------------------------------- 1 | 2 | (defsystem "ci-utils-features" 3 | :description "An internal system that loads the features before loading the rest of the systems" 4 | :author "Neil Lindquist " 5 | :license "MIT" 6 | :pathname "src" 7 | :components ((:file "features"))) 8 | -------------------------------------------------------------------------------- /ci-utils.asd: -------------------------------------------------------------------------------- 1 | 2 | (defsystem "ci-utils" 3 | :description "A set of tools for using CI platforms" 4 | :version "1.0.0" 5 | :author "Neil Lindquist " 6 | :license "MIT" 7 | :depends-on ("ci-utils-features") 8 | :pathname "src" 9 | :serial t 10 | :components ((:file "ci-utils")) 11 | :in-order-to ((test-op (test-op "ci-utils/test")))) 12 | 13 | (defsystem "ci-utils/coveralls" 14 | :description "A set of tools for using CI platforms" 15 | :version "1.0.0" 16 | :author "Neil Lindquist " 17 | :license "MIT" 18 | :defsystem-depends-on ("ci-utils-features") 19 | :depends-on ("ci-utils" 20 | (:feature :coveralls "cl-coveralls") 21 | "split-sequence") 22 | :pathname "src" 23 | :serial t 24 | :components ((:file "coveralls"))) 25 | 26 | 27 | (defsystem "ci-utils/test" 28 | :description "Test for CI-Utils" 29 | :author "Neil Lindquist " 30 | :license "MIT" 31 | :depends-on ("ci-utils" 32 | "ci-utils/coveralls" 33 | "fiveam" 34 | "split-sequence") 35 | :pathname "t" 36 | :components ((:file "tests")) 37 | :perform (test-op (o c) (symbol-call '#:fiveam '#:run! '(:user-tests 38 | :noncoveralls-tests)))) 39 | -------------------------------------------------------------------------------- /config-examples/.appveyor.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Appveyor ### 2 | 3 | image: Visual Studio 2022 4 | 5 | platform: 6 | - x64 7 | 8 | environment: 9 | BIT: 64 10 | COMPILER: msys2 11 | MSYS2_ARCH: x86_64 12 | MSYS2_DIR: msys64 13 | MSYSTEM: MINGW64 14 | ROSWELL_INSTALL_DIR: C:/Users/appveyor/.roswell/ 15 | PATH: c:\msys64\usr\bin;c:\msys64\mingw64\bin;C:\Users\appveyor\.roswell\bin\;%PATH% 16 | PLATFORM: x64 17 | matrix: 18 | # While multiple implementations can be specified, not all implementations work on Windows/Appveyor 19 | - LISP: sbcl-bin 20 | 21 | # note that the roswell scripts have to explicitly be run through bash, 22 | # since cmd doesn't support shabangs and powershell doesn't support exec 23 | install: 24 | - bash -lc "curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh" 25 | - ros install neil-lindquist/ci-utils #for asdf-register-project and run-fiveam 26 | - bash -lc "asdf-register-project" 27 | # - ros install prove #for run-prove 28 | # - ros install rove #for [run-] rove 29 | 30 | build: off 31 | 32 | test_script: 33 | - bash -lc "run-fiveam -e t -l foo/test :foo-tests" 34 | #- bash -lc "run-prove foo.asd" 35 | #- bash -lc "rove foo.asd" 36 | -------------------------------------------------------------------------------- /config-examples/.azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Azure Pipelines ### 2 | 3 | # Some of the configuration is copied from https://pastebin.com/u4gUKtYN 4 | 5 | 6 | trigger: 7 | branches: 8 | include: ['*'] 9 | tags: 10 | include: ['*'] 11 | 12 | variables: 13 | # This URL is pulled out because it's too long to be nicely readable 14 | ROSWELL_ZIP: https://ci.appveyor.com/api/projects/snmsts/roswell-en89n/artifacts/Roswell-x86_64.zip?branch=master&job=Environment%3A%20MSYS2_ARCH%3Dx86_64,%20MSYS2_BITS%3D64,%20MSYSTEM%3DMINGW64,%20METHOD%3Dcross 15 | 16 | jobs: 17 | - job: 'Test' 18 | strategy: 19 | matrix: 20 | # Configure OS and lisp implementations here 21 | # Each combination of OS and implementation needs it's own section 22 | win_sbcl: 23 | target: 'x86_64-windows-10' 24 | imageName: 'windows-latest' 25 | LISP: sbcl-bin 26 | linux_sbcl: 27 | target: 'x86_64-unknown-linux-gnu' 28 | imageName: 'ubuntu-16.04' 29 | LISP: sbcl-bin 30 | linux_ccl: 31 | target: 'x86_64-unknown-linux-gnu' 32 | imageName: 'ubuntu-16.04' 33 | LISP: ccl-bin 34 | mac_sbcl: 35 | target: 'x86_64-apple-darwin' 36 | imageName: 'macos-10.13' 37 | LISP: sbcl-bin 38 | pool: 39 | vmImage: $(imageName) 40 | 41 | steps: 42 | # Install roswell 43 | # Windows needs a seperate installation, due to differences in available tools 44 | - bash: | 45 | PATH=$PATH:$HOME/.roswell/bin:/etc/roswell/bin 46 | echo "##vso[task.setvariable variable=PATH]$PATH" #Store the configured PATH for later steps 47 | curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh 48 | displayName: Install Roswell for *nix 49 | condition: ne( variables['Agent.OS'], 'Windows_NT' ) 50 | - powershell: | 51 | iex "& {$(irm get.scoop.sh)} -RunAsAdmin" 52 | scoop install roswell 53 | ros install %LISP% 54 | ros config 55 | mkdir "$Env:LOCALAPPDATA\config\common-lisp\source-registry.conf.d\" 56 | # $Env:dir = "%AGENT_BUILDDIRECTORY:\=/%" 57 | Set-Content -Path "$Env:LOCALAPPDATA\config\common-lisp\source-registry.conf.d\ci.conf" -Value "(:tree ""$Env:AGENT_BUILDDIRECTORY"")" 58 | displayName: Install Roswell for Windows 59 | condition: eq( variables['Agent.OS'], 'Windows_NT' ) 60 | 61 | - bash: | 62 | set -e # Ensure Azure is informed of any failures 63 | # install ci-utils and register the project's working directory with asdf 64 | ros install neil-lindquist/ci-utils #for register project and run-fiveam 65 | asdf-register-project 66 | 67 | # Run the tests 68 | run-fiveam -e t -l foo/test :foo-tests 69 | #ros install prove 70 | #run-prove foo.asd 71 | #ros install rove 72 | #rove foo.asd 73 | displayName: Run Tests 74 | -------------------------------------------------------------------------------- /config-examples/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Circle CI ### 2 | 3 | version: 2 4 | 5 | # Note that CircleCI's support for multiple jobs with the same steps is nonexistant. 6 | # So, each implementation needs an entry in the jobs group, and to be listed in the workflows section at the bottom. 7 | 8 | jobs: 9 | sbcl: 10 | docker: 11 | - image: circleci/buildpack-deps:stretch-curl 12 | environment: 13 | LISP: sbcl-bin 14 | steps: 15 | - checkout 16 | # This is the only way CircleCI allows setting environmental variables accross steps 17 | - run: 18 | name: Setup Environment Variables 19 | command: | 20 | echo "export PATH=$HOME/.roswell/bin:$PATH" >> $BASH_ENV 21 | 22 | - run: echo $LISP 23 | - run: curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 24 | - run: ros install neil-lindquist/ci-utils # for run-fiveam 25 | #- run: ros install prove # for run-prove 26 | #- run: ros install rove # for [run-] rove 27 | 28 | - run: run-fiveam -e t -l foo/test :foo-tests 29 | #- run: run-prove foo.asd 30 | #- run: rove foo.asd 31 | ccl: 32 | docker: 33 | - image: circleci/buildpack-deps:stretch-curl 34 | environment: 35 | LISP: ccl-bin 36 | steps: 37 | - checkout 38 | # This is the only way CircleCI allows setting environmental variables accross steps 39 | - run: 40 | name: Setup Environment Variables 41 | command: | 42 | echo "export PATH=$HOME/.roswell/bin:$PATH" >> $BASH_ENV 43 | 44 | - run: echo $LISP 45 | - run: curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 46 | - run: ros install neil-lindquist/ci-utils # for run-fiveam 47 | #- run: ros install prove # for run-prove 48 | #- run: ros install rove # for [run-] rove 49 | 50 | - run: run-fiveam -e t -l foo/test :foo-tests 51 | #- run: run-prove foo.asd 52 | #- run: rove foo.asd 53 | 54 | 55 | 56 | workflows: 57 | version: 2 58 | run_tests: 59 | jobs: 60 | - sbcl 61 | - ccl 62 | -------------------------------------------------------------------------------- /config-examples/.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Github Actions ### 2 | name: CI 3 | 4 | # Github Actions allows for running jobs on a wide variety of events 5 | on: 6 | push: # Commits pushed to Github 7 | pull_request: # Pull request is update 8 | workflow_dispatch: # Manually dispatched from Github's UI 9 | schedule: # Run at the first day of each month 10 | # This can detect external factors breaking the tests (such as changes to libraries or CL implementations) 11 | # Syntax follows that of cron 12 | - cron: '0 0 1 * *' 13 | 14 | jobs: 15 | test: 16 | name: ${{ matrix.lisp }} on ${{ matrix.os }} 17 | runs-on: ${{ matrix.os }} 18 | strategy: 19 | # Each combination of lisp and os are tested 20 | matrix: 21 | lisp: [sbcl-bin, ccl-bin] 22 | os: [windows-latest, ubuntu-latest, macOS-latest] 23 | 24 | steps: 25 | # This action checks out our code in the working directory 26 | - uses: actions/checkout@v2 27 | # setup-lisp requires an env variable to be set, not matrix.lisp 28 | - name: Set LISP env var 29 | run: echo "LISP=${{ matrix.lisp }}" >> $GITHUB_ENV 30 | # This action installs roswell and a few other utilities such as qlot 31 | - uses: 40ants/setup-lisp@v2 32 | 33 | # These steps run our tests 34 | # Windows needs to be run with the msys2 shell due to how roswell is installed 35 | - name: Run tests (Non-Windows) 36 | if: runner.os != 'Windows' 37 | shell: bash 38 | run: | 39 | # Install the roswell script for the test library 40 | ros install neil-lindquist/ci-utils # for run-fiveam 41 | #ros install prove # for run-prove: 42 | #ros install rove # for [run-] rove 43 | 44 | # Run the tests 45 | run-fiveam -e t -l foo/test :foo-tests 46 | run-prove foo.asd 47 | rove foo.asd 48 | - name: Run tests (Windows) 49 | if: runner.os == 'Windows' 50 | shell: msys2 {0} 51 | run: | 52 | # Install the roswell script for the test library 53 | ros install neil-lindquist/ci-utils # for run-fiveam 54 | #ros install prove # for run-prove: 55 | #ros install rove # for [run-] rove 56 | 57 | # Run the tests 58 | run-fiveam -e t -l foo/test :foo-tests 59 | run-prove foo.asd 60 | rove foo.asd 61 | -------------------------------------------------------------------------------- /config-examples/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Gitlab CI ### 2 | 3 | # This is the part that is shared between all jobs 4 | .test: 5 | before_script: 6 | - PATH=$HOME/.roswell/bin:$PATH 7 | - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 8 | - ros install neil-lindquist/ci-utils # for run-fiveam and asdf-register-project 9 | #- ros install prove # for run-prove 10 | #- ros install rove # for [run-] rove 11 | - asdf-register-project 12 | 13 | script: 14 | - run-fiveam -e t -l foo/test :foo-tests 15 | #- run-prove foo.asd 16 | #- rove foo.asd 17 | 18 | 19 | # Each job requires a seperate top level form that extends .test 20 | 21 | test-sbcl: 22 | extends: .test 23 | variables: 24 | LISP: sbcl-bin 25 | 26 | test-ccl: 27 | extends: .test 28 | variables: 29 | LISP: ccl-bin 30 | -------------------------------------------------------------------------------- /config-examples/.travis.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Travis CI ### 2 | 3 | language: generic 4 | 5 | addons: 6 | homebrew: 7 | update: true 8 | packages: 9 | - roswell 10 | apt: 11 | packages: 12 | - libc6-i386 # needed for a couple implementations 13 | - default-jre # needed for abcl 14 | 15 | # Runs each lisp implementation on each of the listed OS 16 | os: 17 | - linux 18 | # - osx # OSX has a long setup on travis, so it's likely easier to just run select implementations on OSX 19 | 20 | env: 21 | global: 22 | - PATH=~/.roswell/bin:$PATH 23 | - ROSWELL_INSTALL_DIR=$HOME/.roswell 24 | # - COVERAGE_EXCLUDE=t # for prove or rove 25 | jobs: 26 | # The implementation and whether coverage is send to coveralls are controlled with these environmental variables 27 | - LISP=sbcl-bin COVERALLS=true 28 | - LISP=abcl 29 | - LISP=ecl 30 | - LISP=alisp 31 | - LISP=ccl-bin 32 | - LISP=cmucl 33 | 34 | # Additional OS/Lisp combinations can be added to those generated above 35 | jobs: 36 | include: 37 | - os: osx 38 | env: LISP=sbcl-bin 39 | - os: osx 40 | env: LISP=ccl-bin 41 | 42 | # Some jobs can be marked as allowed to fail 43 | # Note that this should only be used if there is no interest for the library to work on that system 44 | # allow_failures: 45 | # - env: LISP=abcl 46 | # - env: LISP=ecl 47 | # - env: LISP=cmucl 48 | # - env: LISP=alisp 49 | # os: osx 50 | 51 | fast_finish: true 52 | 53 | cache: 54 | directories: 55 | - $HOME/.roswell 56 | - $HOME/.config/common-lisp 57 | 58 | install: 59 | - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh 60 | - ros install ci-utils #for run-fiveam 61 | # - ros install prove #for run-prove 62 | # - ros install rove #for [run-] rove 63 | 64 | # If asdf 3.16 or higher is needed, uncomment the following lines 65 | #- mkdir -p ~/common-lisp 66 | #- if [ "$LISP" == "ccl-bin" ]; then git clone https://gitlab.common-lisp.net/asdf/asdf.git ~/common-lisp; fi 67 | 68 | script: 69 | - run-fiveam -e t -l foo/test :foo-tests 70 | #- run-prove foo.asd 71 | #- rove foo.asd 72 | -------------------------------------------------------------------------------- /config-examples/bitbucket-pipelines.yml: -------------------------------------------------------------------------------- 1 | ### Example configuration for Bitbucket Pipelines ### 2 | 3 | # bitbucket's default image doesn't contain the needed tools for the roswell installation 4 | image: circleci/buildpack-deps:stretch-curl 5 | 6 | pipelines: 7 | default: 8 | - step: 9 | name: Install and test 10 | script: 11 | # Install roswell and the testing framework 12 | - PATH=$HOME/.roswell/bin:$PATH 13 | - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | bash 14 | - ros install neil-lindquist/ci-utils # for run-fiveam and asdf-register-project 15 | #- ros install prove # for run-prove 16 | #- ros install rove # for [run-] rove 17 | - asdf-register-project 18 | 19 | # Run the tests 20 | - run-fiveam -e t -l foo/test :foo-tests 21 | #- run-prove foo.asd 22 | #- rove foo.asd 23 | -------------------------------------------------------------------------------- /docs/Comparison-of-CI-platforms.md: -------------------------------------------------------------------------------- 1 | There are a variety of CI platforms available today, so projects need to decide which platform or platforms to use. 2 | I strongly recommend that, at least for tests, the CI scripts are run on as many Common Lisp implementations as possible, and on OSX and Windows in addition to Linux, to improve the portability of your project. 3 | My basic recommendation for which CI platform to use is Travis CI for Linux and OSX and Appveyor for Windows. 4 | These platforms are well documented and are commonly used platforms for open source projects. 5 | 6 | Currently, CI-Utils supports 7 CI platforms, all of which have cloud hosting and all but one have free plans for open source software. 7 | A brief description of each is listed below for comparison purposes. 8 | If there is another platform that you are interested in, please raise a pull request or issue and we can work through adding support and documentation. 9 | 10 | | Platform | OS | Supported Repository Hosts | 11 | | -------- | -- | -------------------------- | 12 | | [Travis CI](#travis-ci) | Linux, OSX | Github | 13 | | [Appveyor](#appveyor) | Windows | Github, Bitbucket, Gitlab, Azure Repos, and more | 14 | | [CircleCI](#circleci) | Linux, OSX (paid only) | Github, Bitbucket | 15 | | [Azure Pipelines](#azure-pipelines) | Linux, OSX, Windows | Github, Bitbucket, Azure Repos, and more | 16 | | [Gitlab CI](#gitlab-ci) | Linux | Gitlab, Github, Bitbucket, and more | 17 | | [Bitbucket Pipelines](#bitbucket-pipelines) | Linux | Bitbucket | 18 | | [Github Actions](#github-actions) | Linux, OSX, Windows | Github | 19 | 20 | 21 | ### [Travis CI](https://travis-ci.org/) 22 | Travis CI is one of the oldest cloud hosted CI platforms, and thus is well documented and has plenty of examples. 23 | Unfortunately, only Github repositories are supported. 24 | Additionally, Travis only supports Linux and OSX, with OSX builds usually being slower due to a combination of limits on parallel jobs and homebrew needing to update a number of packages every time. 25 | Notably, Travis allows 5 Linux jobs and 2 OSX jobs to be run in parallel. 26 | Support for Windows is being developed; however, when tested, none of the Windows jobs were actually run. 27 | 28 | Travis require [payment for both public and private repositories](https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing). 29 | A free trial is available, providing 1000 minutes of Linux, 500 minutes of Windows, 200 minutes of Mac, or some combination there of. 30 | Additionally, Travis CI Enterprise provides an option for self hosting, as well as other quality of life benefits. 31 | 32 | ### [Appveyor](https://www.appveyor.com/) 33 | Appveyor is another popular CI platform, with a focus Windows. 34 | It's oriented for development of native Windows code, but supports non-C/C++ projects just fine. 35 | Support for Linux jobs is documented; however, when tested it immediately failed to create the folder for the build. 36 | Appveyor supports a variety of repository hosts, allowing it to fit in many workflows. 37 | Finally, Appveyor offers self hosting to all users. 38 | 39 | Appveyor is free for public repositories and a single private repository. 40 | Paid accounts provide unlimited private repositories and running jobs in parallel. 41 | 42 | ### [CircleCI](https://circleci.com/) 43 | CircleCI is designed for performance and effective management of computing resources. 44 | Additionally, it provides the ability to run a single job multiple times in parallel. 45 | This allows a test suite, or other work load, to be parallelized, either manually using the `CIRCLE_NODE_TOTAL` and `CIRCLE_NODE_INDEX` environmental variables or their `circleci tests split` command. 46 | 47 | CircleCI provides a free plan with 1 Linux container for private projects as well as 4 Linux containers and 1 OSX container for public projects. 48 | Note that parallel jobs use multiple containers (i.e. 2x parallelism results in each job using 2 containers). 49 | Additionally, there are paid plans for increased numbers of containers, and a self hosted server. 50 | 51 | ### [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) 52 | Azure Pipelines is the CI service of Microsoft's Azure cloud computing offerings. 53 | Azure pipelines is the only one of these platforms that successfully supports all three major operating systems. 54 | Additionally, it is designed to integrate well with other Azure services. 55 | Azure Pipelines offers both cloud hosted and self hosted servers. 56 | 57 | Azure pipelines provides a free plan with 1 job at a time and up to 1,800 minutes per month for private projects, and 10 jobs in parallel for open source projects. 58 | There are also paid plans that allow for running more jobs in parallel and more build time. 59 | 60 | 61 | ### [Gitlab CI](https://docs.gitlab.com/ee/ci/) 62 | Gitlab provides a CI platform right out of the box for both cloud hosted and self hosted instances of Gitlab, including [gitlab.common-lisp.net](https://gitlab.common-lisp.net). 63 | Interestingly, Gitlab CI also allows, and even encourages, use of it's CI system for repositories not hosted in Gitlab, although this does involve a lightweight mirror of the repository. 64 | 65 | The only limitation of Gitlab's free account for CI purposes is a limit of 2,000 minutes per month when using the cloud hosted instance, and no restrictions for self hosted instances. 66 | 67 | ### [Bitbucket Pipelines](https://bitbucket.org/product/features/pipelines) 68 | Bitbucket pipelines is Bitbucket's CI offering. 69 | It doesn't provide any notable features compared to other platforms, but may be convenient for projects hosted on Bitbucket. 70 | 71 | The free plan only provides 50 minutes, although users with an academic email are able to get 500 minutes for free. 72 | Additionally, non-profit charities can apply for a community subscription that also provides 500 CI minutes. 73 | 74 | 75 | ### [Github Actions](https://github.com/features/actions) 76 | Github Actions is the CI platform provided right from Github. 77 | The focus seems to be one modular actions that provide building blocks for different actions 78 | 79 | Free Github accounts provides 2000 minutes per month, with additional minutes for paid Github accounts. 80 | Additionally, there is a self-hosting option, without a time cap for free accounts. 81 | -------------------------------------------------------------------------------- /docs/Introduction-to-CI.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Introduction to CI Testing 4 | meta-description: A primer for testing Common Lisp libraries on Cloud CI platforms 5 | --- 6 | 7 | Continuous Integration (CI) is the method of running tests, building binaries, and similar task after most committed modifications of a codebase, usually on a cloud platform or internal server for the project. 8 | This allows a project to ensure its tests are run regularly, and makes it obvious whenever the a change causes tests to break. 9 | Other tasks, such as building binaries or updating documentation can reduce the workload of developers while still maintaining those artifacts. 10 | The approach of continuous integration offers benefits to any project that has a series of steps taken after most (or specific types of) changes to the codebase. 11 | This introduction focuses more on running tests since that is the use case for most projects; however, the ideas and most of the tooling generalizes to other tasks. 12 | 13 | 14 | A quick note on styling, because uppercase I and lowercase L can look similar, the abbreviations CI and CL can look similar. 15 | To address this, this project uses the convention that both letters in these acronyms should always be the same case (i.e. CI means Continuous Integration, while Cl will never be used). 16 | I strongly encourage other users of CI with CL to use this convention too. 17 | 18 | 19 | Technically, the phrase "Continuous Integration" originally referred to integrating each developer's working copy of a codebase into the master copy on a regular basis to ensure that integrating the various changes doesn't become a monumental task. 20 | However, the phrase continuous integration more often used to describe automating scripts to run after changes to a codebase, and is used as such in this document and project. 21 | Some people use terms like "Continuous Deployment" and "Continuous Testing", especially if they want to emphasize a particular action that's taken (e.g. deployment and testing respectively). 22 | 23 | 24 | ### Configuration Basics 25 | 26 | The rise of continuous integration tools for small and medium sized projects has been part of the rise of cloud computing and software as a service. 27 | There are a variety of cloud platforms that provide CI services; however, they all follow similar ideas for configuration and usage. 28 | The main method for configuring these platforms is to include a [YAML](https://yaml.org/) configuration file in the root directory of the repository named `.platform.yml` (i.e. `.travis.yml`). 29 | Some platforms have different naming requirements or configuration locations. 30 | You can find example configuration files for most of CI-Util's supported platforms in its [config-examples](https://github.com/neil-lindquist/CI-Utils/tree/master/config-examples) directory. 31 | 32 | The term "build" is used to describe the entire set of scripts and actions that are run after a commit. 33 | Each build consists of a set of "jobs". 34 | The jobs divide the scripts and actions between separate containers. 35 | When running tests, each job will run the tests for one system configuration, such as a combination of lisp implementation and operating system. 36 | If any of the commands in a job fails (by having a non-zero return value), the entire job is marked as a failure and terminated. 37 | Similarly, if any jobs fail, the entire build is marked as a failure. 38 | This propagation of failures helps make it easy to determine if everything was successful. 39 | 40 | There are a couple of ways to keep an eye on the status of your builds. 41 | First, email notifications can be enabled, so that the results of builds are sent to one or more addresses. 42 | Usually, the frequency can be adjusted so that emails are only sent if the build fails, or if there is a change in the build's status. 43 | How notifications are configured and the types of notifications that are supported vary between platforms. 44 | The second main method to monitor build statuses is through badges on the repository's webpage or in it's README. 45 | For example, consider the live badge for CI-Utils on Travis CI: [![Travis Build Status](https://img.shields.io/travis/neil-lindquist/ci-utils.svg?logo=Travis)](https://travis-ci.org/neil-lindquist/CI-Utils), which hopefully tells you that the last build on Travis CI for CI-Utils passed. 46 | These badges are primarily used to show the status of tests, since they provide a convenient way to show people looking at the repository that there are tests that are run regularly, and whether those tests are passing. 47 | 48 | Some commits don't contain changes that require a new CI build. 49 | There are two major ways to tell CI platforms that the commit shouldn't be build. 50 | The first is to limit the branches and tags that CI should be run for, often specific jobs can be disabled outside specific branches/tags. 51 | This is specified in the configuration file, and varies significantly between platforms. 52 | Branch and tag limitations are primarily for limiting actions like building binaries or deploying documentation, which shouldn't happen on every commit. 53 | The second is to skip CI for a specific commit. 54 | To skip building on every platform, add `[skip ci]` to the commit's message. 55 | Alternatively, if CI should be skipped on only some platforms, most platforms obey `[skip ]` in the commit message. 56 | -------------------------------------------------------------------------------- /docs/Other-Resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Other Resources 4 | meta-description: Other resources for testing Common Lisp libraries on Cloud CI platforms 5 | --- 6 | 7 | Links to other documentation and information about using CI, particularly for Common Lips, are provided here. 8 | 9 | Official platform documentation: 10 | * [Travis CI](https://docs.travis-ci.com/) 11 | * [Appveyor](https://www.appveyor.com/docs/) 12 | * [Circle CI](https://circleci.com/docs/) 13 | * [Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops) 14 | * [Gitlab CI](https://docs.gitlab.com/ee/ci/) 15 | * [Bitbucket Pipelines](https://support.atlassian.com/bitbucket-cloud/docs/build-test-and-deploy-with-pipelines/) 16 | * [Github Actions](https://docs.github.com/en/actions) 17 | 18 | Common Lisp specific advice 19 | * [Roswell's CI documentation](https://github.com/roswell/roswell/wiki/Roswell-as-a-Testing-Environment) 20 | * Blog posts by [3b](https://github.com/3b/) for Github Actions: [Part 1](http://3bb.cc/blog/2020/09/11/github-ci/), [Part 2](http://3bb.cc/blog/2020/09/13/github-ci2/), [Part 3](http://3bb.cc/blog/2020/09/25/github-ci3/) 21 | * [lisp-lang.org CI page](https://lisp-lang.org/learn/continuous-integration) 22 | * [The Common Lisp Cookbook - Continuous Integration](https://lispcookbook.github.io/cl-cookbook/testing.html#continuous-integration) 23 | 24 | Common Lisp Libraries 25 | * [cl-coveralls](https://github.com/fukamachi/cl-coveralls/) 26 | * [cl-travis](https://github.com/luismbo/cl-travis) 27 | * [A more recently maintained fork](https://github.com/lispci/cl-travis) 28 | * [40Ants-CI](https://40ants.com/ci/) - A Github Actions workflow 29 | * [setup-lisp](https://40ants.com/setup-lisp/) 30 | * [run-tests](https://40ants.com/run-tests/) 31 | 32 | Select resources for CL test frameworks 33 | * [CLiki's list of CL test libraries](https://www.cliki.net/Test%20Framework) 34 | * [Awesome CL's testing recomendations](https://github.com/CodyReichert/awesome-cl#unit-testing) 35 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | # --- General options --- # 2 | 3 | baseurl: "/CI-Utils" 4 | 5 | # Name of website 6 | title: CI-Utils 7 | 8 | # Short description of your site 9 | description: Documentation for the CI-Utils Common Lisp library. 10 | 11 | # --- Navigation bar options --- # 12 | 13 | # List of links in the navigation bar 14 | navbar-links: 15 | API Documentation: "API" 16 | CI Basics: 17 | - Introduction to CI: "Introduction-to-CI" 18 | - Comparison of CI Platforms: "Comparison-of-CI-platforms" 19 | Other Resources: "Other-Resources" 20 | 21 | # Image to show in the navigation bar - image must be a square (width = height) 22 | # Remove this parameter if you don't want an image in the navbar 23 | # avatar: "/img/avatar.png" 24 | 25 | # If you want to have an image logo in the top-left corner instead of the title text, 26 | # then specify the following parameter 27 | # title-img: /path/to/image 28 | 29 | # --- Footer options --- # 30 | 31 | # Select your active Social Network Links. 32 | # Uncomment the links you want to show in the footer and add your information to each link. 33 | # You can reorder the items to define the link order. 34 | # If you want to add a new link that isn't here, you'll need to also edit the file _data/SocialNetworks.yml 35 | social-network-links: 36 | email: "neillindquist5@gmail.com" 37 | public-key: "/neil-lindquist-public-key.pgp" 38 | github: neil-lindquist/ci-utils 39 | # linkedin: neil-lindquist 40 | # orcid: 0000-0001-9404-3121 41 | # rss: true 42 | # facebook: daattali 43 | # twitter: daattali 44 | # reddit: yourname 45 | # xing: yourname 46 | # stackoverflow: "3943160/daattali" 47 | # snapchat: deanat78 48 | # instagram: deanat78 49 | # youtube: user/deanat78 50 | # spotify: yourname 51 | # telephone: +14159998888 52 | # steam: deanat78 53 | # twitch: yourname 54 | # yelp: yourname 55 | 56 | 57 | # Exclude these files from production site 58 | exclude: 59 | 60 | # Default YAML values (more information on Jekyll's site) 61 | defaults: 62 | - 63 | scope: 64 | path: "" 65 | type: "posts" 66 | values: 67 | layout: "post" 68 | comments: false # add comments to all blog posts 69 | social-share: false # add social media sharing buttons to all blog posts 70 | - 71 | scope: 72 | path: "" # all files 73 | values: 74 | layout: "page" 75 | show-avatar: false 76 | -------------------------------------------------------------------------------- /generate-API-docs.ros: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #|-*- mode:lisp -*-|# 3 | #| 4 | exec ros -Q -- $0 "$@" 5 | |# 6 | 7 | (ql:quickload '(:ci-utils/coveralls :doc-site-generator)) 8 | (use-package :doc-gen) 9 | 10 | (defun main (&rest argv) 11 | (declare (ignore argv)) 12 | 13 | (with-open-file (stream "docs-bin/API.md" 14 | :direction :output 15 | :external-format :utf-8) 16 | 17 | (format stream "---~%~ 18 | layout: page~%~ 19 | title: API Documentation~%~ 20 | meta-description: The API Documentation for the CI-Utils~ 21 | Common Lisp library.~%~ 22 | ---~%~%~%") 23 | 24 | 25 | (print-package-documentation 'ci-utils stream) 26 | (print-package-documentation 'ci-utils/coveralls stream))) 27 | -------------------------------------------------------------------------------- /roswell/asdf-register-project.ros: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #|-*- mode:lisp -*-|# 3 | #| 4 | exec ros -Q -- $0 "$@" 5 | |# 6 | 7 | ;cmucl crashes with silent on 8 | (ql:quickload '(:ci-utils) 9 | :silent (not (member :cmu *features*))) 10 | 11 | (defpackage :ros.script.asdf-register-project 12 | (:use :cl)) 13 | (in-package :ros.script.asdf-register-project) 14 | 15 | 16 | (defun show-help () 17 | (format t "~ 18 | Usage: asdf-register-project [options] 19 | Registers the current project with ASDF. Unless running on a known CI system, 20 | the current working directory will be used as the package directory. 21 | Options 22 | --help|-h - prints this help message") 23 | (uiop:quit 2)) 24 | 25 | 26 | (defun main (&rest argv) 27 | (when (< 0 (length argv)) 28 | (show-help)) 29 | (let* ((source-registry-dir (asdf:user-source-registry-directory :direction :output)) 30 | (source-registry (merge-pathnames (concatenate 'string "ci-utils--build-dir.conf") 31 | source-registry-dir))) 32 | (ensure-directories-exist source-registry) 33 | (with-open-file (stream source-registry 34 | :direction :output 35 | :if-exists :error 36 | :if-does-not-exist :create) 37 | (format stream "(:tree ~S)" (truename (ci-utils:build-dir)))))) 38 | -------------------------------------------------------------------------------- /roswell/run-fiveam.ros: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #|-*- mode:lisp -*-|# 3 | #| 4 | exec ros -Q -- $0 "$@" 5 | |# 6 | 7 | ;cmucl crashes with silent on 8 | (ql:quickload '(:ci-utils/coveralls :fiveam :iterate) 9 | :silent (not (member :cmu *features*))) 10 | 11 | (defpackage :ros.script.run-fiveam 12 | (:use :cl 13 | :iterate)) 14 | (in-package :ros.script.run-fiveam) 15 | 16 | 17 | (defun show-help () 18 | (format t "~ 19 | Usage: run-fiveam [options] ... 20 | Loads the system with quicklisp then calls fiveam:run! with a list of test 21 | names. Each test name is parsed with read-from-string after systems are loaded, 22 | allowing package qualified test names to be used. 23 | 24 | If the COVERALLS environemenal variable is present and non-empty, coverage will 25 | be measured and reported to COVERALLS on platforms supported by CI-Utils. 26 | Additionally, the environmental variable COVERAGE_EXCLUDE is read as a colon 27 | seperated list of paths to exclude from measuring coverage, in addition to those 28 | specified as arguments. 29 | 30 | Note that currently the systems in the project root are loaded with 31 | COVERALLS is enable. This behavior is not to be relied on and may change in 32 | the future, so instead use the `--quicklisp`/`-l` flag. 33 | Options 34 | --help|-h - prints this help message 35 | --quickload|-l - lists an additional system to load 36 | --coverage-exclude|-e - lists a path to excluded from the coverage 37 | measurement~%") 38 | (uiop:quit 2)) 39 | 40 | 41 | (defun main (&rest argv) 42 | (when (> 1 (length argv)) 43 | (show-help)) 44 | (setf fiveam:*on-error* :backtrace 45 | fiveam:*on-failure* :backtrace) 46 | (iter (generate arg-list in argv) 47 | (for arg = (next arg-list)) 48 | (cond 49 | ((or (string= "--help" arg) (string= "-h" arg)) 50 | (show-help)) 51 | ((or (string= "--quickload" arg) (string= "-l" arg)) 52 | (collect (next arg-list) into loaded-systems)) 53 | ((or (string= "--exclude" arg) (string= "-e" arg)) 54 | (collect (next arg-list) into excluded)) 55 | (t 56 | (collect arg into tests))) 57 | ;evaluate tests here with `loaded-systems`, `excluded`, and `tests` in scope 58 | (finally 59 | (setf excluded (nconc excluded (ci-utils/coveralls:coverage-excluded))) 60 | (ci-utils/coveralls:with-coveralls excluded 61 | (when loaded-systems 62 | (ql:quickload loaded-systems)) 63 | (unless (fiveam:run! (mapcar 'read-from-string tests)) 64 | (uiop:quit 1)))))) 65 | -------------------------------------------------------------------------------- /src/ci-utils.lisp: -------------------------------------------------------------------------------- 1 | (uiop:define-package :ci-utils 2 | (:use :cl) 3 | (:export #:cip 4 | #:platform 5 | #:build-dir 6 | #:build-id 7 | #:pull-request-p 8 | #:branch 9 | #:commit-id)) 10 | 11 | (in-package :ci-utils) 12 | 13 | (defun cip () 14 | "Whether lisp is running on a CI platform." 15 | #+ci t 16 | #-ci nil) 17 | 18 | (defun platform () 19 | "Returns the current CI platform. When on a non-ci platform, nil is returned. 20 | The following is the symbols for supported platforms 21 | 22 | | Platform | Symbol Name | 23 | |:-------------------:|:----------------------:| 24 | | Travis CI | `:TRAVIS-CI` | 25 | | Circle CI | `:CIRCLECI` | 26 | | Appveyor | `:APPVEYOR` | 27 | | GitLab CI | `:GITLAB-CI` | 28 | | Bitbucket Pipelines | `:BITBUCKET-PIPELINES` | 29 | | Azure Pipelines | `:AZURE-PIPELINES` | 30 | | Github Actions | `:GITHUB-ACTIONS` | 31 | | unknown ci systems | `:UNKNOWN-CI` | 32 | " 33 | #+travis-ci :travis-ci 34 | #+circleci :circleci 35 | #+appveyor :appveyor 36 | #+gitlab-ci :gitlab-ci 37 | #+bitbucket-pipelines :bitbucket-pipelines 38 | #+azure-pipelines :azure-pipelines 39 | #+github-actions :github-actions 40 | #+unknown-ci :unknown-ci 41 | #-ci nil) 42 | 43 | (defun build-dir () 44 | "Returns the directory that the code was copied into. When not on a known CI 45 | platform, the current working directory is returned." 46 | #+travis-ci (uiop:getenv "TRAVIS_BUILD_DIR") 47 | #+circleci (uiop:getenv "CIRCLE_WORKING_DIRECTORY") 48 | #+appveyor (string-upcase (uiop:getenv "APPVEYOR_BUILD_FOLDER") :end 1) 49 | #+gitlab-ci (uiop:getenv "CI_PROJECT_DIR") 50 | #+bitbucket-pipelines (uiop:getenv "BITBUCKET_CLONE_DIR") 51 | #+azure-pipelines (uiop:getenv "BUILD_SOURCESDIRECTORY") 52 | #+github-actions (uiop:getenv "GITHUB_WORKSPACE") 53 | #+(or (not ci) unknown-ci) (uiop:getcwd)) 54 | 55 | (defun build-id () 56 | "Returns the build id for the given platform. `NIL` is returned on unsupported 57 | platforms." 58 | #+travis-ci (uiop:getenv "TRAVIS_JOB_ID") 59 | #+circleci (uiop:getenv "CIRCLE_BUILD_NUM") 60 | #+appveyor (uiop:getenv "APPVEYOR_JOB_ID") 61 | #+gitlab-ci (uiop:getenv "CI_BUILD_ID") 62 | #+bitbucket-pipelines (uiop:getenv "BITBUCKET_BUILD_NUMBER") 63 | #+azure-pipelines (uiop:getenv "BUILD_BUILDID") 64 | #+github-actions (if (pull-request-p) ; Based on the coveralls action 65 | (commit-id) 66 | (concatenate 'string (commit-id) "-PR-" (pull-request-p))) 67 | #+(or (not ci) unknown-ci) nil) 68 | 69 | (defun pull-request-p () 70 | "Returns whether the build is for a pull/merge request. Unknown and non-ci 71 | platforms are considered to not be pull requests. A string containing the 72 | pull request number is returned for pull requests" 73 | #+travis-ci (unless (string= "false" (uiop:getenv "TRAVIS_PULL_REQUEST")) 74 | (uiop:getenvp "TRAVIS_PULL_REQUEST")) 75 | #+circleci (uiop:getenvp "CIRCLE_PULL_REQUESTS") 76 | #+appveyor (uiop:getenvp "APPVEYOR_PULL_REQUEST_NUMBER") 77 | #+gitlab-ci (uiop:getenvp "CI_MERGE_REQUEST_ID") 78 | #+bitbucket-pipelines (uiop:getenvp "BITBUCKET_PR_ID") 79 | #+azure-pipelines (uiop:getenvp "SYSTEM_PULLREQUEST_PULLREQUESTID") 80 | #+github-actions (when (string= "pull_request" (uiop:getenvp "GITHUB_EVENT_NAME")) 81 | (let ((ref-name (uiop:getenv "GITHUB_REF"))) 82 | (subseq ref-name 10 (- (length ref-name) 6)))) 83 | #+(or (not ci) unknown-ci) nil) 84 | 85 | (defun branch () 86 | "Returns the name of the branch the build is from, or `NIL` for unknown and 87 | non-ci platforms." 88 | #+travis-ci (uiop:getenvp "TRAVIS_BRANCH") 89 | #+circleci (uiop:getenvp "CIRCLE_BRANCH") 90 | #+appveyor (uiop:getenvp "APPVEYOR_REPO_BRANCH") 91 | #+gitlab-ci (uiop:getenvp "CI_COMMIT_REF_NAME") 92 | #+bitbucket-pipelines (or (uiop:getenvp "BITBUCKET_BRANCH") 93 | (uiop:getenvp "BITBUCKET_TAG")) 94 | #+azure-pipelines (uiop:getenvp "BUILD_SOURCEBRANCHNAME") 95 | #+github-actions (subseq (uiop:getenv "GITHUB_REF") 11) 96 | #+(or (not ci) unknown-ci) nil) 97 | 98 | (defun commit-id () 99 | "Returns the ID of the current commit. For git projects, this is the commit's 100 | SHA. `NIL` is returned on unsupported platforms." 101 | #+travis-ci (uiop:getenv "TRAVIS-COMMIT") 102 | #+circleci (uiop:getenv "CIRCLE-SHA1") 103 | #+appveyor (uiop:getenv "APPVEYOR_REPO_COMMIT") 104 | #+gitlab-ci (uiop:getenv "CI_COMMIT_SHA") 105 | #+bitbucket-pipelines (uiop:getenv "BITBUCKET_COMMIT") 106 | #+azure-pipelines (uiop:getenv "BUILD_SOURCEVERSION") 107 | #+github-actions (uiop:getenv "GITHUB_SHA") 108 | #+(or (not ci) unknown-ci) nil) 109 | -------------------------------------------------------------------------------- /src/coveralls.lisp: -------------------------------------------------------------------------------- 1 | (uiop:define-package :ci-utils/coveralls 2 | (:use :cl 3 | :ci-utils) 4 | (:export #:coverallsp 5 | #:with-coveralls 6 | #:coverage-excluded)) 7 | 8 | (in-package :ci-utils/coveralls) 9 | 10 | 11 | (defun coverallsp () 12 | "Whether the current systems has the `COVERALLS` environmental variable set" 13 | #+coveralls t 14 | #-coveralls nil) 15 | 16 | (defmacro with-coveralls (exclude &body body) 17 | "Wraps the body with the `coveralls:with-coveralls` macro if coveralls is enabled" 18 | (declare (ignorable exclude)) 19 | #+coveralls `(coveralls:with-coveralls (:exclude ,exclude) 20 | ,@body) 21 | #-coveralls `(progn 22 | ,@body)) 23 | 24 | (defun coverage-excluded () 25 | "Gets the contents of the COVERAGE_EXCLUDE environemental variable as a list 26 | of path strings" 27 | ; Copied from Eitaro Fukamachi's run-prove under the MIT license 28 | ; https://github.com/fukamachi/prove/blob/master/roswell/run-prove.ros 29 | ; See NOTICE.md for a copy of the license text 30 | (split-sequence:split-sequence #\: 31 | (or (uiop:getenvp "COVERAGE_EXCLUDE") "") 32 | :remove-empty-subseqs t)) 33 | 34 | 35 | ;;; patches for cl-coveralls to support other platforms 36 | #+coveralls 37 | (progn 38 | (defun cl-coveralls.service:service-name () 39 | (ci-utils:platform)) 40 | (defun cl-coveralls.service:service-job-id () 41 | (ci-utils:build-id)) 42 | (defun cl-coveralls.service:project-dir () 43 | (truename (ci-utils:build-dir))) 44 | (defun cl-coveralls.service:commit-sha () 45 | (ci-utils:commit-id)) 46 | (defun cl-coveralls.service:pull-request-num () 47 | (ci-utils:pull-request-p))) 48 | -------------------------------------------------------------------------------- /src/features.lisp: -------------------------------------------------------------------------------- 1 | ;;; Push the new features 2 | 3 | (when (or (uiop:getenvp "CI") 4 | (uiop:getenv "TF_BUILD") ;special case for azure pipelines 5 | (uiop:getenvp "GITHUB_ACTIONS")) ;special case for github actions 6 | (pushnew :ci *features*) 7 | (pushnew (cond 8 | ((uiop:getenvp "TRAVIS") :travis-ci) 9 | ((uiop:getenvp "CIRCLECI") :circleci) 10 | ((uiop:getenvp "APPVEYOR") :appveyor) 11 | ((uiop:getenvp "GITLAB_CI") :gitlab-ci) 12 | ((uiop:getenvp "BITBUCKET_BUILD_NUMBER") :bitbucket-pipelines) 13 | ((string-equal "true" (uiop:getenv "TF_BUILD")) :azure-pipelines) 14 | ((uiop:getenvp "GITHUB_ACTIONS") :github-actions) 15 | (t :unknown-ci)) 16 | *features*)) 17 | 18 | (when (uiop:getenvp "COVERALLS") 19 | (pushnew :coveralls *features*)) 20 | -------------------------------------------------------------------------------- /t/tests.lisp: -------------------------------------------------------------------------------- 1 | 2 | (uiop:define-package :tests 3 | (:use :cl 4 | :ci-utils 5 | :fiveam)) 6 | (in-package :tests) 7 | 8 | 9 | (test :travis-tests 10 | (is-true (member :travis-ci *features*)) 11 | (is-false (member :circleci *features*)) 12 | (is (eq :travis-ci (platform))) 13 | (is (string= (uiop:getenv "TRAVIS_BRANCH") (branch))) 14 | (is (eq (null (uiop:getenvp "TRAVIS_PULL_REQUEST_BRANCH")) 15 | (null (pull-request-p))))) 16 | 17 | (test :circleci-tests 18 | (is-true (member :circleci *features*)) 19 | (is-false (member :travis-ci *features*)) 20 | (is (eq :circleci (platform))) 21 | (is (string= (uiop:getenv "CIRCLE_BRANCH") (branch))) 22 | (is (eq (null (uiop:getenvp "CIRCLE_PULL_REQUEST")) 23 | (null (pull-request-p))))) 24 | 25 | (test :appveyor-tests 26 | (is-true (member :appveyor *features*)) 27 | (is-false (member :circleci *features*)) 28 | (is (eq :appveyor (platform))) 29 | (is (string= (uiop:getenv "APPVEYOR_REPO_BRANCH") (branch))) 30 | (is (eq (null (uiop:getenvp "APPVEYOR_PULL_REQUEST_NUMBER")) 31 | (null (pull-request-p))))) 32 | 33 | (test :gitlab-ci-tests 34 | (is-true (member :gitlab-ci *features*)) 35 | (is-false (member :circleci *features*)) 36 | (is (eq :gitlab-ci (platform))) 37 | (is (string= (uiop:getenv "CI_COMMIT_REF_NAME") (branch))) 38 | (is (eq (null (uiop:getenvp "CI_MERGE_REQUEST_ID")) 39 | (null (pull-request-p))))) 40 | 41 | (test :bitbucket-pipelines-tests 42 | (is-true (member :bitbucket-pipelines *features*)) 43 | (is-false (member :circleci *features*)) 44 | (is (eq :bitbucket-pipelines (platform))) 45 | (is (string= (uiop:getenv "BITBUCKET_BRANCH") (branch))) 46 | (is (eq (null (uiop:getenvp "BITBUCKET_PR_ID")) 47 | (null (pull-request-p))))) 48 | 49 | (test :azure-pipelines-tests 50 | (is-true (member :azure-pipelines *features*)) 51 | (is-false (member :circleci *features*)) 52 | (is (eq :azure-pipelines (platform))) 53 | (is (string= (uiop:getenv "BUILD_SOURCEBRANCHNAME") (branch))) 54 | (is (eq (null (uiop:getenvp "SYSTEM_PULLREQUEST_PULLREQUESTID")) 55 | (null (pull-request-p))))) 56 | 57 | (test :github-actions-tests 58 | (is-true (member :github-actions *features*)) 59 | (is-false (member :circleci *features*)) 60 | (is (eq :github-actions (platform))) 61 | (is (string= (subseq (uiop:getenv "GITHUB_REF") 11) (branch))) 62 | (is (eq (null (string= "pull_request" (uiop:getenvp "GITHUB_EVENT_NAME"))) 63 | (null (pull-request-p))))) 64 | 65 | (test :base-tests 66 | (is-true (member :ci *features*)) 67 | (is-false (member :unknown-ci *features*)) 68 | (is-true (cip)) 69 | (is (equal (uiop:getcwd) (truename (build-dir))))) 70 | 71 | 72 | (test :user-tests 73 | (is-false (member :ci *features*)) 74 | (is-false (member :unknown-ci *features*)) 75 | (is-false (member :travis-ci *features*)) 76 | 77 | (is-false (cip)) 78 | (is-false (platform)) 79 | (is (equal (uiop:getcwd) (build-dir))) 80 | (is-false (pull-request-p)) 81 | (is-false (branch))) 82 | 83 | 84 | (test :coveralls-tests 85 | (is-true (member :coveralls *features*)) 86 | (is (equal '("t" "test-launcher.txt") (ci-utils/coveralls:coverage-excluded))) 87 | (is-true (ci-utils/coveralls:coverallsp))) 88 | 89 | (test :noncoveralls-tests 90 | (is-false (member :coveralls *features*)) 91 | (is-false (ci-utils/coveralls:coverallsp))) 92 | --------------------------------------------------------------------------------