1

I need to find all projects and shared projects within a Gitlab group with subgroups. I managed to list the names of all projects like this:

group = gl.groups.get(11111, lazy=True)

# find all projects, also in subgroups
projects=group.projects.list(include_subgroups=True, all=True)
for prj in projects:
    print(prj.attributes['name'])
print("")

What I am missing is to list also the shared projects within the group. Or maybe to put this in other words: find out all projects where my group is a member. Is this possible with the Python API?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Zozzoy
  • 63
  • 6

4 Answers4

1

So, inspired by the answer of sytech, I found out that it was not working in the first place, as the shared projects were still hidden in the subgroups. So I came up with the following code that digs through all various levels of subgroups to find all shared projects. I assume this can be written way more elegant, but it works for me:

# group definition
main_group_id = 11111

# create empty list that will contain final result
list_subgroups_id_all = []

# create empty list that act as temporal storage of the results outside the function
list_subgroups_id_stored = []



# function to create a list of subgroups of a group (id)
def find_subgroups(group_id):

    # retrieve group object
    group = gl.groups.get(group_id)

    # create empty lists to store id of subgroups
    list_subgroups_id = []

    #iterate through group to find id of all subgroups
    for sub in group.subgroups.list():
        list_subgroups_id.append(sub.id)

    return(list_subgroups_id)


# function to iterate over the various groups for subgroup detection
def iterate_subgroups(group_id, list_subgroups_id_all):

    # for a given id, find existing subgroups (id) and store them in a list
    list_subgroups_id = find_subgroups(group_id)

    # add the found items to the list storage variable, so that the results are not overwritten
    list_subgroups_id_stored.append(list_subgroups_id)

    # for each found subgroup_id, test if it is already part of the total id list
    # if not, keep store it and test for more subgroups
    for test_id in list_subgroups_id:
        if test_id not in list_subgroups_id_all:

            # add it to total subgroup id list (final results list)
            list_subgroups_id_all.append(test_id)

            # check whether test_id contains more subgroups
            list_subgroups_id_tmp = iterate_subgroups(test_id, list_subgroups_id_all)

            #if so, append to stored subgroup list that is currently checked
            list_subgroups_id_stored.append(list_subgroups_id_tmp)

    return(list_subgroups_id_all)

# find all subgroup and subsubgroups, etc... store ids in list
list_subgroups_id_all = iterate_subgroups(main_group_id , list_subgroups_id_all)

print("***ids of all subgroups***")
print(list_subgroups_id_all)
print("")

print("***names of all subgroups***")
list_names = []
for ids in list_subgroups_id_all:
    group = gl.groups.get(ids)
    group_name = group.attributes['name']
    list_names.append(group_name)
print(list_names)
#print(list_subgroups_name_all)
print("")

# print all directly integrated projects of the main group, also those in subgroups
print("***integrated projects***")
group = gl.groups.get(main_group_id)
projects=group.projects.list(include_subgroups=True, all=True)
for prj in projects:
    print(prj.attributes['name'])
print("")

# print all shared projects
print("***shared projects***")
for sub in list_subgroups_id_all:
    group = gl.groups.get(sub)
    for shared_prj in group.shared_projects:
        print(shared_prj['path_with_namespace'])
print("")

One question that remains - at the very beginning I retrieve the main group by its id (here: 11111), but can I actually also get this id by looking for the name of the group? Something like: group_id = gl.group.get(attribute={'name','foo'}) (not working)?

Zozzoy
  • 63
  • 6
0

You can get the shared projects by the .shared_projects attribute:

group = gl.groups.get(11111)
for proj in group.shared_projects:
    print(proj['path_with_namespace'])

However, you cannot use the lazy=True argument to gl.groups.get.

>>> group = gl.groups.get(11111, lazy=True)
>>> group.shared_projects
AttributeError: shared_projects
sytech
  • 29,298
  • 3
  • 45
  • 86
  • Unfortunately, that does not work for me. I only get the same results like before, that means all the projects, but not the shared projects. – Zozzoy Nov 04 '21 at 09:03
0

This code will query all the projects in each subgroup and handle multiple subgroups inside a subgroup as well. it works perfectly and I hope it helps someone else.

import gitlab
import os

# Set your GitLab API access token
access_token = 'GITLAB_ACCESS_TOKEN'
if not access_token:
    raise ValueError("No GitLab access token found. Please set the GITLAB_ACCESS_TOKEN environment variable.")

# Set the URL of your GitLab instance
gitlab_url = os.getenv('GITLAB_URL', 'https://gitLab.com/')

# Replace this with your target subgroup path
subgroup_path = '2323' #'your/subgroup/path or your subgroup number'

# Initialize the GitLab connection
gl = gitlab.Gitlab(gitlab_url, private_token=access_token)

# Recursively find all projects in the subgroup and its subgroups
def find_projects_in_group(group):
    projects = gl.groups.get(group.id).projects.list(all=True)
    
    subgroups = gl.groups.get(group.id).subgroups.list(all=True)
    
    for subgroup in subgroups:
        projects.extend(find_projects_in_group(subgroup))
    return projects

# Find the target subgroup
try:
    target_group = gl.groups.get(subgroup_path)
except gitlab.exceptions.GitlabGetError:
    raise ValueError("Subgroup not found: " + subgroup_path)

# Get the list of projects
projects = find_projects_in_group(target_group)

# Print the list of projects
for project in projects:
    print("project path:["+project.ssh_url_to_repo+"]" )
Amir
  • 1,919
  • 8
  • 53
  • 105
0
# This code will list all files with specific extension (*.pdf)



import gitlab
import re

gl = gitlab.Gitlab('<gitlab url>', private_token='<private gitlab token')
f = open('result.txt', 'w')

def processGroup(groupName, parentGroup):
    # print(groupName)

    group = gl.groups.get(groupName)

    # print('***** ' + group.name + ' ******')

    projects = group.projects.list(iterator=True)
    for project in projects:
        print('\n' + parentGroup + '/' + group.name + '/' + project.name + '\n *********************************************')
        f.write('\n' + parentGroup + '/' + group.name + '/' + project.name + '\n *********************************************\n')
    
        prj = gl.projects.get(project.id)
        try:
            for filename in prj.repository_tree(recursive=True, iterator=True):
                # print(filename.get('path'))
                filenamePath = filename.get('path')
                if re.search('[.]pdf$', filenamePath):
                    print(group.name + '/' + project.name + '/' + filenamePath)
                    f.write(group.name + '/' + project.name + '/' + filenamePath + '\n')
        except:
            print('No files in ' + prj.name) 

    parentGroup = parentGroup + '/' if len(parentGroup) else '' + groupName
    for subGroup in group.subgroups.list(iterator=True):
            processGroup(subGroup.id, parentGroup)
    
 

processGroup('<gitlab group>', '')
f.close()
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user3389071
  • 61
  • 1
  • 4