Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gitlab integration #43

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ __pycache__/
tests/*.log

# Project-specific things to ignore ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

venv
build
dist
docs/_build
Expand Down
10 changes: 9 additions & 1 deletion dev/scripts/filter-github-orgs
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,16 @@ def _alert(ctx, msg, print_usage=True):
STYLE_OPTION,
STYLE_ARGUMENT,
STYLE_SWITCH,
OptionHighlighter,
)
from rich.highlighter import RegexHighlighter
class OptionHighlighter(RegexHighlighter):
"""Highlights our special options."""

highlights = [
r"(^|[^\w\-])(?P<switch>-([^\W0-9][\w\-]*\w|[^\W0-9]))",
r"(^|[^\w\-])(?P<option>--([^\W0-9][\w\-]*\w|[^\W0-9]))",
r"(?P<metavar><[^>]+>)",
]
highlighter = OptionHighlighter()
console = Console(theme=Theme({
"option": STYLE_OPTION,
Expand Down
10 changes: 9 additions & 1 deletion dev/scripts/list-github-orgs
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,16 @@ def _alert(ctx, msg, print_usage=True):
STYLE_OPTION,
STYLE_ARGUMENT,
STYLE_SWITCH,
OptionHighlighter,
)
from rich.highlighter import RegexHighlighter
class OptionHighlighter(RegexHighlighter):
"""Highlights our special options."""

highlights = [
r"(^|[^\w\-])(?P<switch>-([^\W0-9][\w\-]*\w|[^\W0-9]))",
r"(^|[^\w\-])(?P<option>--([^\W0-9][\w\-]*\w|[^\W0-9]))",
r"(?P<metavar><[^>]+>)",
]
highlighter = OptionHighlighter()
console = Console(theme=Theme({
"option": STYLE_OPTION,
Expand Down
181 changes: 137 additions & 44 deletions iga/cli.py

Large diffs are not rendered by default.

52 changes: 47 additions & 5 deletions iga/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
from types import SimpleNamespace

from iga.exceptions import GitHubError, InternalError
from iga.name_utils import split_name



# Constants.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand All @@ -33,7 +34,7 @@
'''List of words such that, if one of the words is the last word in an account
name, mean the account will be assumed to be a software bot of some kind.'''


# Classes.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -98,7 +99,7 @@ class GitHubFile(SimpleNamespace):
def __init__(self, file_dict):
super().__init__(**file_dict)


# Exported module functions.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -331,7 +332,7 @@ def valid_github_release_url(url):
and split_url[6] == 'tag')


def probable_bot(account):
def github_probable_bot(account):
'''Return True if this account is probably a bot.

Bot accounts on GitHub are supposed to have an explicit type value of "bot"
Expand All @@ -349,7 +350,48 @@ def probable_bot(account):
log(f'account {account.login} looks like it {"is" if is_bot else "is NOT"} a bot')
return is_bot


def identity_from_github(account, role=None):
if account.type == 'User':
if account.name:
(given, family) = split_name(account.name)
person_or_org = {'given_name': given,
'family_name': family,
'type': 'personal'}
else:
# The GitHub account record has no name, and InvenioRDM won't pass
# a record without a family name. All we have is the login name.
person_or_org = {'given_name': '',
'family_name': account.login,
'type': 'personal'}

else:
name = account.name.strip() if account.name else ''
person_or_org = {'name': name,
'type': 'organizational'}
result = {'person_or_org': person_or_org}
if account.company and account.type == 'User':
account.company = account.company.strip()
if account.company.startswith('@'):
# Some people write @foo to indicate org account "foo" in GitHub.
# Grab only the first token after the '@'.
log(f'company for {account.login} account starts with @')
try:
import re
candidate = re.search(r'\w+', account.company).group()
org_account = github_account(candidate)
except GitHubError:
# No luck. Take it as-is.
log(f'failed to find {account.company[1:]} as a GitHub account')
result['affiliations'] = [{'name': account.company}]
else:
log(f'using org {candidate} as affiliation for {account.name}')
result['affiliations'] = [{'name': org_account.name}]
else:
result['affiliations'] = [{'name': account.company}]
if role:
result['role'] = {'id': role}
return result

# Helper functions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
144 changes: 144 additions & 0 deletions iga/githublab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import os

from iga.github import (
github_account_repo_tag,
github_release,
github_repo,
github_release_assets,
valid_github_release_url,
github_repo_file,
github_repo_filenames,
github_repo_languages,
github_asset_contents,
github_account,
github_repo_contributors,
identity_from_github,
github_probable_bot,
github_file_url,
)
from iga.gitlab import (
valid_gitlab_release_url,
gitlab_release_assets,
gitlab_repo,
gitlab_repo_file,
gitlab_release,
gitlab_account_repo_tag,
gitlab_repo_filenames,
gitlab_repo_languages,
gitlab_asset_contents,
gitlab_account,
gitlab_repo_contributors,
identity_from_gitlab,
gitlab_file_url,
)


class LazyEnvBool:
def __init__(self, var_name):
self.var_name = var_name

def __bool__(self):
return os.getenv(self.var_name, '').lower() == 'true'

__nonzero__ = __bool__ # For Python 2 compatibility


GITLAB = LazyEnvBool('GITLAB')


def valid_release_url(release_url):
if not GITLAB:
return valid_github_release_url(release_url)
else:
return valid_gitlab_release_url(release_url)


def git_account_repo_tag(release_url):
"""Return tuple (account, repo name, tag) based on the given web URL."""
# Example URL: https://code.jlab.org/physdiv/jrdb/inveniordm_jlab/-/releases/0.1.0
# Note this is not the same as the "release url" below.
if not GITLAB:
return github_account_repo_tag(release_url)
else:
return gitlab_account_repo_tag(release_url)


def git_release(repo_name, tag, account_name=None):
if not GITLAB:
return github_release(account_name, repo_name, tag)
else:
return gitlab_release(repo_name, tag)


def git_repo(repo_name, account_name=None):
if not GITLAB:
return github_repo(account_name, repo_name)
else:
return gitlab_repo(repo_name)


def git_repo_filenames(repo, tag):
if not GITLAB:
return github_repo_filenames(repo, tag)
else:
return gitlab_repo_filenames(repo, tag)


def git_repo_file(repo, tag, filename):
if not GITLAB:
return github_repo_file(repo, tag, filename)
else:
return gitlab_repo_file(repo, tag, filename)


def git_release_assets(repo, tag, account_name=None, all_assets=False):
if not GITLAB:
return github_release_assets(account_name, repo, tag, all_assets)
else:
return gitlab_release_assets(repo, tag, all_assets)


def git_account(repo):
if not GITLAB:
return github_account(repo)
else:
return gitlab_account(repo)


def git_repo_languages(repo):
if not GITLAB:
return github_repo_languages(repo)
else:
return gitlab_repo_languages(repo)


def git_asset_contents(asset):
if not GITLAB:
return github_asset_contents(asset)
else:
return gitlab_asset_contents(asset)


def git_repo_contributors(repo):
if not GITLAB:
return github_repo_contributors(repo)
else:
return gitlab_repo_contributors(repo)


def identity_from_git(account, role=None):
if GITLAB:
return identity_from_gitlab(account, role=None)
else:
return identity_from_github(account, role=role)


def git_probable_bot(account):
return github_probable_bot(account)


def git_file_url(repo, filename, tag):
if not GITLAB:
return github_file_url(repo, filename)
else:
return gitlab_file_url(repo, filename, tag)
Loading