package main import ( "errors" "fmt" "log" "net/http" "os" "path/filepath" "src.opensuse.org/autogits/common" ) const ( GitAuthor = "GiteaBot - AutoDevel" BotName = "prjgit-updater" ) var GiteaToken string type ClonedRepository struct { } type RequestHandler struct { r *common.RequestHandler } func (rw *RequestHandler) processRepositoryAction() { h := rw.r if h.HasError() { return } action := h.Request.Data.(common.RepositoryAction) if action.Repository.Name == "_ObsPrj" { h.Log("repository event %s for _ObsPrj. Ignoring", action.Action) return } h.CreateRepositoryIfNotExist(action.Organization, common.DefaultGitPrj) if stat, err := os.Stat(filepath.Join(h.GitPath, common.DefaultGitPrj)); err != nil || !stat.IsDir() { if errors.Is(err, os.ErrNotExist) { h.GitExec("", "clone", "--depth", "1", action.PrjGit, common.DefaultGitPrj) } } switch action.Action { case "created": h.GitExec(common.DefaultGitPrj, "submodule", "--quiet", "add", "--depth", "1", action.Repository.Clone_Url) h.GitExec(common.DefaultGitPrj, "commit", "-m", "Automatic package inclusion") h.GitExec(common.DefaultGitPrj, "push") case "deleted": if stat, err := os.Stat(filepath.Join(h.GitPath, common.DefaultGitPrj, action.Repository.Name)); err != nil || !stat.IsDir() { h.Log("delete event for %s -- not in project. Ignoring", action.Repository.Name) return } h.GitExec(common.DefaultGitPrj, "rm", action.Repository.Name) h.GitExec(common.DefaultGitPrj, "commit", "-m", "Automatic package removal") h.GitExec(common.DefaultGitPrj, "push") default: h.LogError("%s: %s", "Unknown action type", action.Action) } } func (rw *RequestHandler) processPushAction() { h := rw.r if h.HasError() { return } action := h.Request.Data.(common.PushRequest) if action.Repository.Name == "_ObsPrj" { h.Log("push to _ObsPrj -- ignoring") return } h.GitExec("", "clone", "--depth", "1", h.PrjGit, common.DefaultGitPrj) if stat, err := os.Stat(filepath.Join(h.GitPath, common.DefaultGitPrj, action.Repository.Name)); err != nil || !stat.IsDir() { h.Error = fmt.Errorf("Pushed to package that is not part of the project. Ignoring.") h.LogError("%v: %v", h.Error, err) return } h.GitExec(common.DefaultGitPrj, "submodule", "update", "--init", "--depth", "1", "--checkout", action.Repository.Name) id, _ := h.GitBranchHead(filepath.Join(common.DefaultGitPrj, action.Repository.Name), action.Repository.Default_Branch) for _, commitId := range action.Commits { if commitId.Id == id { h.GitExec(filepath.Join(common.DefaultGitPrj, action.Repository.Name), "fetch", "--depth", "1", "origin", id) h.GitExec(filepath.Join(common.DefaultGitPrj, action.Repository.Name), "checkout", id) h.GitExec(common.DefaultGitPrj, "commit", "-a", "-m", "Automatic update via push") h.GitExec(common.DefaultGitPrj, "push") return } } h.Log("push of refs not on the main branch. ignoring.") } func createListenServer() { http.HandleFunc("/" + BotName, func(res http.ResponseWriter, req *http.Request) { var h RequestHandler; h.r = common.CreateRequestHandler(GitAuthor, BotName) // defer h.Close() if len(req.Header.Get("Content-Type")) == 0 || req.Header["Content-Type"][0] != "application/json" || req.Method != "POST" { h.r.WriteError() res.WriteHeader(http.StatusInternalServerError) return } hdr := req.Header[common.GiteaRequestHeader] if len(hdr) != 1 { h.r.LogError("Unsupported number of %s headers: %d: %#v\n", common.GiteaRequestHeader, len(hdr), hdr) h.r.WriteError() res.WriteHeader(http.StatusInternalServerError) return } reqType := hdr[0] switch reqType { case "repository": h.r.ParseRepositoryRequest(req.Body) h.processRepositoryAction() case "push": h.r.ParsePushRequest(req.Body) h.processPushAction() default: h.r.LogError("Unsupported request type: %s", reqType) res.WriteHeader(http.StatusInternalServerError) } if h.r.HasError() { h.r.WriteError() res.WriteHeader(http.StatusInternalServerError) return } res.Header().Add("Content-Type", "application/json") res.WriteHeader(http.StatusOK) }) log.Fatal(http.ListenAndServe("[::1]:8000", nil)) } func parseGiteaSecretToken() error { GiteaToken = os.Getenv(common.GiteaTokenEnv) if len(GiteaToken) < 10 { return errors.New(common.GiteaTokenEnv + " not provided") } err := os.Setenv(common.GiteaTokenEnv, "") if err != nil { return fmt.Errorf("%s: %v", "Cannot reset "+common.GiteaTokenEnv, err) } return nil } func main() { parseGiteaSecretToken() createListenServer() }