From caaa545320c4300761de6f6008a8a1cd23eaac03 Mon Sep 17 00:00:00 2001 From: k4yt3x Date: Fri, 30 Aug 2024 19:43:34 +0000 Subject: [PATCH] saving current progress Signed-off-by: k4yt3x --- CHANGELOG.md | 4 + cmd/autobump/config_test.go | 12 +- cmd/autobump/git_test.go | 36 ++++-- cmd/autobump/project.go | 232 ++++++++++++++++++------------------ cmd/autobump/utils_test.go | 3 +- go.mod | 2 + go.sum | 2 + 7 files changed, 157 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28cc85a..cba0947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ Exceptions are acceptable depending on the circumstances (critical bug fixes tha - removed redundant release pipeline +### Fixed + +- fixed a typo in authentication method selection + ## [2.14.0] - 2024-03-01 ### Added diff --git a/cmd/autobump/config_test.go b/cmd/autobump/config_test.go index 56ad597..eed3867 100644 --- a/cmd/autobump/config_test.go +++ b/cmd/autobump/config_test.go @@ -3,17 +3,19 @@ package main import ( "errors" "testing" + + "github.com/go-faker/faker/v4" ) func TestValidateGlobalConfig_Success(t *testing.T) { // Arrange globalConfig := GlobalConfig{ Projects: []ProjectConfig{ - {Path: "/home/user/test", ProjectAccessToken: "glpat-ABCDEFGHIJKLMNOPQRST"}, + {Path: "/home/user/test", ProjectAccessToken: faker.Password()}, }, LanguagesConfig: map[string]LanguageConfig{"Go": {}}, GpgKeyPath: "/home/user/.gnupg/autobump.asc", - GitLabAccessToken: "glpat-ABCDEFGHIJKLMNOPQRST", + GitLabAccessToken: faker.Password(), } // Act @@ -43,7 +45,7 @@ func TestValidateGlobalConfig_MissingProjectPath(t *testing.T) { // Arrange globalConfig := GlobalConfig{ Projects: []ProjectConfig{ - {Path: "", ProjectAccessToken: "token1"}, + {Path: "", ProjectAccessToken: faker.Password()}, }, LanguagesConfig: map[string]LanguageConfig{"Go": {}}, } @@ -61,7 +63,7 @@ func TestValidateGlobalConfig_MissingProjectAccessTokenInBatchMode(t *testing.T) // Arrange globalConfig := GlobalConfig{ Projects: []ProjectConfig{ - {Path: "some/path", ProjectAccessToken: ""}, + {Path: faker.Word(), ProjectAccessToken: ""}, }, LanguagesConfig: map[string]LanguageConfig{"Go": {}}, GitLabAccessToken: "", @@ -80,7 +82,7 @@ func TestValidateGlobalConfig_MissingLanguagesConfig(t *testing.T) { // Arrange globalConfig := GlobalConfig{ Projects: []ProjectConfig{ - {Path: "some/path", ProjectAccessToken: "token1"}, + {Path: faker.Word(), ProjectAccessToken: faker.Password()}, }, LanguagesConfig: nil, } diff --git a/cmd/autobump/git_test.go b/cmd/autobump/git_test.go index e26725a..cb0cc14 100644 --- a/cmd/autobump/git_test.go +++ b/cmd/autobump/git_test.go @@ -2,8 +2,11 @@ package main import ( "errors" + "fmt" + "math/rand" "testing" + "github.com/go-faker/faker/v4" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" @@ -13,15 +16,17 @@ import ( func TestGetAuthMethods_Success(t *testing.T) { // Arrange + gitlabAccessToken := faker.Password() + projectAccessToken := faker.Password() globalConfig := GlobalConfig{ - GitLabAccessToken: "glpat-ABCDEFGHIJKLMNOPQRST", + GitLabAccessToken: gitlabAccessToken, } projectConfig := ProjectConfig{ - ProjectAccessToken: "glpat-ABCDEFGHIJKLMNOPQRST", + ProjectAccessToken: projectAccessToken, } // Act - authMethods, err := getAuthMethods(GITLAB, "user", &globalConfig, &projectConfig) + authMethods, err := getAuthMethods(GITLAB, faker.Username(), &globalConfig, &projectConfig) // Assert if err != nil { t.Errorf("expected no error, got %v", err) @@ -32,8 +37,9 @@ func TestGetAuthMethods_Success(t *testing.T) { basicAuthFound := false for _, authMethod := range authMethods { if auth, ok := authMethod.(*http.BasicAuth); ok { - if auth.Password != "glpat-ABCDEFGHIJKLMNOPQRST" { - t.Errorf("expected password to be 'glpat-ABCDEFGHIJKLMNOPQRST', got %v", auth.Password) + if auth.Password != gitlabAccessToken && auth.Password != projectAccessToken { + t.Errorf("expected password to be either gitlabAccessToken or projectAccessToken, got %v", + auth.Password) } basicAuthFound = true } @@ -49,7 +55,7 @@ func TestGetAuthMethods_NoAuthMethodFound(t *testing.T) { projectConfig := ProjectConfig{} // Act - authMethods, err := getAuthMethods(GITLAB, "user", &globalConfig, &projectConfig) + authMethods, err := getAuthMethods(GITLAB, faker.Username(), &globalConfig, &projectConfig) // Assert if !errors.Is(err, ErrNoAuthMethodFound) { t.Errorf("expected error to be ErrNoAuthMethod, got %v", err) @@ -65,7 +71,7 @@ func TestGetAuthMethods_AuthNotImplemented(t *testing.T) { projectConfig := ProjectConfig{} // Act - authMethods, err := getAuthMethods(UNKNOWN, "user", &globalConfig, &projectConfig) + authMethods, err := getAuthMethods(UNKNOWN, faker.Username(), &globalConfig, &projectConfig) // Assert if !errors.Is(err, ErrAuthNotImplemented) { t.Errorf("expected error to be ErrAuthNotImplemented, got %v", err) @@ -110,7 +116,7 @@ func TestGetRemoteServiceType_UnknownService(t *testing.T) { _, err = repo.CreateRemote(&config.RemoteConfig{ Name: "origin", - URLs: []string{"https://example.com/user/repo.git"}, + URLs: []string{faker.URL()}, }) if err != nil { t.Errorf("expected no error, got %v", err) @@ -146,7 +152,7 @@ func TestGetLatestTag_Success(t *testing.T) { if err != nil { t.Errorf("expected no error, got %v", err) } - _, err = file.Write([]byte("hello world")) + _, err = file.Write([]byte(faker.Sentence())) if err != nil { t.Errorf("expected no error, got %v", err) } @@ -159,7 +165,7 @@ func TestGetLatestTag_Success(t *testing.T) { } // Commit the changes - _, err = wt.Commit("initial commit", &git.CommitOptions{ + _, err = wt.Commit(faker.Sentence(), &git.CommitOptions{ All: true, }) if err != nil { @@ -173,7 +179,8 @@ func TestGetLatestTag_Success(t *testing.T) { } // Create a tag on the commit - _, err = repo.CreateTag("1.0.0", head.Hash(), nil) + testTag := fmt.Sprintf("%d.%d.%d", rand.Intn(10), rand.Intn(10), rand.Intn(10)) + _, err = repo.CreateTag(testTag, head.Hash(), nil) if err != nil { t.Errorf("expected no error, got %v", err) } @@ -184,8 +191,11 @@ func TestGetLatestTag_Success(t *testing.T) { if err != nil { t.Errorf("expected no error, got %v", err) } - if tag.Tag.String() != "1.0.0" { - t.Errorf("expected tag to be '1.0.0', got %v", tag.Tag.String()) + if tag.Tag == nil { + t.Errorf("expected tag to be non-nil, got nil") + } + if tag.Tag.String() != testTag { + t.Errorf("expected tag to be '%s', got %v", testTag, tag.Tag.String()) } } diff --git a/cmd/autobump/project.go b/cmd/autobump/project.go index 3a8453a..f15d291 100644 --- a/cmd/autobump/project.go +++ b/cmd/autobump/project.go @@ -3,6 +3,7 @@ package main import ( "errors" "fmt" + "io" "os" "path/filepath" "strings" @@ -204,94 +205,6 @@ func createPullRequest( return nil } -// processRepo: -// - clones the repository if it is a remote repository -// - creates the chore/bump branch -// - updates the CHANGELOG.md file -// - updates the version file -// - commits the changes -// - pushes the branch to the remote repository -// - creates a new merge request on GitLab -func processRepo(globalConfig *GlobalConfig, projectConfig *ProjectConfig) error { - // Initialize RepoContext - ctx := &RepoContext{ - globalConfig: globalConfig, - projectConfig: projectConfig, - } - - // Get global Git config - var err error - ctx.globalGitConfig, err = getGlobalGitConfig() - if err != nil { - return err - } - - // Clone repository if needed - var tmpDir string - tmpDir, err = cloneRepoIfNeeded(ctx) - if err != nil { - return err - } - defer os.RemoveAll(tmpDir) - - projectPath := ctx.projectConfig.Path - changelogPath := filepath.Join(projectPath, "CHANGELOG.md") - - // Setup repository and worktree - err = setupRepo(ctx) - if err != nil { - return err - } - - // Set up the changelog - err = setupChangelog(ctx, changelogPath) - if err != nil { - return err - } - - // Determine if bump is needed - bumpNeeded, err := shouldBumpProject(ctx, changelogPath) - if err != nil { - return err - } - if !bumpNeeded { - return nil - } - - // Ensure the project language is detected - err = ensureProjectLanguage(ctx) - if err != nil { - return err - } - - // Create and switch to bump branch - branchName, err := createBumpBranch(ctx, changelogPath) - if err != nil { - return err - } - - // Update changelog and version files - err = updateChangelogAndVersionFiles(ctx, changelogPath) - if err != nil { - return err - } - - // Commit and push changes - err = commitAndPushChanges(ctx, branchName) - if err != nil { - return err - } - - // Create and checkout pull request - err = createAndCheckoutPullRequest(ctx, branchName) - if err != nil { - return err - } - - log.Infof("Successfully processed project '%s'", ctx.projectConfig.Name) - return nil -} - func cloneRepoIfNeeded(ctx *RepoContext) (string, error) { if strings.HasPrefix(ctx.projectConfig.Path, "https://") || strings.HasPrefix(ctx.projectConfig.Path, "git@") { return cloneRepo(ctx) @@ -472,7 +385,8 @@ func commitChangesWithGPG(ctx *RepoContext) (plumbing.Hash, error) { log.Info("Signing commit with GPG key") gpgKeyID := getOptionFromConfig(cfg, ctx.globalGitConfig, "user", "signingkey") - gpgKeyReader, err := getGpgKeyReader(gpgKeyID, ctx.globalConfig.GpgKeyPath) + var gpgKeyReader *io.Reader + gpgKeyReader, err = getGpgKeyReader(gpgKeyID, ctx.globalConfig.GpgKeyPath) if err != nil { return plumbing.Hash{}, err } @@ -539,32 +453,6 @@ func checkoutToMainBranch(ctx *RepoContext) error { return nil } -// iterateProjects iterates over the projects and processes them using the processRepo function -func iterateProjects(globalConfig *GlobalConfig) error { - var err error - for _, project := range globalConfig.Projects { - // verify if the project path exists - if _, err = os.Stat(project.Path); os.IsNotExist(err) { - // if the project path does not exist, check if it is a remote repository - if !strings.HasPrefix(project.Path, "https://") && - !strings.HasPrefix(project.Path, "git@") { - // if it is neither a local path nor a remote repository, skip the project - log.Errorf("Project path does not exist: %s\n", project.Path) - log.Warn("Skipping project") - err = ErrProjectPathDoesNotExist - continue - } - } - - err = processRepo(globalConfig, &project) - if err != nil { - log.Errorf("Error processing project at %s: %v\n", project.Path, err) - } - } - - return err -} - // addCurrentVersion adds the current version to the CHANGELOG file func addCurrentVersion(ctx *RepoContext, changelogPath string) error { lines, err := readLines(changelogPath) @@ -591,3 +479,117 @@ func addCurrentVersion(ctx *RepoContext, changelogPath string) error { return nil } + +// processRepo: +// - clones the repository if it is a remote repository +// - creates the chore/bump branch +// - updates the CHANGELOG.md file +// - updates the version file +// - commits the changes +// - pushes the branch to the remote repository +// - creates a new merge request on GitLab +func processRepo(globalConfig *GlobalConfig, projectConfig *ProjectConfig) error { + // Initialize RepoContext + ctx := &RepoContext{ + globalConfig: globalConfig, + projectConfig: projectConfig, + } + + // Get global Git config + var err error + ctx.globalGitConfig, err = getGlobalGitConfig() + if err != nil { + return err + } + + // Clone repository if needed + var tmpDir string + tmpDir, err = cloneRepoIfNeeded(ctx) + if err != nil { + return err + } + defer os.RemoveAll(tmpDir) + + projectPath := ctx.projectConfig.Path + changelogPath := filepath.Join(projectPath, "CHANGELOG.md") + + // Setup repository and worktree + err = setupRepo(ctx) + if err != nil { + return err + } + + // Set up the changelog + err = setupChangelog(ctx, changelogPath) + if err != nil { + return err + } + + // Determine if bump is needed + bumpNeeded, err := shouldBumpProject(ctx, changelogPath) + if err != nil { + return err + } + if !bumpNeeded { + return nil + } + + // Ensure the project language is detected + err = ensureProjectLanguage(ctx) + if err != nil { + return err + } + + // Create and switch to bump branch + branchName, err := createBumpBranch(ctx, changelogPath) + if err != nil { + return err + } + + // Update changelog and version files + err = updateChangelogAndVersionFiles(ctx, changelogPath) + if err != nil { + return err + } + + // Commit and push changes + err = commitAndPushChanges(ctx, branchName) + if err != nil { + return err + } + + // Create and checkout pull request + err = createAndCheckoutPullRequest(ctx, branchName) + if err != nil { + return err + } + + log.Infof("Successfully processed project '%s'", ctx.projectConfig.Name) + return nil +} + +// iterateProjects iterates over the projects and processes them using the processRepo function +func iterateProjects(globalConfig *GlobalConfig) error { + var err error + for _, project := range globalConfig.Projects { + // verify if the project path exists + if _, err = os.Stat(project.Path); os.IsNotExist(err) { + // if the project path does not exist, check if it is a remote repository + if !strings.HasPrefix(project.Path, "https://") && + !strings.HasPrefix(project.Path, "git@") { + // if it is neither a local path nor a remote repository, skip the project + log.Errorf("Project path does not exist: %s\n", project.Path) + log.Warn("Skipping project") + err = ErrProjectPathDoesNotExist + continue + } + } + + err = processRepo(globalConfig, &project) + if err != nil { + log.Errorf("Error processing project at %s: %v\n", project.Path, err) + } + } + + return err +} diff --git a/cmd/autobump/utils_test.go b/cmd/autobump/utils_test.go index a5cd9d2..04b69f5 100644 --- a/cmd/autobump/utils_test.go +++ b/cmd/autobump/utils_test.go @@ -10,12 +10,13 @@ import ( "github.com/ProtonMail/go-crypto/openpgp/armor" openpgpErrors "github.com/ProtonMail/go-crypto/openpgp/errors" "github.com/ProtonMail/go-crypto/openpgp/packet" + "github.com/go-faker/faker/v4" ) // generateTestGpgKey generates a new GPG key entity for testing purposes func generateTestGpgKey() (*openpgp.Entity, error) { config := &packet.Config{RSABits: 2048} - entity, err := openpgp.NewEntity("Test User", "Test Key", "test@example.com", config) + entity, err := openpgp.NewEntity(faker.Name(), faker.Sentence(), faker.Email(), config) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index 512f198..bbb26c0 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/cloudflare/circl v1.4.0 // indirect github.com/cyphar/filepath-securejoin v0.3.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-faker/faker/v4 v4.5.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -38,6 +39,7 @@ require ( golang.org/x/net v0.28.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 7291450..0f25fc4 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/go-faker/faker/v4 v4.5.0 h1:ARzAY2XoOL9tOUK+KSecUQzyXQsUaZHefjyF8x6YFHc= +github.com/go-faker/faker/v4 v4.5.0/go.mod h1:p3oq1GRjG2PZ7yqeFFfQI20Xm61DoBDlCA8RiSyZ48M= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=