aboutsummaryrefslogtreecommitdiff
path: root/libc/ci
diff options
context:
space:
mode:
Diffstat (limited to 'libc/ci')
-rw-r--r--libc/ci/README.md13
-rw-r--r--libc/ci/azure-install-rust.yml78
-rw-r--r--libc/ci/azure.yml222
-rw-r--r--libc/ci/build.sh58
-rw-r--r--libc/ci/docker/wasm32-wasi/Dockerfile2
-rw-r--r--libc/ci/dox.sh20
-rwxr-xr-xlibc/ci/run-docker.sh16
-rwxr-xr-xlibc/ci/run.sh2
-rw-r--r--libc/ci/semver.sh9
-rw-r--r--libc/ci/style.rs4
-rw-r--r--libc/ci/style.sh19
11 files changed, 402 insertions, 41 deletions
diff --git a/libc/ci/README.md b/libc/ci/README.md
index 28152e5..3123553 100644
--- a/libc/ci/README.md
+++ b/libc/ci/README.md
@@ -8,19 +8,12 @@ this project.
First up, let's talk about the files in this directory:
-* `run-travis.sh` - a shell script run by all Travis builders, this is
- responsible for setting up the rest of the environment such as installing new
- packages, downloading Rust target libraries, etc.
+* `run-docker.sh` - a shell script run by most builders, it will execute
+ `run.sh` inside a Docker container configured for the target.
* `run.sh` - the actual script which runs tests for a particular architecture.
- Called from the `run-travis.sh` script this will run all tests for the target
- specified.
-* `cargo-config` - Cargo configuration of linkers to use copied into place by
- the `run-travis.sh` script before builds are run.
-
-* `dox.sh` - script called from `run-travis.sh` on only the linux 64-bit nightly
- Travis bots to build documentation for this crate.
+* `dox.sh` - build the documentation of the crate and publish it to gh-pages.
* `landing-page-*.html` - used by `dox.sh` to generate a landing page for all
architectures' documentation.
diff --git a/libc/ci/azure-install-rust.yml b/libc/ci/azure-install-rust.yml
new file mode 100644
index 0000000..eba0669
--- /dev/null
+++ b/libc/ci/azure-install-rust.yml
@@ -0,0 +1,78 @@
+steps:
+ - bash: |
+ set -ex
+ toolchain=$TOOLCHAIN
+ if [ "$toolchain" = "" ]; then
+ toolchain=nightly
+ fi
+ if command -v rustup; then
+ rustup update $toolchain
+ rustup default $toolchain
+ else
+ curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain
+ echo "##vso[task.prependpath]$HOME/.cargo/bin"
+ fi
+ displayName: Install rust (unix)
+ condition: ne( variables['Agent.OS'], 'Windows_NT' )
+ - script: |
+ @echo on
+ if not defined TOOLCHAIN set TOOLCHAIN=nightly
+ rustup update %TOOLCHAIN%-%TARGET%
+ rustup default %TOOLCHAIN%-%TARGET%
+ displayName: Install rust (windows)
+ condition: eq( variables['Agent.OS'], 'Windows_NT' )
+ - script: |
+ set -ex
+ if [ -n "${TARGET}" ]; then
+ rustup target add $TARGET
+ fi
+ condition: ne( variables['Agent.OS'], 'Windows_NT' )
+ displayName: Install target (unix)
+ - script: |
+ @echo on
+ if defined TARGET rustup target add %TARGET%
+ condition: eq( variables['Agent.OS'], 'Windows_NT' )
+ displayName: Install target (windows)
+ - script: |
+ @echo on
+ if "%ARCH%" == "i686" choco install mingw --x86 --force
+ condition: eq( variables['Agent.OS'], 'Windows_NT' )
+ displayName: Install MinGW32 (windows)
+ - bash: |
+ set -ex
+ gcc -print-search-dirs
+ find "C:\ProgramData\Chocolatey" -name "crt2*"
+ find "C:\ProgramData\Chocolatey" -name "dllcrt2*"
+ find "C:\ProgramData\Chocolatey" -name "libmsvcrt*"
+ condition: eq( variables['Agent.OS'], 'Windows_NT' )
+ displayName: Find GCC libraries (windows)
+ - bash: |
+ set -ex
+ if [[ -n ${ARCH_BITS} ]]; then
+ for i in crt2.o dllcrt2.o libmingwex.a libmsvcrt.a ; do
+ cp -f "/C/ProgramData/Chocolatey/lib/mingw/tools/install/mingw${ARCH_BITS}/${ARCH}-w64-mingw32/lib/$i" "`rustc --print sysroot`/lib/rustlib/${TARGET}/lib"
+ done
+ fi
+ condition: eq( variables['Agent.OS'], 'Windows_NT' )
+ displayName: Fix MinGW (windows)
+ - bash: |
+ set -ex
+ rustc -Vv
+ cargo -V
+ rustup -Vv
+ rustup show
+ which rustc
+ which cargo
+ which rustup
+ displayName: Query rust and cargo versions
+ - script: |
+ @echo on
+ where gcc
+ condition: eq( variables['Agent.OS'], 'Windows_NT' )
+ displayName: Query gcc path
+ - bash: |
+ set -ex
+ cargo generate-lockfile
+ cargo generate-lockfile --manifest-path libc-test/Cargo.toml
+ displayName: Generate lockfiles
+
diff --git a/libc/ci/azure.yml b/libc/ci/azure.yml
new file mode 100644
index 0000000..4526361
--- /dev/null
+++ b/libc/ci/azure.yml
@@ -0,0 +1,222 @@
+variables:
+ - group: secrets
+resources:
+ repositories:
+ - repository: rustinfra
+ type: github
+ name: rust-lang/simpleinfra
+ endpoint: gnzlbg
+trigger: ["auto-libc","try"]
+pr: ["master"]
+
+jobs:
+ - job: DockerLinuxTier1
+ pool:
+ vmImage: ubuntu-16.04
+ steps:
+ - template: azure-install-rust.yml
+ - bash: LIBC_CI=1 sh ./ci/run-docker.sh $TARGET
+ displayName: Execute run-docker.sh
+ strategy:
+ matrix:
+ i686-unknown-linux-gnu:
+ TARGET: i686-unknown-linux-gnu
+ x86_64-unknown-linux-gnu:
+ TARGET: x86_64-unknown-linux-gnu
+
+ - job: DockerLinuxTier2
+ dependsOn: DockerLinuxTier1
+ pool:
+ vmImage: ubuntu-16.04
+ steps:
+ - template: azure-install-rust.yml
+ - bash: LIBC_CI=1 sh ./ci/run-docker.sh $TARGET
+ displayName: Execute run-docker.sh
+ strategy:
+ matrix:
+ aarch64-unknown-linux-android:
+ TARGET: aarch64-linux-android
+ aarch64-unknown-linux-gnu:
+ TARGET: aarch64-unknown-linux-gnu
+ aarch64-unknown-linux-musl:
+ TARGET: aarch64-unknown-linux-musl
+ arm-linux-androideabi:
+ TARGET: arm-linux-androideabi
+ arm-unknown-linux-gnueabihf:
+ TARGET: arm-unknown-linux-gnueabihf
+ arm-unknown-linux-musleabihf:
+ TARGET: arm-unknown-linux-musleabihf
+ asmjs-unknown-emscripten:
+ TARGET: asmjs-unknown-emscripten
+ i686-linux-android:
+ TARGET: i686-linux-android
+ i686-unknown-linux-musl:
+ TARGET: i686-unknown-linux-musl
+ mips-unknown-linux-gnu:
+ TARGET: mips-unknown-linux-gnu
+ mips-unknown-linux-musl:
+ TARGET: mips-unknown-linux-musl
+ mips64-unknown-linux-gnuabi64:
+ TARGET: mips64-unknown-linux-gnuabi64
+ mips64el-unknown-linux-gnuabi64:
+ TARGET: mips64el-unknown-linux-gnuabi64
+ mipsel-unknown-linux-musl:
+ TARGET: mipsel-unknown-linux-musl
+ #powerpc-unknown-linux-gnu:
+ # TARGET: powerpc-unknown-linux-gnu
+ powerpc64-unknown-linux-gnu:
+ TARGET: powerpc64-unknown-linux-gnu
+ powerpc64le-unknown-linux-gnu:
+ TARGET: powerpc64le-unknown-linux-gnu
+ #s390x-unknown-linux-gnu:
+ # TARGET: s390x-unknown-linux-gnu
+ #wasm32-wasi
+ # TARGET: wasm32-wasi
+ sparc64-unknown-linux-gnu:
+ TARGET: sparc64-unknown-linux-gnu
+ wasm32-unknown-emscripten:
+ TARGET: wasm32-unknown-emscripten
+ x86_64-linux-android:
+ TARGET: x86_64-linux-android
+ x86_64-unknown-linux-gnux32:
+ TARGET: x86_64-unknown-linux-gnux32
+ x86_64-unknown-linux-musl:
+ TARGET: x86_64-unknown-linux-musl
+
+ - job: DockerOSX64
+ pool:
+ vmImage: macos-10.14
+ steps:
+ - template: azure-install-rust.yml
+ - bash: LIBC_CI=1 sh ./ci/run.sh $TARGET
+ displayName: Execute run.sh
+ strategy:
+ matrix:
+ x86_64-apple-darwin:
+ TARGET: x86_64-apple-darwin
+
+ - job: DockerOSX32
+ pool:
+ vmImage: macos-10.13
+ steps:
+ - template: azure-install-rust.yml
+ - bash: LIBC_CI=1 sh ./ci/run.sh $TARGET
+ displayName: Execute run.sh
+ strategy:
+ matrix:
+ i686-apple-darwin:
+ TARGET: i686-apple-darwin
+
+ - job: Windows
+ pool:
+ vmImage: vs2017-win2016
+ steps:
+ - template: azure-install-rust.yml
+ - bash: LIBC_CI=1 sh ./ci/run.sh $TARGET
+ displayName: Execute run.sh
+ strategy:
+ matrix:
+ x86_64-pc-windows-gnu:
+ TARGET: x86_64-pc-windows-gnu
+ ARCH_BITS: 64
+ ARCH: x86_64
+ x86_64-pc-windows-msvc:
+ TARGET: x86_64-pc-windows-msvc
+ i686-pc-windows-gnu:
+ TARGET: i686-pc-windows-gnu
+ ARCH_BITS: 32
+ ARCH: i686
+ i686-pc-windows-msvc:
+ TARGET: i686-pc-windows-msvc
+
+ - job: StyleAndDocs
+ pool:
+ vmImage: ubuntu-16.04
+ steps:
+ - template: azure-install-rust.yml
+ - script: sh ci/style.sh
+ displayName: Check style
+ - script: sh ci/dox.sh
+ displayName: Generate documentation
+ - template: azure-configs/static-websites.yml@rustinfra
+ parameters:
+ deploy_dir: target/doc
+
+ # FIXME: re-enable these after the next release
+ #- job: SemverLinux
+ # dependsOn: BuildChannelsLinux
+ # continueOnError: true
+ # pool:
+ # vmImage: ubuntu-16.04
+ # steps:
+ # - template: azure-install-rust.yml
+ # - script: sh ci/semver.sh linux
+ # displayName: Check breaking changes
+
+ #- job: SemverOSX
+ # dependsOn: BuildChannelsOSX
+ # continueOnError: true
+ # pool:
+ # vmImage: macos-10.14
+ # steps:
+ # - template: azure-install-rust.yml
+ # - script: sh ci/semver.sh osx
+ # displayName: Check breaking changes
+
+ - job: BuildChannelsLinux
+ dependsOn: StyleAndDocs
+ pool:
+ vmImage: ubuntu-16.04
+ steps:
+ - template: azure-install-rust.yml
+ - script: sh ./ci/build.sh
+ displayName: Execute build.sh
+ strategy:
+ matrix:
+ stable:
+ TOOLCHAIN: stable
+ beta:
+ TOOLCHAIN: beta
+ nightly:
+ TOOLCHAIN: nightly
+ 1.13.0:
+ TOOLCHAIN: 1.13.0
+ 1.19.0:
+ TOOLCHAIN: 1.19.0
+ 1.24.0:
+ TOOLCHAIN: 1.24.0
+ 1.25.0:
+ TOOLCHAIN: 1.25.0
+ 1.30.0:
+ TOOLCHAIN: 1.30.0
+ variables:
+ OS: linux
+
+ - job: BuildChannelsOSX
+ dependsOn: StyleAndDocs
+ pool:
+ vmImage: macos-10.13
+ steps:
+ - template: azure-install-rust.yml
+ - script: sh ./ci/build.sh
+ displayName: Execute build.sh
+ strategy:
+ matrix:
+ stable:
+ TOOLCHAIN: stable
+ beta:
+ TOOLCHAIN: beta
+ nightly:
+ TOOLCHAIN: nightly
+ 1.13.0:
+ TOOLCHAIN: 1.13.0
+ 1.19.0:
+ TOOLCHAIN: 1.19.0
+ 1.24.0:
+ TOOLCHAIN: 1.24.0
+ 1.25.0:
+ TOOLCHAIN: 1.25.0
+ 1.30.0:
+ TOOLCHAIN: 1.30.0
+ variables:
+ OS: osx
diff --git a/libc/ci/build.sh b/libc/ci/build.sh
index 707dd4a..e63b4f7 100644
--- a/libc/ci/build.sh
+++ b/libc/ci/build.sh
@@ -5,13 +5,20 @@
set -ex
-RUST=${TRAVIS_RUST_VERSION}
-OS=${TRAVIS_OS_NAME}
+: "${TOOLCHAIN?The TOOLCHAIN environment variable must be set.}"
+: "${OS?The OS environment variable must be set.}"
+
+RUST=${TOOLCHAIN}
echo "Testing Rust ${RUST} on ${OS}"
+if [ "${TOOLCHAIN}" = "nightly" ] ; then
+ cargo +nightly install cargo-xbuild -Z install-upgrade
+ rustup component add rust-src
+fi
+
test_target() {
- CARGO="${1}"
+ BUILD_CMD="${1}"
TARGET="${2}"
NO_STD="${3}"
@@ -46,21 +53,21 @@ test_target() {
fi
# Test that libc builds without any default features (no libstd)
- "$CARGO" "+${RUST}" build -vv $opt --no-default-features --target "${TARGET}"
+ cargo "+${RUST}" "${BUILD_CMD}" -vv $opt --no-default-features --target "${TARGET}"
# Test that libc builds with default features (e.g. libstd)
# if the target supports libstd
if [ "$NO_STD" != "1" ]; then
- "$CARGO" "+${RUST}" build -vv $opt --target "${TARGET}"
+ cargo "+${RUST}" "${BUILD_CMD}" -vv $opt --target "${TARGET}"
fi
# Test that libc builds with the `extra_traits` feature
- "$CARGO" "+${RUST}" build -vv $opt --no-default-features --target "${TARGET}" \
+ cargo "+${RUST}" "${BUILD_CMD}" -vv $opt --no-default-features --target "${TARGET}" \
--features extra_traits
# Also test that it builds with `extra_traits` and default features:
if [ "$NO_STD" != "1" ]; then
- "$CARGO" "+${RUST}" build -vv $opt --target "${TARGET}" \
+ cargo "+${RUST}" "${BUILD_CMD}" -vv $opt --target "${TARGET}" \
--features extra_traits
fi
}
@@ -115,6 +122,9 @@ i586-unknown-linux-musl \
x86_64-unknown-cloudabi \
"
+# FIXME: temporarirly disable the redox target
+# https://github.com/rust-lang/libc/issues/1457
+# x86_64-unknown-redox
RUST_NIGHTLY_LINUX_TARGETS="\
aarch64-fuchsia \
armv5te-unknown-linux-gnueabi \
@@ -125,7 +135,6 @@ x86_64-fortanix-unknown-sgx \
x86_64-fuchsia \
x86_64-pc-windows-gnu \
x86_64-unknown-linux-gnux32 \
-x86_64-unknown-redox \
"
RUST_OSX_TARGETS="\
@@ -167,11 +176,13 @@ case "${OS}" in
esac
for TARGET in $TARGETS; do
- test_target cargo "$TARGET"
+ test_target build "$TARGET"
done
# FIXME: https://github.com/rust-lang/rust/issues/58564
# sparc-unknown-linux-gnu
+# FIXME: https://github.com/rust-lang/rust/issues/62932
+# thumbv6m-none-eabi
RUST_LINUX_NO_CORE_TARGETS="\
aarch64-pc-windows-msvc \
aarch64-unknown-cloudabi \
@@ -184,6 +195,7 @@ armebv7r-none-eabihf \
armv7-unknown-cloudabi-eabihf \
armv7r-none-eabi \
armv7r-none-eabihf \
+hexagon-unknown-linux-musl \
i586-pc-windows-msvc \
i686-pc-windows-msvc \
i686-unknown-cloudabi \
@@ -199,7 +211,7 @@ powerpc64-unknown-freebsd \
riscv32imac-unknown-none-elf \
riscv32imc-unknown-none-elf \
sparc64-unknown-netbsd \
-thumbv6m-none-eabi \
+
thumbv7em-none-eabi \
thumbv7em-none-eabihf \
thumbv7m-none-eabi \
@@ -212,10 +224,34 @@ x86_64-unknown-haiku \
x86_64-unknown-hermit \
x86_64-unknown-l4re-uclibc \
x86_64-unknown-openbsd \
+armv7-wrs-vxworks \
+aarch64-wrs-vxworks \
+i686-wrs-vxworks \
+x86_64-wrs-vxworks \
+powerpc-wrs-vxworks \
+powerpc-wrs-vxworks-spe \
+powerpc64-wrs-vxworks \
"
if [ "${RUST}" = "nightly" ] && [ "${OS}" = "linux" ]; then
for TARGET in $RUST_LINUX_NO_CORE_TARGETS; do
- test_target xargo "$TARGET" 1
+ test_target xbuild "$TARGET" 1
done
+
+ # Nintendo switch
+ cargo clean
+ mkdir -p target
+ (
+ cd target
+ wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb
+ sudo dpkg -i devkitpro-pacman.deb
+ sudo dkp-pacman -Sy
+ sudo dkp-pacman -Syu
+ sudo dkp-pacman -S -v --noconfirm switch-dev devkitA64
+ )
+ cp ci/switch.json switch.json
+ PATH="$PATH:/opt/devkitpro/devkitA64/bin"
+ PATH="$PATH:/opt/devkitpro/tools/bin"
+ cargo xbuild --target switch.json
fi
+
diff --git a/libc/ci/docker/wasm32-wasi/Dockerfile b/libc/ci/docker/wasm32-wasi/Dockerfile
index d963a44..eb3b5ff 100644
--- a/libc/ci/docker/wasm32-wasi/Dockerfile
+++ b/libc/ci/docker/wasm32-wasi/Dockerfile
@@ -60,7 +60,7 @@ ENV PATH=/root/.cargo/bin:$PATH
RUN apt-get install -y --no-install-recommends python
RUN git clone --recursive https://github.com/CraneStation/wasmtime wasmtime && \
cd wasmtime && \
- git reset --hard 67edb00f29b62864b00179fe4bfa99bc29973285
+ git reset --hard a2647878977726935c3d04c05cabad9607ec7606
RUN cargo build --release --manifest-path wasmtime/Cargo.toml
# And finally in the last image we're going to assemble everything together.
diff --git a/libc/ci/dox.sh b/libc/ci/dox.sh
index ce55081..febe18b 100644
--- a/libc/ci/dox.sh
+++ b/libc/ci/dox.sh
@@ -13,6 +13,14 @@ PLATFORM_SUPPORT=platform-support.md
rm -rf $TARGET_DOC_DIR
mkdir -p $TARGET_DOC_DIR
+if ! rustc --version | grep -E "nightly" ; then
+ echo "Building the documentation requires a nightly Rust toolchain"
+ exit 1
+fi
+
+rustup component add rust-src
+cargo +nightly install cargo-xbuild -Z install-upgrade
+
# List all targets that do currently build successfully:
# shellcheck disable=SC1003
grep '[\d|\w|-]* \\' ci/build.sh > targets
@@ -39,10 +47,13 @@ while read -r target; do
rustup target add "${target}" || true
+ # Enable extra configuration flags:
+ export RUSTDOCFLAGS="--cfg freebsd11"
+
# If cargo doc fails, then try xargo:
if ! cargo doc --target "${target}" \
--no-default-features --features extra_traits ; then
- xargo doc --target "${target}" \
+ cargo xdoc --target "${target}" \
--no-default-features --features extra_traits
fi
@@ -61,10 +72,3 @@ set -x
# Copy the licenses
cp LICENSE-* $TARGET_DOC_DIR/
-
-# If we're on travis, not a PR, and on the right branch, publish!
-if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then
- pip install ghp_import --install-option="--prefix=$HOME/.local"
- "${HOME}/.local/bin/ghp-import" $TARGET_DOC_DIR
- git push -qf "https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git" gh-pages
-fi
diff --git a/libc/ci/run-docker.sh b/libc/ci/run-docker.sh
index c656f59..3c0736a 100755
--- a/libc/ci/run-docker.sh
+++ b/libc/ci/run-docker.sh
@@ -5,6 +5,9 @@
set -ex
+echo "${HOME}"
+pwd
+
run() {
echo "Building docker container for target ${1}"
@@ -18,19 +21,20 @@ run() {
fi
docker run \
- --user "$(id -u)":"$(id -g)" \
--rm \
- --init \
- --volume "${HOME}/.cargo":/cargo \
- $kvm \
+ --user "$(id -u)":"$(id -g)" \
+ --env LIBC_CI \
--env CARGO_HOME=/cargo \
+ --env CARGO_TARGET_DIR=/checkout/target \
+ --volume "$(dirname "$(dirname "$(command -v cargo)")")":/cargo \
--volume "$(rustc --print sysroot)":/rust:ro \
--volume "$(pwd)":/checkout:ro \
--volume "$(pwd)"/target:/checkout/target \
- --env CARGO_TARGET_DIR=/checkout/target \
+ $kvm \
+ --init \
--workdir /checkout \
libc \
- ci/run.sh "${1}"
+ sh -c "HOME=/tmp PATH=\$PATH:/rust/bin exec ci/run.sh ${1}"
}
if [ -z "${1}" ]; then
diff --git a/libc/ci/run.sh b/libc/ci/run.sh
index 8c56979..6f2ca11 100755
--- a/libc/ci/run.sh
+++ b/libc/ci/run.sh
@@ -87,8 +87,6 @@ if [ "$TARGET" = "x86_64-unknown-linux-gnux32" ]; then
opt="--release"
fi
-export LIBC_CI=1
-
cargo test -vv $opt --no-default-features --manifest-path libc-test/Cargo.toml \
--target "${TARGET}"
diff --git a/libc/ci/semver.sh b/libc/ci/semver.sh
index ac6be36..3412501 100644
--- a/libc/ci/semver.sh
+++ b/libc/ci/semver.sh
@@ -4,10 +4,17 @@
set -ex
-OS=${TRAVIS_OS_NAME}
+OS=${1}
echo "Testing Semver on ${OS}"
+if ! rustc --version | grep -E "nightly" ; then
+ echo "Building semverver requires a nightly Rust toolchain"
+ exit 1
+fi
+
+cargo +nightly install semverver -Z install-upgrade
+
TARGETS=
case "${OS}" in
*linux*)
diff --git a/libc/ci/style.rs b/libc/ci/style.rs
index 481f57f..70fc0a0 100644
--- a/libc/ci/style.rs
+++ b/libc/ci/style.rs
@@ -117,7 +117,7 @@ fn check_style(file: &str, path: &Path, err: &mut Errors) {
} else {
prev_blank = false;
}
- if line != line.trim_right() {
+ if line != line.trim_end() {
err.error(path, i, "trailing whitespace");
}
if line.contains("\t") {
@@ -139,7 +139,7 @@ fn check_style(file: &str, path: &Path, err: &mut Errors) {
}
}
- let line = line.trim_left();
+ let line = line.trim_start();
let is_pub = line.starts_with("pub ");
let line = if is_pub {&line[4..]} else {line};
diff --git a/libc/ci/style.sh b/libc/ci/style.sh
new file mode 100644
index 0000000..a6a0017
--- /dev/null
+++ b/libc/ci/style.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env sh
+
+set -ex
+
+rustc ci/style.rs && ./style src
+
+if rustup component add rustfmt-preview ; then
+ which rustfmt
+ rustfmt -V
+ cargo fmt --all -- --check
+fi
+
+if shellcheck --version ; then
+ shellcheck -e SC2103 ci/*.sh
+else
+ echo "shellcheck not found"
+ exit 1
+fi
+