Giter Site home page Giter Site logo

gh-cli-alu0101228587's Introduction

Github Cli

Jaime Simeón Palomar Blumenthal - [email protected]

Se debe de utilizar las funcionalidades de gh para crear un repositorio, conectarse a él y eliminarlo; crear alias y funcionalidades nuevas utilizando nodeJS.

Autenticación

En primer lugar, debemos generar un token en Github accediendo a Settings > Developer Settings > Personal access token.

Personal access token

Una vez ahí, generamos un nuevo token con todos los permisos activos (por comodidad), y guardamos la configuración. Tendremos que copiar y guardar el token que hemos generado en algún fichero seguro, puesto que no podremos volver a obtenerlo una vez salgamos de la página actual.

Tras haberlo salvado, en la terminal modificaremos la variable local GITHUB_TOKEN y la igualaremos a nuestro token:

export GITHUB_TOKEN=ghp_a41qMU21gyhgLzwMZz6Gy434rzkQhvZ4dNzrm

Finalmente nos dirigiremos a nuestro fichero ~/.profile en Ubuntu. Otras distribuciones pueden tener un fichero de configuración distinto. Al final del documento vamos a pegar la línea anterior para que se configure nuestro token cada vez que iniciemos la shell.

Alias

Muchas veces queremos ejecutar comandos mútilples veces y estos son muy largos. Es por esto que disponemos del comando gh alias. La nomenclatura genérica para este comando es la siguiente.

gh alias set <alias> '<comando>'    # Para crear un alias.
gh alias delete <alias>             # Para eliminar un alias.
gh alias list                       # Para listar todos los alias.

Alias para crear repositorios

Vamos a hacer un alias para crear un repositorio en una organización dada:

gh alias set create-repo 'repo create "$2"/"$1"' #gh create-repo [repositorio] [organización o propietario]

Si ejecutamos el comando empleando el alias:

Gh alias repo create

Alias para eliminar repositorios

Vamos a generar una alias para eliminar un repositorio de una organización indicada:

gh alias set delete-repo 'api -X DELETE /repos/"$2"/"$1"' #gh delete-repo [repositorio] [organización o propietario]

Alias para ver organizaciones

gh alias set org-list "api --paginate /user/memberships/orgs --jq '.[].organization | .login, .url'"

¿Qué hace cada una de las opciones y argumentos?

  • --paginate: Junta todos los diferentes request que nos llegan desde el serivicio web.
  • --jq: Filtra la entrada en JSON.
    • .[]: Devuelve todos los elementos del array del fichero Json.
    • .organization: Filtra los elementos que se llamen organization.
    • | .login, .url: Indica que queremos los elementos login y url de organization.

En resumen, '.[].organization | .login, .url' significa:

  • Quiero todos los elementos del array que se llamen organization.
  • Dentro de los elementos organization quiero los atributos login y url.

Extensiones GH

En numerosas ocasiones requeriremos de funcionalidades que de las que no dispone GH nativamente. Con los conocimientos suficientes podremos desarrollarlas y publicarlas nosotros mismos.

La única condición para publicarla una vez desarrollada es que el nombre de la extensión (y por ende, la forma en la que se invoca) tenga la forma gh-[nombre_funcionalidad].

Para esta práctica, elaboraremos una extensión que nos liste los participantes en una organización y los repositorios en esta. La llamaremos gh-members.

En primer lugar, ejecutaremos npm init para inicializar el directorio actual como proyecto node y configuraremos nuestro fichero package.json:

{   // Información de la aplicación
  "name": "gh-members",
  "version": "1.1.0",
  "description": "This extension allows you to list every member and repository of a given organization",
  "main": "gh-members.js",
  "scripts": {
    "start": "node gh-members",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
    // Información del repositorio
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ULL-ESIT-DMSI-1920/gh-members.git"
  },
    // Información del autor
  "keywords": [gh, git, github, api, organization, owner, members, repositories],
  "author": "alu0101228587",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/ULL-ESIT-DMSI-1920/gh-members/issues"
  },
    // Dependencias principales
  "homepage": "https://github.com/ULL-ESIT-DMSI-1920/gh-members#readme",
  "dependencies": {
    "commander": "^8.3.0",
    "shelljs": "^0.8.4"
  }
}

