diff --git a/pkg/cmd/release/promote/promote_test.go b/pkg/cmd/release/promote/promote_test.go index 03dabfdb..af29c229 100644 --- a/pkg/cmd/release/promote/promote_test.go +++ b/pkg/cmd/release/promote/promote_test.go @@ -90,7 +90,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -151,7 +151,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -212,7 +212,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -261,7 +261,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -310,7 +310,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -371,7 +371,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -420,7 +420,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -469,7 +469,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -518,7 +518,7 @@ func TestPromoteRelease_Success(t *testing.T) { }) // Lookup from environment by ID - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -606,7 +606,7 @@ func TestPromoteRelease_Errors(t *testing.T) { RespondWith(resources.Resources[*projects.Project]{ Items: []*projects.Project{fireProject}, }) - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=NonExistent&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=NonExistent&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -628,7 +628,7 @@ func TestPromoteRelease_Errors(t *testing.T) { RespondWith(resources.Resources[*projects.Project]{ Items: []*projects.Project{fireProject}, }) - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) @@ -653,7 +653,7 @@ func TestPromoteRelease_Errors(t *testing.T) { RespondWith(resources.Resources[*projects.Project]{ Items: []*projects.Project{fireProject}, }) - api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=2147483647"). + api.ExpectRequest(t, "GET", "/api/"+spaceID+"/environments/v2?name=&skip=0&ids=Development&take=1"). RespondWith(resources.Resources[*environments.Environment]{ Items: []*environments.Environment{}, }) diff --git a/pkg/executor/release.go b/pkg/executor/release.go index 5ce0c6fc..313d3069 100644 --- a/pkg/executor/release.go +++ b/pkg/executor/release.go @@ -276,30 +276,13 @@ func releasePromote(octopus *client.Client, space *spaces.Space, input any) erro return fmt.Errorf("project not found. %v", err) } - envs, err := environments.Get(octopus, space.ID, environments.EnvironmentQuery{ - IDs: []string{params.FromEnvironment}, - Skip: 0, - Take: math.MaxInt32, - }) + fromEnv, err := getEnvironment(octopus, space, err, params.FromEnvironment) if err != nil { - return fmt.Errorf("environment not found. %v", err) - } - // - if len(envs.Items) == 0 { - envs, err = environments.Get(octopus, space.ID, environments.EnvironmentQuery{ - Name: params.FromEnvironment, - Skip: 0, - Take: math.MaxInt32, - }) - if err != nil || len(envs.Items) == 0 { - return fmt.Errorf("environment not found. %v", err) - } + return err } - // just grab the first environment - sourceEnv := envs.Items[0] dashboardQuery := dashboard.DashboardDynamicQuery{ - Environments: []string{sourceEnv.ID}, + Environments: []string{fromEnv.ID}, Projects: []string{proj.ID}, // If using latest successful, we need previous dashboard items as well // so that we can ensure we get a previous successful deployment @@ -315,7 +298,7 @@ func releasePromote(octopus *client.Client, space *spaces.Space, input any) erro // this is probably unnecessary, but it mimics the existing logic var dashboardItems []*dashboard.DashboardItem for _, item := range dynamicDashboard.Items { - if item.EnvironmentID == sourceEnv.ID && item.ProjectID == proj.ID { + if item.EnvironmentID == fromEnv.ID && item.ProjectID == proj.ID { dashboardItems = append(dashboardItems, item) } } @@ -376,3 +359,50 @@ func compareDashboardItemsByRelease(a, b *dashboard.DashboardItem) int { // we multiply by -1 to order by descending return versioning.Compare(aVersion, bVersion, (*versioning.OctopusVersion).Compare) * -1 } + +func getEnvironment(octopus *client.Client, space *spaces.Space, err error, nameOrID string) (*environments.Environment, error) { + envResponse, err := environments.Get(octopus, space.ID, environments.EnvironmentQuery{ + IDs: []string{nameOrID}, + Skip: 0, + Take: 1, // we are matching on ID, so there should only be one + }) + if err != nil { + return nil, fmt.Errorf("environment not found. %v", err) + } + + // double check the ID and return if true + if len(envResponse.Items) == 1 && envResponse.Items[0].ID == nameOrID { + return envResponse.Items[0], nil + } + + // fallback on checking by name + if len(envResponse.Items) == 0 { + envResponse, err = environments.Get(octopus, space.ID, environments.EnvironmentQuery{ + Name: nameOrID, + Skip: 0, + Take: math.MaxInt32, + }) + if err != nil { + return nil, fmt.Errorf("environment not found. %v", err) + } + } + + // if we have multiple responses, this means that the `Name` filter didn't work + // so we do the filtering ourselves + switch { + case len(envResponse.Items) == 0: + return nil, fmt.Errorf("environment not found") + case len(envResponse.Items) == 1 && strings.EqualFold(envResponse.Items[0].Name, nameOrID): + return envResponse.Items[0], nil + case len(envResponse.Items) > 1: + for _, item := range envResponse.Items { + // find an exact match to the partial match responses + if strings.EqualFold(item.Name, nameOrID) { + return item, nil + } + } + } + + // final fallback + return nil, fmt.Errorf("environment not found") +}