0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GitLab でアクセスできないプロジェクトを探す

Last updated at Posted at 2021-03-31

概要

退職等でブロックしていくときに発生する、次のいずれかを満たすプロジェクトを探す。
名前空間はユーザーとグループのいずれでもよい。

  • 所属メンバーがすべてブロック済である。
  • ブロックされていないメンバーもいるが、Maintainer 権限以上を持つものがいない。

その他:

  • 出力は YAML 的ななにか。
  • これからブロックするユーザーについてあらかじめ確認する場合は、 --block オプションで模擬できる。
  • ユーザーの名前空間だけテストする場合は、 --user オプションで模擬できる。

利用例

./find_missing  # 現状をチェックする
./find_missing --block foo --block bar  # foo と bar をブロックした状況をチェックする
./find_missing --block foo --user foo  # foo をブロックした状況について、 foo/* をチェックする

ソースコード

find_missing
#!/usr/bin/env python3

import argparse
import os

import requests


class GitLabAPI:
    def __init__(self, endpoint, token):
        self.endpoint = endpoint
        self.session = requests.Session()
        self.session.headers.update({'PRIVATE-TOKEN': token})

    def fetch(self, path, verbose=False, **kwargs):
        url = self.endpoint + path if path.startswith('/') else path
        res = None
        while True:
            params = dict(kwargs)
            if res is not None:
                params['page'] = res.headers['X-Next-Page']
            res = self.session.get(url, params=params)
            if verbose:
                current_page = res.headers.get('X-Page', '?')
                total_pages = res.headers.get('X-Total-Pages', '?')
                print(f'# [{current_page}/{total_pages}] {res.url}')
            res.raise_for_status()
            for item in res.json():
                yield item
            if res.headers.get('X-Next-Page', '') == '':
                break

    def get_users(self, **kwargs):
        return self.fetch('/users', **kwargs)

    def get_projects(self, **kwargs):
        return self.fetch('/projects', **kwargs)

    def get_user_projects(self, id_, **kwargs):
        return self.fetch(f'/users/{id_}/projects', **kwargs)

    def get_project_members(self, id_, **kwargs):
        return self.fetch(f'/projects/{id_}/members/all', **kwargs)

def report_project(project, members, notifications):
    roles = {
        0: 'No access',
        5: 'Minimal access',
        10: 'Guest',
        20: 'Reporter',
        30: 'Developer',
        40: 'Maintainer',
        50: 'Owner',
    }
    print('- project:', project['path_with_namespace'])
    print('  visibility:', project['visibility'])
    print('  description:', project['description'].replace('\r\n', ' '))
    print('  members:')
    for member in members:
        name = member['username']
        role = roles.get(member['access_level'], member['access_level'])
        state = member['state'] if member['state'] == 'active' else member['state'].upper()
        print(f'    - {name} ({role}, {state})')
    if len(notifications) > 0:
        print('  notifications:')
        for message in notifications:
            print(f'    - {message}')

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--endpoint',
        default=os.getenv('GITLAB_API_ENDPOINT', None),
        help='GitLab API endpoint [https://example.com/api/v4]')
    parser.add_argument('--token',
        default=os.getenv('GITLAB_API_PRIVATE_TOKEN', None),
        help='GitLab private token')
    parser.add_argument('--user', help='Check for the user project')
    parser.add_argument('--block', action='append', help='Assume the user is blocked')
    args = parser.parse_args()

    gitlab = GitLabAPI(args.endpoint, args.token)

    # check username
    if args.block:
        for name in args.block:
            for obj in gitlab.get_users(username=name):
                break
            else:
                raise RuntimeError(f'User {name} not found')

    if args.user:
        iterable = gitlab.get_user_projects(args.user, verbose=True)
    else:
        iterable = gitlab.get_projects(verbose=True)

    for project in iterable:
        no_active_member = True
        owner_is_blocked = True
        users = []
        for user in gitlab.get_project_members(project['id']):
            if args.block and user['username'] in args.block:
                user['state'] = 'block_simulated'
            if user['state'] == 'active':
                no_active_member = False
                if user['access_level'] >= 40:
                    owner_is_blocked = False
            users.append(user)

        notifications = []
        if no_active_member:
            notifications.append('no active member')
        elif owner_is_blocked:
            notifications.append('owner is blocked')

        if len(notifications) > 0 or args.user:
            report_project(project, users, notifications)


if __name__ == '__main__':
    main()
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?