Skip to content

Commit

Permalink
[#153] Add support for forking repos.
Browse files Browse the repository at this point in the history
  • Loading branch information
netomi committed Dec 5, 2023
1 parent 7f087db commit bf9350f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Added

- Added support for creating new repositories as fork. ([#153](https://gitlab.eclipse.org/eclipsefdn/security/otterdog/-/issues/153))
- Added support for action variables on organizational and repository level. ([#150](https://gitlab.eclipse.org/eclipsefdn/security/otterdog/-/issues/150))
- Added operation `list-members` to display the amount of members for an organization.
- Added support for repository rulesets. ([#53](https://gitlab.eclipse.org/eclipsefdn/security/otterdog/-/issues/53))
- Added support for workflow settings of a repository. ([#113](https://gitlab.eclipse.org/eclipsefdn/security/otterdog/-/issues/113))
Expand Down
11 changes: 11 additions & 0 deletions otterdog/models/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ class Repository(ModelObject):
gh_pages_source_branch: Optional[str]
gh_pages_source_path: Optional[str]

forked_repository: Optional[str] = dataclasses.field(metadata={"model_only": True})
fork_default_branch_only: bool = dataclasses.field(metadata={"model_only": True})

workflows: RepositoryWorkflowSettings = dataclasses.field(metadata={"nested_model": True})

# model only fields
Expand Down Expand Up @@ -279,6 +282,12 @@ def validate(self, context: ValidationContext, parent_object: Any) -> None:
f"'secret_scanning_push_protection' is enabled.",
)

if is_set_and_valid(self.template_repository) and is_set_and_valid(self.forked_repository):
context.add_failure(
FailureType.ERROR,
f"{self.get_model_header()} has 'template_repository' and 'forked_repository' set at the same time.",
)

for webhook in self.webhooks:
webhook.validate(context, self)

Expand Down Expand Up @@ -851,6 +860,8 @@ def apply_live_patch(cls, patch: LivePatch, org_id: str, provider: GitHubProvide
patch.expected_object.to_provider_data(org_id, provider),
patch.expected_object.template_repository,
patch.expected_object.post_process_template_content,
patch.expected_object.forked_repository,
patch.expected_object.fork_default_branch_only,
patch.expected_object.auto_init,
)

Expand Down
6 changes: 5 additions & 1 deletion otterdog/providers/github/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,17 @@ def add_repo(
data: dict[str, str],
template_repository: Optional[str],
post_process_template_content: list[str],
forked_repository: Optional[str],
fork_default_branch_only: bool,
auto_init_repo: bool,
) -> None:
self.rest_api.repo.add_repo(
org_id,
data,
template_repository,
post_process_template_content,
forked_repository,
fork_default_branch_only,
auto_init_repo,
)

Expand Down Expand Up @@ -270,7 +274,7 @@ def get_org_variables(self, org_id: str) -> list[dict[str, Any]]:

def update_org_variable(self, org_id: str, variable_name: str, variable: dict[str, Any]) -> None:
if len(variable) > 0:
self.rest_api.org.update_secret(org_id, variable_name, variable)
self.rest_api.org.update_variable(org_id, variable_name, variable)

def add_org_variable(self, org_id: str, data: dict[str, str]) -> None:
self.rest_api.org.add_variable(org_id, data)
Expand Down
34 changes: 34 additions & 0 deletions otterdog/providers/github/rest/repo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,44 @@ def add_repo(
data: dict[str, Any],
template_repository: Optional[str],
post_process_template_content: list[str],
forked_repository: Optional[str],
fork_default_branch_only: bool,
auto_init_repo: bool,
) -> None:
repo_name = data["name"]

if is_set_and_present(forked_repository):
print_debug(f"forking repo '{forked_repository}' to '{org_id}/{repo_name}'")
upstream_owner, upstream_repo = re.split("/", forked_repository, 1)

try:
fork_data = {
"organization": org_id,
"name": repo_name,
"default_branch_only": fork_default_branch_only,
}

self.requester.request_json(
"POST",
f"/repos/{upstream_owner}/{upstream_repo}/forks",
fork_data,
)

print_debug(f"created repo with name '{repo_name}' from template '{template_repository}'")

# get all the data for the created repo to avoid setting values that can not be changed due
# to defaults from the organization (like web_commit_signoff_required)
current_data = self.get_repo_data(org_id, repo_name)
self._remove_already_active_settings(data, current_data)
self.update_repo(org_id, repo_name, data)

return
except GitHubException as ex:
tb = ex.__traceback__
raise RuntimeError(
f"failed to fork repo '{repo_name}' from repo '{forked_repository}':\n{ex}"
).with_traceback(tb)

if is_set_and_present(template_repository):
print_debug(f"creating repo '{org_id}/{repo_name}' with template '{template_repository}'")
template_owner, template_repo = re.split("/", template_repository, 1)
Expand Down
2 changes: 2 additions & 0 deletions otterdog/resources/schemas/repository.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"type": "array",
"items": { "type": "string" }
},
"forked_repository": { "$ref": "#/definitions/string_or_null" },
"fork_default_branch_only": { "type": "boolean" },
"auto_init": { "type": "boolean" },
"topics": {
"type": "array",
Expand Down

0 comments on commit bf9350f

Please sign in to comment.