Skip to content

Commit 8b7e4ed

Browse files
Bugfix Approving a PackageRevision fails with --db-push-drafts-to-git=true (#1142)
* adding closeDraft fix + unit test Signed-off-by: Catalin-Stratulat-Ericsson <catalin.stratulat@ericsson.com> * removing waffle text descriptions Signed-off-by: Catalin-Stratulat-Ericsson <catalin.stratulat@ericsson.com> --------- Signed-off-by: Catalin-Stratulat-Ericsson <catalin.stratulat@ericsson.com>
1 parent 8cef477 commit 8b7e4ed

2 files changed

Lines changed: 95 additions & 0 deletions

File tree

pkg/cache/dbcache/dbpackagerevision.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ func (pr *dbPackageRevision) UpdateLifecycle(ctx context.Context, newLifecycle p
210210
pr.pkgRevKey.Revision = 0
211211
return pkgerrors.Wrapf(err, "dbPackageRevision:UpdateLifecycle: could not publish package revision %+v", pr.Key())
212212
}
213+
// drops cached stale draft so it doesnt trigger closure
214+
pr.gitPRDraft = nil
213215
} else if porchapi.LifecycleIsPublished(pr.lifecycle) {
214216
return pr.updateLifecycleOnPublishedPR(ctx, newLifecycle)
215217
}

pkg/cache/dbcache/dbpackagerevision_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"errors"
2020
"time"
2121

