BuildPackageVersionBaseline takes in a set of template packages from the server, and for each step+package therein, finds the latest available version. Additional parameters for the feed query can be supplied using the setAdditionalFeedQueryParameters callback. Result is the list of step+package+ver
(octopus *octopusApiClient.Client, packages []releases.ReleaseTemplatePackage, setAdditionalFeedQueryParameters func(releases.ReleaseTemplatePackage, feeds.SearchPackageVersionsQuery) (feeds.SearchPackageVersionsQuery, error))
| 66 | // Result is the list of step+package+versions to use as a baseline. |
| 67 | // The package version override process takes this as an input and layers on top of it |
| 68 | func BuildPackageVersionBaseline(octopus *octopusApiClient.Client, packages []releases.ReleaseTemplatePackage, |
| 69 | setAdditionalFeedQueryParameters func(releases.ReleaseTemplatePackage, feeds.SearchPackageVersionsQuery) (feeds.SearchPackageVersionsQuery, error)) ([]*StepPackageVersion, error) { |
| 70 | result := make([]*StepPackageVersion, 0, len(packages)) |
| 71 | |
| 72 | // step 1: pass over all the packages in the deployment process, group them |
| 73 | // by their feed, then subgroup by packageId |
| 74 | |
| 75 | // map(key: FeedID, value: list of references using the package so we can trace back to steps) |
| 76 | feedsToQuery := make(map[string][]releases.ReleaseTemplatePackage) |
| 77 | for _, pkg := range packages { |
| 78 | |
| 79 | if pkg.FixedVersion != "" { |
| 80 | // If a package has a fixed version it shouldn't be displayed or overridable at all |
| 81 | continue |
| 82 | } |
| 83 | |
| 84 | // If a package is not considered resolvable by the server, don't attempt to query it's feed or lookup |
| 85 | // any potential versions for it; we can't succeed in that because variable templates won't get expanded |
| 86 | // until deployment time |
| 87 | if !pkg.IsResolvable { |
| 88 | result = append(result, &StepPackageVersion{ |
| 89 | PackageID: pkg.PackageID, |
| 90 | ActionName: pkg.ActionName, |
| 91 | PackageReferenceName: pkg.PackageReferenceName, |
| 92 | Version: "", |
| 93 | }) |
| 94 | continue |
| 95 | } |
| 96 | if feedPackages, seenFeedBefore := feedsToQuery[pkg.FeedID]; !seenFeedBefore { |
| 97 | feedsToQuery[pkg.FeedID] = []releases.ReleaseTemplatePackage{pkg} |
| 98 | } else { |
| 99 | // seen both the feed and package, but not against this particular step |
| 100 | feedsToQuery[pkg.FeedID] = append(feedPackages, pkg) |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | if len(feedsToQuery) == 0 { |
| 105 | return make([]*StepPackageVersion, 0), nil |
| 106 | } |
| 107 | |
| 108 | // step 2: load the feed resources, so we can get SearchPackageVersionsTemplate |
| 109 | feedIds := make([]string, 0, len(feedsToQuery)) |
| 110 | for k := range feedsToQuery { |
| 111 | feedIds = append(feedIds, k) |
| 112 | } |
| 113 | sort.Strings(feedIds) // we need to sort them otherwise the order is indeterminate. Server doesn't care but our unit tests fail |
| 114 | foundFeeds, err := octopus.Feeds.Get(feeds.FeedsQuery{IDs: feedIds, Take: len(feedIds)}) |
| 115 | if err != nil { |
| 116 | return nil, err |
| 117 | } |
| 118 | |
| 119 | // step 3: for each package within a feed, ask the server to select the best package version for it, applying the channel rules |
| 120 | for _, feed := range foundFeeds.Items { |
| 121 | packageRefsInFeed, ok := feedsToQuery[feed.GetID()] |
| 122 | if !ok { |
| 123 | return nil, errors.New("internal consistency error; feed ID not found in feedsToQuery") // should never happen |
| 124 | } |
| 125 |
no test coverage detected