[Contrib] Checkout a PR (#6021)
This commit is contained in:
		
							parent
							
								
									9fd8b2621f
								
							
						
					
					
						commit
						9d3732dfd5
					
				
					 2 changed files with 260 additions and 0 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							|  | @ -420,3 +420,7 @@ generate-images: | ||||||
| 					$(TMPDIR)/images/64.png $(TMPDIR)/images/128.png \
 | 					$(TMPDIR)/images/64.png $(TMPDIR)/images/128.png \
 | ||||||
| 					$(PWD)/public/img/favicon.ico | 					$(PWD)/public/img/favicon.ico | ||||||
| 	rm -rf $(TMPDIR)/images | 	rm -rf $(TMPDIR)/images | ||||||
|  | 	 | ||||||
|  | .PHONY: pr | ||||||
|  | pr: | ||||||
|  | 	$(GO) run contrib/pr/checkout.go $(PR) | ||||||
|  |  | ||||||
							
								
								
									
										256
									
								
								contrib/pr/checkout.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								contrib/pr/checkout.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,256 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | Checkout a PR and load the tests data into sqlite database | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"log" | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"os/user" | ||||||
|  | 	"path" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"runtime" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/modules/markup/external" | ||||||
|  | 	"code.gitea.io/gitea/routers" | ||||||
|  | 	"code.gitea.io/gitea/routers/routes" | ||||||
|  | 	"github.com/Unknwon/com" | ||||||
|  | 	"github.com/go-xorm/xorm" | ||||||
|  | 	context2 "github.com/gorilla/context" | ||||||
|  | 	"gopkg.in/src-d/go-git.v4" | ||||||
|  | 	"gopkg.in/src-d/go-git.v4/config" | ||||||
|  | 	"gopkg.in/src-d/go-git.v4/plumbing" | ||||||
|  | 	"gopkg.in/testfixtures.v2" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var codeFilePath = "contrib/pr/checkout.go" | ||||||
|  | 
 | ||||||
|  | func runPR() { | ||||||
|  | 	log.Printf("[PR] Starting gitea ...\n") | ||||||
|  | 	curDir, err := os.Getwd() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	setting.NewContext() | ||||||
|  | 
 | ||||||
|  | 	setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("TempDir: %v\n", err) | ||||||
|  | 	} | ||||||
|  | 	setting.AppDataPath, err = ioutil.TempDir(os.TempDir(), "appdata") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("TempDir: %v\n", err) | ||||||
|  | 	} | ||||||
|  | 	setting.AppWorkPath = curDir | ||||||
|  | 	setting.StaticRootPath = curDir | ||||||
|  | 	setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("url.Parse: %v\n", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	setting.AppURL = "http://localhost:8080/" | ||||||
|  | 	setting.HTTPPort = "8080" | ||||||
|  | 	setting.SSH.Domain = "localhost" | ||||||
|  | 	setting.SSH.Port = 3000 | ||||||
|  | 	setting.InstallLock = true | ||||||
|  | 	setting.SecretKey = "9pCviYTWSb" | ||||||
|  | 	setting.InternalToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8" | ||||||
|  | 	curUser, err := user.Current() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	setting.RunUser = curUser.Username | ||||||
|  | 
 | ||||||
|  | 	log.Printf("[PR] Loading fixtures data ...\n") | ||||||
|  | 	setting.CheckLFSVersion() | ||||||
|  | 	//models.LoadConfigs()
 | ||||||
|  | 	/* | ||||||
|  | 		models.DbCfg.Type = "sqlite3" | ||||||
|  | 		models.DbCfg.Path = ":memory:" | ||||||
|  | 		models.DbCfg.Timeout = 500 | ||||||
|  | 	*/ | ||||||
|  | 	db := setting.Cfg.Section("database") | ||||||
|  | 	db.NewKey("DB_TYPE", "sqlite3") | ||||||
|  | 	db.NewKey("PATH", ":memory:") | ||||||
|  | 	setting.LogSQL = true | ||||||
|  | 	models.LoadConfigs() | ||||||
|  | 	routers.NewServices() | ||||||
|  | 	//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
 | ||||||
|  | 
 | ||||||
|  | 	var helper testfixtures.Helper | ||||||
|  | 	helper = &testfixtures.SQLite{} | ||||||
|  | 	models.NewEngine(func(_ *xorm.Engine) error { | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 	models.HasEngine = true | ||||||
|  | 	//x.ShowSQL(true)
 | ||||||
|  | 	err = models.InitFixtures( | ||||||
|  | 		helper, | ||||||
|  | 		path.Join(curDir, "models/fixtures/"), | ||||||
|  | 	) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Printf("Error initializing test database: %v\n", err) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 	models.LoadFixtures() | ||||||
|  | 	os.RemoveAll(setting.RepoRootPath) | ||||||
|  | 	os.RemoveAll(models.LocalCopyPath()) | ||||||
|  | 	os.RemoveAll(models.LocalWikiPath()) | ||||||
|  | 	com.CopyDir(path.Join(curDir, "integrations/gitea-repositories-meta"), setting.RepoRootPath) | ||||||
|  | 
 | ||||||
|  | 	log.Printf("[PR] Setting up router\n") | ||||||
|  | 	//routers.GlobalInit()
 | ||||||
|  | 	external.RegisterParsers() | ||||||
|  | 	m := routes.NewMacaron() | ||||||
|  | 	routes.RegisterRoutes(m) | ||||||
|  | 
 | ||||||
|  | 	log.Printf("[PR] Ready for testing !\n") | ||||||
|  | 	log.Printf("[PR] Login with user1, user2, user3, ... with pass: password\n") | ||||||
|  | 	/* | ||||||
|  | 		log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL) | ||||||
|  | 
 | ||||||
|  | 		if setting.LFS.StartServer { | ||||||
|  | 			log.Info("LFS server enabled") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if setting.EnablePprof { | ||||||
|  | 			go func() { | ||||||
|  | 				log.Info("Starting pprof server on localhost:6060") | ||||||
|  | 				log.Info("%v", http.ListenAndServe("localhost:6060", nil)) | ||||||
|  | 			}() | ||||||
|  | 		} | ||||||
|  | 	*/ | ||||||
|  | 
 | ||||||
|  | 	//Start the server
 | ||||||
|  | 	http.ListenAndServe(":8080", context2.ClearHandler(m)) | ||||||
|  | 
 | ||||||
|  | 	log.Printf("[PR] Cleaning up ...\n") | ||||||
|  | 	/* | ||||||
|  | 		if err = os.RemoveAll(setting.Indexer.IssuePath); err != nil { | ||||||
|  | 			fmt.Printf("os.RemoveAll: %v\n", err) | ||||||
|  | 			os.Exit(1) | ||||||
|  | 		} | ||||||
|  | 		if err = os.RemoveAll(setting.Indexer.RepoPath); err != nil { | ||||||
|  | 			fmt.Printf("Unable to remove repo indexer: %v\n", err) | ||||||
|  | 			os.Exit(1) | ||||||
|  | 		} | ||||||
|  | 	*/ | ||||||
|  | 	if err = os.RemoveAll(setting.RepoRootPath); err != nil { | ||||||
|  | 		log.Fatalf("os.RemoveAll: %v\n", err) | ||||||
|  | 	} | ||||||
|  | 	if err = os.RemoveAll(setting.AppDataPath); err != nil { | ||||||
|  | 		log.Fatalf("os.RemoveAll: %v\n", err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	var runPRFlag = flag.Bool("run", false, "Run the PR code") | ||||||
|  | 	flag.Parse() | ||||||
|  | 	if *runPRFlag { | ||||||
|  | 		runPR() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	//Otherwise checkout PR
 | ||||||
|  | 	if len(os.Args) != 2 { | ||||||
|  | 		log.Fatal("Need only one arg: the PR number") | ||||||
|  | 	} | ||||||
|  | 	pr := os.Args[1] | ||||||
|  | 
 | ||||||
|  | 	codeFilePath = filepath.FromSlash(codeFilePath) //Convert to running OS
 | ||||||
|  | 
 | ||||||
|  | 	//Copy this file if it will not exist in the PR branch
 | ||||||
|  | 	dat, err := ioutil.ReadFile(codeFilePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to cache this code file : %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	repo, err := git.PlainOpen(".") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to open the repo : %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	//Find remote upstream
 | ||||||
|  | 	remotes, err := repo.Remotes() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to list remotes of repo : %v", err) | ||||||
|  | 	} | ||||||
|  | 	remoteUpstream := "origin" //Default
 | ||||||
|  | 	for _, r := range remotes { | ||||||
|  | 		if r.Config().URLs[0] == "https://github.com/go-gitea/gitea" || r.Config().URLs[0] == "git@github.com:go-gitea/gitea.git" { //fetch at index 0
 | ||||||
|  | 			remoteUpstream = r.Config().Name | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	branch := fmt.Sprintf("pr-%s-%d", pr, time.Now().Unix()) | ||||||
|  | 	branchRef := plumbing.NewBranchReferenceName(branch) | ||||||
|  | 
 | ||||||
|  | 	log.Printf("Fetching PR #%s in %s\n", pr, branch) | ||||||
|  | 	if runtime.GOOS == "windows" { | ||||||
|  | 		//Use git cli command for windows
 | ||||||
|  | 		runCmd("git", "fetch", "origin", fmt.Sprintf("pull/%s/head:%s", pr, branch)) | ||||||
|  | 	} else { | ||||||
|  | 		ref := fmt.Sprintf("refs/pull/%s/head:%s", pr, branchRef) | ||||||
|  | 		err = repo.Fetch(&git.FetchOptions{ | ||||||
|  | 			RemoteName: remoteUpstream, | ||||||
|  | 			RefSpecs: []config.RefSpec{ | ||||||
|  | 				config.RefSpec(ref), | ||||||
|  | 			}, | ||||||
|  | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatalf("Failed to fetch %s from %s : %v", ref, remoteUpstream, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tree, err := repo.Worktree() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to parse git tree : %v", err) | ||||||
|  | 	} | ||||||
|  | 	log.Printf("Checkout PR #%s in %s\n", pr, branch) | ||||||
|  | 	err = tree.Checkout(&git.CheckoutOptions{ | ||||||
|  | 		Branch: branchRef, | ||||||
|  | 		//Force:  runtime.GOOS == "windows",
 | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to checkout %s : %v", branch, err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	//Copy this file if not exist
 | ||||||
|  | 	if _, err := os.Stat(codeFilePath); os.IsNotExist(err) { | ||||||
|  | 		err = os.MkdirAll(filepath.Dir(codeFilePath), 0755) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatalf("Failed to duplicate this code file in PR : %v", err) | ||||||
|  | 		} | ||||||
|  | 		err = ioutil.WriteFile(codeFilePath, dat, 0644) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatalf("Failed to duplicate this code file in PR : %v", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	time.Sleep(5 * time.Second) | ||||||
|  | 	//Start with integration test
 | ||||||
|  | 	runCmd("go", "run", "-tags", "sqlite sqlite_unlock_notify", codeFilePath, "-run") | ||||||
|  | } | ||||||
|  | func runCmd(cmd ...string) { | ||||||
|  | 	log.Printf("Executing : %s ...\n", cmd) | ||||||
|  | 	c := exec.Command(cmd[0], cmd[1:]...) | ||||||
|  | 	c.Stdout = os.Stdout | ||||||
|  | 	c.Stderr = os.Stderr | ||||||
|  | 	if err := c.Start(); err != nil { | ||||||
|  | 		log.Panicln(err) | ||||||
|  | 	} | ||||||
|  | 	if err := c.Wait(); err != nil { | ||||||
|  | 		log.Panicln(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue