Difference between revisions of "Continuous Integration"

From D Wiki
Jump to: navigation, search
m
(Add GitHub actions using setup-dlang)
 
(4 intermediate revisions by 2 users not shown)
Line 52: Line 52:
 
script:
 
script:
 
  - dub test --arch "$ARCH"
 
  - dub test --arch "$ARCH"
 +
</syntaxhighlight>
 +
 +
=== Enabling core dump ===
 +
 +
You can enable a core dump on case of test failing with this :
 +
 +
<syntaxhighlight lang="yaml">
 +
addons:
 +
    apt:
 +
        update: true
 +
        packages:
 +
            - gdb
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="yaml">
 +
# Enable core dumps
 +
before_script:
 +
    - ulimit -c unlimited -S
 +
    - sudo mkdir /cores/ && sudo chmod 777 /cores/
 +
    - echo "/cores/%E.%p" | sudo tee /proc/sys/kernel/core_pattern
 +
 +
after_failure:
 +
    - ./scripts/core-dump.sh
 +
</syntaxhighlight>
 +
 +
And adding "core-dump.sh" script to the repository, on "scripts" folder :
 +
<syntaxhighlight lang="bash">
 +
#!/bin/bash
 +
 +
set -veo pipefail
 +
 +
for file in /cores/*; do
 +
    echo "Core file: $file"
 +
    EXECUTABLE_FILE=$(echo "$file" | sed 's/\/cores\///' | sed -E 's/\.[0-9]+$//' | tr '!' '/')
 +
    echo "Executable: $EXECUTABLE_FILE"
 +
    gdb -c "$file" "$EXECUTABLE_FILE" -ex 'set print pretty on' -ex "thread apply all bt" -ex "set pagination 0" -ex 'info files' -ex 'p $_siginfo._sifields._sigfault.si_addr' -ex 'info locals' -ex 'info frame' -ex 'info args' -ex 'p *sym' -batch
 +
done
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 78: Line 115:
 
environment:
 
environment:
 
  matrix:
 
  matrix:
  - DC: dmd
+
    - DC: dmd
    DVersion: 2.071.0
+
      DVersion: stable
    arch: x64
+
      arch: x64
  - DC: dmd
+
    - DC: dmd
    DVersion: 2.071.0
+
      DVersion: stable
    arch: x86
+
      arch: x86
  - DC: dmd
+
     - DC: ldc
     DVersion: 2.070.0
+
      DVersion: stable
    arch: x64
+
      arch: x86
  - DC: dmd
+
     - DC: ldc
    DVersion: 2.070.0
+
      DVersion: stable
    arch: x86
+
      arch: x64
  - DC: ldc
 
     DVersion: 1.0.0
 
    arch: x64
 
  - DC: ldc
 
    DVersion: 0.17.0
 
    arch: x64
 
  
 
skip_tags: true
 
skip_tags: true
Line 104: Line 135:
  
 
install:
 
install:
   - ps: function ResolveDMD
+
   - ps: function ResolveLatestDMD
 
         {
 
         {
 
             $version = $env:DVersion;
 
             $version = $env:DVersion;
 
             if($version -eq "stable") {
 
             if($version -eq "stable") {
 
                 $latest = (Invoke-WebRequest "http://downloads.dlang.org/releases/LATEST").toString();
 
                 $latest = (Invoke-WebRequest "http://downloads.dlang.org/releases/LATEST").toString();
                 $urls = @("http://downloads.dlang.org/releases/2.x/$($latest)/dmd.$($latest).windows.7z");
+
                 $url = "http://downloads.dlang.org/releases/2.x/$($latest)/dmd.$($latest).windows.7z";
 
             }elseif($version -eq "beta") {
 
             }elseif($version -eq "beta") {
 
                 $latest = (Invoke-WebRequest "http://downloads.dlang.org/pre-releases/LATEST").toString();
 
                 $latest = (Invoke-WebRequest "http://downloads.dlang.org/pre-releases/LATEST").toString();
 
                 $latestVersion = $latest.split("-")[0].split("~")[0];
 
                 $latestVersion = $latest.split("-")[0].split("~")[0];
                 $urls = @("http://downloads.dlang.org/pre-releases/2.x/$($latestVersion)/dmd.$($latest).windows.7z");
+
                 $url = "http://downloads.dlang.org/pre-releases/2.x/$($latestVersion)/dmd.$($latest).windows.7z";
            }elseif($version -eq "nightly") {
 
                $urls = @("http://nightlies.dlang.org/dmd-master-2017-05-20/dmd.master.windows.7z");
 
 
             }else {
 
             }else {
                 $urls = @("http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z");
+
                 $url = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z";
 +
            }
 +
            if($env:arch -eq "x64"){
 +
                $env:PATH += ";C:\dmd2\windows\bin64;";
 
             }
 
             }
 
             $env:PATH += ";C:\dmd2\windows\bin;";
 
             $env:PATH += ";C:\dmd2\windows\bin;";
             return $urls;
+
             return $url;
 
         }
 
         }
   - ps: function ResolveLDC
+
   - ps: function ResolveLatestLDC
 
         {
 
         {
            if($env:arch -eq "x86"){
 
                $archBits = "32";
 
            }
 
            elseif($env:arch -eq "x64"){
 
                $archBits = "64";
 
            }
 
 
             $version = $env:DVersion;
 
             $version = $env:DVersion;
 
             $arch = $env:arch;
 
             $arch = $env:arch;
 
             if($version -eq "stable") {
 
             if($version -eq "stable") {
 
                 $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r","");
 
                 $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r","");
                 $urls = @("https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z");
+
                 $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
 
             }elseif($version -eq "beta") {
 
             }elseif($version -eq "beta") {
 
                 $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r","");
 
                 $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r","");
                 $urls = @("https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z");
+
                 $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
 
             } else {
 
             } else {
 
                 $latest = $version;
 
                 $latest = $version;
                 $urls = @("https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-$($arch).7z");
+
                 $url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-$($arch).7z";
                $urls += "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-win$($archBits)-msvc.zip";
 
 
             }
 
             }
             $env:PATH += ";C:\ldc2-$($latest)-windows-$($arch)\bin;C:\ldc2-$($latest)-win$($archBits)-msvc\bin";
+
             $env:PATH += ";C:\ldc2-$($latest)-windows-$($arch)\bin";
 
             $env:DC = "ldc2";
 
             $env:DC = "ldc2";
             return $urls;
+
             return $url;
 
         }
 
         }
 
   - ps: function SetUpDCompiler
 
   - ps: function SetUpDCompiler
Line 151: Line 176:
 
             $env:toolchain = "msvc";
 
             $env:toolchain = "msvc";
 
             if($env:DC -eq "dmd"){
 
             if($env:DC -eq "dmd"){
                $env:DMD = "dmd";
+
              echo "downloading ...";
                $urls = ResolveDMD;
+
              $url = ResolveLatestDMD;
 +
              echo $url;
 +
              Invoke-WebRequest $url -OutFile "c:\dmd.7z";
 +
              echo "finished.";
 +
              pushd c:\\;
 +
              7z x dmd.7z > $null;
 +
              popd;
 
             }
 
             }
 
             elseif($env:DC -eq "ldc"){
 
             elseif($env:DC -eq "ldc"){
                $env:DC = "ldmd2";
+
              echo "downloading ...";
                $env:DMD = "ldmd2";
+
              $url = ResolveLatestLDC;
                $urls = ResolveLDC;
+
              echo $url;
 +
              Invoke-WebRequest $url -OutFile "c:\ldc.zip";
 +
              echo "finished.";
 +
              pushd c:\\;
 +
              7z x ldc.zip > $null;
 +
              popd;
 
             }
 
             }
            echo "downloading...";
 
            echo urls=$urls;
 
            foreach($tryUrl in $urls){
 
                $dloadOk = $true;
 
                echo Trying $tryUrl;
 
                try{
 
                    Invoke-WebRequest $tryUrl -OutFile "c:\compiler.archive";
 
                }
 
                catch [Net.WebException]{
 
                    $dloadOk = $false;
 
                }
 
                if($dloadOk -eq $true){
 
                    break;
 
                }
 
            }
 
            echo "extracting...";
 
            pushd c:\\;
 
            7z x compiler.archive > $null;
 
            popd;
 
            echo "finished.";
 
 
         }
 
         }
 
   - ps: SetUpDCompiler
 
   - ps: SetUpDCompiler
  - powershell -Command Invoke-WebRequest https://code.dlang.org/files/dub-1.9.0-windows-x86.zip -OutFile dub.zip
+
 
  - 7z x dub.zip -odub > nul
 
  - set PATH=%CD%\%binpath%;%CD%\dub;%PATH%
 
  - dub --version
 
  # Some older LDC/GDC compilers don't come with rdmd
 
  - ps: function SetUpRDMD
 
        {
 
            if((Get-Command "rdmd.exe" -ErrorAction SilentlyContinue) -eq $null)
 
            {
 
                Invoke-WebRequest "http://downloads.dlang.org/releases/2.x/2.080.0/dmd.2.080.0.windows.7z" -OutFile "c:\rdmd-dmd.7z";
 
                pushd c:\\;
 
                7z x -ordmd-dmd rdmd-dmd.7z > $null;
 
                popd;
 
            }
 
        }
 
  - ps: SetUpRDMD
 
  - set PATH=%PATH%;c:\rdmd-dmd\dmd2\windows\bin
 
  
 
before_build:
 
before_build:
 +
 
   - ps: if($env:arch -eq "x86"){
 
   - ps: if($env:arch -eq "x86"){
 
             $env:compilersetupargs = "x86";
 
             $env:compilersetupargs = "x86";
Line 221: Line 222:
 
  - echo %DMD%
 
  - echo %DMD%
 
  - echo %PATH%
 
  - echo %PATH%
 +
- dub --version
 
  - '%DC% --help'
 
  - '%DC% --help'
 
  - dub test --arch=%Darch% --compiler=%DC%
 
  - dub test --arch=%Darch% --compiler=%DC%
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
Like in Travis, you can use a specify version, setting '''DVersion''', and you can choose between the 32bit or 64bit compiler with '''arch''' :
 +
 +
<syntaxhighlight lang="yaml">
 +
matrix:
 +
        - DC: dmd
 +
          DVersion: 2.087.1
 +
          arch: x86
 +
</syntaxhighlight>
  
 
If you have troubles with a specific version or compiler on Windows, you might want to allow failure in your build matrix until you get them fixed. For example to allow failure with ldc, you would add the following:
 
If you have troubles with a specific version or compiler on Windows, you might want to allow failure in your build matrix until you get them fixed. For example to allow failure with ldc, you would add the following:
Line 240: Line 250:
  
 
Gitlab own CI service requires to use a docker image to test D your project. See [https://gitlab.com/basile.b/dlang-ci minimal example]
 
Gitlab own CI service requires to use a docker image to test D your project. See [https://gitlab.com/basile.b/dlang-ci minimal example]
 +
 +
[[Category:Building]]
 +
 +
 +
== GitHub Actions (Windows, Linux, OSX) ==
 +
 +
Using the [https://github.com/marketplace/actions/d-compiler-installation setup-dlang] action it is possible to trivially use GitHub Actions with D, all you need to do is add a D installation step to the workflow yaml file:
 +
 +
<syntaxhighlight lang="yaml">
 +
steps:
 +
    - uses: actions/checkout@v2 # checkout respository
 +
    - uses: dlang-community/setup-dlang@v1 # install & configure a D compiler
 +
      with:
 +
        compiler: dmd-latest # specify latest dmd
 +
    - name: Run tests # use D as usual
 +
      run: dub test
 +
</syntaxhighlight>
 +
 +
With GitHub Actions it is also possible to test on multiple platforms and compilers without repeating your workflow definitions multiple times. Here is a full workflow example:
 +
 +
<syntaxhighlight lang="yaml">
 +
name: Run all D Tests
 +
on: [push, pull_request]
 +
 +
jobs:
 +
    test:
 +
        name: Dub Tests
 +
        strategy:
 +
            matrix:
 +
                os: [ubuntu-latest, windows-latest, macOS-latest]
 +
                dc: [dmd-latest, ldc-latest, dmd-2.085.0, ldc-1.17.0]
 +
            exclude:
 +
                - { os: macOS-latest, dc: dmd-2.085.0 }
 +
 +
        runs-on: ${{ matrix.os }}
 +
        steps:
 +
            - uses: actions/checkout@v2
 +
 +
            - name: Install D compiler
 +
              uses: dlang-community/setup-dlang@v1
 +
              with:
 +
                  compiler: ${{ matrix.dc }}
 +
 +
            - name: Run tests
 +
              run: dub -q test
 +
</syntaxhighlight>
 +
 +
The above example test 11 possible combinations: the latest <code>dmd</code> and latest <code>ldc</code> on all three platforms, <code>ldc-1.17.0</code> on all three platforms, and <code>dmd-2.085.0</code> on <code>ubuntu-latest</code> and <code>windows-latest</code>.
 +
 +
Valid version examples are:
 +
 +
* <code>dmd-latest</code>
 +
* <code>ldc-latest</code>
 +
* <code>dmd-beta</code>
 +
* <code>ldc-beta</code>
 +
* <code>dmd-2.088.0</code>
 +
* <code>dmd-2.088.0-beta.2</code>
 +
* <code>ldc-1.17.0</code>
 +
* <code>ldc-1.18.0-beta1</code>
 +
* <code>dmd-master</code>
 +
* <code>ldc-master</code>

Latest revision as of 12:41, 16 July 2020

Continuously testing your project is ensures a conflict-free shipping. For all the listed Continuous Integration providers, you will need a free account to enable building.

Travis

Travis has built-in support for D and building your project with D is as easy as adding to your .travis.yml file, the compilers to be tested :

# latest dmd, gdc and ldc
d:
  - dmd
  - gdc
  - ldc

You can also choose specific versions:

d:
  - dmd-2.071.0
  - ldc-1.0.0

A full list of supported compiler versions along with the corresponding DMD frontend versions is available at https://semitwist.com/travis-d-compilers.

Travis also offers OS X build environment, which you can enable by adding:

os:
 - linux
 - osx

More information is also available at Travis's documentation.

Testing 32-bit

All Travis containers use 64-bit, so if you want to test 32-bit is a bit tricky. One common trick is to use Travis build matrix feature to individually toggle extra builds as Mac OS X is x86-64 only since 10.7.

env:
 - ARCH="x86_64"
matrix:
  include:
    - {os: linux, d: dmd-2.071.0, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}}
    - {os: linux, d: ldc-1.0.0, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}}
script:
 - dub test --arch "$ARCH"

Enabling core dump

You can enable a core dump on case of test failing with this :

addons:
    apt:
        update: true
        packages:
            - gdb
# Enable core dumps
before_script:
    - ulimit -c unlimited -S
    - sudo mkdir /cores/ && sudo chmod 777 /cores/
    - echo "/cores/%E.%p" | sudo tee /proc/sys/kernel/core_pattern

after_failure:
    - ./scripts/core-dump.sh

And adding "core-dump.sh" script to the repository, on "scripts" folder :

#!/bin/bash

set -veo pipefail

for file in /cores/*; do
    echo "Core file: $file"
    EXECUTABLE_FILE=$(echo "$file" | sed 's/\/cores\///' | sed -E 's/\.[0-9]+$//' | tr '!' '/')
    echo "Executable: $EXECUTABLE_FILE"
    gdb -c "$file" "$EXECUTABLE_FILE" -ex 'set print pretty on' -ex "thread apply all bt" -ex "set pagination 0" -ex 'info files' -ex 'p $_siginfo._sifields._sigfault.si_addr' -ex 'info locals' -ex 'info frame' -ex 'info args' -ex 'p *sym' -batch
done

CircleCi

CircleCi doesn't support D out-of-the-box yet, but it is easy to install dmd and dub with a single line in your `circle.yml`:

dependencies:
  override:
    - source "$(curl -fsS  --retry 3 https://dlang.org/install.sh | bash -s dmd --activate)"
test:
  override:
    - dub test

AppVeyor (Windows)

Testing your project on Windows is currently a bit more complicated, but we are working on simplifying this integration. At the moment the best way to go is to extend your setup from this `appveyor.yml`:

platform: x64
environment:
 matrix:
    - DC: dmd
      DVersion: stable
      arch: x64
    - DC: dmd
      DVersion: stable
      arch: x86
    - DC: ldc
      DVersion: stable
      arch: x86
    - DC: ldc
      DVersion: stable
      arch: x64

skip_tags: true
branches:
  only:
    - master
    - stable

install:
  - ps: function ResolveLatestDMD
        {
            $version = $env:DVersion;
            if($version -eq "stable") {
                $latest = (Invoke-WebRequest "http://downloads.dlang.org/releases/LATEST").toString();
                $url = "http://downloads.dlang.org/releases/2.x/$($latest)/dmd.$($latest).windows.7z";
            }elseif($version -eq "beta") {
                $latest = (Invoke-WebRequest "http://downloads.dlang.org/pre-releases/LATEST").toString();
                $latestVersion = $latest.split("-")[0].split("~")[0];
                $url = "http://downloads.dlang.org/pre-releases/2.x/$($latestVersion)/dmd.$($latest).windows.7z";
            }else {
                $url = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z";
            }
            if($env:arch -eq "x64"){
                $env:PATH += ";C:\dmd2\windows\bin64;";
            }
            $env:PATH += ";C:\dmd2\windows\bin;";
            return $url;
        }
  - ps: function ResolveLatestLDC
        {
            $version = $env:DVersion;
            $arch = $env:arch;
            if($version -eq "stable") {
                $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r","");
                $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
            }elseif($version -eq "beta") {
                $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r","");
                $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
            } else {
                $latest = $version;
                $url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-$($arch).7z";
            }
            $env:PATH += ";C:\ldc2-$($latest)-windows-$($arch)\bin";
            $env:DC = "ldc2";
            return $url;
        }
  - ps: function SetUpDCompiler
        {
            $env:toolchain = "msvc";
            if($env:DC -eq "dmd"){
              echo "downloading ...";
              $url = ResolveLatestDMD;
              echo $url;
              Invoke-WebRequest $url -OutFile "c:\dmd.7z";
              echo "finished.";
              pushd c:\\;
              7z x dmd.7z > $null;
              popd;
            }
            elseif($env:DC -eq "ldc"){
              echo "downloading ...";
              $url = ResolveLatestLDC;
              echo $url;
              Invoke-WebRequest $url -OutFile "c:\ldc.zip";
              echo "finished.";
              pushd c:\\;
              7z x ldc.zip > $null;
              popd;
            }
        }
  - ps: SetUpDCompiler


before_build:

  - ps: if($env:arch -eq "x86"){
            $env:compilersetupargs = "x86";
            $env:Darch = "x86";
            $env:DConf = "m32";
        }elseif($env:arch -eq "x64"){
            $env:compilersetupargs = "amd64";
            $env:Darch = "x86_64";
            $env:DConf = "m64";
        }
  - ps: $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall";
  - '"%compilersetup%" %compilersetupargs%'

build_script:
 - echo dummy build script - dont remove me

test_script:
 - echo %PLATFORM%
 - echo %Darch%
 - echo %DC%
 - echo %DMD%
 - echo %PATH%
 - dub --version
 - '%DC% --help'
 - dub test --arch=%Darch% --compiler=%DC%

Like in Travis, you can use a specify version, setting DVersion, and you can choose between the 32bit or 64bit compiler with arch :

matrix:		
        - DC: dmd
          DVersion: 2.087.1
          arch: x86

If you have troubles with a specific version or compiler on Windows, you might want to allow failure in your build matrix until you get them fixed. For example to allow failure with ldc, you would add the following:

matrix:		
  allow_failures:		
    - DC: ldc

For a up-to-date AppVeyor setup, you can also always head to AppVeyor-D, or DUB or Mir.


Gitlab CI

Gitlab own CI service requires to use a docker image to test D your project. See minimal example


GitHub Actions (Windows, Linux, OSX)

Using the setup-dlang action it is possible to trivially use GitHub Actions with D, all you need to do is add a D installation step to the workflow yaml file:

steps:
    - uses: actions/checkout@v2 # checkout respository
    - uses: dlang-community/setup-dlang@v1 # install & configure a D compiler
      with:
        compiler: dmd-latest # specify latest dmd
    - name: Run tests # use D as usual
      run: dub test

With GitHub Actions it is also possible to test on multiple platforms and compilers without repeating your workflow definitions multiple times. Here is a full workflow example:

name: Run all D Tests
on: [push, pull_request]

jobs:
    test:
        name: Dub Tests
        strategy:
            matrix:
                os: [ubuntu-latest, windows-latest, macOS-latest]
                dc: [dmd-latest, ldc-latest, dmd-2.085.0, ldc-1.17.0]
            exclude:
                - { os: macOS-latest, dc: dmd-2.085.0 }

        runs-on: ${{ matrix.os }}
        steps:
            - uses: actions/checkout@v2

            - name: Install D compiler
              uses: dlang-community/setup-dlang@v1
              with:
                  compiler: ${{ matrix.dc }}

            - name: Run tests
              run: dub -q test

The above example test 11 possible combinations: the latest dmd and latest ldc on all three platforms, ldc-1.17.0 on all three platforms, and dmd-2.085.0 on ubuntu-latest and windows-latest.

Valid version examples are:

  • dmd-latest
  • ldc-latest
  • dmd-beta
  • ldc-beta
  • dmd-2.088.0
  • dmd-2.088.0-beta.2
  • ldc-1.17.0
  • ldc-1.18.0-beta1
  • dmd-master
  • ldc-master