diff --git a/models/helper_environment.go b/models/helper_environment.go
index 112df96823..bc9d4c8fce 100644
--- a/models/helper_environment.go
+++ b/models/helper_environment.go
@@ -10,6 +10,19 @@ import (
 	"strings"
 )
 
+// env keys for git hooks need
+const (
+	EnvRepoName     = "GITEA_REPO_NAME"
+	EnvRepoUsername = "GITEA_REPO_USER_NAME"
+	EnvRepoIsWiki   = "GITEA_REPO_IS_WIKI"
+	EnvPusherName   = "GITEA_PUSHER_NAME"
+	EnvPusherEmail  = "GITEA_PUSHER_EMAIL"
+	EnvPusherID     = "GITEA_PUSHER_ID"
+	EnvKeyID        = "GITEA_KEY_ID"
+	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY"
+	EnvIsInternal   = "GITEA_INTERNAL_PUSH"
+)
+
 // InternalPushingEnvironment returns an os environment to switch off hooks on push
 // It is recommended to avoid using this unless you are pushing within a transaction
 // or if you absolutely are sure that post-receive and pre-receive will do nothing
diff --git a/models/release.go b/models/release.go
index ebd2b6d384..0f670f374f 100644
--- a/models/release.go
+++ b/models/release.go
@@ -119,9 +119,15 @@ func InsertRelease(rel *Release) error {
 	return err
 }
 
+// InsertReleasesContext insert releases
+func InsertReleasesContext(ctx DBContext, rels []*Release) error {
+	_, err := ctx.e.Insert(rels)
+	return err
+}
+
 // UpdateRelease updates all columns of a release
-func UpdateRelease(rel *Release) error {
-	_, err := x.ID(rel.ID).AllCols().Update(rel)
+func UpdateRelease(ctx DBContext, rel *Release) error {
+	_, err := ctx.e.ID(rel.ID).AllCols().Update(rel)
 	return err
 }
 
@@ -212,10 +218,10 @@ func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, er
 }
 
 // GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
