From 5c69e834077fd3154dad0ab322f647050b566ab1 Mon Sep 17 00:00:00 2001 From: Dominic Evans Date: Thu, 23 Jan 2025 15:59:31 +0000 Subject: [PATCH 1/2] feat: add --default-branch-only cmdline option Add a cmdline option to only mirror the default branch of a given action between github.com and the target GitHub Enterprise instance, though still mirroring all tags. This is particularly useful when syncing verified publisher actions that may contain a large number of stale and/or ongoing development branches and we only ever really want to sync the tagged releases from the main branch for consumption. This additionally avoids the "triggered actions storm" that can happen when syncing many branches. Contributes-to: actions/actions-sync#12 Signed-off-by: Dominic Evans --- src/pull.go | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/pull.go b/src/pull.go index 84ae3812..d36cb3d8 100644 --- a/src/pull.go +++ b/src/pull.go @@ -9,11 +9,13 @@ import ( "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" + "github.com/go-git/go-git/v5/plumbing" "github.com/spf13/cobra" ) type PullOnlyFlags struct { - SourceURL string + DefaultBranchOnly bool + SourceURL string } type PullFlags struct { @@ -27,6 +29,7 @@ func (f *PullFlags) Init(cmd *cobra.Command) { } func (f *PullOnlyFlags) Init(cmd *cobra.Command) { + cmd.Flags().BoolVar(&f.DefaultBranchOnly, "default-branch-only", false, "Only pull the default branch") cmd.Flags().StringVar(&f.SourceURL, "source-url", "https://github.com", "The domain to pull from") } @@ -45,24 +48,25 @@ func Pull(ctx context.Context, flags *PullFlags) error { return err } - return PullManyWithGitImpl(ctx, flags.SourceURL, flags.CacheDir, repoNames, gitImplementation{}) + return PullManyWithGitImpl(ctx, flags.SourceURL, flags.CacheDir, flags.DefaultBranchOnly, repoNames, gitImplementation{}) } -func PullManyWithGitImpl(ctx context.Context, sourceURL, cacheDir string, repoNames []string, gitimpl GitImplementation) error { +func PullManyWithGitImpl(ctx context.Context, sourceURL, cacheDir string, defaultBranchOnly bool, repoNames []string, gitimpl GitImplementation) error { for _, repoName := range repoNames { - if err := PullWithGitImpl(ctx, sourceURL, cacheDir, repoName, gitimpl); err != nil { + if err := PullWithGitImpl(ctx, sourceURL, cacheDir, defaultBranchOnly, repoName, gitimpl); err != nil { return err } } return nil } -func PullWithGitImpl(ctx context.Context, sourceURL, cacheDir string, repoName string, gitimpl GitImplementation) error { +func PullWithGitImpl(ctx context.Context, sourceURL, cacheDir string, defaultBranchOnly bool, repoName string, gitimpl GitImplementation) error { originRepoName, destRepoName, err := extractSourceDest(repoName) if err != nil { return err } + _ = os.MkdirAll(cacheDir, 0755) _, err = os.Stat(cacheDir) if err != nil { return err @@ -73,8 +77,9 @@ func PullWithGitImpl(ctx context.Context, sourceURL, cacheDir string, repoName s if !gitimpl.RepositoryExists(dst) { fmt.Fprintf(os.Stdout, "pulling %s to %s ...\n", originRepoName, dst) _, err := gitimpl.CloneRepository(dst, &git.CloneOptions{ - SingleBranch: false, - URL: fmt.Sprintf("%s/%s", sourceURL, originRepoName), + ReferenceName: plumbing.HEAD, + SingleBranch: defaultBranchOnly, + URL: fmt.Sprintf("%s/%s", sourceURL, originRepoName), }) if err != nil { if strings.Contains(err.Error(), "authentication required") { @@ -89,10 +94,15 @@ func PullWithGitImpl(ctx context.Context, sourceURL, cacheDir string, repoName s return err } + refspec := config.RefSpec("+refs/heads/*:refs/heads/*") + if defaultBranchOnly { + refspec = "+refs/tags/*:refs/tags/*" + } + fmt.Fprintf(os.Stdout, "fetching * refs for %s ...\n", originRepoName) err = repo.FetchContext(ctx, &git.FetchOptions{ RefSpecs: []config.RefSpec{ - config.RefSpec("+refs/heads/*:refs/heads/*"), + refspec, }, Tags: git.AllTags, }) From 43fa51aefe2211971415f5dc0905912c3f07c672 Mon Sep 17 00:00:00 2001 From: Dominic Evans Date: Thu, 23 Jan 2025 16:10:19 +0000 Subject: [PATCH 2/2] doc: describe --default-branch-only cmdline option Signed-off-by: Dominic Evans --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e081cb0a..30cbf408 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ When there are machines which have access to both the public internet and the GH - `cache-dir` _(required)_ The directory in which to cache repositories as they are synced. This speeds up re-syncing. +- `default-branch-only` _(optional)_ + Optionally if you wish to only synchronize the single default branch rather than the default behaviour of syncing all branches. - `destination-url` _(required)_ The URL of the GHES instance to sync repositories onto. - `destination-token` _(required)_ @@ -65,6 +67,8 @@ When no machine has access to both the public internet and the GHES instance: - `cache-dir` _(required)_ The directory to cache the pulled repositories into. +- `default-branch-only` _(optional)_ + Optionally if you wish to only synchronize the single default branch rather than the default behaviour of syncing all branches. - `repo-name` _(optional)_ A single repository to be synced. In the format of `owner/repo`. Optionally if you wish the repository to be named different on your GHES instance you can provide an alias in the format: `upstream_owner/upstream_repo:destination_owner/destination_repo` - `repo-name-list` _(optional)_