diff --git a/README.md b/README.md index 531cb366f0ef39942dbd991ac599f269c262d0f5..9aecd80f22f075d1ceceabd7ee71042395185964 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ # Practical Work Manager (pwm) Programme python pour gérer les travaux pratiques des étudiants avec la contrainte d'utiliser le gitlab d'HEPIA. +Ce script permet d'automatiser de nombreuses tâches, notamment la création de nombreuses repositories d'un coup, ou encore cloner toutes les repositories contenues dans un groupe, etc. -## TL;DR +## Utilisation - Créer un groupe et les repositories en une seule commande, avec un repository "image" optionnel et un fichier d'emails (voir [Syntaxe du fichier YAML (REPOS_FILE)](#syntaxe-du-fichier-yaml-repos_file) : ```bash python pwm -t TOKEN group_repos GROUP_NAME REPOS_FILE [-i IMPORT_URL] ``` +- Créer, au sein d'un groupe existant, les repositories en une seule commande, avec un repository "image" optionnel et un fichier d'emails (voir [Syntaxe du fichier YAML (REPOS_FILE)](#syntaxe-du-fichier-yaml-repos_file) : + ```bash + python pwm -t TOKEN repos GROUP_ID REPOS_FILE [-i IMPORT_URL] + ``` - Clone tous les projets des étudiants d'un groupe gitlab (`ID`) dans un répertoire créé à la volée : ```bash python pwm -t TOKEN clone ID DIRECTORY @@ -18,10 +23,11 @@ Programme python pour gérer les travaux pratiques des étudiants avec la contra ``` - [Practical Work Manager (pwm)](#practical-work-manager-pwm) - - [TL;DR](#tldr) + - [Utilisation](#utilisation) - [Workflow d'utilisation](#workflow-dutilisation) - [Utilisation de pwm](#utilisation-de-pwm) - [Création d'un groupe et des projets](#création-dun-groupe-et-des-projets) + - [Création des projets au sein d'un groupe existant](#création-des-projets-au-sein-dun-groupe-existant) - [Création d'un groupe seulement](#création-dun-groupe-seulement) - [Création d'un sous-projet dans le groupe](#création-dun-sous-projet-dans-le-groupe) - [Clone de tous les repositories](#clone-de-tous-les-repositories) @@ -31,6 +37,7 @@ Programme python pour gérer les travaux pratiques des étudiants avec la contra - [Emails seulement](#emails-seulement) ## Workflow d'utilisation + Pour expliquer la démarche d'utilisation, prenons le scénario suivant : - L'enseignant Michel Albuquerque prépare un nouveau travail pratique (TP). Il souhaite forcer les étudiants à utiliser git et gitedu pour qu'ils versionnent leur code et pour qu'il puisse visualiser et recevoir leur rendus. - Les TPs sont à faire par groupe ou de manière individuelle. @@ -59,9 +66,13 @@ source .venv/bin/activate pip install -r requirements.txt ``` -pwm se présente sous la forme d'une CLI. Il nécessite un `token` gitlab, pouvant être généré [sur cette page](https://gitedu.hesge.ch/profile/personal_access_tokens), en cochant la case "api". Ce `token` peut ensuite être utilisé de trois manières : +pwm se présente sous la forme d'une CLI. Il nécessite un `token` gitlab, pouvant être généré [sur cette page](https://gitedu.hesge.ch/-/profile/personal_access_tokens), en cochant la case "api". -1. Écrit dans le fichier `~/.gitedu_token` +**Attention** : une fois crée, le token est affiché une fois seulement sur la page et ne sera ensuite plus jamais visible. + +Le `token` peut ensuite être utilisé de trois manières : + +1. Écrit dans le fichier `~/.gitedu_token` (conseil : réaliser ensuite un `chmod 600 ~/.gitedu_token` pour en protéger l'accès) 2. Placé dans la variable d'environnement `GITEDU_TOKEN` 3. Donné en argument de `pwm` avec l'option `-t` ou `--token` @@ -72,18 +83,64 @@ Selon les commandes, un `project_id` ou `group_id` est également nécessaire, i L'exécution du programme sans arguments affiche l'aide et le détail pour chaque sous-commande. ### Création d'un groupe et des projets + ```bash python pwm group_repos GROUP_NAME REPOS_FILE [-h] [--visibility VISIBILITY] [-i IMPORT_URL] [-x EXPIRES_AT] ``` Exécute les opérations de création de groupe et de repositories à partir d'un fichier YAML (voir [Syntaxe du fichier YAML (REPOS_FILE)](#syntaxe-du-fichier-yaml-repos_file)). Voir les sous-sections suivantes pour les détails des sous-commandes. +### Création des projets au sein d'un groupe existant + +```bash +python pwm repos GROUP_ID REPOS_FILE [-h] [-i IMPORT_URL] [-x EXPIRES_AT] +``` +Exécute les opérations de création de repositories à partir d'un fichier YAML (voir [Syntaxe du fichier YAML (REPOS_FILE)](#syntaxe-du-fichier-yaml-repos_file)). Voir les sous-sections suivantes pour les détails des sous-commandes. + +#### Exemple d'utilisation + +Soit le fichier `psa_groups.yml` qui defini les 3 groupes d'étudiants ci-dessous : + +``` +- name: group1 + emails: + - prenom.nom11@hesge.ch + - prenom.nom12@hesge.ch +- name: group2 + emails: + - prenom.nom21@hesge.ch + - prenom.nom22@hesge.ch +- name: group3 + emails: + - prenom.nom31@hesge.ch + - prenom.nom32@hesge.ch +``` + +On commence par activer l'environnement python : + +``` +python3 -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +``` + +Ensuite, on exécute le script qui va créer les groupes définis dans le fichier yml ci-dessus dans le groupe gitlab 1458 existant et populer chaque repository avec la repo passé en argument (ici une repo vide sur github) : + +``` +python3 pwm repos 1458 psa_2022.yml -i https://github.com/florentgluck/empty.git +``` + +Comme aucun token n'est spécifié, le script utilise celui se trouvant dans le fichier `~/.gitedu_token`. +A noter qu'on pourrait également ajouter l'argument `-t <token>` avant l'argument `repos` pour spécifier le token sur la ligne de commande. + ### Création d'un groupe seulement + ```bash python pwm group [-h] [--visibility VISIBILITY] GROUP_NAME ``` Crée un groupe au sens gitlab du terme, nommé `GROUP_NAME`, avec la visibilité optionnelle `VISIBILITY` (`private`, `internal` ou `public`), par défaut privée. Si le groupe existe déjà, ne fait rien. Retourne le `group_id` du groupe créé, nécessaire pour la création des sous-projets par exemple. ### Création d'un sous-projet dans le groupe + ```bash python pwm repo [-h] [-n NAME] [-i IMPORT_URL] [-x EXPIRES_AT] GROUP_ID EMAILS ``` @@ -95,21 +152,25 @@ Crée un dépôt git (projet) au sein d'un groupe à partir de l'URL d'un projet - `EMAILS` : une liste d'emails des étudiants. Les emails sont séparés par une virgule. Peut contenir un seul email. ### Clone de tous les repositories + ```bash python pwm clone [-h] [-g | -f] [-u UNTIL_DATE] ID DIRECTORY ``` Clone tous les repositories d'un groupe (`-g`) ou tous les forks d'un projet (`-f`) selon l'id (`ID`) donné dans un répertoire nommé `DIRECTORY`. Si une date `UNTIL_DATE` (au format `YYYY-MM-DD hh:mm`) est donnée, exécute un `git checkout` sur le premier commit précédant cette date. Affiche sur la sortie standard les membres du groupe (avec un droit d'accès supérieur à *Reporter*), l'url web du repo et dans quel sous-répertoire se trouvent les fichiers. ### Liste des projets d'un groupe ou des membres d'un projet + ```bash python pwm list [-h] [-p | -m] [-s SHOW] ID ``` Liste les projets d'un groupe ou les membres d'un projet selon l'id `ID`. L'argument `--show` (ou `-s`) permet de choisir quelles informations à afficher (par défaut le nom) : `[all | name | url | ssh]`. ## Syntaxe du fichier YAML (REPOS_FILE) + Le fichier YAML doit respecter une des deux syntaxes suivantes. ### Noms et emails + Pour chaque projet créé, un nom et une liste d'emails doivent être renseignés : ```yaml @@ -128,6 +189,7 @@ Pour chaque projet créé, un nom et une liste d'emails doivent être renseigné ``` ### Emails seulement + Si uniquement les emails sont fournis, prend le premier nom de chaque email pour nom de projet : ```yaml diff --git a/pwm b/pwm index 523c97cc8becad813cf89f9ffa3e7b996fd9cd08..fd1e8d3b362553722ffbc39260d014482548e3b7 100644 --- a/pwm +++ b/pwm @@ -246,6 +246,29 @@ def command_create_group_repos(args): print() +def command_create_repos(args): + """ + Create a set of repositories inside the specified (existing) group. For each repository listed + in the given file, create a repository. + """ + group_id = args.group_id + + with open(args.repos_file) as f: + repos = yaml.full_load(f) + for repo in repos: + if 'name' in repo: + name = repo['name'] + elif 'emails' in repo: + name = repo['emails'][0].split('@')[0] + else: + print('YAML file not correct, exit and delete group') + delete_group(args.token, group_id) + exit(1) + create_repository( + args.token, group_id, repo['emails'], name, args.import_url, args.expires_at) + print() + + def command_create_group(args): """ Call create_group @@ -346,6 +369,18 @@ if __name__ == '__main__': help="Expiration date to kick off students from this project, at 00:00:00. YYYY-MM-DD format (optional).") parser_group_repos.set_defaults(func=command_create_group_repos) + parser_repos = subparsers.add_parser( + 'repos', help='Create repos inside existing group') + parser_repos.add_argument( + "group_id", metavar="GROUP_ID", help="The existing group id.") + parser_repos.add_argument( + "repos_file", metavar="REPOS_FILE", help="YAML file with projects names and/or students emails.") + parser_repos.add_argument("-i", "--import_url", + help="Import the publicly accessible project by URL given here (optional).") + parser_repos.add_argument("-x", "--expires_at", + help="Expiration date to kick off students from this project, at 00:00:00. YYYY-MM-DD format (optional).") + parser_repos.set_defaults(func=command_create_repos) + parser_group = subparsers.add_parser('group', help='Create gitlab group') parser_group.add_argument( "group_name", metavar="GROUP_NAME", help="The group name.")