Acciones de GitHub simples que interactúen con la API de GitHub

Quería hacer una acción de GitHub que cerrase educadamente cada PR recibido en algunos repositorios. GitHub permite desactivar el gestor de issues en un repositorio, pero no permite desactivar el gestor de pull requests. Es decir, siempre un proyecto va a aceptar pull requests y contribuciones externas. Algo con lo que en algunos casos no me llevo bien.

Aunque para algunos proyectos me parece bien, en proyectos más artesanales no me gusta aceptar código ajeno porque al fin y al cabo es una artesanía. Igual que en la playa no voy por ahí poniéndole torres a los castillos de arena que están haciendo otras personas, incluso aunque los estén haciendo en un lugar público y no en el jardín de su propia casa, me interesaría restringir la participación en algunos repositorios donde la gracia es precisamente que se construye artesanalmente.

La GDPR me pone una excusa bastante buena para hacer esto, puesto que si son repositorios que voy a estar alojando en mi servidor y sirviendo desde mi propio servidor de Git, me puede poner en un problema legal estar sirviendo nombres y direcciones de correo electrónico de otras personas, dentro de los commits del repositorio y de la interfaz web.

El resumen es que existe una acción reusable llamada actions/github-script que sirve precisamente para interactuar con la API de GitHub desde GitHub Actions. Es mucho más conveniente que hacer scripts que hagan lo mismo con los tokens, y también más seguro que utilizar integraciones del marketplace. Lo que se hace es pasar el parámetro script con el código JavaScript que se quiere ejecutar. El README de la acción explica las variables que hay a mano, pero se puede reducir a:

  • github: es un cliente de Octokit que se nos proporciona con la sesión ya iniciada.
  • context: contiene información del workflow, como el ID de ejecución, el nombre del repositorio, o el número de issue. No está documentado, pero su código es fácil de entender.

Tener a mano la documentación REST de GitHub puede ayudar, sobre todo para los casos en los que no está bien explicado qué valores enumerados puede tomar un parámetro.

También es importante considerar los permissions de la acción, ya que para hacer operaciones POST, PUT y DELETE con la API de GitHub, habrá que configurar la acción para que use un GITHUB_TOKEN de lectura y escritura, ya que el que hay por defecto sólo es de lectura y sólo vale para recuperar información. La API de GitHub trata a los pull requests como una especialización de un issue, pero en realidad hay que darle permiso de escritura tanto a los issues como a los pull-requests.

Con todo, me hice una acción que cierra un PR «en el momento» de abrirlo. Lo de «en el momento» va entre comillas porque después de todo las acciones se ejecutan cuando se puedan, pero lo importante es que eventualmente el pull request será cerrado:

name: Close PR

on:
  pull_request_target:
    types: [opened]

jobs:
  run:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
    steps:
    - uses: actions/github-script@v7
      with:
        script: |
          github.rest.issues.createComment({
            owner: context.repo.owner,
            repo: context.repo.repo,
            issue_number: context.issue.number,
            body: 'Este repo no acepta PRs, pero gracias por participar',
          })
          github.rest.issues.update({
            owner: context.repo.owner,
            repo: context.repo.repo,
            issue_number: context.issue.number,
            state: 'closed',
            state_reason: 'not_planned',
          })

Para los repositorios en los que vaya a aplicar esto, debería ponerlo en el README claramente. Puede sonar maleducado desaprovechar el tiempo de alguien que ha hecho un fork para modificar un archivo, pero considero que si en el README estoy dejando claro que no quiero que se haga esto, entonces estoy haciendo todo lo que puedo por mi parte.