diff options
Diffstat (limited to 'ci')
-rw-r--r-- | ci/bash.yml | 17 | ||||
-rw-r--r-- | ci/build.ps1 | 30 | ||||
-rwxr-xr-x | ci/build.sh | 39 | ||||
-rwxr-xr-x | ci/coverity.sh | 65 | ||||
-rw-r--r-- | ci/docker.yml | 33 | ||||
-rw-r--r-- | ci/nightly.yml | 22 | ||||
-rw-r--r-- | ci/powershell.yml | 17 | ||||
-rwxr-xr-x | ci/setup-linux.sh | 13 | ||||
-rw-r--r-- | ci/setup-mingw.ps1 | 25 | ||||
-rwxr-xr-x | ci/setup-osx.sh | 8 | ||||
-rw-r--r-- | ci/test.ps1 | 72 | ||||
-rwxr-xr-x | ci/test.sh | 198 |
12 files changed, 539 insertions, 0 deletions
diff --git a/ci/bash.yml b/ci/bash.yml new file mode 100644 index 000000000..d776a3649 --- /dev/null +++ b/ci/bash.yml @@ -0,0 +1,17 @@ +# These are the steps used for building on machines with bash. +steps: +- bash: . '$(Build.SourcesDirectory)/ci/build.sh' + displayName: Build + workingDirectory: '$(Build.BinariesDirectory)' + env: ${{ parameters.environmentVariables }} +- bash: . '$(Build.SourcesDirectory)/ci/test.sh' + displayName: Test + workingDirectory: '$(Build.BinariesDirectory)' + env: ${{ parameters.environmentVariables }} +- task: PublishTestResults@2 + displayName: Publish Test Results + condition: succeededOrFailed() + inputs: + testResultsFiles: 'results_*.xml' + searchFolder: '$(Build.BinariesDirectory)' + mergeTestResults: true diff --git a/ci/build.ps1 b/ci/build.ps1 new file mode 100644 index 000000000..159c1dd1b --- /dev/null +++ b/ci/build.ps1 @@ -0,0 +1,30 @@ +Set-StrictMode -Version Latest + +$ErrorActionPreference = "Stop" +$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' + +if ($Env:SOURCE_DIR) { $SourceDirectory = $Env:SOURCE_DIR } else { $SourceDirectory = Split-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) -Parent } +$BuildDirectory = $(Get-Location).Path + +Write-Host "Source directory: ${SourceDirectory}" +Write-Host "Build directory: ${BuildDirectory}" +Write-Host "" +Write-Host "Operating system version:" +Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, BuildNumber, OSArchitecture | Format-List +Write-Host "PATH: ${Env:PATH}" +Write-Host "" + +Write-Host "##############################################################################" +Write-Host "## Configuring build environment" +Write-Host "##############################################################################" + +Invoke-Expression "cmake ${SourceDirectory} -DBUILD_EXAMPLES=ON ${Env:CMAKE_OPTIONS}" +if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) } + +Write-Host "" +Write-Host "##############################################################################" +Write-Host "## Building libgit2" +Write-Host "##############################################################################" + +cmake --build . +if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) } diff --git a/ci/build.sh b/ci/build.sh new file mode 100755 index 000000000..a1deab3f2 --- /dev/null +++ b/ci/build.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# +# Environment variables: +# +# SOURCE_DIR: Set to the directory of the libgit2 source (optional) +# If not set, it will be derived relative to this script. + +set -e + +SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} +BUILD_DIR=$(pwd) +CC=${CC:-cc} + +indent() { sed "s/^/ /"; } + +echo "Source directory: ${SOURCE_DIR}" +echo "Build directory: ${BUILD_DIR}" +echo "" +echo "Operating system version:" +uname -a 2>&1 | indent +echo "CMake version:" +cmake --version 2>&1 | indent +echo "Compiler version:" +$CC --version 2>&1 | indent +echo "" + +echo "##############################################################################" +echo "## Configuring build environment" +echo "##############################################################################" + +echo cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS} +cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS} + +echo "" +echo "##############################################################################" +echo "## Building libgit2" +echo "##############################################################################" + +cmake --build . diff --git a/ci/coverity.sh b/ci/coverity.sh new file mode 100755 index 000000000..a97fae8c8 --- /dev/null +++ b/ci/coverity.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -e + +# Environment check +[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1 + +SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} +BUILD_DIR=$(pwd) + +case $(uname -m) in + i?86) BITS=32 ;; + amd64|x86_64) BITS=64 ;; +esac +SCAN_TOOL=https://scan.coverity.com/download/cxx/linux${BITS} +TOOL_BASE=$(pwd)/_coverity-scan + +# Install coverity tools +if [ ! -d "$TOOL_BASE" ]; then + echo "Downloading coverity..." + mkdir -p "$TOOL_BASE" + pushd "$TOOL_BASE" + wget -O coverity_tool.tgz $SCAN_TOOL \ + --post-data "project=libgit2&token=$COVERITY_TOKEN" + tar xzf coverity_tool.tgz + popd + TOOL_DIR=$(find "$TOOL_BASE" -type d -name 'cov-analysis*') + ln -s "$TOOL_DIR" "$TOOL_BASE"/cov-analysis +fi + +cp "${SOURCE_DIR}/script/user_nodefs.h" "$TOOL_BASE"/cov-analysis/config/user_nodefs.h + +COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build" + +# Configure and build +cmake ${SOURCE_DIR} + +COVERITY_UNSUPPORTED=1 \ + $COV_BUILD --dir cov-int \ + cmake --build . + +# Upload results +tar czf libgit2.tgz cov-int +SHA=$(cd ${SOURCE_DIR} && git rev-parse --short HEAD) + +HTML="$(curl \ + --silent \ + --write-out "\n%{http_code}" \ + --form token="$COVERITY_TOKEN" \ + --form email=libgit2@gmail.com \ + --form file=@libgit2.tgz \ + --form version="$SHA" \ + --form description="libgit2 build" \ + https://scan.coverity.com/builds?project=libgit2)" +# Body is everything up to the last line +BODY="$(echo "$HTML" | head -n-1)" +# Status code is the last line +STATUS_CODE="$(echo "$HTML" | tail -n1)" + +echo "${BODY}" + +if [ "${STATUS_CODE}" != "200" -a "${STATUS_CODE}" != "201" ]; then + echo "Received error code ${STATUS_CODE} from Coverity" + exit 1 +fi diff --git a/ci/docker.yml b/ci/docker.yml new file mode 100644 index 000000000..e92510478 --- /dev/null +++ b/ci/docker.yml @@ -0,0 +1,33 @@ +# These are the steps used in a container-based build in VSTS. +steps: +- task: docker@0 + displayName: Build + inputs: + action: 'Run an image' + imageName: ${{ parameters.imageName }} + volumes: | + $(Build.SourcesDirectory):/src + $(Build.BinariesDirectory):/build + envVars: ${{ parameters.environmentVariables }} + workDir: '/build' + containerCommand: '/src/ci/build.sh' + detached: false +- task: docker@0 + displayName: Test + inputs: + action: 'Run an image' + imageName: ${{ parameters.imageName }} + volumes: | + $(Build.SourcesDirectory):/src + $(Build.BinariesDirectory):/build + envVars: ${{ parameters.environmentVariables }} + workDir: '/build' + containerCommand: '/src/ci/test.sh' + detached: false +- task: publishtestresults@2 + displayName: Publish Test Results + condition: succeededOrFailed() + inputs: + testResultsFiles: 'results_*.xml' + searchFolder: '$(Build.BinariesDirectory)' + mergeTestResults: true diff --git a/ci/nightly.yml b/ci/nightly.yml new file mode 100644 index 000000000..4d6d8a3e8 --- /dev/null +++ b/ci/nightly.yml @@ -0,0 +1,22 @@ +resources: +- repo: self + +jobs: +- job: coverity + displayName: 'Coverity' + pool: + vmImage: 'Ubuntu 16.04' + steps: + - task: Docker@0 + displayName: Build + inputs: + action: 'Run an image' + imageName: 'libgit2/trusty-openssl:latest' + volumes: | + $(Build.SourcesDirectory):/src + $(Build.BinariesDirectory):/build + envVars: | + COVERITY_TOKEN=$(COVERITY_TOKEN) + workDir: '/build' + containerCommand: '/src/ci/coverity.sh' + detached: false diff --git a/ci/powershell.yml b/ci/powershell.yml new file mode 100644 index 000000000..a2eb175d5 --- /dev/null +++ b/ci/powershell.yml @@ -0,0 +1,17 @@ +# These are the steps used for building on machines with PowerShell. +steps: +- powershell: . '$(Build.SourcesDirectory)\ci\build.ps1' + displayName: Build + workingDirectory: '$(Build.BinariesDirectory)' + env: ${{ parameters.environmentVariables }} +- powershell: . '$(Build.SourcesDirectory)\ci\test.ps1' + displayName: Test + workingDirectory: '$(Build.BinariesDirectory)' + env: ${{ parameters.environmentVariables }} +- task: PublishTestResults@2 + displayName: Publish Test Results + condition: succeededOrFailed() + inputs: + testResultsFiles: 'results_*.xml' + searchFolder: '$(Build.BinariesDirectory)' + mergeTestResults: true diff --git a/ci/setup-linux.sh b/ci/setup-linux.sh new file mode 100755 index 000000000..a0db14ee0 --- /dev/null +++ b/ci/setup-linux.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +set -e +set -x + +TMPDIR=${TMPDIR:-/tmp} + +if [ -z "$SKIP_APT" ]; then + apt-get update + apt-get -y install build-essential pkg-config clang cmake openssl libssl-dev libssh2-1-dev libcurl4-gnutls-dev openssh-server +fi + +mkdir -p /var/run/sshd diff --git a/ci/setup-mingw.ps1 b/ci/setup-mingw.ps1 new file mode 100644 index 000000000..76ecd3987 --- /dev/null +++ b/ci/setup-mingw.ps1 @@ -0,0 +1,25 @@ +Set-StrictMode -Version Latest + +$ErrorActionPreference = "Stop" +$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' + +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem"); + +Write-Host "##############################################################################" +Write-Host "## Downloading mingw" +Write-Host "##############################################################################" + +if ($env:ARCH -eq "amd64") { + $mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip" + $platform = "x86_64" +} else { + $mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip" + $platform = "x86" +} + +$wc = New-Object net.webclient +$wc.Downloadfile($mingw_uri, "${Env:TEMP}/mingw-${Env:ARCH}.zip") + +[System.IO.Compression.ZipFile]::ExtractToDirectory("${Env:TEMP}/mingw-${Env:ARCH}.zip", $Env:TEMP) diff --git a/ci/setup-osx.sh b/ci/setup-osx.sh new file mode 100755 index 000000000..564910e41 --- /dev/null +++ b/ci/setup-osx.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -x + +brew update +brew install pkgconfig zlib curl openssl libssh2 + +ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib diff --git a/ci/test.ps1 b/ci/test.ps1 new file mode 100644 index 000000000..1cf02118f --- /dev/null +++ b/ci/test.ps1 @@ -0,0 +1,72 @@ +Set-StrictMode -Version Latest + +$ErrorActionPreference = "Stop" +$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' + +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +$SourceDir = Split-Path (Split-Path (Get-Variable MyInvocation).Value.MyCommand.Path) +$BuildDir = Get-Location +$global:Success = $true + +if ($Env:SKIP_TESTS) { exit } + +# Ask ctest what it would run if we were to invoke it directly. This lets +# us manage the test configuration in a single place (tests/CMakeLists.txt) +# instead of running clar here as well. But it allows us to wrap our test +# harness with a leak checker like valgrind. Append the option to write +# JUnit-style XML files. +function run_test { + $TestName = $args[0] + + $TestCommand = (ctest -N -V -R "^$TestName$") -join "`n" -replace "(?ms).*\n^[0-9]*: Test command: ","" -replace "\n.*","" + $TestCommand += " -r${BuildDir}\results_${TestName}.xml" + + Write-Host $TestCommand + Invoke-Expression $TestCommand + + if ($LastExitCode -ne 0) { $global:Success = $false } +} + +Write-Host "##############################################################################" +Write-Host "## Configuring test environment" +Write-Host "##############################################################################" + +if (-not $Env:SKIP_PROXY_TESTS) { + Write-Host "" + Write-Host "Starting HTTP proxy..." + Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -OutFile poxyproxy.jar + javaw -jar poxyproxy.jar -d --port 8080 --credentials foo:bar +} + +Write-Host "" +Write-Host "##############################################################################" +Write-Host "## Running (offline) tests" +Write-Host "##############################################################################" + +run_test offline + +if (-not $Env:SKIP_ONLINE_TESTS) { + Write-Host "" + Write-Host "##############################################################################" + Write-Host "## Running (online) tests" + Write-Host "##############################################################################" + + run_test online +} + +if (-not $Env:SKIP_PROXY_TESTS) { + Write-Host "" + Write-Host "Running proxy tests" + Write-Host "" + + $Env:GITTEST_REMOTE_PROXY_URL="localhost:8080" + $Env:GITTEST_REMOTE_PROXY_USER="foo" + $Env:GITTEST_REMOTE_PROXY_PASS="bar" + + run_test proxy + + taskkill /F /IM javaw.exe +} + +if (-Not $global:Success) { exit 1 } diff --git a/ci/test.sh b/ci/test.sh new file mode 100755 index 000000000..fea9d82d7 --- /dev/null +++ b/ci/test.sh @@ -0,0 +1,198 @@ +#!/usr/bin/env bash + +set -e + +if [ -n "$SKIP_TESTS" ]; then + exit 0 +fi + +SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} +BUILD_DIR=$(pwd) +TMPDIR=${TMPDIR:-/tmp} +USER=${USER:-$(whoami)} + +SUCCESS=1 + +VALGRIND="valgrind --leak-check=full --show-reachable=yes --error-exitcode=125 --num-callers=50 --suppressions=\"$SOURCE_DIR/libgit2_clar.supp\"" +LEAKS="MallocStackLogging=1 MallocScribble=1 leaks -quiet -atExit -- nohup" + +cleanup() { + echo "Cleaning up..." + + if [ ! -z "$GITDAEMON_DIR" -a -f "${GITDAEMON_DIR}/pid" ]; then + echo "Stopping git daemon..." + kill $(cat "${GITDAEMON_DIR}/pid") + fi + + if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then + echo "Stopping SSH..." + kill $(cat "${SSHD_DIR}/pid") + fi + + echo "Done." +} + +failure() { + echo "Test exited with code: $1" + SUCCESS=0 +} + +# Ask ctest what it would run if we were to invoke it directly. This lets +# us manage the test configuration in a single place (tests/CMakeLists.txt) +# instead of running clar here as well. But it allows us to wrap our test +# harness with a leak checker like valgrind. Append the option to write +# JUnit-style XML files. +run_test() { + TEST_CMD=$(ctest -N -V -R "^${1}$" | sed -n 's/^[0-9]*: Test command: //p') + TEST_CMD="${TEST_CMD} -r${BUILD_DIR}/results_${1}.xml" + + if [ "$LEAK_CHECK" = "valgrind" ]; then + RUNNER="$VALGRIND $TEST_CMD" + elif [ "$LEAK_CHECK" = "leaks" ]; then + RUNNER="$LEAKS $TEST_CMD" + else + RUNNER="$TEST_CMD" + fi + + eval $RUNNER || failure +} + +# Configure the test environment; run them early so that we're certain +# that they're started by the time we need them. + +echo "##############################################################################" +echo "## Configuring test environment" +echo "##############################################################################" + +if [ -z "$SKIP_GITDAEMON_TESTS" ]; then + echo "Starting git daemon..." + GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX` + git init --bare "${GITDAEMON_DIR}/test.git" + git daemon --listen=localhost --export-all --enable=receive-pack --pid-file="${GITDAEMON_DIR}/pid" --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null & +fi + +if [ -z "$SKIP_PROXY_TESTS" ]; then + echo "Starting HTTP proxy..." + curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar + java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar >/dev/null 2>&1 & +fi + +if [ -z "$SKIP_SSH_TESTS" ]; then + echo "Starting ssh daemon..." + HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX` + SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX` + git init --bare "${SSHD_DIR}/test.git" + cat >"${SSHD_DIR}/sshd_config" <<-EOF + Port 2222 + ListenAddress 0.0.0.0 + Protocol 2 + HostKey ${SSHD_DIR}/id_rsa + PidFile ${SSHD_DIR}/pid + AuthorizedKeysFile ${HOME}/.ssh/authorized_keys + LogLevel DEBUG + RSAAuthentication yes + PasswordAuthentication yes + PubkeyAuthentication yes + ChallengeResponseAuthentication no + StrictModes no + # Required here as sshd will simply close connection otherwise + UsePAM no + EOF + ssh-keygen -t rsa -f "${SSHD_DIR}/id_rsa" -N "" -q + /usr/sbin/sshd -f "${SSHD_DIR}/sshd_config" -E "${SSHD_DIR}/log" + + # Set up keys + mkdir "${HOME}/.ssh" + ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" -q + cat "${HOME}/.ssh/id_rsa.pub" >>"${HOME}/.ssh/authorized_keys" + while read algorithm key comment; do + echo "[localhost]:2222 $algorithm $key" >>"${HOME}/.ssh/known_hosts" + done <"${SSHD_DIR}/id_rsa.pub" + + # Get the fingerprint for localhost and remove the colons so we can + # parse it as a hex number. Older versions have a different output + # format. + if [[ $(ssh -V 2>&1) == OpenSSH_6* ]]; then + SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':') + else + SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :) + fi +fi + +# Run the tests that do not require network connectivity. + +if [ -z "$SKIP_OFFLINE_TESTS" ]; then + echo "" + echo "##############################################################################" + echo "## Running (offline) tests" + echo "##############################################################################" + + run_test offline +fi + +if [ -z "$SKIP_ONLINE_TESTS" ]; then + # Run the various online tests. The "online" test suite only includes the + # default online tests that do not require additional configuration. The + # "proxy" and "ssh" test suites require further setup. + + echo "" + echo "##############################################################################" + echo "## Running (online) tests" + echo "##############################################################################" + + run_test online +fi + +if [ -z "$SKIP_GITDAEMON_TESTS" ]; then + echo "" + echo "Running gitdaemon tests" + echo "" + + export GITTEST_REMOTE_URL="git://localhost/test.git" + run_test gitdaemon + unset GITTEST_REMOTE_URL +fi + +if [ -z "$SKIP_PROXY_TESTS" ]; then + echo "" + echo "Running proxy tests" + echo "" + + export GITTEST_REMOTE_PROXY_URL="localhost:8080" + export GITTEST_REMOTE_PROXY_USER="foo" + export GITTEST_REMOTE_PROXY_PASS="bar" + run_test proxy + unset GITTEST_REMOTE_PROXY_URL + unset GITTEST_REMOTE_PROXY_USER + unset GITTEST_REMOTE_PROXY_PASS +fi + +if [ -z "$SKIP_SSH_TESTS" ]; then + echo "" + echo "Running ssh tests" + echo "" + + export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git" + export GITTEST_REMOTE_USER=$USER + export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa" + export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub" + export GITTEST_REMOTE_SSH_PASSPHRASE="" + export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}" + run_test ssh + unset GITTEST_REMOTE_URL + unset GITTEST_REMOTE_USER + unset GITTEST_REMOTE_SSH_KEY + unset GITTEST_REMOTE_SSH_PUBKEY + unset GITTEST_REMOTE_SSH_PASSPHRASE + unset GITTEST_REMOTE_SSH_FINGERPRINT +fi + +cleanup + +if [ "$SUCCESS" -ne "1" ]; then + echo "Some tests failed." + exit 1 +fi + +echo "Success." +exit 0 |