Example #1
0
def main():
    p = ArgumentParser(description="mass add team members to repos, optionally creating new repos")
    p.add_argument("fn", help=".xlsx with group info")
    p.add_argument("oauth", help="Oauth file")
    p.add_argument("-stem", help="beginning of repo names", default="")
    p.add_argument("-orgname", help="Github Organization", required=True)
    p.add_argument("-col", help="columns for Username, teamname", nargs="+", required=True)
    p.add_argument("-private", help="create private repos", action="store_true")
    p.add_argument("-create", help="create repo if not existing", action="store_true")
    p = p.parse_args()

    fn = Path(p.fn).expanduser()

    if fn.suffix in (".xls", ".xlsx"):
        teams = pandas.read_excel(fn, usecols=p.col).squeeze().dropna()
    elif fn.suffix == ".csv":
        teams = pandas.read_csv(fn, usecols=p.col).squeeze().dropna()
    else:
        raise ValueError(f"Unknown file type {fn}")

    if not teams.ndim == 2:
        raise ValueError(
            "need to have member names and team names. Check that -col argument matches spreadsheet."
        )
    # %%
    op, sess = connect(p.oauth, p.orgname)
    check_api_limit(sess)

    adder(teams, p.stem, p.private, p.create, op, sess)
Example #2
0
def main(oauth: Path, orgname: str, stem: str):
    # %% authentication
    user, sess = gb.connect(oauth)
    assert isinstance(user, github.AuthenticatedUser.AuthenticatedUser
                      ), "unwatch is for users only, not orgs"
    gb.check_api_limit(sess)
    # %% get organization handle
    org = gb.user_or_org(sess, orgname)
    # %% prepare to loop over repos
    repos = gb.get_repos(org)

    to_act = [
        repo for repo in repos
        if user.has_in_watched(repo) and repo.name.startswith(stem)
    ]
    if not to_act:
        raise SystemExit(
            f"There were no repos left to unwatch with {stem} in {orgname}")

    print("\ntype affirmative to UNWATCH",
          "\n".join([repo.full_name for repo in to_act]))
    if input() != "affirmative":
        raise SystemExit("Aborted")

    for repo in to_act:
        user.remove_from_watched(repo)
        print("UnWatched:", repo.full_name)
Example #3
0
def main():
    p = ArgumentParser(
        description=
        "mass add team members to repos, optionally creating new repos")
    p.add_argument("fn", help=".xlsx with group info")
    p.add_argument("oauth", help="Oauth file")
    p.add_argument("-orgname", help="Github Organization", required=True)
    p.add_argument("-col",
                   help="column for GitHub Username",
                   nargs="+",
                   required=True)
    p = p.parse_args()

    fn = Path(p.fn).expanduser()

    if fn.suffix in (".xls", ".xlsx"):
        users = pandas.read_excel(fn, usecols=p.col).squeeze().dropna()
    elif fn.suffix == ".csv":
        users = pandas.read_csv(fn, usecols=p.col).squeeze().dropna()
    else:
        raise ValueError(f"Unknown file type {fn}")

    if not users.ndim == 1:
        raise ValueError(
            "need to have member names. Check that -col argument matches spreadsheet."
        )
    # %%
    op, sess = connect(p.oauth, p.orgname)
    check_api_limit(sess)

    adder(users, op, sess)
Example #4
0
def main():
    p = ArgumentParser(description="List user/organization repos")
    p.add_argument("user", help="Git remote username / organization name")
    p.add_argument("oauth", help="Oauth filename", nargs="?")
    p.add_argument("-p",
                   "--pattern",
                   help="only repos with name starting with this string")
    p.add_argument("-settings",
                   help="open settings page for each repo",
                   action="store_true")
    p.add_argument("-alerts",
                   help="open alerts page for each repo",
                   action="store_true")
    P = p.parse_args()

    # %% authentication
    sess = gb.session(P.oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, P.user)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    if P.pattern:
        repos = (repo for repo in repos if repo.name.startswith(P.pattern))

    for repo in repos:
        print(repo.full_name)
        if P.settings:
            webbrowser.open_new_tab("https://github.com/" + repo.full_name +
                                    "/settings")
        if P.alerts:
            webbrowser.open_new_tab("https://github.com/" + repo.full_name +
                                    "/network/alerts")
