ghclassroom
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

ghclassroom

Es una CLI configurable para la calificación de repositorios, permite enlazar calificadores para evaluar y escribir los resultados.

Características

  • Comando para clonar repositorios personalizado
  • Ejecución en paralelo (la cli no trabaja en paralelo, pero lanza los comandos las veces especificadas, por lo que desde la perspectiva de la cli es asíncrono)
  • Capaz de filtrar que repositorios tomar en cuenta
  • Permite acoplar un grader (se comunican por i/o)
    • ejecución por repositorio o un sólo proceso
  • Permite acoplar un writer (se comunican por i/o)
    • se ejecuta como único proceso

Instalar

npm install -g ghclassroom

CLI

ghclassroom --help # ayuda de la cli
ghclassroom init # crea los archivos de configuración
ghclassroom # corre la cli con la configuración local
ghclassroom logs # permite hacer búsquedas en el log

Configuración

Se recomienda visualizarlo en un editor que entienda javascript/typescript, por ejemplo VSCode, ya que le permite visualizar el tipado de la configuración (lo siguiente son los tipos de la configuración, no el archivo en sí).

export type Command = string | {
  bin: string,
  args: CommandArg[]
}

export interface Config {
  // el archivo csv descargado desde Github Classroom
  classroomFile: string

  /*
    Si está en modo step ghclassroom va ejecutar
    las fases linealmente, es decir que aunque
    el repositorio ya esté disponible para ejecutar
    el evaluador este no lo hará hasta que todos
    estén clonados.

    Si está en el modo student ghclassroom ejecuta
    la siguiente etapa inmediatamente después de
    que la anterior termine, por ejemplo si ya
    se clonó el repositorio esté empezará con
    la evaluación y al terminar la evaluación
    seguirá con la escritura de los resultados,
    sin importar si hay todavía repositorios
    que no se han clonado o evaluado.
  */
  executeBy: "step" | "student"

  // Permite modificar el cómo se clona los
  // repositorios
  clone: {
    /*
      Permite describir como se va clonar, los comandos
      se unen a través de un newline, gracias a esto
      los comandos mantienen el mismo contexto

      Hay dos formas de describir un comando:
      1. escribe el comando como string ej: "mkdir -p temp"
      2. describe el comando
        - se debe especificar el binario
        - se listan los argumentos
        - los argumentos pueden ser estáticos (un string)
        o dinámicos si se utiliza una función, esta toma
        el contexto de los comandos y devuelve un
        string, ejemplo de estos son cloneDirectory,
        y los que se construyen a partir de las funciones
        para crear enlaces de git.
    */
    cmd: Command[]

    // debe devolver el directorio del respositorio
    // por lo que tenga cuidado de usar cd en el comando
    // para clonar ya que este directorio se crear
    // a partir de la posición actual
    getCloneDirectory: (student: Student) => string

    // muestra la salida de la clonación
    showOutput: boolean
  }

  // toma el continido de la fila en el archivo csv
  // y debería devolver un verdadero si se debe
  // tomar en cuenta
  filter?: (student: Student) => boolean

  // la cantidad de instancias de los procesos
  // que se lanzan, por ejemplo con el valor de 5
  // significa que se clonan 5 repositorios a la vez,
  // se evaluan 5 estudiantes a la vez (si es una sola
  // instancia el evaluador se envían uno de tras de otro)
  // y se envían 5 mensajes al proceso de escritura
  parallel: number

  // configuración del evaluador
  grader?: {
    // mismo concepto que clone.cmd.
    cmd: Command[]

    // Si es verdadero, se lanzará el comando
    // por cada repositorio, note que estará posicionado
    // en dicha carpeta.

    // Si es falso, se lanza una única vez el comando
    // y se posiciona en la carpeta dónde está ejecutando
    // ghclassroom.
    byStudent: boolean
  }

  // Como lanzar el proceso para escribir resultados,
  // este se ejecuta una única vez y se espera que
  // se mantenga vivo en todo el proceso.

  // El comadno se ejecuta en la misma carpeta
  // en la que se está ejecutando ghclassroom
  writer?: {
    cmd: Command[]
  }
}

archivo de configuración

