Provisioning: handle .git extension more gracefully (#108213)

* Move .git to repository packages

* Bump nanogit 2025-07-17

This version handles `.git` extension internally so that the client
doesn't have to worry about it

* Put back mutation for Github

* Mutate also git URL for clarity
This commit is contained in:
Roberto Jiménez Sánchez
2025-07-18 13:25:21 +02:00
committed by GitHub
parent 446054a61d
commit 4847882ee7
8 changed files with 231 additions and 41 deletions
@@ -2,6 +2,7 @@ package github
import (
"context"
"strings"
"k8s.io/apimachinery/pkg/runtime"
@@ -21,6 +22,15 @@ func Mutator(secrets secrets.RepositorySecrets) controller.Mutator {
return nil
}
// Trim trailing ".git" and any trailing slash from the GitHub URL, if present, using the strings package.
if repo.Spec.GitHub.URL != "" {
url := repo.Spec.GitHub.URL
url = strings.TrimRight(url, "/")
url = strings.TrimSuffix(url, ".git")
url = strings.TrimRight(url, "/")
repo.Spec.GitHub.URL = url
}
if repo.Spec.GitHub.Token != "" {
secretName := repo.Name + githubTokenSecretSuffix
nameOrValue, err := secrets.Encrypt(ctx, repo, secretName, repo.Spec.GitHub.Token)
@@ -22,6 +22,74 @@ func TestMutator(t *testing.T) {
expectedEncryptedToken string
expectedError string
}{
{
name: "trims trailing .git and slash from GitHub URL",
obj: &provisioning.Repository{
ObjectMeta: metav1.ObjectMeta{
Name: "repo1",
Namespace: "default",
},
Spec: provisioning.RepositorySpec{
GitHub: &provisioning.GitHubRepositoryConfig{
URL: "https://github.com/org/repo.git/",
},
},
},
setupMocks: func(mockSecrets *secrets.MockRepositorySecrets) {},
expectedToken: "",
expectedEncryptedToken: "",
},
{
name: "trims only trailing slash from GitHub URL",
obj: &provisioning.Repository{
ObjectMeta: metav1.ObjectMeta{
Name: "repo2",
Namespace: "default",
},
Spec: provisioning.RepositorySpec{
GitHub: &provisioning.GitHubRepositoryConfig{
URL: "https://github.com/org/repo/",
},
},
},
setupMocks: func(mockSecrets *secrets.MockRepositorySecrets) {},
expectedToken: "",
expectedEncryptedToken: "",
},
{
name: "trims only trailing .git from GitHub URL",
obj: &provisioning.Repository{
ObjectMeta: metav1.ObjectMeta{
Name: "repo3",
Namespace: "default",
},
Spec: provisioning.RepositorySpec{
GitHub: &provisioning.GitHubRepositoryConfig{
URL: "https://github.com/org/repo.git",
},
},
},
setupMocks: func(mockSecrets *secrets.MockRepositorySecrets) {},
expectedToken: "",
expectedEncryptedToken: "",
},
{
name: "does not trim if no .git or slash",
obj: &provisioning.Repository{
ObjectMeta: metav1.ObjectMeta{
Name: "repo4",
Namespace: "default",
},
Spec: provisioning.RepositorySpec{
GitHub: &provisioning.GitHubRepositoryConfig{
URL: "https://github.com/org/repo",
},
},
},
setupMocks: func(mockSecrets *secrets.MockRepositorySecrets) {},
expectedToken: "",
expectedEncryptedToken: "",
},
{
name: "successful token encryption",
obj: &provisioning.Repository{
@@ -114,7 +114,10 @@ func (r *githubRepository) Validate() (list field.ErrorList) {
}
func ParseOwnerRepoGithub(giturl string) (owner string, repo string, err error) {
parsed, e := url.Parse(strings.TrimSuffix(giturl, ".git"))
giturl = strings.TrimSuffix(giturl, ".git")
giturl = strings.TrimSuffix(giturl, "/")
parsed, e := url.Parse(giturl)
if e != nil {
err = e
return