diff --git a/internal/push/push.go b/internal/push/push.go index ee6ee4e..f8a6366 100644 --- a/internal/push/push.go +++ b/internal/push/push.go @@ -14,6 +14,8 @@ import ( "path/filepath" "strings" + "github.com/go-git/go-git/v5/plumbing" + "github.com/github/codeql-action-sync/internal/githubapiutil" log "github.com/sirupsen/logrus" @@ -22,6 +24,7 @@ import ( "github.com/github/codeql-action-sync/internal/version" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" + "github.com/go-git/go-git/v5/plumbing/transport" githttp "github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/google/go-github/v32/github" "github.com/mitchellh/ioprogress" @@ -142,35 +145,53 @@ func (pushService *pushService) pushGit(repository *github.Repository, initialPu } refSpecBatches := [][]config.RefSpec{} + remoteReferences, err := remote.List(&git.ListOptions{Auth: credentials}) + if err != nil && err != transport.ErrEmptyRemoteRepository { + return errors.Wrap(err, "Error listing remote references.") + } + deleteRefSpecs := []config.RefSpec{} + for _, remoteReference := range remoteReferences { + _, err := gitRepository.Reference(remoteReference.Name(), false) + if err != nil && err != plumbing.ErrReferenceNotFound { + return errors.Wrapf(err, "Error finding local reference %s.", remoteReference.Name()) + } + if err == plumbing.ErrReferenceNotFound { + deleteRefSpecs = append(deleteRefSpecs, config.RefSpec(":"+remoteReference.Name().String())) + } + } + refSpecBatches = append(refSpecBatches, deleteRefSpecs) + if initialPush { releasePathStats, err := ioutil.ReadDir(pushService.cacheDirectory.ReleasesPath()) if err != nil { return errors.Wrap(err, "Error reading releases.") } - refSpecBatches = append(refSpecBatches, []config.RefSpec{}) + initialRefSpecs := []config.RefSpec{} for _, releasePathStat := range releasePathStats { - refSpecBatches[0] = append(refSpecBatches[0], config.RefSpec("+refs/tags/"+releasePathStat.Name()+":refs/tags/"+releasePathStat.Name())) + initialRefSpecs = append(initialRefSpecs, config.RefSpec("+refs/tags/"+releasePathStat.Name()+":refs/tags/"+releasePathStat.Name())) } + refSpecBatches = append(refSpecBatches, initialRefSpecs) } else { // We've got to push `main` on its own, so that it will be made the default branch if the repository has just been created. We then push everything else afterwards. - refSpecBatches = [][]config.RefSpec{ + refSpecBatches = append(refSpecBatches, []config.RefSpec{ config.RefSpec("+refs/heads/main:refs/heads/main"), }, []config.RefSpec{ config.RefSpec("+refs/*:refs/*"), }, - } + ) } for _, refSpecs := range refSpecBatches { - err = remote.PushContext(pushService.ctx, &git.PushOptions{ - RefSpecs: refSpecs, - Auth: credentials, - Progress: os.Stderr, - Force: true, - }) - if err != nil && errors.Cause(err) != git.NoErrAlreadyUpToDate { - return errors.Wrap(err, "Error pushing Action to GitHub Enterprise Server.") + if len(refSpecs) != 0 { + err = remote.PushContext(pushService.ctx, &git.PushOptions{ + RefSpecs: refSpecs, + Auth: credentials, + Progress: os.Stderr, + }) + if err != nil && errors.Cause(err) != git.NoErrAlreadyUpToDate { + return errors.Wrap(err, "Error pushing Action to GitHub Enterprise Server.") + } } } diff --git a/internal/push/push_test.go b/internal/push/push_test.go index aecc753..2487224 100644 --- a/internal/push/push_test.go +++ b/internal/push/push_test.go @@ -150,6 +150,35 @@ func TestPushGit(t *testing.T) { "bd82b85707bc13904e3526517677039d4da4a9bb refs/heads/very-ignored-branch", "bd82b85707bc13904e3526517677039d4da4a9bb refs/tags/an-ignored-tag-too", "26936381e619a01122ea33993e3cebc474496805 refs/tags/v2", + "26936381e619a01122ea33993e3cebc474496805 refs/heads/a-ref-that-will-need-pruning", + }) + + pushService = getTestPushService(t, "./push_test/action-cache-modified/", "") + err = pushService.pushGit(&repository, true) + require.NoError(t, err) + test.CheckExpectedReferencesInRepository(t, destinationPath, []string{ + "26936381e619a01122ea33993e3cebc474496805 refs/tags/codeql-bundle-20200101", + "26936381e619a01122ea33993e3cebc474496805 refs/tags/codeql-bundle-20200630", + "b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/heads/main", + "26936381e619a01122ea33993e3cebc474496805 refs/heads/v1", + "e529a54fad10a936308b2220e05f7f00757f8e7c refs/heads/v3", + "bd82b85707bc13904e3526517677039d4da4a9bb refs/heads/very-ignored-branch", + "bd82b85707bc13904e3526517677039d4da4a9bb refs/tags/an-ignored-tag-too", + "26936381e619a01122ea33993e3cebc474496805 refs/tags/v2", + }) + + err = pushService.pushGit(&repository, false) + require.NoError(t, err) + test.CheckExpectedReferencesInRepository(t, destinationPath, []string{ + "26936381e619a01122ea33993e3cebc474496805 refs/tags/codeql-bundle-20200101", + "26936381e619a01122ea33993e3cebc474496805 refs/tags/codeql-bundle-20200630", + "b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/heads/main", + "26936381e619a01122ea33993e3cebc474496805 refs/heads/v1", + "e529a54fad10a936308b2220e05f7f00757f8e7c refs/heads/v3", + "bd82b85707bc13904e3526517677039d4da4a9bb refs/heads/very-ignored-branch", + "bd82b85707bc13904e3526517677039d4da4a9bb refs/tags/an-ignored-tag-too", + "26936381e619a01122ea33993e3cebc474496805 refs/tags/v2", + "26936381e619a01122ea33993e3cebc474496805 refs/heads/a-ref-that-will-need-pruning/because-it-now-has-this-extra-bit", }) } diff --git a/internal/push/push_test/action-cache-initial/git/packed-refs b/internal/push/push_test/action-cache-initial/git/packed-refs index 6376d60..dc98aa8 100644 --- a/internal/push/push_test/action-cache-initial/git/packed-refs +++ b/internal/push/push_test/action-cache-initial/git/packed-refs @@ -1,4 +1,5 @@ # pack-refs with: peeled fully-peeled sorted +26936381e619a01122ea33993e3cebc474496805 refs/heads/a-ref-that-will-need-pruning b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/heads/main 26936381e619a01122ea33993e3cebc474496805 refs/heads/v1 e529a54fad10a936308b2220e05f7f00757f8e7c refs/heads/v3 diff --git a/internal/push/push_test/action-cache-modified/git/HEAD b/internal/push/push_test/action-cache-modified/git/HEAD new file mode 100644 index 0000000..b870d82 --- /dev/null +++ b/internal/push/push_test/action-cache-modified/git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/internal/push/push_test/action-cache-modified/git/config b/internal/push/push_test/action-cache-modified/git/config new file mode 100644 index 0000000..07d359d --- /dev/null +++ b/internal/push/push_test/action-cache-modified/git/config @@ -0,0 +1,4 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true diff --git a/internal/push/push_test/action-cache-modified/git/objects/26/936381e619a01122ea33993e3cebc474496805 b/internal/push/push_test/action-cache-modified/git/objects/26/936381e619a01122ea33993e3cebc474496805 new file mode 100644 index 0000000..7fbf639 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/26/936381e619a01122ea33993e3cebc474496805 differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/28/509716746a9e77e3f752e9df740cb443bf9960 b/internal/push/push_test/action-cache-modified/git/objects/28/509716746a9e77e3f752e9df740cb443bf9960 new file mode 100644 index 0000000..338bce9 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/28/509716746a9e77e3f752e9df740cb443bf9960 differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/internal/push/push_test/action-cache-modified/git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 new file mode 100644 index 0000000..adf6411 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/61/8dc8ffee7af67e4e2dfdbe416c53cca6099fab b/internal/push/push_test/action-cache-modified/git/objects/61/8dc8ffee7af67e4e2dfdbe416c53cca6099fab new file mode 100644 index 0000000..f5ebfb6 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/61/8dc8ffee7af67e4e2dfdbe416c53cca6099fab differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/80/8d4d2d6b7aa39089b99ca0d89f1fc6a2bc63ec b/internal/push/push_test/action-cache-modified/git/objects/80/8d4d2d6b7aa39089b99ca0d89f1fc6a2bc63ec new file mode 100644 index 0000000..355281f Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/80/8d4d2d6b7aa39089b99ca0d89f1fc6a2bc63ec differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/86/e83156c07aea03c86a7cd7c5f6b0ee1453c2d7 b/internal/push/push_test/action-cache-modified/git/objects/86/e83156c07aea03c86a7cd7c5f6b0ee1453c2d7 new file mode 100644 index 0000000..12a77d4 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/86/e83156c07aea03c86a7cd7c5f6b0ee1453c2d7 differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/8e/38374296a8ca208f5e526da24c5b09f3f48624 b/internal/push/push_test/action-cache-modified/git/objects/8e/38374296a8ca208f5e526da24c5b09f3f48624 new file mode 100644 index 0000000..e6fc9ad Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/8e/38374296a8ca208f5e526da24c5b09f3f48624 differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/b9/f01aa2c50f49898d4c7845a66be8824499fe9d b/internal/push/push_test/action-cache-modified/git/objects/b9/f01aa2c50f49898d4c7845a66be8824499fe9d new file mode 100644 index 0000000..180d98a Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/b9/f01aa2c50f49898d4c7845a66be8824499fe9d differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/bd/82b85707bc13904e3526517677039d4da4a9bb b/internal/push/push_test/action-cache-modified/git/objects/bd/82b85707bc13904e3526517677039d4da4a9bb new file mode 100644 index 0000000..b443de7 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/bd/82b85707bc13904e3526517677039d4da4a9bb differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/cd/0f803f72414d81157588de0cb622f47f4bb9bc b/internal/push/push_test/action-cache-modified/git/objects/cd/0f803f72414d81157588de0cb622f47f4bb9bc new file mode 100644 index 0000000..8ae6955 Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/cd/0f803f72414d81157588de0cb622f47f4bb9bc differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/d1/231c269d15582e06ded28babdb8c224ba7e6ed b/internal/push/push_test/action-cache-modified/git/objects/d1/231c269d15582e06ded28babdb8c224ba7e6ed new file mode 100644 index 0000000..9dd5dcb Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/d1/231c269d15582e06ded28babdb8c224ba7e6ed differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/e5/29a54fad10a936308b2220e05f7f00757f8e7c b/internal/push/push_test/action-cache-modified/git/objects/e5/29a54fad10a936308b2220e05f7f00757f8e7c new file mode 100644 index 0000000..1f691db Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/e5/29a54fad10a936308b2220e05f7f00757f8e7c differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/e5/f2bcf5a8815c924448ff3a54455983df118ee4 b/internal/push/push_test/action-cache-modified/git/objects/e5/f2bcf5a8815c924448ff3a54455983df118ee4 new file mode 100644 index 0000000..9ee4f2a Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/e5/f2bcf5a8815c924448ff3a54455983df118ee4 differ diff --git a/internal/push/push_test/action-cache-modified/git/objects/e7/014e2af66d5b702946763455de2dcf9eb93c4f b/internal/push/push_test/action-cache-modified/git/objects/e7/014e2af66d5b702946763455de2dcf9eb93c4f new file mode 100644 index 0000000..c06b61c Binary files /dev/null and b/internal/push/push_test/action-cache-modified/git/objects/e7/014e2af66d5b702946763455de2dcf9eb93c4f differ diff --git a/internal/push/push_test/action-cache-modified/git/packed-refs b/internal/push/push_test/action-cache-modified/git/packed-refs new file mode 100644 index 0000000..2ece843 --- /dev/null +++ b/internal/push/push_test/action-cache-modified/git/packed-refs @@ -0,0 +1,10 @@ +# pack-refs with: peeled fully-peeled sorted +26936381e619a01122ea33993e3cebc474496805 refs/heads/a-ref-that-will-need-pruning/because-it-now-has-this-extra-bit +b9f01aa2c50f49898d4c7845a66be8824499fe9d refs/heads/main +26936381e619a01122ea33993e3cebc474496805 refs/heads/v1 +e529a54fad10a936308b2220e05f7f00757f8e7c refs/heads/v3 +bd82b85707bc13904e3526517677039d4da4a9bb refs/heads/very-ignored-branch +bd82b85707bc13904e3526517677039d4da4a9bb refs/tags/an-ignored-tag-too +26936381e619a01122ea33993e3cebc474496805 refs/tags/codeql-bundle-20200101 +26936381e619a01122ea33993e3cebc474496805 refs/tags/codeql-bundle-20200630 +26936381e619a01122ea33993e3cebc474496805 refs/tags/v2 diff --git a/internal/push/push_test/action-cache-modified/git/refs/.gitkeep b/internal/push/push_test/action-cache-modified/git/refs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200101/assets/bundle.bin b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200101/assets/bundle.bin new file mode 100644 index 0000000..31bd07b --- /dev/null +++ b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200101/assets/bundle.bin @@ -0,0 +1 @@ +This isn't really a CodeQL bundle either! diff --git a/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200101/metadata.json b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200101/metadata.json new file mode 100644 index 0000000..13b82ef --- /dev/null +++ b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200101/metadata.json @@ -0,0 +1,4 @@ +{ + "tag_name": "codeql-bundle-20200101", + "target_commitish": "main" +} diff --git a/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200630/assets/bundle.bin b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200630/assets/bundle.bin new file mode 100644 index 0000000..fe72b6d --- /dev/null +++ b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200630/assets/bundle.bin @@ -0,0 +1 @@ +This isn't really a CodeQL bundle! diff --git a/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200630/metadata.json b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200630/metadata.json new file mode 100644 index 0000000..11fc58a --- /dev/null +++ b/internal/push/push_test/action-cache-modified/releases/codeql-bundle-20200630/metadata.json @@ -0,0 +1,4 @@ +{ + "tag_name": "codeql-bundle-20200630", + "target_commitish": "main" +}