Example #5
0
def main():
    p = ArgumentParser(
        description="Set Private GitHub repos for a user/organization with repo names matching pattern"
    )
    p.add_argument("userorgname", help="GitHub username / organizations")
    p.add_argument("oauth", help="Oauth filename")
    p.add_argument("pattern", help="make private repos with name starting with this string")
    P = p.parse_args()

    # %% authentication
    sess = gb.session(P.oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, P.userorgname)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    to_act = [repo for repo in repos if repo.name.startswith(P.pattern) and not repo.private]
    if not to_act:
        raise SystemExit(
            f"There were no repos left to make private with {P.pattern} in {P.userorgname}"
        )

    print("\ntype affirmative to make PRIVATE", "\n".join([repo.full_name for repo in to_act]))
    if input() != "affirmative":
        raise SystemExit("Aborted")

    for repo in to_act:
        repo.edit(private=True)
        print("private:", repo.full_name)
Example #6
0
def main():
    p = ArgumentParser(description="List organziation repos not in any team")
    p.add_argument("oauth", help="Oauth file")
    p.add_argument("orgname", help="Github Organization")
    p.add_argument("-stem", help="repos startin with this")
    p.add_argument("-put_team", help="put matching repos in this team")
    p = p.parse_args()

    op, sess = gb.connect_github(p.oauth, p.orgname)
    gb.check_api_limit(sess)

    lister(op, sess, p.stem, p.put_team)
Example #7
0
def main(username: str, oauth: str, stem: str):
    # %% authentication
    sess = gb.session(P.oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, P.user)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    to_act = (repo for repo in repos if repo.name.startswith(stem) and not repo.archived)

    for repo in to_act:
        print(repo.full_name)
Example #8
0
def main():
    p = ArgumentParser(description="add staff to teams")
    p.add_argument("oauth", help="Oauth file")
    p.add_argument("orgname", help="Github Organization")
    p.add_argument("-stem", help="repos startin with this", required=True)
    p.add_argument("-staff",
                   help="put matching repos in this team",
                   nargs="+",
                   required=True)
    p = p.parse_args()

    op, sess = gb.connect_github(p.oauth, p.orgname)
    gb.check_api_limit(sess)

    adder(op, sess, p.stem, p.staff)
def main():
    p = ArgumentParser(description='Set all collaborator permission to "read"')
    p.add_argument("user", help="GitHub username / organizations")
    p.add_argument("oauth", help="Oauth filename")
    p.add_argument("pattern",
                   help="modify repos with name starting with this string")
    p.add_argument("--omit", help="dont consider these admins", nargs="+")
    P = p.parse_args()

    # %% authentication
    sess = gb.session(P.oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, P.user)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    to_modify = [repo for repo in repos if repo.name.startswith(P.pattern)]

    print(
        "\ntype affirmative to remove all collaborators from\n",
        "\n".join([repo.full_name for repo in to_modify]),
    )
    modify = input() == "affirmative"

    for repo in to_modify:
        gb.check_api_limit(sess)

        collabs = repo.get_collaborators()

        admins = [c.login for c in collabs if c.login not in P.omit]
        if not admins:
            continue

        print("admins", repo.full_name, " ".join(admins))
        if modify:
            if repo.archived:
                logging.error(
                    f"could not remove collabs from archived {repo.full_name}")
                webbrowser.open_new_tab("https://github.com/" +
                                        repo.full_name + "/settings")
                continue

            for admin in admins:
                repo.remove_from_collaborators(admin)
Example #10
0
def main(username: str, oauth: str, stem: str):
    # %% authentication
    sess = gb.session(P.oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, P.user)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    # filter repos
    to_act = (repo for repo in repos if repo.name.startswith(stem)
              and repo.name != ".github" and not repo.fork
              and not repo.archived and repo.owner.login == userorg.login)

    for repo in to_act:
        try:
            repo.get_license()
        except github.GithubException:
            print(repo.full_name)
