Skip to content

Commit

Permalink
feat: allow warehouse git subs to select commits by tag (#1446)
Browse files Browse the repository at this point in the history
Signed-off-by: Kent Rancourt <[email protected]>
  • Loading branch information
krancour committed Feb 2, 2024
1 parent fc05523 commit 397fc3e
Show file tree
Hide file tree
Showing 19 changed files with 1,462 additions and 581 deletions.
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ linters-settings:
skip-generated: true
custom-order: true
goconst:
ignore-tests: true
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
Expand Down
3 changes: 3 additions & 0 deletions api/v1alpha1/freight_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ type GitCommit struct {
ID string `json:"id,omitempty"`
// Branch denotes the branch of the repository where this commit was found.
Branch string `json:"branch,omitempty"`
// Tag denotes a tag in the repository that matched selection criteria and
// resolved to this commit.
Tag string `json:"tag,omitempty"`
// HealthCheckCommit is the ID of a specific commit. When specified,
// assessments of Stage health will used this value (instead of ID) when
// determining if applicable sources of Argo CD Application resources
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ message GitCommit {
optional string health_check_commit = 4 [json_name = "healthCheckCommit"];
string message = 5 [json_name = "message"];
string author = 6 [json_name = "author"];
string tag = 7 [json_name = "tag"];
}

message GitRepoUpdate {
Expand All @@ -77,6 +78,10 @@ message GitRepoUpdate {
message GitSubscription {
string repo_url = 1 [json_name = "repoURL"];
string branch = 2 [json_name = "branch"];
string commit_selection_strategy = 3 [json_name = "commitSelectionStrategy"];
optional string semver_constraint = 4 [json_name = "semverConstraint"];
optional string allow_tags = 5 [json_name = "allowTags"];
repeated string ignore_tags = 6 [json_name = "ignoreTags"];
}

message Health {
Expand Down
51 changes: 48 additions & 3 deletions api/v1alpha1/warehouse_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ package v1alpha1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

// +kubebuilder:validation:Enum={Lexical,NewestFromBranch,NewestTag,SemVer}
type CommitSelectionStrategy string

const (
CommitSelectionStrategyLexical CommitSelectionStrategy = "Lexical"
CommitSelectionStrategyNewestFromBranch CommitSelectionStrategy = "NewestFromBranch"
CommitSelectionStrategyNewestTag CommitSelectionStrategy = "NewestTag"
CommitSelectionStrategySemVer CommitSelectionStrategy = "SemVer"
)

// +kubebuilder:validation:Enum={Digest,Lexical,NewestBuild,SemVer}
type ImageTagSelectionStrategy string

Expand Down Expand Up @@ -59,13 +69,48 @@ type GitSubscription struct {
//+kubebuilder:validation:MinLength=1
//+kubebuilder:validation:Pattern=`^https://(\w+([\.-]\w+)*@)?\w+([\.-]\w+)*(:[\d]+)?(/.*)?$`
RepoURL string `json:"repoURL"`
// Branch references a particular branch of the repository. This field is
// optional. When not specified, the subscription is implicitly to the
// repository's default branch.
// CommitSelectionStrategy specifies the rules for how to identify the newest
// commit of interest in the repository specified by the RepoURL field. This
// field is optional. When left unspecified, the field is implicitly treated
// as if its value were "NewestFromBranch".
//
// +kubebuilder:default=NewestFromBranch
CommitSelectionStrategy CommitSelectionStrategy `json:"commitSelectionStrategy,omitempty"`
// Branch references a particular branch of the repository. The value in this
// field only has any effect when the CommitSelectionStrategy is
// NewestFromBranch or left unspecified (which is implicitly the same as
// NewestFromBranch). This field is optional. When left unspecified, (and the
// CommitSelectionStrategy is NewestFromBranch or unspecified), the
// subscription is implicitly to the repository's default branch.
//
//+kubebuilder:validation:MinLength=1
//+kubebuilder:validation:Pattern=`^\w+([-/]\w+)*$`
Branch string `json:"branch,omitempty"`
// SemverConstraint specifies constraints on what new tagged commits are
// considered in determining the newest commit of interest. The value in this
// field only has any effect when the CommitSelectionStrategy is SemVer. This
// field is optional. When left unspecified, there will be no constraints,
// which means the latest semantically tagged commit will always be used. Care
// should be taken with leaving this field unspecified, as it can lead to the
// unanticipated rollout of breaking changes.
//
//+kubebuilder:validation:Optional
SemverConstraint string `json:"semverConstraint,omitempty"`
// AllowTags is a regular expression that can optionally be used to limit the
// tags that are considered in determining the newest commit of interest. The
// value in this field only has any effect when the CommitSelectionStrategy is
// Lexical, NewestTag, or SemVer. This field is optional.
//
//+kubebuilder:validation:Optional
AllowTags string `json:"allowTags,omitempty"`
// IgnoreTags is a list of tags that must be ignored when determining the
// newest commit of interest. No regular expressions or glob patterns are
// supported yet. The value in this field only has any effect when the
// CommitSelectionStrategy is Lexical, NewestTag, or SemVer. This field is
// optional.
//
//+kubebuilder:validation:Optional
IgnoreTags []string `json:"ignoreTags,omitempty"`
// InsecureSkipTLSVerify specifies whether certificate verification errors
// should be ignored when connecting to the repository. This should be enabled
// only with great caution.
Expand Down
7 changes: 6 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions charts/kargo/crds/kargo.akuity.io_freights.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ spec:
repoURL:
description: RepoURL is the URL of a Git repository.
type: string
tag:
description: Tag denotes a tag in the repository that matched selection
criteria and resolved to this commit.
type: string
type: object
type: array
id:
Expand Down
12 changes: 12 additions & 0 deletions charts/kargo/crds/kargo.akuity.io_stages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,10 @@ spec:
repoURL:
description: RepoURL is the URL of a Git repository.
type: string
tag:
description: Tag denotes a tag in the repository that matched
selection criteria and resolved to this commit.
type: string
type: object
type: array
id:
Expand Down Expand Up @@ -699,6 +703,10 @@ spec:
repoURL:
description: RepoURL is the URL of a Git repository.
type: string
tag:
description: Tag denotes a tag in the repository that
matched selection criteria and resolved to this commit.
type: string
type: object
type: array
id:
Expand Down Expand Up @@ -900,6 +908,10 @@ spec:
repoURL:
description: RepoURL is the URL of a Git repository.
type: string
tag:
description: Tag denotes a tag in the repository that
matched selection criteria and resolved to this commit.
type: string
type: object
type: array
id:
Expand Down
46 changes: 45 additions & 1 deletion charts/kargo/crds/kargo.akuity.io_warehouses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,47 @@ spec:
git:
description: Git describes a subscriptions to a Git repository.
properties:
allowTags:
description: AllowTags is a regular expression that can
optionally be used to limit the tags that are considered
in determining the newest commit of interest. The value
in this field only has any effect when the CommitSelectionStrategy
is Lexical, NewestTag, or SemVer. This field is optional.
type: string
branch:
description: Branch references a particular branch of the
repository. This field is optional. When not specified,
repository. The value in this field only has any effect
when the CommitSelectionStrategy is NewestFromBranch or
left unspecified (which is implicitly the same as NewestFromBranch).
This field is optional. When left unspecified, (and the
CommitSelectionStrategy is NewestFromBranch or unspecified),
the subscription is implicitly to the repository's default
branch.
minLength: 1
pattern: ^\w+([-/]\w+)*$
type: string
commitSelectionStrategy:
default: NewestFromBranch
description: CommitSelectionStrategy specifies the rules
for how to identify the newest commit of interest in the
repository specified by the RepoURL field. This field
is optional. When left unspecified, the field is implicitly
treated as if its value were "NewestFromBranch".
enum:
- Lexical
- NewestFromBranch
- NewestTag
- SemVer
type: string
ignoreTags:
description: IgnoreTags is a list of tags that must be ignored
when determining the newest commit of interest. No regular
expressions or glob patterns are supported yet. The value
in this field only has any effect when the CommitSelectionStrategy
is Lexical, NewestTag, or SemVer. This field is optional.
items:
type: string
type: array
insecureSkipTLSVerify:
description: InsecureSkipTLSVerify specifies whether certificate
verification errors should be ignored when connecting
Expand All @@ -95,6 +128,17 @@ spec:
minLength: 1
pattern: ^https://(\w+([\.-]\w+)*@)?\w+([\.-]\w+)*(:[\d]+)?(/.*)?$
type: string
semverConstraint:
description: SemverConstraint specifies constraints on what
new tagged commits are considered in determining the newest
commit of interest. The value in this field only has any
effect when the CommitSelectionStrategy is SemVer. This
field is optional. When left unspecified, there will be
no constraints, which means the latest semantically tagged
commit will always be used. Care should be taken with
leaving this field unspecified, as it can lead to the
unanticipated rollout of breaking changes.
type: string
required:
- repoURL
type: object
Expand Down
18 changes: 14 additions & 4 deletions internal/api/types/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ func FromGitCommitProto(g *v1alpha1.GitCommit) *kargoapi.GitCommit {
RepoURL: g.GetRepoUrl(),
ID: g.GetId(),
Branch: g.GetBranch(),
Tag: g.GetTag(),
HealthCheckCommit: g.GetHealthCheckCommit(),
}
}
Expand Down Expand Up @@ -321,8 +322,12 @@ func FromGitSubscriptionProto(s *v1alpha1.GitSubscription) *kargoapi.GitSubscrip
return nil
}
return &kargoapi.GitSubscription{
RepoURL: s.GetRepoUrl(),
Branch: s.GetBranch(),
RepoURL: s.GetRepoUrl(),
CommitSelectionStrategy: kargoapi.CommitSelectionStrategy(s.GetCommitSelectionStrategy()),
Branch: s.GetBranch(),
SemverConstraint: s.GetSemverConstraint(),
AllowTags: s.GetAllowTags(),
IgnoreTags: s.GetIgnoreTags(),
}
}

Expand Down Expand Up @@ -793,8 +798,12 @@ func ToSubscriptionsProto(s kargoapi.Subscriptions) *v1alpha1.Subscriptions {

func ToGitSubscriptionProto(g kargoapi.GitSubscription) *v1alpha1.GitSubscription {
return &v1alpha1.GitSubscription{
RepoUrl: g.RepoURL,
Branch: g.Branch,
RepoUrl: g.RepoURL,
CommitSelectionStrategy: string(g.CommitSelectionStrategy),
Branch: g.Branch,
SemverConstraint: proto.String(g.SemverConstraint),
AllowTags: proto.String(g.AllowTags),
IgnoreTags: g.IgnoreTags,
}
}

Expand Down Expand Up @@ -1093,6 +1102,7 @@ func ToGitCommitProto(g kargoapi.GitCommit) *v1alpha1.GitCommit {
RepoUrl: g.RepoURL,
Id: g.ID,
Branch: g.Branch,
Tag: g.Tag,
HealthCheckCommit: proto.String(g.HealthCheckCommit),
Message: g.Message,
Author: g.Author,
Expand Down
20 changes: 20 additions & 0 deletions internal/controller/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type Repo interface {
// LastCommitID returns the ID (sha) of the most recent commit to the current
// branch.
LastCommitID() (string, error)
// ListTags returns a slice of tags in the repository.
ListTags() ([]string, error)
// CommitMessage returns the text of the most recent commit message associated
// with the specified commit ID.
CommitMessage(id string) (string, error)
Expand Down Expand Up @@ -353,6 +355,24 @@ func (r *repo) LastCommitID() (string, error) {
errors.Wrap(err, "error obtaining ID of last commit")
}

func (r *repo) ListTags() ([]string, error) {
if _, err :=
libExec.Exec(r.buildCommand("fetch", "origin", "--tags")); err != nil {
return nil, errors.Wrapf(err, "error fetching tags from repo %q", r.url)
}
tagsBytes, err := libExec.Exec(r.buildCommand("tag", "--list", "--sort", "-creatordate"))
if err != nil {
return nil, errors.Wrapf(err, "error listing tags for repo %q", r.url)
}
tags := []string{}
scanner := bufio.NewScanner(bytes.NewReader(tagsBytes))
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
tags = append(tags, strings.TrimSpace(scanner.Text()))
}
return tags, nil
}

func (r *repo) CommitMessage(id string) (string, error) {
msgBytes, err := libExec.Exec(
r.buildCommand("log", "-n", "1", "--pretty=format:%s", id),
Expand Down
Loading

0 comments on commit 397fc3e

Please sign in to comment.