Skip to content

Commit 44139e4

Browse files
authored
Merge pull request #30 from github/homepage-safety-check
Implement a safety check to ensure we're not force-pushing over a non-Action repository.
2 parents c283978 + 28b2855 commit 44139e4

File tree

6 files changed

+35
-10
lines changed

6 files changed

+35
-10
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ From a machine with access to both GitHub.com and GitHub Enterprise Server use t
2626
* `--cache-dir` - A temporary directory in which to store data downloaded from GitHub.com before it is uploaded to GitHub Enterprise Server. If not specified a directory next to the sync tool will be used.
2727
* `--source-token` - A token to access the API of GitHub.com. This is normally not required, but can be provided if you have issues with API rate limiting. If provided, it should have the `public_repo` scope.
2828
* `--destination-repository` - The name of the repository in which to create or update the CodeQL Action. If not specified `github/codeql-action` will be used.
29+
* `--force` - By default the tool will not overwrite existing repositories. Providing this flag will allow it to.
2930

3031
### I don't have a machine that can access both GitHub.com and GitHub Enterprise Server.
3132
From a machine with access to GitHub.com use the `./codeql-action-sync pull` command to download a copy of the CodeQL Action and bundles to a local folder.
@@ -45,6 +46,7 @@ Now use the `./codeql-action-sync push` command to upload the CodeQL Action and
4546
**Optional Arguments:**
4647
* `--cache-dir` - The directory to which the Action was previously downloaded.
4748
* `--destination-repository` - The name of the repository in which to create or update the CodeQL Action. If not specified `github/codeql-action` will be used.
49+
* `--force` - By default the tool will not overwrite existing repositories. Providing this flag will allow it to.
4850

4951
## Contributing
5052
For more details on contributing improvements to this tool, see our [contributor guide](CONTRIBUTING.md).

cmd/push.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ var pushCmd = &cobra.Command{
1313
RunE: func(cmd *cobra.Command, args []string) error {
1414
version.LogVersion()
1515
cacheDirectory := cachedirectory.NewCacheDirectory(rootFlags.cacheDir)
16-
return push.Push(cmd.Context(), cacheDirectory, pushFlags.destinationURL, pushFlags.destinationToken, pushFlags.destinationRepository)
16+
return push.Push(cmd.Context(), cacheDirectory, pushFlags.destinationURL, pushFlags.destinationToken, pushFlags.destinationRepository, pushFlags.force)
1717
},
1818
}
1919

2020
type pushFlagFields struct {
2121
destinationURL string
2222
destinationToken string
2323
destinationRepository string
24+
force bool
2425
}
2526

2627
var pushFlags = pushFlagFields{}
@@ -31,4 +32,5 @@ func (f *pushFlagFields) Init(cmd *cobra.Command) {
3132
cmd.Flags().StringVar(&f.destinationToken, "destination-token", "", "A token to access the API on the GitHub Enterprise instance.")
3233
cmd.MarkFlagRequired("destination-token")
3334
cmd.Flags().StringVar(&f.destinationRepository, "destination-repository", "github/codeql-action", "The name of the repository to create on GitHub Enterprise.")
35+
cmd.Flags().BoolVar(&f.force, "force", false, "Replace the existing repository even if it was not created by the sync tool.")
3436
}