Lo realmente importante de este fichero son las dependencias. Son librerías que utilizaremos para la ejecución de nuestro programa. En este fichero también especificaremos qué versiones queremos de estas dependencias.

Ahora, si ejecutamos npm install, NPM leerá las dependencias previamente especificadas e instalará esos módulos principales y los módulos secundarios que estos requieran para funcionar.

Todo lo instalado se encuentra en el directorio node_modules, y las versiones correspondientes en el fichero package-lock.json.

Seguidamente configuraremos un pequeño script de bash (gh-members) que compruebe si Node está instalado y localice la dirección absoluta del script JavaScript donde implementaremos todas las funcionalidades de la aplicación.

### Especificación del intérprete bash
#!/usr/bin/env bash
set -e

# Si Node no está instalado lanza un menzaje de error
# y finaliza la ejecución del programa
if ! type -p node >/dev/null; then
   echo "Node not found on the system" >&2
   exit 1
fi

# Calcula la dirección absoluta del script.
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

# Ejecuta el script JavaScript pasándole cualquier argumento
${SCRIPT_DIR}/gh-members.js "$@"

Finalmente, pasaremos a implementar todas las funcionalidades en el fichero gh-members.js. En primer lugar instanciaremos los módulos que vayamos a utilizar y que previamente especificamos en las dependencias (package.json):

const fs = require("fs");
const shell = require('shelljs');
const { Command } = require('commander');
const program = new Command();

Podemos llamar a cualquier método o atributo público de program, por ejemlo, de la siguiente manera: program.[atributo o método].

Ahora debemos comprobar si git y gh están instalados en el sistema y, sino, lanzar un mensaje de error e interrumpir la ejecución:

if (!shell.which('git')) {
	shell.echo("Git not installed.");
	shell.exit(1);
}

if (!shell.which('gh')) {
	shell.echo("gh not installed.");
	shell.exit(1);
}

Continuamos especificando las opciones con las que podremos ejecutar la aplicación. También le indicaremos a la aplicación que tiene que ir consumiendo estas opciones o, dicho de otro modo, parseando el array argv:

program                                                     // Equivale a:
	.version(config.version)                                // progarm.version(config.version)
	.option('-r, --repo', 'List repositories of owner')     // program.option('-r, --repo', 'List repositories of owner')
	.option('-o, --owner <owner>', 'Specify owner')         // program.option('-o, --owner <owner>', 'Specify owner')

program.parse(process.argv);                                // Parsea argv.

Una cosa a tener en cuenta es que al utilizar el método .option de program (o el módulo Commander) se crean variables para cada opción cuyo nombre es el de la opción larga de esa opción: para la primera opción es program.opts().repo y para la segunda program.opts().owner. Por mayor comodidad vamos a procesar program.opts() y vamos a quedarnos con las dos variables repo y owner.

const { repo, owner } = program.opts();

Finalmente implementaremos la lógica de la aplicación: Si no nos da un argumento, lanza la ayuda y termina la ejecución; si nos da el nombre de una organización (opción -o), devuelve la lista con sus miembros; y si le pasamos la opción -r también nos dará la lista de repositorios de esa organización.

if (!owner) {
	console.log("Owner not specified. Sending help...");

	program.help();
	shell.exit(1);
}

console.log(`\n-- Members of ${owner} --\n`);
shell.exec(`gh api -X GET /orgs/${owner}/members --jq ".[].login"`);

if (repo) {
	console.log(`\n-- Repositories of ${owner} --\n`);
	shell.exec(`gh api -X GET /orgs/${owner}/repos --jq '.[].name'`);
}

El repo de la extensión tiene que ser un subrepo del de la práctica.

Hacemos gh extension create gh-nombre en el repo de la práctica Nos movemos al directorio de la extensión y hacemos gh repo create --public ULL-ESIT-DMSI-1920/gh-nombre git submodule add direccionhttps

Para clonar un super repo git clone --recurse-submodules direccion

gh api -X GET /user/orgs

Open in Visual Studio Code

gh-cli-alu0101228587's People

Contributors

jpalomarbl avatar github-classroom[bot] avatar

Watchers

Casiano Rodriguez-Leon avatar

gh-cli-alu0101228587's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.