-func GetReleasesByRepoIDAndNames(repoID int64, tagNames []string) (rels []*Release, err error) {
-	err = x.
-		Desc("created_unix").
+func GetReleasesByRepoIDAndNames(ctx DBContext, repoID int64, tagNames []string) (rels []*Release, err error) {
+	err = ctx.e.
 		In("tag_name", tagNames).
+		Desc("created_unix").
 		Find(&rels, Release{RepoID: repoID})
 	return rels, err
 }
diff --git a/models/update.go b/models/update.go
index 17ee9ad5fa..8e18450db7 100644
--- a/models/update.go
+++ b/models/update.go
@@ -7,42 +7,8 @@ package models
 import (
 	"fmt"
 	"strings"
-	"time"
-
-	"code.gitea.io/gitea/modules/git"
-	"code.gitea.io/gitea/modules/timeutil"
 )
 
-// env keys for git hooks need
-const (
-	EnvRepoName     = "GITEA_REPO_NAME"
-	EnvRepoUsername = "GITEA_REPO_USER_NAME"
-	EnvRepoIsWiki   = "GITEA_REPO_IS_WIKI"
-	EnvPusherName   = "GITEA_PUSHER_NAME"
-	EnvPusherEmail  = "GITEA_PUSHER_EMAIL"
-	EnvPusherID     = "GITEA_PUSHER_ID"
-	EnvKeyID        = "GITEA_KEY_ID"
-	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY"
-	EnvIsInternal   = "GITEA_INTERNAL_PUSH"
-)
-
-// PushUpdateAddDeleteTags updates a number of added and delete tags
-func PushUpdateAddDeleteTags(repo *Repository, gitRepo *git.Repository, addTags, delTags []string) error {
-	sess := x.NewSession()
-	defer sess.Close()
-	if err := sess.Begin(); err != nil {
-		return fmt.Errorf("Unable to begin sess in PushUpdateDeleteTags: %v", err)
-	}
-	if err := pushUpdateDeleteTags(sess, repo, delTags); err != nil {
-		return err
-	}
-	if err := pushUpdateAddTags(sess, repo, gitRepo, addTags); err != nil {
-		return err
-	}
-
-	return sess.Commit()
-}
-
 // PushUpdateDeleteTags updates a number of delete tags
 func PushUpdateDeleteTags(repo *Repository, tags []string) error {
 	sess := x.NewSession()
@@ -57,6 +23,11 @@ func PushUpdateDeleteTags(repo *Repository, tags []string) error {
 	return sess.Commit()
 }
 
+// PushUpdateDeleteTagsContext updates a number of delete tags with context
+func PushUpdateDeleteTagsContext(ctx DBContext, repo *Repository, tags []string) error {
+	return pushUpdateDeleteTags(ctx.e, repo, tags)
+}
+
 func pushUpdateDeleteTags(e Engine, repo *Repository, tags []string) error {
 	if len(tags) == 0 {
 		return nil
@@ -111,125 +82,6 @@ func PushUpdateDeleteTag(repo *Repository, tagName string) error {
 	return nil
 }
 
-// PushUpdateAddTags updates a number of add tags
-func PushUpdateAddTags(repo *Repository, gitRepo *git.Repository, tags []string) error {
-	sess := x.NewSession()
-	defer sess.Close()
-	if err := sess.Begin(); err != nil {
-		return fmt.Errorf("Unable to begin sess in PushUpdateAddTags: %v", err)
-	}
-	if err := pushUpdateAddTags(sess, repo, gitRepo, tags); err != nil {
-		return err
-	}
-
-	return sess.Commit()
-}
-func pushUpdateAddTags(e Engine, repo *Repository, gitRepo *git.Repository, tags []string) error {
-	if len(tags) == 0 {
-		return nil
-	}
-
-	lowerTags := make([]string, 0, len(tags))
-	for _, tag := range tags {
-		lowerTags = append(lowerTags, strings.ToLower(tag))
-	}
-
-	releases := make([]Release, 0, len(tags))
-	if err := e.Where("repo_id = ?", repo.ID).
-		In("lower_tag_name", lowerTags).Find(&releases); err != nil {
-		return fmt.Errorf("GetRelease: %v", err)
-	}
-	relMap := make(map[string]*Release)
-	for _, rel := range releases {
-		relMap[rel.LowerTagName] = &rel
-	}
-
-	newReleases := make([]*Release, 0, len(lowerTags)-len(relMap))
-
-	emailToUser := make(map[string]*User)
-
-	for i, lowerTag := range lowerTags {
-		tag, err := gitRepo.GetTag(tags[i])
-		if err != nil {
-			return fmt.Errorf("GetTag: %v", err)
-		}
-		commit, err := tag.Commit()
-		if err != nil {
-			return fmt.Errorf("Commit: %v", err)
-		}
-
-		sig := tag.Tagger
-		if sig == nil {
-			sig = commit.Author
-		}
-		if sig == nil {
-			sig = commit.Committer
-		}
-		var author *User
-		var createdAt = time.Unix(1, 0)
-
-		if sig != nil {
-			var ok bool
-			author, ok = emailToUser[sig.Email]
-			if !ok {
-				author, err = GetUserByEmail(sig.Email)
-				if err != nil && !IsErrUserNotExist(err) {
-					return fmt.Errorf("GetUserByEmail: %v", err)
-				}
-			}
-			createdAt = sig.When
-		}
-
-		commitsCount, err := commit.CommitsCount()
-		if err != nil {
-			return fmt.Errorf("CommitsCount: %v", err)
-		}
-
-		rel, has := relMap[lowerTag]
-
-		if !has {
-			rel = &Release{
-				RepoID:       repo.ID,
-				Title:        "",
-				TagName:      tags[i],
-				LowerTagName: lowerTag,
-				Target:       "",
-				Sha1:         commit.ID.String(),
-				NumCommits:   commitsCount,
-				Note:         "",
-				IsDraft:      false,
-				IsPrerelease: false,
-				IsTag:        true,
-				CreatedUnix:  timeutil.TimeStamp(createdAt.Unix()),
-			}
-			if author != nil {
-				rel.PublisherID = author.ID
-			}
-
-			newReleases = append(newReleases, rel)
-		} else {
-			rel.Sha1 = commit.ID.String()
-			rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix())
-			rel.NumCommits = commitsCount
-			rel.IsDraft = false
-			if rel.IsTag && author != nil {
-				rel.PublisherID = author.ID
-			}
-			if _, err = e.ID(rel.ID).AllCols().Update(rel); err != nil {
-				return fmt.Errorf("Update: %v", err)
-			}
-		}
-	}
-
-	if len(newReleases) > 0 {
-		if _, err := e.Insert(newReleases); err != nil {
-			return fmt.Errorf("Insert: %v", err)
-		}
-	}
-
-	return nil
-}
-
 // SaveOrUpdateTag must be called for any push actions to add tag
 func SaveOrUpdateTag(repo *Repository, newRel *Release) error {
 	rel, err := GetRelease(repo.ID, newRel.TagName)
diff --git a/models/user.go b/models/user.go
index ee66acf1a6..fda3bb5eab 100644
--- a/models/user.go
+++ b/models/user.go
@@ -1452,6 +1452,11 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
 
 // GetUserByEmail returns the user object by given e-mail if exists.
 func GetUserByEmail(email string) (*User, error) {
+	return GetUserByEmailContext(DefaultDBContext(), email)
+}
+
+// GetUserByEmailContext returns the user object by given e-mail if exists with db context
+func GetUserByEmailContext(ctx DBContext, email string) (*User, error) {
 	if len(email) == 0 {
 		return nil, ErrUserNotExist{0, email, 0}
 	}
@@ -1459,7 +1464,7 @@ func GetUserByEmail(email string) (*User, error) {
 	email = strings.ToLower(email)
 	// First try to find the user by primary email
 	user := &User{Email: email}
-	has, err := x.Get(user)
+	has, err := ctx.e.Get(user)
 	if err != nil {
 		return nil, err
 	}
@@ -1469,19 +1474,19 @@ func GetUserByEmail(email string) (*User, error) {
 
 	// Otherwise, check in alternative list for activated email addresses
 	emailAddress := &EmailAddress{Email: email, IsActivated: true}
-	has, err = x.Get(emailAddress)
+	has, err = ctx.e.Get(emailAddress)
 	if err != nil {
 		return nil, err
 	}
 	if has {
-		return GetUserByID(emailAddress.UID)
+		return getUserByID(ctx.e, emailAddress.UID)
 	}
 
 	// Finally, if email address is the protected email address:
 	if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) {
 		username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress))
 		user := &User{LowerName: username}
-		has, err := x.Get(user)
+		has, err := ctx.e.Get(user)
 		if err != nil {
 			return nil, err
 		}
diff --git a/modules/repofiles/update.go b/modules/repofiles/update.go
index c0f669d687..20b83655f5 100644
--- a/modules/repofiles/update.go
+++ b/modules/repofiles/update.go
@@ -732,7 +732,7 @@ func createCommitRepoActions(repo *models.Repository, gitRepo *git.Repository, o
 			Commits:           commits,
 		})
 	}
-	if err := models.PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil {
+	if err := repo_module.PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil {
 		return nil, fmt.Errorf("PushUpdateAddDeleteTags: %v", err)
 	}
 	return actions, nil
diff --git a/modules/repository/update.go b/modules/repository/update.go
new file mode 100644
index 0000000000..975f577da8
--- /dev/null
+++ b/modules/repository/update.go
@@ -0,0 +1,134 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package repository
+
+import (
+	"fmt"
+	"strings"
+	"time"
+
+	"code.gitea.io/gitea/models"
+	"code.gitea.io/gitea/modules/git"
+	"code.gitea.io/gitea/modules/timeutil"
+)
+
+// PushUpdateAddDeleteTags updates a number of added and delete tags
+func PushUpdateAddDeleteTags(repo *models.Repository, gitRepo *git.Repository, addTags, delTags []string) error {
+	return models.WithTx(func(ctx models.DBContext) error {
+		if err := models.PushUpdateDeleteTagsContext(ctx, repo, delTags); err != nil {
+			return err
+		}
+		return pushUpdateAddTags(ctx, repo, gitRepo, addTags)
+	})
+}
+
+// pushUpdateAddTags updates a number of add tags
+func pushUpdateAddTags(ctx models.DBContext, repo *models.Repository, gitRepo *git.Repository, tags []string) error {
+	if len(tags) == 0 {
+		return nil
+	}
+
+	lowerTags := make([]string, 0, len(tags))
+	for _, tag := range tags {
+		lowerTags = append(lowerTags, strings.ToLower(tag))
+	}
+
+	releases, err := models.GetReleasesByRepoIDAndNames(ctx, repo.ID, lowerTags)
+	if err != nil {
+		return fmt.Errorf("GetReleasesByRepoIDAndNames: %v", err)
+	}
+	relMap := make(map[string]*models.Release)
+	for _, rel := range releases {
+		relMap[rel.LowerTagName] = rel
+	}
+
+	newReleases := make([]*models.Release, 0, len(lowerTags)-len(relMap))
+
+	emailToUser := make(map[string]*models.User)
+
+	for i, lowerTag := range lowerTags {
+		tag, err := gitRepo.GetTag(tags[i])
+		if err != nil {
+			return fmt.Errorf("GetTag: %v", err)
+		}
+		commit, err := tag.Commit()
+		if err != nil {
+			return fmt.Errorf("Commit: %v", err)
+		}
+
+		sig := tag.Tagger
+		if sig == nil {
+			sig = commit.Author
+		}
+		if sig == nil {
+			sig = commit.Committer
+		}
+		var author *models.User
+		var createdAt = time.Unix(1, 0)
+
+		if sig != nil {
+			var ok bool
+			author, ok = emailToUser[sig.Email]
+			if !ok {
+				author, err = models.GetUserByEmailContext(ctx, sig.Email)
+				if err != nil && !models.IsErrUserNotExist(err) {
+					return fmt.Errorf("GetUserByEmail: %v", err)
+				}
+				if author != nil {
+					emailToUser[sig.Email] = author
+				}
+			}
+			createdAt = sig.When
+		}
+
+		commitsCount, err := commit.CommitsCount()
+		if err != nil {
+			return fmt.Errorf("CommitsCount: %v", err)
+		}
+
+		rel, has := relMap[lowerTag]
+
+		if !has {
+			rel = &models.Release{
+				RepoID:       repo.ID,
+				Title:        "",
+				TagName:      tags[i],
+				LowerTagName: lowerTag,
+				Target:       "",
+				Sha1:         commit.ID.String(),
+				NumCommits:   commitsCount,
+				Note:         "",
+				IsDraft:      false,
+				IsPrerelease: false,
+				IsTag:        true,
+				CreatedUnix:  timeutil.TimeStamp(createdAt.Unix()),
+			}
+			if author != nil {
+				rel.PublisherID = author.ID
+			}
+
+			newReleases = append(newReleases, rel)
+		} else {
+			rel.Sha1 = commit.ID.String()
+			rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix())
+			rel.NumCommits = commitsCount
+			rel.IsDraft = false
+			if rel.IsTag && author != nil {
+				rel.PublisherID = author.ID
+			}
+			if err = models.UpdateRelease(ctx, rel); err != nil {
+				return fmt.Errorf("Update: %v", err)
+			}
+		}
+	}
+
+	if len(newReleases) > 0 {
+		if err = models.InsertReleasesContext(ctx, newReleases); err != nil {
+			return fmt.Errorf("Insert: %v", err)
+		}
+	}
+
+	return nil
+}
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index 6b6b22f3a1..5177add99c 100644
--- a/routers/repo/repo.go
+++ b/routers/repo/repo.go
@@ -420,7 +420,7 @@ func RedirectDownload(ctx *context.Context) {
 	)
 	tagNames := []string{vTag}
 	curRepo := ctx.Repo.Repository
-	releases, err := models.GetReleasesByRepoIDAndNames(curRepo.ID, tagNames)
+	releases, err := models.GetReleasesByRepoIDAndNames(models.DefaultDBContext(), curRepo.ID, tagNames)
 	if err != nil {
 		if models.IsErrAttachmentNotExist(err) {
 			ctx.Error(404)
diff --git a/services/release/release.go b/services/release/release.go
index 0f19db9ee2..cc3b98afac 100644
--- a/services/release/release.go
+++ b/services/release/release.go
@@ -102,7 +102,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea
 	}
 	rel.LowerTagName = strings.ToLower(rel.TagName)
 
-	if err = models.UpdateRelease(rel); err != nil {
+	if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil {
 		return err
 	}
 
@@ -145,7 +145,7 @@ func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
 		rel.Title = ""
 		rel.Note = ""
 
-		if err = models.UpdateRelease(rel); err != nil {
+		if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil {
 			return fmt.Errorf("Update: %v", err)
 		}
 	}