func (s ReleaseImageSpec) selectWorkloads(ctx context.Context, rc ReleaseContext, results Result) ([]*WorkloadUpdate, error) {
	prefilters, postfilters, err := s.filters(rc)
	if err != nil {
		return nil, err
	}
	return rc.SelectWorkloads(ctx, results, prefilters, postfilters)
}
Take the spec given in the job, and figure out which workloads are
in question based on the running workloads and those defined in the
repo. Fill in the release results along the way.
package update
import (
	"context"
	"fmt"
	"strings"
	"github.com/pkg/errors"
	"github.com/fluxcd/flux/pkg/image"
	"github.com/fluxcd/flux/pkg/policy"
	"github.com/fluxcd/flux/pkg/registry"
	"github.com/fluxcd/flux/pkg/resource"
	"github.com/go-kit/kit/log"
)
const (
	ResourceSpecAll = ResourceSpec("<all>")
	ImageSpecLatest = ImageSpec("<all latest>")
)
var (
	ErrInvalidReleaseKind = errors.New("invalid release kind")
)
type ReleaseKind string
type ReleaseType string
const (
	ReleaseKindPlan    ReleaseKind = "plan"
	ReleaseKindExecute ReleaseKind = "execute"
)
func ParseReleaseKind(s string) (ReleaseKind, error) {
	switch s {
	case string(ReleaseKindPlan):
		return ReleaseKindPlan, nil
	case string(ReleaseKindExecute):
		return ReleaseKindExecute, nil
	default:
		return "", ErrInvalidReleaseKind
	}
}
const UserAutomated = "<automated>"
type ReleaseContext interface {
	SelectWorkloads(context.Context, Result, []WorkloadFilter, []WorkloadFilter) ([]*WorkloadUpdate, error)
	Registry() registry.Registry
}
type ReleaseImageSpec struct {
	ServiceSpecs []ResourceSpec  
	ImageSpec    ImageSpec
	Kind         ReleaseKind
	Excludes     []resource.ID
	Force        bool
}
func (s ReleaseImageSpec) ReleaseType() ReleaseType {
	switch {
	case s.ImageSpec == ImageSpecLatest:
		return "latest_images"
	default:
		return "specific_image"
	}
}
func (s ReleaseImageSpec) CalculateRelease(ctx context.Context, rc ReleaseContext, logger log.Logger) ([]*WorkloadUpdate, Result, error) {
	results := Result{}
	timer := NewStageTimer("select_workloads")
	updates, err := s.selectWorkloads(ctx, rc, results)
	timer.ObserveDuration()
	if err != nil {
		return nil, nil, err
	}
	s.markSkipped(results)
	timer = NewStageTimer("lookup_images")
	updates, err = s.calculateImageUpdates(rc, updates, results, logger)
	timer.ObserveDuration()
	if err != nil {
		return nil, nil, err
	}
	return updates, results, nil
}
func (s ReleaseImageSpec) ReleaseKind() ReleaseKind {
	return s.Kind
}
func (s ReleaseImageSpec) CommitMessage(result Result) string {
	image := strings.Trim(s.ImageSpec.String(), "<>")
	var workloads []string
	for _, spec := range s.ServiceSpecs {
		workloads = append(workloads, strings.Trim(spec.String(), "<>"))
	}
	return fmt.Sprintf("Release %s to %s", image, strings.Join(workloads, ", "))
}