22+
kptfilev1 "github.com/kptdev/kpt/api/kptfile/v1"
2223
porchapi "github.com/kptdev/porch/api/porch/v1alpha1"
2324
configapi "github.com/kptdev/porch/api/porchconfig/v1alpha1"
2425
cachetypes "github.com/kptdev/porch/pkg/cache/types"
@@ -27,6 +28,7 @@ import (
2728
externalrepotypes "github.com/kptdev/porch/pkg/externalrepo/types"
2829
"github.com/kptdev/porch/pkg/repository"
2930
mockcachetypes "github.com/kptdev/porch/test/mockery/mocks/porch/pkg/cache/types"
31+
mockrepo "github.com/kptdev/porch/test/mockery/mocks/porch/pkg/repository"
3032
"github.com/stretchr/testify/mock"
3133
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3234
)
@@ -741,3 +743,94 @@ func (t *DbTestSuite) TestBackfillUpstreamRefName() {
741743

742744
t.deleteTestRepo(dbRepo.Key())
743745
}
746+
747+
func (t *DbTestSuite) TestDBPackageRevisionPublishWithPushDraftsToGit() {
748+
mockCache := mockcachetypes.NewMockCache(t.T())
749+
cachetypes.CacheInstance = mockCache
750+
externalrepo.ExternalRepoInUnitTestMode = true
751+
752+
ctx := t.Context()
753+
namespace := "my-ns"
754+
repoName := "publish-push-drafts-repo"
755+
756+
testRepo := t.createTestRepo(namespace, repoName)
757+
testRepo.spec = &configapi.Repository{
758+
Spec: configapi.RepositorySpec{
759+
Git: &configapi.GitRepository{
760+
Repo: "https://aurl/repo.git",
761+
},
762+
},
763+
}
764+
mockCache.EXPECT().GetRepository(mock.Anything).Return(testRepo).Maybe()
765+
766+
// Stand in for the git repository. Using a mock rather than the fake external repo means
767+
// every call made to git is asserted, so an unexpected second close fails the test.
768+
extRepo := mockrepo.NewMockRepository(t.T())
769+
extRepo.EXPECT().Key().Return(repository.RepositoryKey{Namespace: namespace, Name: repoName}).Maybe()
770+
771+
testRepo.externalRepo = extRepo
772+
testRepo.pushDraftsToGit = true
773+
testRepo.gitPRCache = make(map[string]repository.PackageRevision)
774+
775+
// Create: a git draft is opened and then closed, yielding the cached git PR.
776+
initialGitDraft := mockrepo.NewMockPackageRevisionDraft(t.T())
777+
cachedGitPR := mockrepo.NewMockPackageRevision(t.T())
778+
extRepo.EXPECT().CreatePackageRevisionDraft(mock.Anything, mock.Anything).Return(initialGitDraft, nil).Once()
779+
extRepo.EXPECT().ClosePackageRevisionDraft(mock.Anything, initialGitDraft, 0).Return(cachedGitPR, nil).Once()
780+
781+
newPRDef := porchapi.PackageRevision{
782+
Spec: porchapi.PackageRevisionSpec{
783+
RepositoryName: repoName,
784+
PackageName: "my-package",
785+
WorkspaceName: "my-workspace",
786+
Lifecycle: porchapi.PackageRevisionLifecycleDraft,
787+
},
788+
}
789+
790+
prDraft, err := testRepo.CreatePackageRevisionDraft(ctx, &newPRDef)
791+
t.Require().NoError(err)
792+
793+
dbPR, err := testRepo.ClosePackageRevisionDraft(ctx, prDraft, 0)
794+
t.Require().NoError(err)
795+
t.Require().Nil(dbPR.(*dbPackageRevision).gitPRDraft, "closing a draft must release the git draft handle")
796+
797+
// Propose.
798+
err = dbPR.UpdateLifecycle(ctx, porchapi.PackageRevisionLifecycleProposed)
799+
t.Require().NoError(err)
800+
801+
dbPR, err = testRepo.ClosePackageRevisionDraft(ctx, dbPR.(repository.PackageRevisionDraft), 0)
802+
t.Require().NoError(err)
803+
804+
// Approve. dbRepository.UpdatePackageRevision reopens the cached git PR as a draft, and
805+
// publishPR opens and closes a second one with the real revision number.
806+
staleGitDraft := mockrepo.NewMockPackageRevisionDraft(t.T())
807+
publishGitDraft := mockrepo.NewMockPackageRevisionDraft(t.T())
808+
publishedGitPR := mockrepo.NewMockPackageRevision(t.T())
809+
810+
extRepo.EXPECT().UpdatePackageRevision(mock.Anything, cachedGitPR).Return(staleGitDraft, nil).Once()
811+
extRepo.EXPECT().UpdatePackageRevision(mock.Anything, cachedGitPR).Return(publishGitDraft, nil).Once()
812+
publishGitDraft.EXPECT().UpdateLifecycle(mock.Anything, porchapi.PackageRevisionLifecyclePublished).Return(nil).Once()
813+
// The revision number, never 0, is what reaches git for a Published draft.
814+
extRepo.EXPECT().ClosePackageRevisionDraft(mock.Anything, publishGitDraft, 1).Return(publishedGitPR, nil).Once()
815+
publishedGitPR.EXPECT().GetLock(mock.Anything).Return(kptfilev1.Upstream{}, kptfilev1.Locator{}, nil).Once()
816+
817+
approveDraft, err := testRepo.UpdatePackageRevision(ctx, dbPR)
818+
t.Require().NoError(err)
819+
t.Require().Equal(staleGitDraft, approveDraft.(*dbPackageRevision).gitPRDraft)
820+
821+
err = approveDraft.UpdateLifecycle(ctx, porchapi.PackageRevisionLifecyclePublished)
822+
t.Require().NoError(err)
823+
t.Require().Nil(approveDraft.(*dbPackageRevision).gitPRDraft,
824+
"publishing must release the stale git draft handle so it is not closed with version 0")
825+
826+
// No further git calls are expected here: staleGitDraft is never closed.
827+
publishedPR, err := testRepo.ClosePackageRevisionDraft(ctx, approveDraft, 0)
828+
t.Require().NoError(err)
829+
t.Require().Equal(1, publishedPR.Key().Revision)
830+
t.Require().Equal(porchapi.PackageRevisionLifecyclePublished, publishedPR.Lifecycle(ctx))
831+
832+
// Other tests in this suite assert on database-wide package revision counts, so drop
833+
// everything this test created. Close only removes cached packages, not external ones.
834+
extRepo.EXPECT().Close(mock.Anything).Return(nil).Once()
835+
t.Require().NoError(testRepo.Close(ctx))
836+
}

0 commit comments

Comments
 (0)