mirror of
https://github.com/dokku/dokku.git
synced 2026-05-18 05:05:46 +02:00
feat: allow builders to be detected based on repository contents
Rather than hardcode two builders, allow builders to specify a `builder-detect` trigger. This trigger can be used to specify if the builder should or should not be used for an application. Each builder takes stdin and can decide if it wants to emit it or emit it's own image source type. If the final value is empty, then Dokku will default to herokuish (and cnb once that is stable). In addition, a future change may allow users to manually specify a builder in the case they wish to override the choice selected by Dokku. This change enables users to build custom builder plugins and have those plugins used for building an image asset. By way of example, an enterprising user could create a `builder-lambda` based on lambci, and then pair this with a scheduler plugin that updates a lambda function on AWS. Alternatively, a user might decide they wish to place their Dockerfile in a specific directory for their applications - such as an `_infrastructure` directory - and create a plugin to override how that is detected within Dokku.
This commit is contained in:
@@ -143,6 +143,24 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
# TODO
|
||||
```
|
||||
|
||||
### `builder-detect`
|
||||
|
||||
- Description: Allows overriding the auto-detected `herokuish` builder in favor of a custom one. Dockerfile gets lowest builder precedence.
|
||||
- Invoked by: `dokku deploy`
|
||||
- Arguments: `$APP` `$SOURCECODE_WORK_DIR`
|
||||
- Example:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
APP="$1"; SOURCECODE_WORK_DIR="$2"
|
||||
|
||||
if [[ -f "$SOURCECODE_WORK_DIR/project.toml" ]]; then
|
||||
echo -n "cnb"
|
||||
fi
|
||||
```
|
||||
|
||||
### `builder-create-dokku-image`
|
||||
|
||||
- Description: Allows modification of the configured dokku-image
|
||||
|
||||
1
plugins/20_events/builder-detect
Symbolic link
1
plugins/20_events/builder-detect
Symbolic link
@@ -0,0 +1 @@
|
||||
hook
|
||||
22
plugins/builder-cnb/builder-detect
Executable file
22
plugins/builder-cnb/builder-detect
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
trigger-builder-cnb-builder-detect() {
|
||||
declare desc="builder-cnb builder-detect plugin trigger"
|
||||
declare trigger="builder-detect"
|
||||
declare APP="$1" SOURCECODE_WORK_DIR="$2"
|
||||
|
||||
if [[ -f "$SOURCECODE_WORK_DIR/project.toml" ]]; then
|
||||
echo "cnb"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$(config_get "$APP" DOKKU_CNB_EXPERIMENTAL || true)" == "1" ]]; then
|
||||
echo "cnb"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
trigger-builder-cnb-builder-detect "$@"
|
||||
30
plugins/builder-dockerfile/builder-detect
Executable file
30
plugins/builder-dockerfile/builder-detect
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
trigger-builder-dockerfile-builder-detect() {
|
||||
declare desc="builder-dockerfile builder-detect plugin trigger"
|
||||
declare trigger="builder-detect"
|
||||
declare APP="$1" SOURCECODE_WORK_DIR="$2"
|
||||
|
||||
# buildpacks always win against dockerfile detection
|
||||
# that includes cnb
|
||||
if [[ -f "$SOURCECODE_WORK_DIR/project.toml" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# buildpacks always win against dockerfile detection
|
||||
# that includes cnb
|
||||
if [[ "$(config_get "$APP" DOKKU_CNB_EXPERIMENTAL || true)" == "1" ]]; then
|
||||
echo "cnb"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -f "$SOURCECODE_WORK_DIR/Dockerfile" ]]; then
|
||||
echo "dockerfile"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
trigger-builder-dockerfile-builder-detect "$@"
|
||||
27
plugins/builder-herokuish/builder-detect
Executable file
27
plugins/builder-herokuish/builder-detect
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/builder-herokuish/functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
trigger-builder-herokuish-builder-detect() {
|
||||
declare desc="builder-herokuish builder-detect plugin trigger"
|
||||
declare trigger="builder-detect"
|
||||
declare APP="$1" SOURCECODE_WORK_DIR="$2"
|
||||
|
||||
if fn-has-buildpacks-file "$SOURCECODE_WORK_DIR"; then
|
||||
echo "herokuish"
|
||||
return
|
||||
fi
|
||||
|
||||
if fn-has-buildpack-dotenv "$SOURCECODE_WORK_DIR"; then
|
||||
echo "herokuish"
|
||||
return
|
||||
fi
|
||||
|
||||
if fn-has-buildpack-env "$APP"; then
|
||||
echo "herokuish"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
trigger-builder-herokuish-builder-detect "$@"
|
||||
38
plugins/builder-herokuish/functions
Executable file
38
plugins/builder-herokuish/functions
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
fn-has-buildpacks-file() {
|
||||
declare SOURCECODE_WORK_DIR="$1"
|
||||
|
||||
if [[ -f "$SOURCECODE_WORK_DIR/.buildpacks" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
fn-has-buildpack-dotenv() {
|
||||
declare SOURCECODE_WORK_DIR="$1"
|
||||
|
||||
if [[ ! -f "$SOURCECODE_WORK_DIR/.env" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if grep -q BUILDPACK_URL "$SOURCECODE_WORK_DIR/.env"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
fn-has-buildpack-env() {
|
||||
declare APP="$1"
|
||||
|
||||
if [[ -n $(config_get "$APP" BUILDPACK_URL || true) ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
@@ -49,18 +49,15 @@ git_build_app_repo() {
|
||||
git_trigger_build() {
|
||||
declare desc="triggers the actual build process for a given app within a directory at a particular revision"
|
||||
declare APP="$1" TMP_WORK_DIR="$2" REV="$3"
|
||||
local BUILDER
|
||||
|
||||
plugn trigger post-extract "$APP" "$TMP_WORK_DIR" "$REV"
|
||||
if [[ -f Dockerfile ]] && [[ "$(
|
||||
[[ -f .env ]] && grep -q BUILDPACK_URL .env
|
||||
echo $?
|
||||
)" != "0" ]] && [[ ! -f ".buildpacks" ]] && [[ -z $(config_get "$APP" BUILDPACK_URL || true) ]]; then
|
||||
plugn trigger pre-receive-app "$APP" "dockerfile" "$TMP_WORK_DIR" "$REV"
|
||||
dokku_receive "$APP" "dockerfile" "$TMP_WORK_DIR"
|
||||
else
|
||||
plugn trigger pre-receive-app "$APP" "herokuish" "$TMP_WORK_DIR" "$REV"
|
||||
dokku_receive "$APP" "herokuish" "$TMP_WORK_DIR"
|
||||
fi
|
||||
|
||||
BUILDER="$(plugn trigger builder-detect "$APP" "$TMP_WORK_DIR" | tail -n1 || true)"
|
||||
[[ -z "$BUILDER" ]] && BUILDER="herokuish"
|
||||
|
||||
plugn trigger pre-receive-app "$APP" "$BUILDER" "$TMP_WORK_DIR" "$REV"
|
||||
dokku_receive "$APP" "$BUILDER" "$TMP_WORK_DIR"
|
||||
}
|
||||
|
||||
git_deploy_branch() {
|
||||
|
||||
@@ -41,18 +41,15 @@ tar_build() {
|
||||
tar_trigger_build() {
|
||||
declare desc="triggers the actual build process for a given app within a directory at a particular revision"
|
||||
declare APP="$1" TMP_WORK_DIR="$2" REV="$3"
|
||||
local BUILDER
|
||||
|
||||
plugn trigger post-extract "$APP" "$TMP_WORK_DIR" "$REV"
|
||||
if [[ -f Dockerfile ]] && [[ "$(
|
||||
[[ -f .env ]] && grep -q BUILDPACK_URL .env
|
||||
echo $?
|
||||
)" != "0" ]] && [[ ! -f ".buildpacks" ]] && [[ -z $(config_get "$APP" BUILDPACK_URL || true) ]]; then
|
||||
plugn trigger pre-receive-app "$APP" "dockerfile" "$TMP_WORK_DIR" "$REV"
|
||||
dokku_receive "$APP" "dockerfile" "$TMP_WORK_DIR"
|
||||
else
|
||||
plugn trigger pre-receive-app "$APP" "herokuish" "$TMP_WORK_DIR" "$REV"
|
||||
dokku_receive "$APP" "herokuish" "$TMP_WORK_DIR"
|
||||
fi
|
||||
|
||||
BUILDER="$(plugn trigger builder-detect "$APP" "$TMP_WORK_DIR" | tail -n1 || true)"
|
||||
[[ -z "$BUILDER" ]] && BUILDER="herokuish"
|
||||
|
||||
plugn trigger pre-receive-app "$APP" "$BUILDER" "$TMP_WORK_DIR" "$REV"
|
||||
dokku_receive "$APP" "$BUILDER" "$TMP_WORK_DIR"
|
||||
}
|
||||
|
||||
cmd-tar-in() {
|
||||
|
||||
121
tests/unit/builder.bats
Normal file
121
tests/unit/builder.bats
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
create_app
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
}
|
||||
|
||||
@test "(builder) builder-detect [cnb]" {
|
||||
local TMP=$(mktemp -d "/tmp/dokku.me.XXXXX")
|
||||
trap 'popd &>/dev/null || true; rm -rf "$TMP"' INT TERM
|
||||
|
||||
# test project.toml
|
||||
run touch "$TMP/project.toml"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "dokku plugin:trigger builder-detect $TEST_APP $TMP | tail -n1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "cnb"
|
||||
|
||||
sudo rm -rf $TMP/*
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
# test DOKKU_CNB_EXPERIMENTAL env var
|
||||
run /bin/bash -c "dokku config:set $TEST_APP DOKKU_CNB_EXPERIMENTAL=1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "dokku plugin:trigger builder-detect $TEST_APP $TMP | tail -n1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "cnb"
|
||||
}
|
||||
|
||||
@test "(builder) builder-detect [dockerfile]" {
|
||||
local TMP=$(mktemp -d "/tmp/dokku.me.XXXXX")
|
||||
trap 'popd &>/dev/null || true; rm -rf "$TMP"' INT TERM
|
||||
|
||||
run touch "$TMP/Dockerfile"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "dokku plugin:trigger builder-detect $TEST_APP $TMP | tail -n1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "dockerfile"
|
||||
}
|
||||
|
||||
@test "(builder) builder-detect [herokuish]" {
|
||||
local TMP=$(mktemp -d "/tmp/dokku.me.XXXXX")
|
||||
trap 'popd &>/dev/null || true; rm -rf "$TMP"' INT TERM
|
||||
|
||||
touch "$TMP/Dockerfile"
|
||||
|
||||
# test buildpacks
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "touch $TMP/.buildpacks"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "dokku plugin:trigger builder-detect $TEST_APP $TMP | tail -n1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "herokuish"
|
||||
|
||||
sudo rm -rf $TMP/*
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
# test .env
|
||||
run /bin/bash -c "echo BUILDPACK_URL=null > $TMP/.env"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "dokku plugin:trigger builder-detect $TEST_APP $TMP | tail -n1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "herokuish"
|
||||
|
||||
sudo rm -rf $TMP/*
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
# test BUILDPACK_URL env var
|
||||
run /bin/bash -c "dokku config:set $TEST_APP BUILDPACK_URL=null"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
|
||||
chown -R dokku:dokku "$TMP"
|
||||
run /bin/bash -c "dokku plugin:trigger builder-detect $TEST_APP $TMP | tail -n1"
|
||||
echo "output: $output"
|
||||
echo "status: $status"
|
||||
assert_success
|
||||
assert_output "herokuish"
|
||||
}
|
||||
Reference in New Issue
Block a user