usr/bin/ci 0000755 00000001441 14720724750 0006456 0 ustar 00 #!/bin/sh
# ci (GNU RCS) 5.9.0
#
# Copyright (C) 2013 Thien-Thi Nguyen
#
# This file is part of GNU RCS.
#
# GNU RCS is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GNU RCS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
d=`echo "$0" | sed 's|[^/]*$||'`
exec "$d"rcs ci "$@"
# ci ends here
setup-host 0000755 00000002675 14723071644 0006627 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=$(dirname "$0")
SELFDIR=$(cd "$SELFDIR" && pwd)
PASSENGER_ROOT=$(cd "$SELFDIR/../.." && pwd)
# shellcheck source=lib/functions.sh
source "$SELFDIR/lib/functions.sh"
cd "$PASSENGER_ROOT"
header "Setting up stuff on the host"
autodetect_environment
sanity_check_environment
echo
if [[ "$OS" = macos && "$1" = "" ]]; then
echo "Usage: ./dev/ci/setup-host " >&2
exit 1
fi
if $IN_JENKINS; then
# Relax permissions. Necessary for unit tests which test permissions.
header2 "Relaxing file permissions"
echo "+ Setting umask"
umask u=rwx,g=rx,o=rx
run chmod g+rx,o+rx .
echo "+ chmodding files"
find ./* -type f -print0 | xargs -0 -n 512 chmod g+r,o+r
echo "+ chmodding directories"
find ./* -type d -print0 | xargs -0 -n 512 chmod g+rx,o+rx
# Create this file now because otherwise it would be owned by root,
# which Jenkins cannot remove.
run touch test/test.log
echo
fi
header2 "Creating cache directories"
run mkdir -p "$CACHE_DIR"
run mkdir -p "$CACHE_DIR/bundle"
run mkdir -p "$CACHE_DIR/ccache"
run mkdir -p "$CACHE_DIR/npm"
echo
# Directory must exist so that Jenkinsfile can run archiveArtefacts().
header2 "Creating buildout directory"
run mkdir -p buildout buildout/testlogs
echo
if [[ "$OS" = macos ]]; then
export CI_COMMAND="./dev/ci/setup-host $*"
exec "$PASSENGER_ROOT/dev/ci/scripts/debug-console-wrapper.sh" \
"$PASSENGER_ROOT/dev/ci/scripts/setup-host-natively.sh" "$@"
fi
run-tests-natively 0000755 00000002110 14723071644 0010271 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=$(dirname "$0")
SELFDIR=$(cd "$SELFDIR" && pwd)
PASSENGER_ROOT=$(cd "$SELFDIR/../.." && pwd)
# shellcheck source=lib/functions.sh
source "$SELFDIR/lib/functions.sh"
cd "$PASSENGER_ROOT"
autodetect_environment
sanity_check_environment
echo
if [[ "$OS" != macos ]]; then
echo "ERROR: this script can only be run on macOS." >&2
exit 1
fi
if [[ -e ~/.password ]]; then
# If possible, unlock the keychain in order to prevent password prompts.
echo "+ Unlocking keychain"
if [[ -e ~/Library/Keychains/login.keychain ]]; then
run security unlock-keychain -p "$(cat ~/.password)" ~/Library/Keychains/login.keychain
fi
if [[ -e ~/Library/Keychains/login.keychain-db ]]; then
run security unlock-keychain -p "$(cat ~/.password)" ~/Library/Keychains/login.keychain-db
fi
fi
export HOMEBREW_NO_GITHUB_API="disable"
export HOMEBREW_NO_INSTALL_FROM_API="disable"
export CI_COMMAND="./dev/ci/run-tests-natively $*"
exec "$PASSENGER_ROOT/dev/ci/scripts/debug-console-wrapper.sh" \
"$PASSENGER_ROOT/dev/ci/scripts/run-tests-natively-stage2.sh" "$@"
tests/binaries/test-macos 0000755 00000002021 14723071644 0011512 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger binaries test" Jenkins job. It runs
# runs tests on the binaries generated by the "build-macos" script.
#
# Required environment variables:
#
# WORKSPACE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# OUTPUT_DIR (defaults to $WORKSPACE/output)
# RUNTIME_DIR (defaults to $WORKSPACE/cache/runtime)
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/binaries"
# shellcheck source=../../../../packaging/binaries/shared/lib/library.sh
source "./shared/lib/library.sh"
require_envvar WORKSPACE "$WORKSPACE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
OUTPUT_DIR="${OUTPUT_DIR:-$WORKSPACE/output}"
RUNTIME_DIR="${RUNTIME_DIR:-$WORKSPACE/cache/runtime}"
RUNTIME_VERSION=$(cat shared/definitions/macos_runtime_version)
run mkdir -p "$OUTPUT_DIR"
run ./macos/package \
-i "$OUTPUT_DIR" \
-o "$OUTPUT_DIR"
run ./macos/test \
-p "$PASSENGER_ROOT" \
-r "$RUNTIME_DIR/$RUNTIME_VERSION" \
-i "$OUTPUT_DIR" \
-I "$OUTPUT_DIR"
tests/binaries/Jenkinsfile 0000644 00000006173 14723071644 0011705 0 ustar 00 JOB_NAME_AS_ID = null
def setupLinuxTest(enablerFlag, architecture, block) {
if (enablerFlag) {
node("linux && ${architecture}") {
withEnv([
"OUTPUT_DIR=${env.WORKSPACE}/output-linux-${architecture}",
"CACHE_DIR=${env.JENKINS_HOME}/cache/${env.JOB_NAME_AS_ID}/linux-${architecture}/executor-${env.EXECUTOR_NUMBER}",
"ARCHITECTURE=${architecture}"
], block)
}
} else {
echo 'Test skipped.'
}
}
def setupMacosTest(enablerFlag, block) {
if (enablerFlag) {
node('macos') {
withEnv([
"OUTPUT_DIR=${env.WORKSPACE}/output-macos",
"CACHE_DIR=${env.WORKSPACE}/cache/${env.JOB_NAME_AS_ID}/macos/executor-${env.EXECUTOR_NUMBER}",
"RUNTIME_DIR=${env.WORKSPACE}/cache/${env.JOB_NAME_AS_ID}/macos/executor-${env.EXECUTOR_NUMBER}/runtime"
], block)
}
} else {
echo 'Test skipped.'
}
}
pipeline {
agent { node { label 'master-pipeline' } }
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 45, unit: 'MINUTES')
disableConcurrentBuilds()
timestamps()
ansiColor('xterm')
}
parameters {
booleanParam(name: 'LINUX_X86_64', defaultValue: true, description: 'Linux x86_64 binaries')
booleanParam(name: 'LINUX_ARM64', defaultValue: true, description: 'Linux arm64 binaries')
booleanParam(name: 'MACOS', defaultValue: true, description: 'macOS binaries')
}
stages {
stage('Initialize') {
steps {
script {
// The syntaxes 'env.FOO = FOO = ...' and 'FOO = env.FOO = ...'
// do not work for some reason; one of them will become null.
// So we split the assignments in two separate statements.
env.JOB_NAME_AS_ID = env.JOB_NAME.replace(' ', '-')
JOB_NAME_AS_ID = env.JOB_NAME_AS_ID
if (env.JOB_NAME.indexOf('Enterprise') != -1) {
env.ENTERPRISE = '1'
} else {
env.ENTERPRISE = '0'
}
// For debugging purposes
sh 'env | sort'
}
}
}
stage('Build') {
steps {
script {
parallel(
'Linux x86_64': {
setupLinuxTest(params.LINUX_X86_64, 'x86_64') {
checkout scm
sh './dev/ci/tests/binaries/build-linux'
archiveArtifacts artifacts: 'output-linux-x86_64/**/*'
sh './dev/ci/tests/binaries/test-linux'
}
},
'Linux arm64': {
setupLinuxTest(params.LINUX_ARM64, 'aarch64') {
checkout scm
sh './dev/ci/tests/binaries/build-linux'
archiveArtifacts artifacts: 'output-linux-aarch64/**/*'
sh './dev/ci/tests/binaries/test-linux'
}
},
'macOS': {
setupMacosTest(params.MACOS) {
checkout scm
sh './dev/ci/tests/binaries/prepare-macos'
sh './dev/ci/tests/binaries/build-macos'
archiveArtifacts artifacts: 'output-macos/**/*'
sh './dev/ci/tests/binaries/test-macos'
}
}
)
}
}
}
}
}
tests/binaries/prepare-macos 0000755 00000002077 14723071644 0012204 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger binaries test" Jenkins job. It set ups
# a runtime directory for the "build-macos" script.
#
# Required environment variables:
#
# WORKSPACE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# OUTPUT_DIR (defaults to $WORKSPACE/output)
# CACHE_DIR (defaults to $WORKSPACE/cache)
# RUNTIME_DIR (defaults to $CACHE_DIR/runtime)
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/binaries"
# shellcheck source=../../../../packaging/binaries/shared/lib/library.sh
source "./shared/lib/library.sh"
require_envvar WORKSPACE "$WORKSPACE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
OUTPUT_DIR="${OUTPUT_DIR:-$WORKSPACE/output}"
CACHE_DIR="${CACHE_DIR:-$WORKSPACE/cache}"
RUNTIME_DIR="${RUNTIME_DIR:-$CACHE_DIR/runtime}"
RUNTIME_VERSION=$(cat shared/definitions/macos_runtime_version)
run mkdir -p "$OUTPUT_DIR"
run mkdir -p "$CACHE_DIR"
run mkdir -p "$RUNTIME_DIR/$RUNTIME_VERSION"
run ./macos/setup-runtime \
-c "$CACHE_DIR" \
-o "$RUNTIME_DIR/$RUNTIME_VERSION" \
-j 1
tests/binaries/build-linux 0000755 00000001724 14723071644 0011700 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger binaries test" Jenkins job. It builds
# generic Linux binaries for a specific architecture.
#
# Required environment variables:
#
# WORKSPACE
# ARCHITECTURE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# OUTPUT_DIR (defaults to $WORKSPACE/output)
# CACHE_DIR (defaults to $WORKSPACE/cache)
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/binaries"
# shellcheck source=../../../../packaging/binaries/shared/lib/library.sh
source "./shared/lib/library.sh"
require_envvar WORKSPACE "$WORKSPACE"
require_envvar ARCHITECTURE "$ARCHITECTURE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
OUTPUT_DIR="${OUTPUT_DIR:-$WORKSPACE/output}"
CACHE_DIR="${CACHE_DIR:-$WORKSPACE/cache}"
run mkdir -p "$OUTPUT_DIR"
run mkdir -p "$CACHE_DIR"
run ./linux/build \
-p "$PASSENGER_ROOT" \
-c "$CACHE_DIR" \
-o "$OUTPUT_DIR" \
-a "$ARCHITECTURE" \
-j 1 \
passenger nginx
tests/binaries/test-linux 0000755 00000002137 14723071644 0011557 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger binaries test" Jenkins job. It runs
# runs tests on the binaries generated by the "build-linux" script.
#
# Required environment variables:
#
# WORKSPACE
# ARCHITECTURE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# OUTPUT_DIR (defaults to $WORKSPACE/output)
# ENTERPRISE
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/binaries"
# shellcheck source=../../../../packaging/binaries/shared/lib/library.sh
source "./shared/lib/library.sh"
require_envvar WORKSPACE "$WORKSPACE"
require_envvar ARCHITECTURE "$ARCHITECTURE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
OUTPUT_DIR="${OUTPUT_DIR:-$WORKSPACE/output}"
EXTRA_TEST_PARAMS=()
if [[ "$ENTERPRISE" = 1 ]]; then
EXTRA_TEST_PARAMS=(-L /etc/passenger-enterprise-license)
fi
run mkdir -p "$OUTPUT_DIR"
run mkdir -p "$CACHE_DIR"
run ./linux/package \
-i "$OUTPUT_DIR" \
-o "$OUTPUT_DIR" \
-a "$ARCHITECTURE"
run ./linux/test \
-p "$PASSENGER_ROOT" \
-i "$OUTPUT_DIR" \
-I "$OUTPUT_DIR" \
-a "$ARCHITECTURE" \
"${EXTRA_TEST_PARAMS[@]}"
tests/binaries/build-macos 0000755 00000002056 14723071644 0011642 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger binaries test" Jenkins job. It builds
# generic macOS binaries.
#
# Required environment variables:
#
# WORKSPACE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# OUTPUT_DIR (defaults to $WORKSPACE/output)
# CACHE_DIR (defaults to $WORKSPACE/cache)
# RUNTIME_DIR (defaults to $CACHE_DIR/runtime)
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/binaries"
# shellcheck source=../../../../packaging/binaries/shared/lib/library.sh
source "./shared/lib/library.sh"
require_envvar WORKSPACE "$WORKSPACE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
OUTPUT_DIR="${OUTPUT_DIR:-$WORKSPACE/output}"
CACHE_DIR="${CACHE_DIR:-$WORKSPACE/cache}"
RUNTIME_DIR="${RUNTIME_DIR:-$CACHE_DIR/runtime}"
RUNTIME_VERSION=$(cat shared/definitions/macos_runtime_version)
run mkdir -p "$OUTPUT_DIR"
run mkdir -p "$CACHE_DIR"
run ./macos/build \
-p "$PASSENGER_ROOT" \
-r "$RUNTIME_DIR/$RUNTIME_VERSION" \
-c "$CACHE_DIR" \
-o "$OUTPUT_DIR" \
-j 1 \
passenger nginx
tests/ruby/setup 0000644 00000000115 14723071644 0007757 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes
tests/ruby/run 0000644 00000000124 14723071644 0007423 0 ustar 00 #!/usr/bin/env bash
set -e
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:ruby
tests/source-packaging/setup 0000644 00000000115 14723071644 0012220 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes
tests/source-packaging/run 0000644 00000000140 14723071644 0011662 0 ustar 00 #!/usr/bin/env bash
set -e
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:source_packaging
tests/debian/Jenkinsfile 0000644 00000005050 14723071644 0011324 0 ustar 00 def getDefaultDistros() {
def distroInfo = readFile("packaging/debian/internal/lib/distro_info.sh")
def matcher = distroInfo =~ /DEFAULT_DISTROS="(.+?)"/
if (matcher.find()) {
matcher.group(1).split().sort()
} else {
error("Unable to parse packaging/debian/internal/lib/distro_info.sh")
}
}
def testDebianPackages(distro, arch, params) {
if ((!distro in params) || params[distro]) {
node("linux && ${arch}") {
def env = [
"CACHE_DIR=${env.JENKINS_HOME}/cache/${env.JOB_NAME}/${distro}-${arch}",
"DISTRIBUTION=${distro}",
"ARCHITECTURE=${arch}"
]
withEnv(env) {
checkout scm
sh './dev/ci/tests/debian/run'
}
}
} else {
echo 'Test skipped.'
}
}
pipeline {
agent { node { label 'master-pipeline' } }
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 90, unit: 'MINUTES')
disableConcurrentBuilds()
timestamps()
}
parameters {
booleanParam(name: 'focal', defaultValue: true, description: 'Test Ubuntu 20.04 packages')
booleanParam(name: 'jammy', defaultValue: true, description: 'Test Ubuntu 22.04 packages')
booleanParam(name: 'mantic', defaultValue: true, description: 'Test Ubuntu 23.10 packages')
booleanParam(name: 'buster', defaultValue: true, description: 'Test Debian 10 packages')
booleanParam(name: 'bullseye',defaultValue: true, description: 'Test Debian 11 packages')
booleanParam(name: 'bookworm',defaultValue: true, description: 'Test Debian 12 packages')
}
stages {
stage('Initialize') {
steps {
script {
if (env.JOB_NAME.indexOf('Enterprise') != -1) {
env.ENTERPRISE = '1'
} else {
env.ENTERPRISE = '0'
}
// For debugging purposes
sh 'env | sort'
}
}
}
stage('Test') {
steps {
script {
def defaultDistros = getDefaultDistros()
def i
def parallelSteps = [:]
def archs = ['amd64', 'arm64']
// We use a plain loop over .each because of this bug:
// https://issues.jenkins-ci.org/browse/JENKINS-27421
for (j = 0; j < archs.size(); j++) {
def arch = archs[j]
for (i = 0; i < defaultDistros.size(); i++) {
def distro = defaultDistros[i]
parallelSteps["${distro} ${arch}"] = {
testDebianPackages(distro, arch, params)
}
}
}
parallel(parallelSteps)
}
}
}
}
}
tests/debian/run 0000755 00000003013 14723071644 0007667 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger Debian packaging test" Jenkins job. It builds
# packages for a specific distribution and architecture and runs tests on the resulting packages.
#
# Required environment variables:
#
# WORKSPACE
# DISTRIBUTION
# ARCHITECTURE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# CACHE_DIR (defaults to $WORKSPACE/cache)
# ENTERPRISE
# DEBUG_CONSOLE
#
# Sample invocation in Vagrant dev environment:
#
# env WORKSPACE=$HOME DISTRIBUTION=el7 ARCHITECTURE=x86_64 PASSENGER_ROOT=/passenger ./dev/ci/debian/run
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/debian"
# shellcheck source=../../../../packaging/debian/internal/lib/library.sh
source "./internal/lib/library.sh"
require_envvar WORKSPACE "$WORKSPACE"
require_envvar DISTRIBUTION "$DISTRIBUTION"
require_envvar ARCHITECTURE "$ARCHITECTURE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
CACHE_DIR="${CACHE_DIR:-$WORKSPACE/cache}"
if [[ "$DEBUG_CONSOLE" = true ]]; then
EXTRA_TEST_PARAMS=-D
else
EXTRA_TEST_PARAMS=
fi
if [[ "$ENTERPRISE" = 1 ]]; then
EXTRA_TEST_PARAMS="$EXTRA_TEST_PARAMS -e /etc/passenger-enterprise-license"
fi
run mkdir -p "$CACHE_DIR"
run ./build \
-w "$WORKSPACE/work" \
-c "$CACHE_DIR" \
-o "$WORKSPACE/output" \
-p "$PASSENGER_ROOT" \
-d "$DISTRIBUTION" \
-a "$ARCHITECTURE" \
-R \
pkg:all
run ./test \
-p "$PASSENGER_ROOT" \
-d "$WORKSPACE/output/$DISTRIBUTION" \
-c "$CACHE_DIR" \
-x "$DISTRIBUTION" \
-j \
$EXTRA_TEST_PARAMS
tests/rpm/Jenkinsfile 0000644 00000004531 14723071644 0010703 0 ustar 00 def setupTest(enablerFlag, distribution, architecture, block) {
if (enablerFlag) {
node("linux && ${architecture}") {
withEnv([
"CACHE_DIR=${env.JENKINS_HOME}/cache/${env.JOB_NAME}/${distribution}-${architecture}",
"DISTRIBUTION=${distribution}",
"ARCHITECTURE=${architecture}"
], block)
}
} else {
echo 'Test skipped.'
}
}
pipeline {
agent { node { label 'master-pipeline' } }
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 45, unit: 'MINUTES')
disableConcurrentBuilds()
timestamps()
}
parameters {
booleanParam(name: 'EL7', defaultValue: true, description: 'RHEL 7 tests')
booleanParam(name: 'EL8', defaultValue: true, description: 'RHEL 8 tests')
booleanParam(name: 'EL9', defaultValue: true, description: 'RHEL 9 tests')
}
stages {
stage('Initialize') {
steps {
script {
if (env.JOB_NAME.indexOf('Enterprise') != -1) {
env.ENTERPRISE = '1'
} else {
env.ENTERPRISE = '0'
}
// For debugging purposes
sh 'env | sort'
}
}
}
stage('Test') {
steps {
script {
parallel(
'el7 x86_64': {
setupTest(params.EL7, 'el7', 'x86_64') {
checkout scm
sh './dev/ci/tests/rpm/run'
}
},
'el8 x86_64': {
setupTest(params.EL8, 'el8', 'x86_64') {
checkout scm
sh './dev/ci/tests/rpm/run'
}
},
'el9 x86_64': {
setupTest(params.EL9, 'el9', 'x86_64') {
checkout scm
sh './dev/ci/tests/rpm/run'
}
},
'el7 aarch64': {
setupTest(false, 'el7', 'aarch64') {
checkout scm
sh './dev/ci/tests/rpm/run'
}
},
'el8 aarch64': {
setupTest(params.EL8, 'el8', 'aarch64') {
checkout scm
sh './dev/ci/tests/rpm/run'
}
},
'el9 aarch64': {
setupTest(params.EL9, 'el9', 'aarch64') {
checkout scm
sh './dev/ci/tests/rpm/run'
}
}
)
}
}
}
}
}
tests/rpm/run 0000755 00000003257 14723071644 0007255 0 ustar 00 #!/usr/bin/env bash
# This script is from the "Passenger RPM packaging test" Jenkins job. It builds
# packages for a specific distribution and architecture and runs tests on the resulting packages.
#
# Required environment variables:
#
# WORKSPACE
# DISTRIBUTION
# ARCHITECTURE
#
# Optional environment variables:
#
# PASSENGER_ROOT (defaults to $WORKSPACE)
# CACHE_DIR (defaults to $WORKSPACE/cache)
# ENTERPRISE
# DEBUG_CONSOLE
#
# Sample invocation in Vagrant dev environment:
#
# env WORKSPACE=$HOME DISTRIBUTION=el7 ARCHITECTURE=x86_64 PASSENGER_ROOT=/passenger ./dev/ci/rpm/run
set -e
SELFDIR=$(dirname "$0")
cd "$SELFDIR/../../../../packaging/rpm"
# shellcheck source=../../../../packaging/rpm/internal/lib/library.sh
source "./internal/lib/library.sh"
# shellcheck source=../../../../packaging/rpm/internal/lib/distro_info.sh
source "./internal/lib/distro_info.sh"
require_envvar WORKSPACE "$WORKSPACE"
require_envvar DISTRIBUTION "$DISTRIBUTION"
require_envvar ARCHITECTURE "$ARCHITECTURE"
PASSENGER_ROOT="${PASSENGER_ROOT:-$WORKSPACE}"
CACHE_DIR="${CACHE_DIR:-$WORKSPACE/cache}"
TEST_DISTRO_NAME=$(el_name_to_distro_name "$DISTRIBUTION")
if [[ "$DEBUG_CONSOLE" = true ]]; then
EXTRA_TEST_PARAMS=-D
else
EXTRA_TEST_PARAMS=
fi
if [[ "$ENTERPRISE" = 1 ]]; then
EXTRA_TEST_PARAMS="$EXTRA_TEST_PARAMS -e /etc/passenger-enterprise-license"
fi
run mkdir -p "$CACHE_DIR"
run ./build \
-w "$WORKSPACE/work" \
-c "$CACHE_DIR" \
-o "$WORKSPACE/output" \
-p "$PASSENGER_ROOT" \
-d "$DISTRIBUTION" \
-a "$ARCHITECTURE" \
-R \
rpm:all
run ./test \
-p "$PASSENGER_ROOT" \
-d "$WORKSPACE/output/$DISTRIBUTION" \
-c "$CACHE_DIR" \
-x "$TEST_DISTRO_NAME" \
-j \
$EXTRA_TEST_PARAMS
tests/apache2/setup 0000644 00000000136 14723071644 0010304 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes NODE_MODULES=yes
tests/apache2/run 0000644 00000000334 14723071644 0007750 0 ustar 00 #!/usr/bin/env bash
set -e
run ./bin/passenger-install-apache2-module --auto
run rvmsudo ./bin/passenger-install-apache2-module --auto --no-compile
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:integration:apache2
tests/nodejs/setup 0000644 00000000136 14723071644 0010263 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes NODE_MODULES=yes
tests/nodejs/run 0000644 00000000124 14723071644 0007724 0 ustar 00 #!/usr/bin/env bash
set -e
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:node
tests/homebrew-packaging/setup 0000644 00000001242 14723071644 0012532 0 ustar 00 #!/usr/bin/env bash
set -e
if ! rvm-exec system gem list | grep -qE '^rack '; then
# The native packaging test runs passenger-install-*-module with the system Ruby,
# which in turn requires the 'rack' gem to be installed in the system Ruby's
# default RubyGems path. 'rake test:install_deps' installs to a local bundler
# directory but not to the default RubyGems path.
export rvmsudo_secure_path=0
retry_run 3 rvmsudo rvm-exec system gem install rack --no-document
fi
retry_run 3 rvm-exec system rake test:install_deps DEVDEPS_DEFAULT=no BASE_DEPS=yes SUDO=yes
retry_run 3 gem install bundler -v 1.17.2 --no-document
retry_run 3 rake test:install_deps BASE_DEPS=yes
tests/homebrew-packaging/run 0000644 00000002265 14723071644 0012204 0 ustar 00 #!/usr/bin/env bash
set -e
## Begin debugging flags
SKIP_TARBALL_CREATION=false
SKIP_OSS_UPDATE_CHECK=false
TEST_FORMULA_ARGS=()
## End debugging flags
if ! $SKIP_TARBALL_CREATION; then
run rm -rf pkg
run bundle exec rake package:set_official package:tarball
fi
if [[ -e passenger.gemspec ]]; then
FORMULA_FILENAME=packaging/homebrew/Formula/passenger.rb
NGINX_FORMULA_ARGS=()
if ! $SKIP_OSS_UPDATE_CHECK; then
echo
header2 "Checking whether OSS formula is up-to-date"
run ./packaging/homebrew/verify-oss-formula-uptodate \
-c "$CACHE_DIR/homebrew-core.git" \
-r upstream
fi
else
FORMULA_FILENAME=packaging/homebrew-enterprise/Formula/passenger-enterprise.rb
NGINX_FORMULA_ARGS=(-g packaging/homebrew-enterprise/Formula/nginx-passenger-enterprise.rb)
fi
FORMULA_BASENAME=$(basename "$FORMULA_FILENAME")
echo
header2 "Modifying formula"
run ./packaging/homebrew/modify-formula \
--passenger-dir . \
--formula "$FORMULA_FILENAME" \
--tarball pkg/*.tar.gz \
--output "pkg/$FORMULA_BASENAME"
echo
header2 "Testing formula"
run ./packaging/homebrew/test-formula \
-p . \
-f "pkg/$FORMULA_BASENAME" \
-t pkg/*.tar.gz \
"${NGINX_FORMULA_ARGS[@]}" \
"${TEST_FORMULA_ARGS[@]}"
tests/standalone/setup 0000644 00000000115 14723071644 0011126 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes
tests/standalone/run 0000644 00000000146 14723071644 0010576 0 ustar 00 #!/usr/bin/env bash
set -e
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:integration:standalone
tests/nginx-dynamic/setup 0000644 00000000115 14723071644 0011543 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes
tests/nginx-dynamic/run 0000644 00000001476 14723071644 0011222 0 ustar 00 #!/usr/bin/env bash
set -e
TEST_DYNAMIC_WITH_NGINX_VERSION=$(ruby -r "$PASSENGER_ROOT/src/ruby_supportlib/phusion_passenger.rb" -e 'puts PhusionPassenger::PREFERRED_NGINX_VERSION')
NGINX_ADDON_DIR=$(./bin/passenger-config --nginx-addon-dir)
echo "+ Nginx addon dir: $NGINX_ADDON_DIR"
echo
header2 "Compliing Passenger"
run rake "-j$COMPILE_CONCURRENCY" nginx:as_dynamic_module
echo
header2 "Downloading and compiling Nginx"
cd buildout
run curl -sSLO https://www.nginx.org/download/nginx-$TEST_DYNAMIC_WITH_NGINX_VERSION.tar.gz
run tar -xzf nginx-$TEST_DYNAMIC_WITH_NGINX_VERSION.tar.gz
echo "+ Entering nginx-$TEST_DYNAMIC_WITH_NGINX_VERSION"
cd "nginx-$TEST_DYNAMIC_WITH_NGINX_VERSION"
run ./configure --with-cc='ccache cc' --with-cc-opt='-Wno-error' --add-dynamic-module="$NGINX_ADDON_DIR"
run make "-j$COMPILE_CONCURRENCY"
tests/cxx/setup 0000644 00000000115 14723071644 0007600 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes
tests/cxx/run 0000644 00000000310 14723071644 0007241 0 ustar 00 #!/usr/bin/env bash
set -e
header2 "Running C++ tests"
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:cxx
echo
header2 "Running OXT tests"
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:oxt
tests/nginx/setup 0000644 00000000136 14723071644 0010124 0 ustar 00 #!/usr/bin/env bash
set -e
retry_run 3 rake test:install_deps BASE_DEPS=yes NODE_MODULES=yes
tests/nginx/run 0000644 00000000265 14723071644 0007573 0 ustar 00 #!/usr/bin/env bash
set -e
run ./bin/passenger-install-nginx-module --auto --prefix=/tmp/nginx --auto-download
run bundle exec rake "-j$COMPILE_CONCURRENCY" test:integration:nginx
README.md 0000644 00000012222 14723071644 0006032 0 ustar 00 # Continuous integration test suite
This directory contains scripts that invoke the Passenger test suite. These scripts are invoked from the Passenger continuous integration environment, based on Jenkins.
The following diagrams explain how the different files fit together.
## Flow on Linux
~~~
Invoke: dev/ci/setup-host
| |
| +-- Load: dev/ci/scripts/setup-host
| |
| +-- Relax file permissions (if in Jenkins)
| |
| +-- Create cache directories
| |
| +-- Create buildout directory
|
Invoke: dev/ci/run-tests-with-docker
|
+-- Exec: Docker container
Entrypoint: dev/ci/scripts/docker-entrypoint.sh
|
+-- Exec: dev/ci/scripts/debug-console-wrapper.sh dev/ci/scripts/docker-entrypoint-stage2.sh
|
+-- Invoke: dev/ci/scripts/docker-entrypoint-stage2.sh
| |
| +-- Load: dev/ci/lib/setup-container.sh
| | |
| | +-- Create test/config.json
| | |
| | +-- Relax home permission
| | |
| | +-- Remove previous build products
| | |
| | +-- Load: dev/ci/lib/set-container-envvars.sh
| | | |
| | | +-- Set RVM version and various envvars
| | |
| | +-- Load: dev/ci/tests//setup
| |
| +-- Load: dev/ci/tests//run
|
+-- (if docker-entrypoint-stage2.sh exited with an error)
| Populate buildout/testlogs
|
+-- (if docker-entrypoint-stage2.sh exited with an error,
| and DEBUG_CONSOLE is set to 0)
| Print error message and exit
|
+-- (if docker-entrypoint-stage2.sh exited with an error,
and DEBUG_CONSOLE is set to 1)
|
+-- Load: dev/ci/lib/set-container-envvars.sh
| |
| +-- Set RVM version and various envvars
|
+-- Invoke: bash
~~~
## Flow on macOS
~~~
Invoke: dev/ci/setup-host
| |
| +-- Relax file permissions (if in Jenkins)
| |
| +-- Create cache directories
| |
| +-- Create buildout directory
| |
| +-- Exec: dev/ci/scripts/debug-console-wrapper.sh dev/ci/scripts/setup-host-natively.sh
| |
| +-- Invoke: dev/ci/scripts/setup-host-natively.sh
| | |
| | +-- Load: dev/ci/lib/setup-container.sh
| | |
| | +-- Create test/config.json
| | |
| | +-- Relax home permission
| | |
| | +-- Remove previous build products
| | |
| | +-- Load: dev/ci/lib/set-container-envvars.sh
| | | |
| | | +-- Set RVM version and various envvars
| | |
| | +-- Load: dev/ci/tests//setup
| |
| +-- (if setup-host-natively.sh exited with an error)
| | Populate buildout/testlogs
| |
| +-- (if setup-host-natively.sh exited with an error,
| | and DEBUG_CONSOLE is set to 0)
| | Print error message and exit
| |
| +-- (if setup-host-natively.sh exited with an error,
| and DEBUG_CONSOLE is set to 1)
| |
| +-- Load: dev/ci/lib/set-container-envvars.sh
| | |
| | +-- Set RVM version and various envvars
| |
| +-- Invoke: bash
|
Invoke: dev/ci/run-tests-natively
|
+-- Exec: dev/ci/scripts/debug-console-wrapper.sh dev/ci/scripts/run-tests-natively-stage2.sh
|
+-- Invoke: dev/ci/scripts/run-tests-natively-stage2.sh
| |
| +-- Load: dev/lib/set-container-envvars.sh
| | |
| | +-- Set RVM version and various envvars
| |
| +-- Load: dev/ci/tests//run
|
+-- (if run-tests-natively-stage2.sh exited with an error)
| Populate buildout/testlogs
|
+-- (if run-tests-natively-stage2.sh exited with an error,
| and DEBUG_CONSOLE is set to 0)
| Print error message and exit
|
+-- (if run-tests-natively-stage2.sh exited with an error,
and DEBUG_CONSOLE is set to 1)
|
+-- Load: dev/ci/lib/set-container-envvars.sh
| |
| +-- Set RVM version and various envvars
|
+-- Invoke: bash
~~~
run-tests-with-docker 0000755 00000002032 14723071644 0010661 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=$(dirname "$0")
SELFDIR=$(cd "$SELFDIR" && pwd)
PASSENGER_ROOT=$(cd "$SELFDIR/../.." && pwd)
# shellcheck source=lib/functions.sh
source "$SELFDIR/lib/functions.sh"
cd "$PASSENGER_ROOT"
autodetect_environment
sanity_check_environment
echo
if [[ "$OS" != linux ]]; then
echo "ERROR: this script can only be run on Linux." >&2
exit 1
fi
if tty -s; then
TTY_ARGS='-t -i'
else
TTY_ARGS=
fi
run_exec docker run --rm $TTY_ARGS \
-v "$PASSENGER_ROOT:/passenger" \
-v "$CACHE_DIR:/passenger/.ci_cache" \
-e "APP_UID=$(id -u)" \
-e "APP_GID=$(id -g)" \
-e "DEBUG_CONSOLE=$DEBUG_CONSOLE" \
-e "TEST_RUBY_VERSION=$TEST_RUBY_VERSION" \
-e "COMPILE_CONCURRENCY=$COMPILE_CONCURRENCY" \
-e "SUDO=$SUDO" \
phusion/passenger-ci-docker-env:2.0.4 \
/sbin/my_init --skip-runit --skip-startup-files --quiet -- \
/passenger/dev/ci/scripts/inituidgid \
/sbin/setuser app \
/bin/bash -lc 'cd /passenger && exec "$@"' \
./dev/ci/scripts/docker-entrypoint.sh \
./dev/ci/scripts/docker-entrypoint.sh \
"$@"
scripts/docker-entrypoint.sh 0000755 00000000677 14723071644 0012274 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=/passenger/dev/ci/scripts
PASSENGER_ROOT=/passenger
# shellcheck source=../lib/functions.sh
source "$SELFDIR/../lib/functions.sh"
cd "$PASSENGER_ROOT"
header "Inside Docker container"
autodetect_environment
echo
export CI_COMMAND="./dev/ci/run-tests-with-docker $*"
exec "$PASSENGER_ROOT/dev/ci/scripts/debug-console-wrapper.sh" \
"$PASSENGER_ROOT/dev/ci/scripts/docker-entrypoint-stage2.sh" "$@"
scripts/run-tests-natively-stage2.sh 0000755 00000000721 14723071644 0013562 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=$(dirname "$0")
SELFDIR=$(cd "$SELFDIR" && pwd)
PASSENGER_ROOT=$(cd "$SELFDIR/../../.." && pwd)
# shellcheck source=../lib/functions.sh
source "$SELFDIR/../lib/functions.sh"
# shellcheck source=../lib/set-container-envvars.sh
source "$SELFDIR/../lib/set-container-envvars.sh"
add_bundler_path_to_gem_path
echo
header "Running test suite: $1"
# shellcheck source=/dev/null
source "$PASSENGER_ROOT/dev/ci/tests/$1/run"
scripts/inituidgid 0000755 00000000655 14723071644 0010330 0 ustar 00 #!/usr/bin/env bash
set -e
chown -R "$APP_UID:$APP_GID" /home/app
groupmod -g "$APP_GID" app
usermod -u "$APP_UID" -g "$APP_GID" app
# There's something strange with either Docker or the kernel, so that
# the 'app' user cannot access its home directory even after a proper
# chown/chmod. We work around it like this.
mv /home/app /home/app2
cp -dpR /home/app2 /home/app
rm -rf /home/app2
if [[ $# -gt 0 ]]; then
exec "$@"
fi
scripts/setup-host-natively.sh 0000755 00000000502 14723071644 0012543 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=$(dirname "$0")
SELFDIR=$(cd "$SELFDIR" && pwd)
PASSENGER_ROOT=$(cd "$SELFDIR/../../.." && pwd)
# shellcheck source=../lib/functions.sh
source "$SELFDIR/../lib/functions.sh"
# shellcheck source=../lib/setup-container.sh
source "$PASSENGER_ROOT/dev/ci/lib/setup-container.sh"
scripts/debug-console-wrapper.sh 0000755 00000001334 14723071644 0013007 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=$(dirname "$0")
SELFDIR=$(cd "$SELFDIR" && pwd)
PASSENGER_ROOT=$(cd "$SELFDIR/../../.." && pwd)
# shellcheck source=../lib/functions.sh
source "$SELFDIR/../lib/functions.sh"
if ! "$@"; then
echo
echo "-----------------------------"
echo
echo "*** An error occurred ***"
if [[ "$DEBUG_CONSOLE" == 1 ]]; then
echo
echo "*** DEBUG_CONSOLE set to 1, so launching a debugging console..."
echo
set +e
# shellcheck source=../lib/set-container-envvars.sh
source "$PASSENGER_ROOT/dev/ci/lib/set-container-envvars.sh"
header2 "Launching bash"
bash -l
else
echo "If you want to debug this, run '$CI_COMMAND' with the environment variable DEBUG_CONSOLE=1."
fi
exit 1
fi
scripts/docker-entrypoint-stage2.sh 0000755 00000000651 14723071644 0013447 0 ustar 00 #!/usr/bin/env bash
set -eo pipefail
SELFDIR=/passenger/dev/ci/scripts
PASSENGER_ROOT=/passenger
# shellcheck source=../lib/functions.sh
source "$SELFDIR/../lib/functions.sh"
# shellcheck source=../lib/setup-container.sh
source "$PASSENGER_ROOT/dev/ci/lib/setup-container.sh"
add_bundler_path_to_gem_path
echo
echo
header "Running test suite: $1"
# shellcheck source=/dev/null
source "$PASSENGER_ROOT/dev/ci/tests/$1/run"
lib/set-container-envvars.sh 0000644 00000003117 14723071644 0012115 0 ustar 00 #!/usr/bin/env bash
# Do not `set -e` here because debug-console-wrapper.sh
# relies on this fact.
export DEVDEPS_DEFAULT=no
# shellcheck disable=SC2153
export DEPS_TARGET="$CACHE_DIR/bundle"
export USE_CCACHE=true
export COMPILE_CONCURRENCY=${COMPILE_CONCURRENCY:-2}
export NPM_ARGS="--cache '$CACHE_DIR/npm'"
export npm_config_cache="$CACHE_DIR/npm"
export CCACHE_DIR="$CACHE_DIR/ccache"
export CCACHE_COMPRESS=1
export CCACHE_COMPRESSLEVEL=3
export CCACHE_BASEDIR="$PASSENGER_ROOT"
export CCACHE_SLOPPINESS=time_macros
# shellcheck disable=SC2155
export CCACHE_LOGFILE="$(pwd)/buildout/testlogs/ccache.log"
# We want Bundler invocations to be explicit. For example,
# when running 'rake test:install_deps', we do not want
# to invoke Bundler there because the goal might be to
# install the Rake version as specified in the Gemfile,
# which we may not have yet.
export NOEXEC_DISABLE=1
if [[ "$EXECUTOR_NUMBER" != "" ]]; then
(( TEST_PORT_BASE=64000+EXECUTOR_NUMBER*10 ))
export TEST_PORT_BASE
fi
if [[ "$OS" = macos ]]; then
# Ensure that Homebrew tools can be found
eval "$(/usr/libexec/path_helper -s)"
else
export LC_CTYPE=C.UTF-8
fi
if [[ -f ~/.rvm/scripts/rvm ]]; then
# shellcheck source=/dev/null
source ~/.rvm/scripts/rvm
else
# shellcheck source=/dev/null
source /usr/local/rvm/scripts/rvm
fi
if [[ "$TEST_RUBY_VERSION" != "" ]]; then
header2 "Using Ruby version $TEST_RUBY_VERSION"
run rvm use "$TEST_RUBY_VERSION"
echo
fi
# RVM's cd override causes problems (probably thanks to bash
# error handling being weird and quirky:
# https://news.ycombinator.com/item?id=14321213)
unset cd
lib/setup-container.sh 0000644 00000002413 14723071644 0010776 0 ustar 00 #!/usr/bin/env bash
if ! grep -q passenger.test /etc/hosts; then
header2 "Updating /etc/hosts"
sudo sh -c "cat >> /etc/hosts" < test/config.json
fi
echo "+ Done."
echo
# Relax permissions on home directory so that the application root
# permission checks pass.
header2 "Relaxing home permission"
run chmod g+x,o+x "$HOME"
echo
header2 "Removing previous build products"
run rm -rf buildout/*
run mkdir buildout/testlogs
run rm -f test/test.log
run rm -rf /tmp/psg-test-* /tmp/passenger-error-*.html
echo
# shellcheck source=../lib/set-container-envvars.sh
source "$PASSENGER_ROOT/dev/ci/lib/set-container-envvars.sh"
header "Running test-specific preparations"
# shellcheck source=/dev/null
source "$PASSENGER_ROOT/dev/ci/tests/$1/setup"
echo '+ Done.'
echo
lib/functions.sh 0000644 00000006142 14723071644 0007671 0 ustar 00 #!/usr/bin/env bash
set -e
RESET=$(echo -e "\\033[0m")
BOLD=$(echo -e "\\033[1m")
YELLOW=$(echo -e "\\033[33m")
BLUE_BG=$(echo -e "\\033[44m")
function header()
{
local title="$1"
echo "${BLUE_BG}${YELLOW}${BOLD}${title}${RESET}"
echo "------------------------------------------"
}
function header2()
{
local title="$1"
echo "### ${BOLD}${title}${RESET}"
echo
}
function run()
{
echo "+ $*"
"$@"
}
function run_exec()
{
echo "+ exec $*"
exec "$@"
}
function retry_run()
{
local reset='\x1B[0m'
local red='\x1B[31m'
local yellow='\x1B[33m'
local max_tries="$1"
local number=2
shift
echo "+ $*"
while true; do
if "$@"; then
return 0
elif [[ $number -le $max_tries ]]; then
echo -e "${yellow}The command \"$*\" failed. Retrying, $number of $max_tries:${reset}"
(( number++ ))
else
echo -e "${red}The command \"$*\" failed after $max_tries attempts. Giving up.${reset}"
return 1
fi
done
}
function require_envvar()
{
local name="$1"
local value="$2"
if [[ "$value" = "" ]]; then
echo "ERROR: the environment variable '$name' is required."
exit 1
fi
}
function autodetect_environment()
{
echo "Environment autodetection results:"
if [[ -e /usr/bin/sw_vers ]]; then
echo "Operating system: macOS"
export OS=macos
else
echo "Operating system: Linux"
export OS=linux
fi
if [[ "$JENKINS_HOME" != "" ]]; then
echo "Running in Jenkins: yes"
export IN_JEKINS=true
if [ $OS = "linux" ]; then
export CACHE_DIR="$JENKINS_HOME/cache/$JOB_NAME/executor-$EXECUTOR_NUMBER"
else
require_envvar WORKSPACE "$WORKSPACE"
export CACHE_DIR="$WORKSPACE/cache/$JOB_NAME/executor-$EXECUTOR_NUMBER"
fi
else
echo "Running in Jenkins: no"
export IN_JENKINS=false
export CACHE_DIR="$PASSENGER_ROOT/.ci_cache"
fi
echo "Cache directory: $CACHE_DIR"
}
function sanity_check_environment()
{
if $IN_JENKINS; then
if [[ "$JOB_NAME" = "" ]]; then
echo "ERROR: Jenkins environment detected, but JOB_NAME environment variable not set." >&2
return 1
fi
if [[ "$EXECUTOR_NUMBER" = "" ]]; then
echo "ERROR: Jenkins environment detected, but EXECUTOR_NUMBER environment variable not set." >&2
return 1
fi
fi
}
# The following is necessary to make the C++ tests work.
# They invoke Ruby scripts which require gems installed
# by Bundler, but these scripts are not invoked with
# Bundler, so they can only find these gems through GEM_PATH.
function add_bundler_path_to_gem_path()
{
local bundle_path
if bundle_path=$(bundle show rake); then
bundle_path=$(dirname "$bundle_path")
bundle_path=$(dirname "$bundle_path")
echo "Adding $bundle_path to GEM_PATH"
export GEM_PATH="$bundle_path:$GEM_PATH"
local bundle_bin_path="$bundle_path/bin"
echo "Adding $bundle_bin_path to PATH"
export PATH="$bundle_bin_path:$PATH"
fi
}
function _cleanup()
{
set +e
local pids
pids=$(jobs -p)
if [[ "$pids" != "" ]]; then
# shellcheck disable=SC2086
kill $pids 2>/dev/null
fi
if [[ $(type -t cleanup) == function ]]; then
cleanup
fi
}
trap _cleanup EXIT