From 1058e1f5ade92b2dd7c1ad1f37fb5c2afcb7e9d6 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 24 Sep 2026 18:25:56 -0400 Subject: [PATCH] fix: check app directory when creating a new app --- plugins/apps/functions.go | 7 ++++- plugins/apps/subcommands.go | 4 +-- tests/unit/apps_1.bats | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/plugins/apps/functions.go b/plugins/apps/functions.go index f146dec1f..798ddd9ff 100644 --- a/plugins/apps/functions.go +++ b/plugins/apps/functions.go @@ -14,6 +14,11 @@ func appExists(appName string) error { return common.VerifyAppName(appName) } +// checks if an app directory already exists, regardless of app visibility +func appNameTaken(appName string) bool { + return common.DirectoryExists(common.AppRoot(appName)) +} + // checks if an app is locked func appIsLocked(appName string) bool { lockPath := getLockPath(appName) @@ -27,7 +32,7 @@ func createApp(appName string) error { return err } - if err := appExists(appName); err == nil { + if appNameTaken(appName) { return errors.New("Name is already taken") } diff --git a/plugins/apps/subcommands.go b/plugins/apps/subcommands.go index 4538f81d6..96942a6e3 100644 --- a/plugins/apps/subcommands.go +++ b/plugins/apps/subcommands.go @@ -27,7 +27,7 @@ func CommandClone(oldAppName string, newAppName string, skipDeploy bool, ignoreE return err } - if err := appExists(newAppName); err == nil { + if appNameTaken(newAppName) { if ignoreExisting { common.LogWarn("Name is already taken") return nil @@ -178,7 +178,7 @@ func CommandRename(oldAppName string, newAppName string, skipDeploy bool) error return err } - if err := appExists(newAppName); err == nil { + if appNameTaken(newAppName) { return errors.New("Name is already taken") } diff --git a/tests/unit/apps_1.bats b/tests/unit/apps_1.bats index 7799ae7f1..5bbfcda55 100644 --- a/tests/unit/apps_1.bats +++ b/tests/unit/apps_1.bats @@ -2,11 +2,15 @@ load test_helper +APP_FILTER_PLUGIN_NAME="app-filter-test" + setup() { global_setup } teardown() { + rm -rf "${PLUGIN_ENABLED_PATH:?}/$APP_FILTER_PLUGIN_NAME" "${PLUGIN_AVAILABLE_PATH:?}/$APP_FILTER_PLUGIN_NAME" + dokku --force apps:destroy "$TEST_APP-source" &>/dev/null || true global_teardown } @@ -489,3 +493,59 @@ teardown() { destroy_app } + +@test "(apps) apps:create, apps:clone, and apps:rename with an existing filtered app" { + create_app + create_app "$TEST_APP-source" + + setup_app_filter_plugin "$TEST_APP" + + run /bin/bash -c "dokku apps:create $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Name is already taken" + assert_output_not_contains "Creating $TEST_APP" + + run /bin/bash -c "dokku apps:clone $TEST_APP-source $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Name is already taken" + + run /bin/bash -c "dokku apps:rename $TEST_APP-source $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Name is already taken" + + rm -rf "${PLUGIN_ENABLED_PATH:?}/$APP_FILTER_PLUGIN_NAME" "${PLUGIN_AVAILABLE_PATH:?}/$APP_FILTER_PLUGIN_NAME" + + destroy_app 0 "$TEST_APP-source" + destroy_app +} + +setup_app_filter_plugin() { + declare desc="installs a plugin that filters out a single app" + declare FILTERED_APP="$1" + local PLUGIN_DIR="$PLUGIN_AVAILABLE_PATH/$APP_FILTER_PLUGIN_NAME" + mkdir -p "$PLUGIN_DIR" + + cat <"$PLUGIN_DIR/plugin.toml" +[plugin] +description = "test plugin filtering out a single app" +version = "0.1.0" +[plugin.config] +EOF + + cat <"$PLUGIN_DIR/user-auth-app" +#!/usr/bin/env bash +shift 2 +for app in "\$@"; do + [[ "\$app" == "$FILTERED_APP" ]] || echo "\$app" +done +EOF + chmod +x "$PLUGIN_DIR/user-auth-app" + + dokku plugin:enable "$APP_FILTER_PLUGIN_NAME" +}