Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions integration-tests/environment_delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package tests

import (
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"

"github.com/upsun/cli/pkg/mockapi"
)

func TestEnvironmentDelete(t *testing.T) {
authServer := mockapi.NewAuthServer(t)
defer authServer.Close()

apiHandler := mockapi.NewHandler(t)
apiServer := httptest.NewServer(apiHandler)
defer apiServer.Close()

projectID := mockapi.ProjectID()
apiHandler.SetProjects([]*mockapi.Project{{
ID: projectID,
Links: mockapi.MakeHALLinks(
"self=/projects/"+projectID,
"environments=/projects/"+projectID+"/environments",
),
DefaultBranch: "main",
}})
apiHandler.SetEnvironments([]*mockapi.Environment{
makeEnv(projectID, "main", "production", "active", nil),
makeEnv(projectID, "test-1", "development", "active", "main"),
makeEnv(projectID, "test-2", "development", "active", "main"),
makeEnv(projectID, "dev", "development", "active", "main"),
})

f := newCommandFactory(t, apiServer.URL, authServer.URL)
f.Run("cc")

cases := []struct {
name string
args []string
extraEnv []string
wantErr bool
wantStdErr []string
wantMissing []string
}{
{
name: "single wildcard argument",
args: []string{"test-*"},
wantStdErr: []string{"2 environments found by ID.", "Selected environments: test-1, test-2"},
wantMissing: []string{"Specified environment not found"},
},
{
name: "wildcard option",
args: []string{"-e", "test-*"},
wantStdErr: []string{"2 environments found by ID.", "Selected environments: test-1, test-2"},
wantMissing: []string{"Specified environment not found"},
},
{
name: "ignores an unknown branch variable",
args: []string{"--type", "development"},
extraEnv: []string{"PLATFORM_BRANCH=missing"},
wantStdErr: []string{"3 environments found matching type(s): development"},
wantMissing: []string{"Specified environment not found"},
},
{
name: "missing environment",
args: []string{"missing"},
wantErr: true,
wantStdErr: []string{"Environment not found: missing", "0 environments found by ID."},
wantMissing: []string{"Specified environment not found"},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
f.extraEnv = c.extraEnv
args := append([]string{"environment:delete", "-p", projectID}, c.args...)
// Decline any confirmation, so nothing is deleted.
_, stdErr, err := f.RunInteractive("n\nn\n", args...)
if c.wantErr {
assert.Error(t, err)
}
for _, s := range c.wantStdErr {
assert.Contains(t, stdErr, s)
}
for _, s := range c.wantMissing {
assert.NotContains(t, stdErr, s)
}
})
}
}
12 changes: 5 additions & 7 deletions legacy/src/Command/Environment/EnvironmentDeleteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ protected function configure(): void

protected function execute(InputInterface $input, OutputInterface $output): int
{
// Select the current project, deliberately ignoring the 'environment'
// argument and option, as those will be processed separately.
$inputCopy = clone $input;
$inputCopy->setArgument('environment', null);
$inputCopy->setOption('environment', null);
$selection = $this->selector->getSelection($input, new SelectorConfig(envRequired: false));
// Select only the project: the 'environment' argument and option are processed separately.
$selection = $this->selector->getSelection($input, new SelectorConfig(selectEnv: false));

$environments = $this->api->getEnvironments($selection->getProject());

Expand All @@ -103,7 +99,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if ($specifiedEnvironmentIds) {
$anythingSpecified = true;
$allIds = \array_map(fn(Environment $e) => $e->id, $environments);
$specifiedEnvironmentIds = Wildcard::select($allIds, $specifiedEnvironmentIds);
// Keep exact IDs even if they don't match, so they can be reported as not found.
$exactIds = array_filter($specifiedEnvironmentIds, fn(string $id): bool => !str_contains($id, '%') && !str_contains($id, '*'));
$specifiedEnvironmentIds = array_values(array_unique(array_merge(Wildcard::select($allIds, $specifiedEnvironmentIds), $exactIds)));
$notFound = array_diff($specifiedEnvironmentIds, array_keys($environments));
if (!empty($notFound)) {
// Refresh the environments list if any environment is not found.
Expand Down
4 changes: 3 additions & 1 deletion legacy/src/Selector/Selector.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ public function getSelection(InputInterface $input, ?SelectorConfig $config = nu
$environment = null;

$envArgName = $config->envArgName;
if ($input->hasArgument($envArgName)
if (!$config->selectEnv) {
$this->debug('Skipping environment selection');
} elseif ($input->hasArgument($envArgName)
&& $input->getArgument($envArgName) !== null
&& $input->getArgument($envArgName) !== []) {
if ($input->hasOption($envOptionName) && Option::stringOrNull($input, $envOptionName)) {
Expand Down
2 changes: 2 additions & 0 deletions legacy/src/Selector/SelectorConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class SelectorConfig
{
public function __construct(
public bool $envRequired = true,
// Set to false to select only the project, e.g. when the command handles environments itself.
public bool $selectEnv = true,
public string $envArgName = 'environment',
public string $chooseProjectText = 'Enter a number to choose a project:',
public string $chooseEnvText = 'Enter a number to choose an environment:',
Expand Down
Loading