Skip to content

Commit c3f8282

Browse files
committed
Support GitHub Enterprise
GitHub can be hosted by companies for their own usage (under their own URL). This changset removes the hard-coded url to `github.com` and makes it confligurable for a user, which GitHub-instances shall be supported. Closes #134
1 parent 73e23e1 commit c3f8282

19 files changed

+176
-88
lines changed

docs/reference.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3356,6 +3356,7 @@ Parameter | Description
33563356
Name | Type | Description
33573357
---- | ---- | -----------
33583358
<span style="white-space: nowrap;">`--allstar-app-ids`</span> | *list* | Flag used to set AllStar GitHub app id aliases. See https://github.com/ossf/allstar.
3359+
<span style="white-space: nowrap;">`--github-allowed-hosts`</span> | *list* | If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported.
33593360
<span style="white-space: nowrap;">`--github-api-bearer-auth`</span> | *boolean* | If using a token for GitHub access, bearer auth might be required
33603361
<span style="white-space: nowrap;">`--github-destination-delete-pr-branch`</span> | *boolean* | Overwrite git.github_destination delete_pr_branch field
33613362
<span style="white-space: nowrap;">`--gql-commit-history-override`</span> | *list* | Flag used to target GraphQL params 'first' arguments in the event the defaults are over or underusing the api ratelimit. The flag value should be semicolon separated. This should be rarely used for repos that don't fit well in our defaults. E.g. '50;5;5' represent 50 commits, 5 PRs for each commit, 5 reviews per PR
@@ -3404,6 +3405,7 @@ Name | Type | Description
34043405
<span style="white-space: nowrap;">`--git-destination-push`</span> | *string* | If set, overrides the git destination push reference.
34053406
<span style="white-space: nowrap;">`--git-destination-url`</span> | *string* | If set, overrides the git destination URL.
34063407
<span style="white-space: nowrap;">`--git-skip-checker`</span> | *boolean* | If true and git.destination has a configured checker, it will not be used in the migration.
3408+
<span style="white-space: nowrap;">`--github-allowed-hosts`</span> | *list* | If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported.
34073409
<span style="white-space: nowrap;">`--github-api-bearer-auth`</span> | *boolean* | If using a token for GitHub access, bearer auth might be required
34083410
<span style="white-space: nowrap;">`--github-destination-delete-pr-branch`</span> | *boolean* | Overwrite git.github_destination delete_pr_branch field
34093411
<span style="white-space: nowrap;">`--gql-commit-history-override`</span> | *list* | Flag used to target GraphQL params 'first' arguments in the event the defaults are over or underusing the api ratelimit. The flag value should be semicolon separated. This should be rarely used for repos that don't fit well in our defaults. E.g. '50;5;5' represent 50 commits, 5 PRs for each commit, 5 reviews per PR
@@ -3444,6 +3446,7 @@ Name | Type | Description
34443446
<span style="white-space: nowrap;">`--git-fuzzy-last-rev`</span> | *boolean* | By default Copybara will try to migrate the revision listed as the version in the metadata file from github. This flag tells Copybara to first find the git tag which most closely matches the metadata version, and use that for the migration.
34453447
<span style="white-space: nowrap;">`--git-origin-log-batch`</span> | *int* | Read the origin git log in batches of n commits. Might be needed for large migrations resulting in git logs of more than 1 GB.
34463448
<span style="white-space: nowrap;">`--git-origin-rebase-ref`</span> | *string* | When importing a change from a Git origin ref, it will be rebased to this ref, if set. A common use case: importing a Github PR, rebase it to the main branch (usually 'master'). Note that, if the repo uses submodules, they won't be rebased.
3449+
<span style="white-space: nowrap;">`--github-allowed-hosts`</span> | *list* | If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported.
34473450
<span style="white-space: nowrap;">`--github-api-bearer-auth`</span> | *boolean* | If using a token for GitHub access, bearer auth might be required
34483451
<span style="white-space: nowrap;">`--github-destination-delete-pr-branch`</span> | *boolean* | Overwrite git.github_destination delete_pr_branch field
34493452
<span style="white-space: nowrap;">`--gql-commit-history-override`</span> | *list* | Flag used to target GraphQL params 'first' arguments in the event the defaults are over or underusing the api ratelimit. The flag value should be semicolon separated. This should be rarely used for repos that don't fit well in our defaults. E.g. '50;5;5' represent 50 commits, 5 PRs for each commit, 5 reviews per PR
@@ -3539,6 +3542,7 @@ Name | Type | Description
35393542
<span style="white-space: nowrap;">`--git-destination-push`</span> | *string* | If set, overrides the git destination push reference.
35403543
<span style="white-space: nowrap;">`--git-destination-url`</span> | *string* | If set, overrides the git destination URL.
35413544
<span style="white-space: nowrap;">`--git-skip-checker`</span> | *boolean* | If true and git.destination has a configured checker, it will not be used in the migration.
3545+
<span style="white-space: nowrap;">`--github-allowed-hosts`</span> | *list* | If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported.
35423546
<span style="white-space: nowrap;">`--github-api-bearer-auth`</span> | *boolean* | If using a token for GitHub access, bearer auth might be required
35433547
<span style="white-space: nowrap;">`--github-destination-delete-pr-branch`</span> | *boolean* | Overwrite git.github_destination delete_pr_branch field
35443548
<span style="white-space: nowrap;">`--github-destination-pr-branch`</span> | *string* | If set, uses this branch for creating the pull request instead of using a generated one
@@ -3605,6 +3609,7 @@ Name | Type | Description
36053609
<span style="white-space: nowrap;">`--git-fuzzy-last-rev`</span> | *boolean* | By default Copybara will try to migrate the revision listed as the version in the metadata file from github. This flag tells Copybara to first find the git tag which most closely matches the metadata version, and use that for the migration.
36063610
<span style="white-space: nowrap;">`--git-origin-log-batch`</span> | *int* | Read the origin git log in batches of n commits. Might be needed for large migrations resulting in git logs of more than 1 GB.
36073611
<span style="white-space: nowrap;">`--git-origin-rebase-ref`</span> | *string* | When importing a change from a Git origin ref, it will be rebased to this ref, if set. A common use case: importing a Github PR, rebase it to the main branch (usually 'master'). Note that, if the repo uses submodules, they won't be rebased.
3612+
<span style="white-space: nowrap;">`--github-allowed-hosts`</span> | *list* | If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported.
36083613
<span style="white-space: nowrap;">`--github-api-bearer-auth`</span> | *boolean* | If using a token for GitHub access, bearer auth might be required
36093614
<span style="white-space: nowrap;">`--github-destination-delete-pr-branch`</span> | *boolean* | Overwrite git.github_destination delete_pr_branch field
36103615
<span style="white-space: nowrap;">`--github-force-import`</span> | *boolean* | Force import regardless of the state of the PR
@@ -3644,6 +3649,7 @@ Parameter | Description
36443649
Name | Type | Description
36453650
---- | ---- | -----------
36463651
<span style="white-space: nowrap;">`--allstar-app-ids`</span> | *list* | Flag used to set AllStar GitHub app id aliases. See https://github.com/ossf/allstar.
3652+
<span style="white-space: nowrap;">`--github-allowed-hosts`</span> | *list* | If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported.
36473653
<span style="white-space: nowrap;">`--github-api-bearer-auth`</span> | *boolean* | If using a token for GitHub access, bearer auth might be required
36483654
<span style="white-space: nowrap;">`--github-destination-delete-pr-branch`</span> | *boolean* | Overwrite git.github_destination delete_pr_branch field
36493655
<span style="white-space: nowrap;">`--gql-commit-history-override`</span> | *list* | Flag used to target GraphQL params 'first' arguments in the event the defaults are over or underusing the api ratelimit. The flag value should be semicolon separated. This should be rarely used for repos that don't fit well in our defaults. E.g. '50;5;5' represent 50 commits, 5 PRs for each commit, 5 reviews per PR

