You've already forked goreleaser
							
							
				mirror of
				https://github.com/goreleaser/goreleaser.git
				synced 2025-10-30 23:58:09 +02:00 
			
		
		
		
	fix(aur): allow to have multiple AUR configs pointing to the same repo (#4712)
- using the sha256 of the git url as repo name so we avoid race conditions - actually made the git client have a global lock so it doesn't step over itself closes #4679 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							6e0f426339
						
					
				
				
					commit
					08851dce61
				
			| @@ -19,14 +19,11 @@ import ( | |||||||
| 	"golang.org/x/crypto/ssh" | 	"golang.org/x/crypto/ssh" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var gil sync.Mutex | ||||||
|  |  | ||||||
| // DefaulGitSSHCommand used for git over SSH. | // DefaulGitSSHCommand used for git over SSH. | ||||||
| const DefaulGitSSHCommand = `ssh -i "{{ .KeyPath }}" -o StrictHostKeyChecking=accept-new -F /dev/null` | const DefaulGitSSHCommand = `ssh -i "{{ .KeyPath }}" -o StrictHostKeyChecking=accept-new -F /dev/null` | ||||||
|  |  | ||||||
| var cloneLock = cloneGlobalLock{ |  | ||||||
| 	l:     sync.Mutex{}, |  | ||||||
| 	repos: map[string]bool{}, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type gitClient struct { | type gitClient struct { | ||||||
| 	branch string | 	branch string | ||||||
| } | } | ||||||
| @@ -46,6 +43,9 @@ func (g *gitClient) CreateFiles( | |||||||
| 	message string, | 	message string, | ||||||
| 	files []RepoFile, | 	files []RepoFile, | ||||||
| ) (err error) { | ) (err error) { | ||||||
|  | 	gil.Lock() | ||||||
|  | 	defer gil.Unlock() | ||||||
|  |  | ||||||
| 	url, err := tmpl.New(ctx).Apply(repo.GitURL) | 	url, err := tmpl.New(ctx).Apply(repo.GitURL) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("git: failed to template git url: %w", err) | 		return fmt.Errorf("git: failed to template git url: %w", err) | ||||||
| @@ -79,7 +79,8 @@ func (g *gitClient) CreateFiles( | |||||||
| 	cwd := filepath.Join(parent, name) | 	cwd := filepath.Join(parent, name) | ||||||
| 	env := []string{fmt.Sprintf("GIT_SSH_COMMAND=%s", sshcmd)} | 	env := []string{fmt.Sprintf("GIT_SSH_COMMAND=%s", sshcmd)} | ||||||
|  |  | ||||||
| 	if err := cloneLock.clone(url, func() error { | 	if _, err := os.Stat(cwd); errors.Is(err, os.ErrNotExist) { | ||||||
|  | 		log.Infof("cloning %s %s", name, cwd) | ||||||
| 		if err := os.MkdirAll(parent, 0o755); err != nil { | 		if err := os.MkdirAll(parent, 0o755); err != nil { | ||||||
| 			return fmt.Errorf("git: failed to create parent: %w", err) | 			return fmt.Errorf("git: failed to create parent: %w", err) | ||||||
| 		} | 		} | ||||||
| @@ -98,21 +99,17 @@ func (g *gitClient) CreateFiles( | |||||||
| 		}); err != nil { | 		}); err != nil { | ||||||
| 			return fmt.Errorf("git: failed to setup local repository: %w", err) | 			return fmt.Errorf("git: failed to setup local repository: %w", err) | ||||||
| 		} | 		} | ||||||
| 		if g.branch == "" { | 		if g.branch != "" { | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 		if err := runGitCmds(ctx, cwd, env, [][]string{ |  | ||||||
| 			{"checkout", g.branch}, |  | ||||||
| 		}); err != nil { |  | ||||||
| 			if err := runGitCmds(ctx, cwd, env, [][]string{ | 			if err := runGitCmds(ctx, cwd, env, [][]string{ | ||||||
| 				{"checkout", "-b", g.branch}, | 				{"checkout", g.branch}, | ||||||
| 			}); err != nil { | 			}); err != nil { | ||||||
| 				return fmt.Errorf("git: could not checkout branch %s: %w", g.branch, err) | 				if err := runGitCmds(ctx, cwd, env, [][]string{ | ||||||
|  | 					{"checkout", "-b", g.branch}, | ||||||
|  | 				}); err != nil { | ||||||
|  | 					return fmt.Errorf("git: could not checkout branch %s: %w", g.branch, err) | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil |  | ||||||
| 	}); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, file := range files { | 	for _, file := range files { | ||||||
| @@ -216,20 +213,3 @@ func runGitCmds(ctx *context.Context, cwd string, env []string, cmds [][]string) | |||||||
| func nameFromURL(url string) string { | func nameFromURL(url string) string { | ||||||
| 	return strings.TrimSuffix(url[strings.LastIndex(url, "/")+1:], ".git") | 	return strings.TrimSuffix(url[strings.LastIndex(url, "/")+1:], ".git") | ||||||
| } | } | ||||||
|  |  | ||||||
| type cloneGlobalLock struct { |  | ||||||
| 	l     sync.Mutex |  | ||||||
| 	repos map[string]bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *cloneGlobalLock) clone(url string, fn func() error) error { |  | ||||||
| 	c.l.Lock() |  | ||||||
| 	defer c.l.Unlock() |  | ||||||
|  |  | ||||||
| 	if c.repos[url] { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	c.repos[url] = true |  | ||||||
| 	return fn() |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ package aur | |||||||
| import ( | import ( | ||||||
| 	"bufio" | 	"bufio" | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"crypto/sha256" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -385,7 +386,7 @@ func doPublish(ctx *context.Context, pkgs []*artifact.Artifact) error { | |||||||
| 			URL:        cfg.GitURL, | 			URL:        cfg.GitURL, | ||||||
| 			SSHCommand: cfg.GitSSHCommand, | 			SSHCommand: cfg.GitSSHCommand, | ||||||
| 		}, | 		}, | ||||||
| 		Name: cfg.Name, | 		Name: fmt.Sprintf("%x", sha256.Sum256([]byte(cfg.GitURL))), | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	files := make([]client.RepoFile, 0, len(pkgs)) | 	files := make([]client.RepoFile, 0, len(pkgs)) | ||||||
|   | |||||||
| @@ -482,6 +482,88 @@ func TestRunPipe(t *testing.T) { | |||||||
| 	requireEqualRepoFiles(t, folder, ".", "foo", url) | 	requireEqualRepoFiles(t, folder, ".", "foo", url) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestRunPipeMultipleConfigurations(t *testing.T) { | ||||||
|  | 	url := testlib.GitMakeBareRepository(t) | ||||||
|  | 	key := testlib.MakeNewSSHKey(t, "") | ||||||
|  |  | ||||||
|  | 	folder := t.TempDir() | ||||||
|  | 	ctx := testctx.NewWithCfg( | ||||||
|  | 		config.Project{ | ||||||
|  | 			Dist:        folder, | ||||||
|  | 			ProjectName: "foo", | ||||||
|  | 			AURs: []config.AUR{ | ||||||
|  | 				{ | ||||||
|  | 					Name:        "foo", | ||||||
|  | 					IDs:         []string{"foo"}, | ||||||
|  | 					PrivateKey:  key, | ||||||
|  | 					License:     "MIT", | ||||||
|  | 					GitURL:      url, | ||||||
|  | 					Description: "The foo aur", | ||||||
|  | 					Directory:   "foo", | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					Name:        "bar", | ||||||
|  | 					IDs:         []string{"bar"}, | ||||||
|  | 					PrivateKey:  key, | ||||||
|  | 					License:     "MIT", | ||||||
|  | 					GitURL:      url, | ||||||
|  | 					Description: "The bar aur", | ||||||
|  | 					Directory:   "bar", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		testctx.WithCurrentTag("v1.0.1-foo"), | ||||||
|  | 		testctx.WithSemver(1, 0, 1, "foo"), | ||||||
|  | 		testctx.WithVersion("1.0.1-foo"), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	path := filepath.Join(folder, "bin.tar.gz") | ||||||
|  | 	ctx.Artifacts.Add(&artifact.Artifact{ | ||||||
|  | 		Name:    "bar_bin.tar.gz", | ||||||
|  | 		Path:    path, | ||||||
|  | 		Goos:    "linux", | ||||||
|  | 		Goarch:  "amd64", | ||||||
|  | 		Goamd64: "v1", | ||||||
|  | 		Type:    artifact.UploadableArchive, | ||||||
|  | 		Extra: map[string]interface{}{ | ||||||
|  | 			artifact.ExtraID:       "bar", | ||||||
|  | 			artifact.ExtraFormat:   "tar.gz", | ||||||
|  | 			artifact.ExtraBinaries: []string{"bar"}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | 	ctx.Artifacts.Add(&artifact.Artifact{ | ||||||
|  | 		Name:    "bin.tar.gz", | ||||||
|  | 		Path:    path, | ||||||
|  | 		Goos:    "linux", | ||||||
|  | 		Goarch:  "amd64", | ||||||
|  | 		Goamd64: "v1", | ||||||
|  | 		Type:    artifact.UploadableArchive, | ||||||
|  | 		Extra: map[string]interface{}{ | ||||||
|  | 			artifact.ExtraID:       "foo", | ||||||
|  | 			artifact.ExtraFormat:   "tar.gz", | ||||||
|  | 			artifact.ExtraBinaries: []string{"name"}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	f, err := os.Create(path) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	require.NoError(t, f.Close()) | ||||||
|  | 	client := client.NewMock() | ||||||
|  |  | ||||||
|  | 	require.NoError(t, Pipe{}.Default(ctx)) | ||||||
|  | 	require.NoError(t, runAll(ctx, client)) | ||||||
|  | 	require.NoError(t, Pipe{}.Publish(ctx)) | ||||||
|  |  | ||||||
|  | 	dir := t.TempDir() | ||||||
|  | 	_, err = git.Run(testctx.New(), "-C", dir, "clone", url, "repo") | ||||||
|  | 	require.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	require.FileExists(t, filepath.Join(dir, "repo", "foo", ".SRCINFO")) | ||||||
|  | 	require.FileExists(t, filepath.Join(dir, "repo", "foo", "PKGBUILD")) | ||||||
|  | 	require.FileExists(t, filepath.Join(dir, "repo", "bar", ".SRCINFO")) | ||||||
|  | 	require.FileExists(t, filepath.Join(dir, "repo", "bar", "PKGBUILD")) | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestRunPipeNoBuilds(t *testing.T) { | func TestRunPipeNoBuilds(t *testing.T) { | ||||||
| 	ctx := testctx.NewWithCfg(config.Project{ | 	ctx := testctx.NewWithCfg(config.Project{ | ||||||
| 		ProjectName: "foo", | 		ProjectName: "foo", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user