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
32 changes: 31 additions & 1 deletion pkg/argocd/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"sigs.k8s.io/kustomize/kyaml/order"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"

"github.com/argoproj-labs/argocd-image-updater/pkg/common"
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"

"github.com/argoproj-labs/argocd-image-updater/ext/git"
Expand Down Expand Up @@ -128,6 +129,33 @@ func TemplateBranchName(branchName string, changeList []ChangeEntry) string {

type changeWriter func(app *v1alpha1.Application, wbc *WriteBackConfig, gitC git.Client) (err error, skip bool)

// getWriteBackBranch returns the branch to use for write-back operations.
// It first checks for a branch specified in annotations, then uses the
// targetRevision from the matching git source, falling back to getApplicationSource.
func getWriteBackBranch(app *v1alpha1.Application) string {
if app == nil {
return ""
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we cannot take the annotation value as is, since it can be a composite form like "main:changes". See https://argocd-image-updater.readthedocs.io/en/latest/basics/update-methods/#specifying-a-branch-to-commit-to

I guess we dont' see the above block. Line 200 already handles this case. See next comment.

// If git repository is specified, find matching source
if gitRepo, ok := app.GetAnnotations()[common.GitRepositoryAnnotation]; ok {
if app.Spec.HasMultipleSources() {
for _, s := range app.Spec.Sources {
if s.RepoURL == gitRepo {
log.WithContext().AddField("application", app.GetName()).
Debugf("Using target revision '%s' from matching source '%s'", s.TargetRevision, gitRepo)
return s.TargetRevision
}
}
log.WithContext().AddField("application", app.GetName()).
Debugf("No matching source found for git repository %s, falling back to primary source", gitRepo)
}
}

// Fall back to getApplicationSource's targetRevision
// This maintains consistency with how other parts of the code select the source
return getApplicationSource(app).TargetRevision
}

// commitChanges commits any changes required for updating one or more images
// after the UpdateApplication cycle has finished.
func commitChangesGit(app *v1alpha1.Application, wbc *WriteBackConfig, changeList []ChangeEntry, write changeWriter) error {
Expand Down Expand Up @@ -164,9 +192,11 @@ func commitChangesGit(app *v1alpha1.Application, wbc *WriteBackConfig, changeLis
// config, or taken from the application spec's targetRevision. If the
// target revision is set to the special value HEAD, or is the empty
// string, we'll try to resolve it to a branch name.
checkOutBranch := getApplicationSource(app).TargetRevision
var checkOutBranch string
if wbc.GitBranch != "" {
checkOutBranch = wbc.GitBranch
} else {
checkOutBranch = getWriteBackBranch(app)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the gitbranch is set, we always take it. So I think we only need to call the func getWriteBackBranch if wbc.GitBranch is empty (in the else clause).

logCtx.Tracef("targetRevision for update is '%s'", checkOutBranch)
if checkOutBranch == "" || checkOutBranch == "HEAD" {
Expand Down
131 changes: 131 additions & 0 deletions pkg/argocd/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/tag"

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

"sigs.k8s.io/kustomize/api/types"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"

Expand Down Expand Up @@ -329,3 +331,132 @@ func Test_updateKustomizeFile(t *testing.T) {
})
}
}

func Test_getApplicationSource(t *testing.T) {
t.Run("multi-source without git repo annotation", func(t *testing.T) {
app := &v1alpha1.Application{
ObjectMeta: v1.ObjectMeta{
Name: "test-app",
},
Spec: v1alpha1.ApplicationSpec{
Sources: v1alpha1.ApplicationSources{
{
RepoURL: "https://charts.bitnami.com/bitnami",
TargetRevision: "18.2.3",
Chart: "nginx",
Helm: &v1alpha1.ApplicationSourceHelm{},
},
{
RepoURL: "https://github.com/chengfang/image-updater-examples.git",
TargetRevision: "main",
},
},
},
}

source := getApplicationSource(app)
assert.Equal(t, "18.2.3", source.TargetRevision)
assert.Equal(t, "https://charts.bitnami.com/bitnami", source.RepoURL)
})

t.Run("single source application", func(t *testing.T) {
app := &v1alpha1.Application{
ObjectMeta: v1.ObjectMeta{
Name: "test-app",
},
Spec: v1alpha1.ApplicationSpec{
Source: &v1alpha1.ApplicationSource{
RepoURL: "https://github.com/example/repo.git",
TargetRevision: "main",
},
},
}

source := getApplicationSource(app)
assert.Equal(t, "main", source.TargetRevision)
assert.Equal(t, "https://github.com/example/repo.git", source.RepoURL)
})
}

func Test_getWriteBackBranch(t *testing.T) {
t.Run("nil application", func(t *testing.T) {
branch := getWriteBackBranch(nil)
assert.Equal(t, "", branch)
})

t.Run("matching git-repository annotation", func(t *testing.T) {
app := &v1alpha1.Application{
ObjectMeta: v1.ObjectMeta{
Name: "test-app",
Annotations: map[string]string{
"argocd-image-updater.argoproj.io/git-repository": "https://github.com/chengfang/image-updater-examples.git",
},
},
Spec: v1alpha1.ApplicationSpec{
Sources: v1alpha1.ApplicationSources{
{
RepoURL: "https://charts.bitnami.com/bitnami",
TargetRevision: "18.2.3",
Chart: "nginx",
},
{
RepoURL: "https://github.com/chengfang/image-updater-examples.git",
TargetRevision: "main",
},
},
},
}

branch := getWriteBackBranch(app)
assert.Equal(t, "main", branch)
})

t.Run("fallback to primary source when no match", func(t *testing.T) {
app := &v1alpha1.Application{
ObjectMeta: v1.ObjectMeta{
Name: "test-app",
},
Spec: v1alpha1.ApplicationSpec{
Sources: v1alpha1.ApplicationSources{
{
RepoURL: "https://charts.bitnami.com/bitnami",
TargetRevision: "18.2.3",
Chart: "nginx",
Helm: &v1alpha1.ApplicationSourceHelm{},
},
{
RepoURL: "https://github.com/chengfang/image-updater-examples.git",
TargetRevision: "main",
},
},
},
}

branch := getWriteBackBranch(app)
assert.Equal(t, "18.2.3", branch)
})

t.Run("git-repository annotation with non-matching URL", func(t *testing.T) {
app := &v1alpha1.Application{
ObjectMeta: v1.ObjectMeta{
Name: "test-app",
Annotations: map[string]string{
"argocd-image-updater.argoproj.io/git-repository": "https://github.com/different/repo.git",
},
},
Spec: v1alpha1.ApplicationSpec{
Sources: v1alpha1.ApplicationSources{
{
RepoURL: "https://charts.bitnami.com/bitnami",
TargetRevision: "18.2.3",
Chart: "nginx",
Helm: &v1alpha1.ApplicationSourceHelm{},
},
},
},
}

branch := getWriteBackBranch(app)
assert.Equal(t, "18.2.3", branch)
})
}
Loading