java/com/google/copybara/git/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ java_library(
7373
"//java/com/google/copybara/monitor",
7474
"//java/com/google/copybara/profiler",
7575
"//java/com/google/copybara/revision",
76+
"//java/com/google/copybara/starlark",
7677
"//java/com/google/copybara/templatetoken",
7778
"//java/com/google/copybara/transform",
7879
"//java/com/google/copybara/transform/patch",

java/com/google/copybara/git/GitHubOptions.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
import com.google.copybara.jcommander.DurationConverter;
4040
import com.google.copybara.jcommander.GreaterThanZeroListValidator;
4141
import com.google.copybara.jcommander.SemicolonSeparatedListSplitter;
42+
import com.google.copybara.starlark.StarlarkUtil;
4243
import com.google.copybara.util.console.Console;
44+
import net.starlark.java.eval.EvalException;
45+
4346
import java.io.IOException;
4447
import java.time.Duration;
4548
import java.util.List;
@@ -86,6 +89,17 @@ public class GitHubOptions implements Option {
8689
arity = 1)
8790
public boolean gitHubApiBearerAuth = false;
8891

92+
@Parameter(
93+
names = "--github-allowed-hosts",
94+
description = "If using GitHub Enterprise, one needs to specify valid hosts. By default only `github.com` is supported."
95+
)
96+
public List<String> gitHubAllowedHosts = ImmutableList.of("github.com");
97+
98+
public GitHubHost getGitHubHost(String url) throws EvalException {
99+
GitHubHost host = GitHubHost.fromUrl(url);
100+
StarlarkUtil.check(gitHubAllowedHosts.contains(host.getHost()), "'%s' is not a valid GitHub url", host.getHost());
101+
return host;
102+
}
89103

90104
public GitHubOptions(GeneralOptions generalOptions, GitOptions gitOptions) {
91105
this.generalOptions = Preconditions.checkNotNull(generalOptions);
@@ -100,7 +114,7 @@ public LazyResourceLoader<GitHubApi> newGitHubApiSupplier(
100114
GitHubHost ghHost) {
101115
return (console) -> {
102116
String project = ghHost.getProjectNameFromUrl(url);
103-
return newGitHubRestApi(project, checker, credentials, console);
117+
return newGitHubRestApi(ghHost, project, checker, credentials, console);
104118
};
105119
}
106120

@@ -112,7 +126,7 @@ public LazyResourceLoader<GitHubGraphQLApi> newGitHubGraphQLApiSupplier(
112126
GitHubHost ghHost) {
113127
return (console) -> {
114128
String project = ghHost.getProjectNameFromUrl(url);
115-
return newGitHubGraphQLApi(project, checker, credentials, console);
129+
return newGitHubGraphQLApi(ghHost, project, checker, credentials, console);
116130
};
117131
}
118132

@@ -121,9 +135,9 @@ public LazyResourceLoader<GitHubGraphQLApi> newGitHubGraphQLApiSupplier(
121135
*
122136
* <p>The project for 'https://github.com/foo/bar' is 'foo/bar'.
123137
*/
124-
public GitHubApi newGitHubRestApi(
138+
public GitHubApi newGitHubRestApi(GitHubHost ghHost,
125139
String gitHubProject, @Nullable CredentialFileHandler credentials) throws RepoException {
126-
return newGitHubRestApi(
140+
return newGitHubRestApi(ghHost,
127141
gitHubProject, /* checker= */ null, credentials, generalOptions.console());
128142
}
129143

@@ -134,6 +148,7 @@ public GitHubApi newGitHubRestApi(
134148
* <p>The project for 'https://github.com/foo/bar' is 'foo/bar'.
135149
*/
136150
public GitHubApi newGitHubRestApi(
151+
GitHubHost ghHost,
137152
String gitHubProject,
138153
@Nullable Checker checker,
139154
@Nullable CredentialFileHandler credentials,
@@ -144,7 +159,7 @@ public GitHubApi newGitHubRestApi(
144159
if (storePath == null) {
145160
storePath = "~/.git-credentials";
146161
}
147-
GitHubApiTransport transport = newTransport(repo, storePath, console);
162+
GitHubApiTransport transport = newTransport(ghHost, repo, storePath, console);
148163
if (checker != null) {
149164
transport = new GitHubApiTransportWithChecker(transport, new ApiChecker(checker, console));
150165
}
@@ -156,9 +171,9 @@ public GitHubApi newGitHubRestApi(
156171
*
157172
* <p>The project for 'https://github.com/foo/bar' is 'foo/bar'.
158173
*/
159-
public GitHubGraphQLApi newGitHubGraphQLApi(
174+
public GitHubGraphQLApi newGitHubGraphQLApi(GitHubHost ghHost,
160175
String gitHubProject, @Nullable CredentialFileHandler credentials) throws RepoException {
161-
return newGitHubGraphQLApi(
176+
return newGitHubGraphQLApi(ghHost,
162177
gitHubProject, /* checker= */ null, credentials, generalOptions.console());
163178
}
164179

@@ -169,6 +184,7 @@ public GitHubGraphQLApi newGitHubGraphQLApi(
169184
* <p>The project for 'https://github.com/foo/bar' is 'foo/bar'.
170185
*/
171186
public GitHubGraphQLApi newGitHubGraphQLApi(
187+
GitHubHost ghHost,
172188
String gitHubProject,
173189
@Nullable Checker checker,
174190
@Nullable CredentialFileHandler credentials,
@@ -180,7 +196,7 @@ public GitHubGraphQLApi newGitHubGraphQLApi(
180196
if (storePath == null) {
181197
storePath = "~/.git-credentials";
182198
}
183-
GitHubApiTransport transport = newTransport(repo, storePath, console);
199+
GitHubApiTransport transport = newTransport(ghHost, repo, storePath, console);
184200
if (checker != null) {
185201
transport = new GitHubApiTransportWithChecker(transport, new ApiChecker(checker, console));
186202
}
@@ -210,9 +226,9 @@ public void validateEndpointChecker(@Nullable Checker checker) throws Validation
210226
// Accept any by default
211227
}
212228

213-
private GitHubApiTransport newTransport(
229+
private GitHubApiTransport newTransport(GitHubHost ghHost,
214230
GitRepository repo, String storePath, Console console) {
215-
return new GitHubApiTransportImpl(
231+
return new GitHubApiTransportImpl(ghHost,
216232
repo, newHttpTransport(), storePath, gitHubApiBearerAuth, console);
217233
}
218234

java/com/google/copybara/git/GitHubPrDestination.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ public ImmutableList<DestinationEffect> write(
234234
return result.build();
235235
}
236236

237-
GitHubApi api = gitHubOptions.newGitHubRestApi(getProjectName(), credentials);
237+
GitHubApi api = gitHubOptions.newGitHubRestApi(ghHost, getProjectName(), credentials);
238238

239239
ImmutableList<PullRequest> pullRequests =
240240
api.getPullRequests(
@@ -346,7 +346,7 @@ public Endpoint getFeedbackEndPoint(Console console) throws ValidationException
346346
}
347347

348348
private String asHttpsUrl() throws ValidationException {
349-
return "https://github.com/" + getProjectName();
349+
return ghHost.projectAsUrl(getProjectName());
350350
}
351351

352352
@VisibleForTesting

java/com/google/copybara/git/GitHubPrOrigin.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ public String showDiff(GitRevision revisionFrom, GitRevision revisionTo) throws
269269
/** Given a commit SHA, use the GitHub API to (try to) look up info for a corresponding PR. */
270270
private PullRequest getPrFromSha(String project, String sha)
271271
throws RepoException, ValidationException {
272-
GitHubApi gitHubApi = gitHubOptions.newGitHubRestApi(project, credentials);
272+
GitHubApi gitHubApi = gitHubOptions.newGitHubRestApi(ghHost, project, credentials);
273273
IssuesAndPullRequestsSearchResults searchResults =
274274
gitHubApi.getIssuesOrPullRequestsSearchResults(
275275
new IssuesAndPullRequestsSearchRequestParams(
@@ -299,13 +299,13 @@ private PullRequest getPrFromSha(String project, String sha)
299299
private PullRequest getPrFromNumber(String project, long prNumber)
300300
throws RepoException, ValidationException {
301301
try (ProfilerTask ignore = generalOptions.profiler().start("github_api_get_pr")) {
302-
return gitHubOptions.newGitHubRestApi(project, credentials).getPullRequest(project, prNumber);
302+
return gitHubOptions.newGitHubRestApi(ghHost, project, credentials).getPullRequest(project, prNumber);
303303
}
304304
}
305305

306306
private GitRevision getRevisionForPR(String project, PullRequest prData)
307307
throws RepoException, ValidationException {
308-
GitHubApi api = gitHubOptions.newGitHubRestApi(project, credentials);
308+
GitHubApi api = gitHubOptions.newGitHubRestApi(ghHost, project, credentials);
309309
int prNumber = (int) prData.getNumber();
310310
boolean actuallyUseMerge = this.useMerge;
311311
ImmutableListMultimap.Builder<String, String> labels = ImmutableListMultimap.builder();

java/com/google/copybara/git/GitHubPrWriteHook.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void beforePush(
9595
}
9696
for (Change<?> originalChange : originChanges) {
9797
String projectName = ghHost.getProjectNameFromUrl(repoUrl);
98-
GitHubApi api = gitHubOptions.newGitHubRestApi(projectName, creds);
98+
GitHubApi api = gitHubOptions.newGitHubRestApi(ghHost, projectName, creds);
9999

100100
try {
101101
ImmutableList<PullRequest> pullRequests =

java/com/google/copybara/git/GitHubPreSubmitApprovalsProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public ImmutableList<ChangeWithApprovals> tryPresubmitUserValidation(
202202
ImmutableList.builder();
203203
ImmutableList<Review> reviews = null;
204204
try {
205-
reviews = this.githubOptions.newGitHubRestApi(projectId, creds)
205+
reviews = this.githubOptions.newGitHubRestApi(githubHost, projectId, creds)
206206
.getReviews(projectId, prNumber);
207207
} catch (RepoException | ValidationException e) {
208208
console.warnFmt(

java/com/google/copybara/git/GitHubWriteHook.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public class GitHubWriteHook extends DefaultWriteHook {
9292
private PullRequest getPrFromNumber(String project, long prNumber)
9393
throws RepoException, ValidationException {
9494
try (ProfilerTask ignore = generalOptions.profiler().start("github_api_get_pr")) {
95-
return gitHubOptions.newGitHubRestApi(project, creds).getPullRequest(project, prNumber);
95+
return gitHubOptions.newGitHubRestApi(ghHost, project, creds).getPullRequest(project, prNumber);
9696
}
9797
}
9898

@@ -106,7 +106,7 @@ public void beforePush(
106106
throws ValidationException, RepoException {
107107

108108
String configProjectName = ghHost.getProjectNameFromUrl(repoUrl);
109-
GitHubApi api = gitHubOptions.newGitHubRestApi(configProjectName, creds);
109+
GitHubApi api = gitHubOptions.newGitHubRestApi(ghHost, configProjectName, creds);
110110

111111

112112
// TODO(joshgoldman): add credentials to the GitRepository object for pushing to the fork
@@ -204,7 +204,7 @@ public ImmutableList<DestinationEffect> afterPush(String serverResponse, Message
204204
return baseEffects.build();
205205
}
206206
String projectId = ghHost.getProjectNameFromUrl(repoUrl);
207-
GitHubApi api = gitHubOptions.newGitHubRestApi(projectId, creds);
207+
GitHubApi api = gitHubOptions.newGitHubRestApi(ghHost, projectId, creds);
208208

209209
if (!originChanges.isEmpty()) {
210210
if (gitHubOptions.githubPrBranchDeletionDelay != null) {

0 commit comments

Comments
 (0)