cmd/sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var syncCmd = &cobra.Command{
1818
if err != nil {
1919
return err
2020
}
21-
err = push.Push(cmd.Context(), cacheDirectory, pushFlags.destinationURL, pushFlags.destinationToken, pushFlags.destinationRepository)
21+
err = push.Push(cmd.Context(), cacheDirectory, pushFlags.destinationURL, pushFlags.destinationToken, pushFlags.destinationRepository, pushFlags.force)
2222
if err != nil {
2323
return err
2424
}

internal/push/push.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@ import (
2828
const remoteName = "enterprise"
2929
const repositoryHomepage = "https://github.com/github/codeql-action-sync-tool/"
3030

31+
const errorAlreadyExists = "The destination repository already exists, but it was not created with the CodeQL Action sync tool. If you are sure you want to push the CodeQL Action to it, re-run this command with the `--force` flag."
32+
3133
type pushService struct {
3234
ctx context.Context
3335
cacheDirectory cachedirectory.CacheDirectory
3436
githubEnterpriseClient *github.Client
3537
destinationRepositoryName string
3638
destinationRepositoryOwner string
3739
destinationToken string
40+
force bool
3841
}
3942

4043
func (pushService *pushService) createRepository() (*github.Repository, error) {
@@ -76,6 +79,9 @@ func (pushService *pushService) createRepository() (*github.Repository, error) {
7679
if err != nil && (response == nil || response.StatusCode != http.StatusNotFound) {
7780
return nil, errors.Wrap(err, "Error checking if destination repository exists.")
7881
}
82+
if response.StatusCode != http.StatusNotFound && repositoryHomepage != repository.GetHomepage() && !pushService.force {
83+
return nil, errors.Errorf(errorAlreadyExists)
84+
}
7985
desiredRepositoryProperties := github.Repository{
8086
Name: github.String(pushService.destinationRepositoryName),
8187
Homepage: github.String(repositoryHomepage),
@@ -286,7 +292,7 @@ func (pushService *pushService) pushReleases() error {
286292
return nil
287293
}
288294

289-
func Push(ctx context.Context, cacheDirectory cachedirectory.CacheDirectory, destinationURL string, destinationToken string, destinationRepository string) error {
295+
func Push(ctx context.Context, cacheDirectory cachedirectory.CacheDirectory, destinationURL string, destinationToken string, destinationRepository string, force bool) error {
290296
err := cacheDirectory.CheckOrCreateVersionFile(false, version.Version())
291297
if err != nil {
292298
return err
@@ -317,6 +323,7 @@ func Push(ctx context.Context, cacheDirectory cachedirectory.CacheDirectory, des
317323
destinationRepositoryOwner: destinationRepositoryOwner,
318324
destinationRepositoryName: destinationRepositoryName,
319325
destinationToken: destinationToken,
326+
force: force,
320327
}
321328

322329
repository, err := pushService.createRepository()

internal/push/push_test.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,35 @@ func TestUpdateRepositoryWhenUserIsOwner(t *testing.T) {
6464
test.ServeHTTPResponseFromFile(t, http.StatusOK, "./push_test/api/user-is-owner.json", response)
6565
}).Methods("GET")
6666
githubTestServer.HandleFunc("/api/v3/repos/destination-repository-owner/destination-repository-name", func(response http.ResponseWriter, request *http.Request) {
67-
response.Write([]byte("{}"))
67+
test.ServeHTTPResponseFromObject(t, github.Repository{Homepage: github.String(repositoryHomepage)}, response)
6868
}).Methods("GET")
6969
githubTestServer.HandleFunc("/api/v3/repos/destination-repository-owner/destination-repository-name", func(response http.ResponseWriter, request *http.Request) {
7070
response.Write([]byte("{}"))
7171
}).Methods("PATCH")
72-
githubTestServer.HandleFunc("/api/v3/user/repos", func(response http.ResponseWriter, request *http.Request) {
73-
response.Write([]byte("{}"))
74-
}).Methods("POST")
7572
_, err := pushService.createRepository()
7673
require.NoError(t, err)
7774
}
7875

76+
func TestUpdateRepositoryWhenUserIsOwnerForced(t *testing.T) {
77+
temporaryDirectory := test.CreateTemporaryDirectory(t)
78+
githubTestServer, githubEnterpriseURL := test.GetTestHTTPServer(t)
79+
pushService := getTestPushService(t, temporaryDirectory, githubEnterpriseURL)
80+
githubTestServer.HandleFunc("/api/v3/user", func(response http.ResponseWriter, request *http.Request) {
81+
test.ServeHTTPResponseFromFile(t, http.StatusOK, "./push_test/api/user-is-owner.json", response)
82+
}).Methods("GET")
83+
githubTestServer.HandleFunc("/api/v3/repos/destination-repository-owner/destination-repository-name", func(response http.ResponseWriter, request *http.Request) {
84+
test.ServeHTTPResponseFromObject(t, github.Repository{}, response)
85+
}).Methods("GET")
86+
githubTestServer.HandleFunc("/api/v3/repos/destination-repository-owner/destination-repository-name", func(response http.ResponseWriter, request *http.Request) {
87+
test.ServeHTTPResponseFromObject(t, github.Repository{}, response)
88+
}).Methods("PATCH")
89+
_, err := pushService.createRepository()
90+
require.EqualError(t, err, errorAlreadyExists)
91+
pushService.force = true
92+
_, err = pushService.createRepository()
93+
require.NoError(t, err)
94+
}
95+
7996
func TestCreateOrganizationAndRepositoryWhenOrganizationIsOwner(t *testing.T) {
8097
temporaryDirectory := test.CreateTemporaryDirectory(t)
8198
githubTestServer, githubEnterpriseURL := test.GetTestHTTPServer(t)

internal/push/push_test/action-cache-initial/git/config

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,3 @@
22
repositoryformatversion = 0
33
filemode = true
44
bare = true
5-
[remote "enterprise"]
6-
url = /tmp/codeql-action-sync-tests128816160/target
7-
fetch = +refs/heads/*:refs/remotes/enterprise/*

0 commit comments

Comments
 (0)