Example #11
0
def main(user: str, oauth: Path, pattern: str, only_empty: bool) -> typing.List[str]:
    # %% authentication
    sess = gb.session(oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, user)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    to_act = (repo for repo in repos if repo.name.startswith(pattern))

    empty: typing.List[str] = []
    for repo in to_act:
        print(f"examining {repo.name}", end="\r")
        authors: typing.Dict[str, int] = {}
        try:
            for commit in repo.get_commits():
                if only_empty:
                    break
                if not commit.stats:  # GitHub API bug?
                    continue
                if commit.stats.total == 0:
                    continue
                if not commit.author:  # GitHub API bug?
                    continue
                if commit.author.login in authors:
                    authors[commit.author.login] += commit.stats.total
                else:
                    authors[commit.author.login] = commit.stats.total
            if not only_empty:
                ax = figure().gca()
                ax.scatter(authors.keys(), authors.values())
                ax.get_yaxis().get_major_formatter().set_useOffset(False)
                ax.set_ylabel("total LoC changed")
                ax.set_yscale("log")
                ax.set_title(repo.name)
        except github.GithubException as exc:
            if "empty" in exc.data["message"]:
                empty.append(repo.name)
    print()  # flush stdout \r

    return sorted(empty)
def main():
    p = ArgumentParser(description="mass create repos for teams")
    p.add_argument("fn", help=".xlsx with group info")
    p.add_argument("oauth", help="Oauth file")
    p.add_argument("orgname", help="Github Organization")
    p.add_argument("-stem", help="beginning of repo names", default="")
    p.add_argument(
        "-col", help="column(s) for TeamName OR TeamNumber, TeamName", nargs="+", required=True
    )
    p.add_argument("-private", help="create private repos", action="store_true")
    p = p.parse_args()

    fn = Path(p.fn).expanduser()

    teams = pandas.read_excel(fn, usecols=",".join(p.col)).squeeze().dropna().drop_duplicates()
    # %%
    op, sess = connect(p.oauth, p.orgname)
    check_api_limit(sess)

    if teams.ndim == 1:
        by_num(teams, p.stem, p.private, op, sess)
    elif teams.shape[1] == 2:
        by_name(teams, p.stem, p.private, op, sess)
def main():
    p = ArgumentParser(description="mass copy files by language")
    p.add_argument("copyfn", help="file to copy into repos")
    p.add_argument("targetfn", help="path to copy file into in repos")
    p.add_argument("language", help="coding language to consider (case-sensitive)")
    p.add_argument("oauth", help="Oauth file")
    p.add_argument("userorg", help="Github Username or Organization")
    p.add_argument("-stem", help="beginning of repo names", default="")
    P = p.parse_args()

    language = P.language
    copyfn = Path(P.copyfn).expanduser().resolve(True)
    copy_text = copyfn.read_text()
    target = P.targetfn
    sess = gb.session(P.oauth)
    gb.check_api_limit(sess)
    # %% get user / organization handle
    userorg = gb.user_or_org(sess, P.userorg)
    # %% prepare to loop over repos
    repos = gb.get_repos(userorg)

    to_act = (repo for repo in repos if repo.name.startswith(P.stem))
    for repo in to_act:
        # sometimes a large amount of HTML, CSS, or docs show up as first language.
        langs = repo.get_languages()
        if not langs.get(language):
            continue
        try:
            existing = repo.get_contents(target)
            existing_code = base64.b64decode(existing.content).decode("utf8")
            if existing_code.strip() != copy_text.strip():
                print(repo.full_name, "different from", copyfn)
                repo.update_file(target, "update CI", copy_text, existing.sha)
        except github.GithubException:  # file not exist on remote
            print("copying", copyfn, "to", target, "in", repo.full_name)
            repo.create_file(target, "init CI", copy_text)
Example #14
0
def main(P):
    op, sess = connect(P.oauth, P.orgname)
    check_api_limit(sess)

    return get_collabs(op, sess, P.stem, P.regex)