/*
El archivo de configuración devuelve una función
con el objetivo que el usuario tenga algunas
utilidades a la mano.

Creación de links para clonar:
    entre las utilidades se encuentra createSSHUrlGit
    que devuelve un SSH URL válido, createPATUrlGit
    que devuelve un link que utiliza los personal
    access token para clonar, por lo que para obtener
    el enlace objetivo se puede utilizar los mismos para
    construirlos.

studentRepoUrl: este argumento de comando devuelve
el url que provee el csv.

cloneDirectory: este argumento de comando no debería
alterarse y debería ser usado, utiliza internamente
la función getCloneDirectory (definida por el usuario)
y le pasa el estudiante objetivo para obtener el directorio
que se va utilizar.

getCloneDirectory: es una implementación por defecto
para el directorio de clonación, que devuelve el
roster_identifier. En el caso del comando git clone
de toda la vida al no obtener nada clona el repositorio
con el nombre del mismo, pero esto puede no ser
siempre cierto por lo que valdría la pena implementar
tu propia función getCloneDirectory en caso de no
tener roster_identifier
*/
export const config = ({
    createSSHUrlGit,
    cloneDirectory,
    getCloneDirectory
}) => {
    return {
        // configuración
    }
}

Grader

Este componente debe ser implementado por usted, para los mensajes se puede utilizar el paquete de messaging (si lo implementa con node.js).

import { MessagingNode, MessageType } from "ghclassroom/messaging"

const inout = new MessagingNode(process.stdin, process.stdout)

inout.on("message", (message) => {
  // manejar la petición

  // ...

  // enviar una respuesta
  inout.sendMessage({
    tag: message.tag, // recuerde responder a la conversación
    type: MessageType.response,
    comment: "...",
    grade: 100
  })
})

Lo de arriba expone el paquete clroom-messaging incluída en la CLI de ghclassroom.

En sí lo que debe soportar es leer y escribir JSON por consola. La CLI ghclassroom soporta la lectura sin importar si se envían newlines, lo que debe cumplir es que sea un JSON válido (esto gracias a stream-json) por lo que no se debe preocupar como imprimir a pantalla. Por otro lado ghclassroom escribe en la entrada de su evaluador en una sola línea (se usa JSON.stringify() y se separan por medio de un newline\n cada mensaje). El lenguaje para su implementación queda a su criterio, pero tenga en cuenta que debe ser posible arrancarlo por medio de lo declarado en config.grader.cmd.

Writer

Si el archivo en el que se van a escribir los resultados es un CSV, te puede interesar: csvwriter, para evitar trabajo extra :).

Formato de peticiones

Grader

{
    "tag": "<identifica la comunicación>",
    "type": "request",
    "student": { ... }, // la fila del csv en forma de objeto
    "path": "/path/to/repo" // es absoluto
}

Writer

{
    "tag": "<identifica la comunicación>",
    "type": "request",
    "student": { ... }, // la fila del csv en forma de objeto
    "grade": 90, // el tipo depende del grader
    "comment": "..." // el tipo depende del grader
}

Formato de respuestas

Grader

// error
{
    "tag": "<el tag que se envío>",
    "type": "error",
    "comment": "..."
}

// ok!
{
    "tag": "<el tag que se envío>",
    "type": "response",
    "grade": 90,
    "comment": "..." // se va mandar al writer
}

Writer

// error
{
    "tag": "<el tag que se envío>",
    "type": "error",
    "status": "...", // lo define el writer
    "missings": ["id"] // ver explicación en el paquete csvw-cli
}

// ok!
{
    "tag": "<el tag que se envío>",
    "type": "response",
    "status": "...", // lo define el writer
}

Buscar en Log

Utilizando ghclassroom logs es posible buscar entre los diferentes logs. En pantalla aparecerá las fechas de los logs con el más reciente encabezando la lista.

El log se crea por etapa, cuándo se clona un repositorio es registrado en el log (aunque falle), al igual que cuándo se evalua o se escribe, sin embargo estos son omitidos si no son parte de la configuración (ya que no se ejecutarían).

Un caso de uso pueda ser cuándo se evaluaron los repositorios, pero el carnet del estudiante no fue encontrado en el archivo dónde se está escribiendo, esto se traduce a un fallo en la etapa de write, por lo que aplicar los filtros Paso = write y Estado = failed encontrará a estas situaciones, y podrá ver por ende la nota aunque no se haya escrito satisfactoriamente:

{
  student: {
    assignment_name: '...',
    assignment_url: '...',
    starter_code_url: '...',
    github_username: 'gbenm',
    roster_identifier: '033',
    student_repository_name: '...',
    student_repository_url: '...',
    submission_timestamp: '',
    points_awarded: '0',
    points_available: '0'
  },
  step: 'write',
  grade: 96,
  writeStatus: 'not found',
  missings: [ "033" ],
  status: 'failed'
}

Package Sidebar

Install

npm i ghclassroom

Weekly Downloads

0

Version

1.0.0

License

MIT

Unpacked Size

109 kB

Total Files

44

Last publish

Collaborators

  • bengm