diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2019-09-15 23:28:25 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-15 23:28:25 +0800 |
commit | 4959bf1c097917576472f9f66afa0fb615500c07 (patch) | |
tree | 9c2db8d5a91c1e6d97a1e66470347b647d01cfb0 /services/release | |
parent | be0f7ff9bf6da5b1642a98ff02f313ba39ee4518 (diff) | |
download | gitea-4959bf1c097917576472f9f66afa0fb615500c07.tar.gz gitea-4959bf1c097917576472f9f66afa0fb615500c07.zip |
Move create release from models to a standalone package (#7539)
* move create release from models to a standalone package
* fix lint
* fix comment year
* fix lint
* fix lint
* fix package import name
* fix vendor
* fix go mod
* some refactors
* fix vendor
* use go1.12 make vendor
* fix vendor
Diffstat (limited to 'services/release')
-rw-r--r-- | services/release/release.go | 132 | ||||
-rw-r--r-- | services/release/release_test.go | 161 |
2 files changed, 293 insertions, 0 deletions
diff --git a/services/release/release.go b/services/release/release.go new file mode 100644 index 0000000000..4451633798 --- /dev/null +++ b/services/release/release.go @@ -0,0 +1,132 @@ +// Copyright 2019 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 release + +import ( + "fmt" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/timeutil" +) + +func createTag(gitRepo *git.Repository, rel *models.Release) error { + // Only actual create when publish. + if !rel.IsDraft { + if !gitRepo.IsTagExist(rel.TagName) { + commit, err := gitRepo.GetCommit(rel.Target) + if err != nil { + return fmt.Errorf("GetCommit: %v", err) + } + + // Trim '--' prefix to prevent command line argument vulnerability. + rel.TagName = strings.TrimPrefix(rel.TagName, "--") + if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil { + if strings.Contains(err.Error(), "is not a valid tag name") { + return models.ErrInvalidTagName{ + TagName: rel.TagName, + } + } + return err + } + rel.LowerTagName = strings.ToLower(rel.TagName) + } + commit, err := gitRepo.GetTagCommit(rel.TagName) + if err != nil { + return fmt.Errorf("GetTagCommit: %v", err) + } + + rel.Sha1 = commit.ID.String() + rel.CreatedUnix = timeutil.TimeStamp(commit.Author.When.Unix()) + rel.NumCommits, err = commit.CommitsCount() + if err != nil { + return fmt.Errorf("CommitsCount: %v", err) + } + } else { + rel.CreatedUnix = timeutil.TimeStampNow() + } + return nil +} + +// CreateRelease creates a new release of repository. +func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) error { + isExist, err := models.IsReleaseExist(rel.RepoID, rel.TagName) + if err != nil { + return err + } else if isExist { + return models.ErrReleaseAlreadyExist{ + TagName: rel.TagName, + } + } + + if err = createTag(gitRepo, rel); err != nil { + return err + } + + rel.LowerTagName = strings.ToLower(rel.TagName) + if err = models.InsertRelease(rel); err != nil { + return err + } + + if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil { + return err + } + + if !rel.IsDraft { + if err := rel.LoadAttributes(); err != nil { + log.Error("LoadAttributes: %v", err) + } else { + mode, _ := models.AccessLevel(rel.Publisher, rel.Repo) + if err := models.PrepareWebhooks(rel.Repo, models.HookEventRelease, &api.ReleasePayload{ + Action: api.HookReleasePublished, + Release: rel.APIFormat(), + Repository: rel.Repo.APIFormat(mode), + Sender: rel.Publisher.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } else { + go models.HookQueue.Add(rel.Repo.ID) + } + } + } + + return nil +} + +// UpdateRelease updates information of a release. +func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) (err error) { + if err = createTag(gitRepo, rel); err != nil { + return err + } + rel.LowerTagName = strings.ToLower(rel.TagName) + + if err = models.UpdateRelease(rel); err != nil { + return err + } + + if err = rel.LoadAttributes(); err != nil { + return err + } + + err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs) + + // even if attachments added failed, hooks will be still triggered + mode, _ := models.AccessLevel(doer, rel.Repo) + if err1 := models.PrepareWebhooks(rel.Repo, models.HookEventRelease, &api.ReleasePayload{ + Action: api.HookReleaseUpdated, + Release: rel.APIFormat(), + Repository: rel.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }); err1 != nil { + log.Error("PrepareWebhooks: %v", err) + } else { + go models.HookQueue.Add(rel.Repo.ID) + } + + return err +} diff --git a/services/release/release_test.go b/services/release/release_test.go new file mode 100644 index 0000000000..91dd0a73b5 --- /dev/null +++ b/services/release/release_test.go @@ -0,0 +1,161 @@ +// Copyright 2018 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 release + +import ( + "path/filepath" + "testing" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + models.MainTest(m, filepath.Join("..", "..")) +} + +func TestRelease_Create(t *testing.T) { + assert.NoError(t, models.PrepareTestDatabase()) + + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + repoPath := models.RepoPath(user.Name, repo.Name) + + gitRepo, err := git.OpenRepository(repoPath) + assert.NoError(t, err) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.1", + Target: "master", + Title: "v0.1 is released", + Note: "v0.1 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: false, + }, nil)) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.1.1", + Target: "65f1bf27bc3bf70f64657658635e66094edbcb4d", + Title: "v0.1.1 is released", + Note: "v0.1.1 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: false, + }, nil)) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.1.2", + Target: "65f1bf2", + Title: "v0.1.2 is released", + Note: "v0.1.2 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: false, + }, nil)) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.1.3", + Target: "65f1bf2", + Title: "v0.1.3 is released", + Note: "v0.1.3 is released", + IsDraft: true, + IsPrerelease: false, + IsTag: false, + }, nil)) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.1.4", + Target: "65f1bf2", + Title: "v0.1.4 is released", + Note: "v0.1.4 is released", + IsDraft: false, + IsPrerelease: true, + IsTag: false, + }, nil)) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.1.5", + Target: "65f1bf2", + Title: "v0.1.5 is released", + Note: "v0.1.5 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: true, + }, nil)) +} + +func TestRelease_MirrorDelete(t *testing.T) { + assert.NoError(t, models.PrepareTestDatabase()) + + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + repoPath := models.RepoPath(user.Name, repo.Name) + migrationOptions := models.MigrateRepoOptions{ + Name: "test_mirror", + Description: "Test mirror", + IsPrivate: false, + IsMirror: true, + RemoteAddr: repoPath, + Wiki: true, + SyncReleasesWithTags: true, + } + mirror, err := models.MigrateRepository(user, user, migrationOptions) + assert.NoError(t, err) + + gitRepo, err := git.OpenRepository(repoPath) + assert.NoError(t, err) + + findOptions := models.FindReleasesOptions{IncludeDrafts: true, IncludeTags: true} + initCount, err := models.GetReleaseCountByRepoID(mirror.ID, findOptions) + assert.NoError(t, err) + + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v0.2", + Target: "master", + Title: "v0.2 is released", + Note: "v0.2 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: true, + }, nil)) + + err = mirror.GetMirror() + assert.NoError(t, err) + + ok := models.RunMirrorSync(mirror.Mirror) + assert.True(t, ok) + + count, err := models.GetReleaseCountByRepoID(mirror.ID, findOptions) + assert.NoError(t, err) + assert.EqualValues(t, initCount+1, count) + + release, err := models.GetRelease(repo.ID, "v0.2") + assert.NoError(t, err) + assert.NoError(t, models.DeleteReleaseByID(release.ID, user, true)) + + ok = models.RunMirrorSync(mirror.Mirror) + assert.True(t, ok) + + count, err = models.GetReleaseCountByRepoID(mirror.ID, findOptions) + assert.NoError(t, err) + assert.EqualValues(t, initCount, count) +} |