Comprobar si una solicitud de extracción está actualizada con la rama de destino

6 minutos de lectura

Avatar de usuario de Brad Cooley
brad cooley

Nuestro proyecto usa sucursales protegidas y requiere que la sucursal base de un PR esté actualizada con la sucursal de destino para fusionarse. También estamos usando Jenkins para construir el encabezado no fusionado del PR porque el complemento que usamos reconstruirá automáticamente todos los PR abiertos cuando cambie la rama de destino, lo que puede obstruir rápidamente una canalización. Por lo tanto, en el caso de que se abra un PR sin estar actualizado con la rama de destino, queremos poder detener la canalización de Jenkins de inmediato y notificar al confirmador que deben fusionarse primero.

Entonces, al usar la API de GitHub, me gustaría poder saber si una solicitud de extracción está actualizada con la rama de destino. Lo más parecido a esto parece ser el atributo “fusionable” en una solicitud de extracción, pero parece que solo indica si se PUEDE realizar una fusión automática segura, no si la rama ya está actualizada.

¿Hay una etiqueta json de API directa que se pueda ver? Si no es así, ¿existe una forma sencilla de verificar esto manualmente con los comandos de git?

  • Verificaciones de estado requeridas tener una opción para Require branches to be up to date before merging. Si bien esto no responde a la parte de API de su pregunta, puede ser un flujo de trabajo válido para considerar.

    – osowski

    11 dic 2016 a las 22:32

Avatar de usuario de Scott Weldon
scott weldon

No sé si GitHub expone esta información a través de su API, pero puedes detectar esto manualmente con los comandos de Git. Desea encontrar lo que se conoce como la base de combinación y asegurarse de que esta confirmación sea la misma que la punta de master (o cualquiera que sea su rama principal).

En la forma de un script bash, se vería así:

if [ $(git merge-base @ master) == $(git rev-parse master) ]
then
  echo "Your branch is up to date."
  exit 0
else
  echo "You need to merge / rebase."
  exit 1
fi

Si incluye este script como un paso de compilación, los valores de salida deberían hacer que Jenkins falle el trabajo si es necesario.

Como se menciona en la respuesta de Dmitry, con las versiones más nuevas de Git puedes usar el --is-ancestor bandera para git merge-base para simplificarlo a un comando. El script entonces se vería así:

if git merge-base --is-ancestor master @
then
  echo "Your branch is up to date."
  exit 0
else
  echo "You need to merge / rebase."
  exit 1
fi

  • incluso podría usar BITBUCKET_PR_DESTINATION_BRANCH en lugar de maestro para hacerlo dinámico

    –Jorge Wander Santana Ureña

    3 oct 2021 a las 22:20

  • @Jorge Gracias, esa es una buena opción para Bitbucket; presumiblemente GitHub tiene algo similar.

    –Scott Weldon

    5 oct 2021 a las 17:20

  • Uy, mi mal. tienes razón jeje.

    –Jorge Wander Santana Ureña

    5 oct 2021 a las 20:24

  • Agregué echo para obtener los resultados: git merge-base –is-ancestor master @ ; eco $?

    – STF

    17 ene a las 13:37

  • Además, generalmente Github envía a Jenkins la rama fusionada, por lo que debe verificar si la rama de origen está actualizada: git merge-base –is-ancestor origin/master origin/${ghprbSourceBranch};

    – STF

    19 de enero a las 6:28

Si desea utilizar la API de github. Cualquier API que devuelva el objeto de solicitud de extracción tendrá el mergeable_state campo en él. si su valor es behind, eso significa que la rama base se actualiza después de que se crea la solicitud de extracción. es decir: la rama de solicitud de extracción está desactualizada.

Aquí está mergestatestatus explicación

Si está manejando respuestas de webhook en el servidor de Jenkings, la mayoría de los eventos de solicitud de extracción, como los eventos de solicitud de extracción creados, editados, cerrados o de comentarios, incluirán el mergeable_state información en el objeto de solicitud de extracción.

Avatar de usuario de Dmitry
Dmitri

Hay una forma moderna de hacerlo.

git merge-base --is-ancestor A B

ver git-merge-base

avatar de usuario de anask
Anask

Deberá usar la API GraphQL de GitHub y recuperar el mergeStateStatus valor como otros han mencionado. El script de shell de muestra a continuación asume que ya conoce el número de la solicitud de extracción y tiene un Token de acceso personal de GitHub.

# get-merge-state-status.sh example

# $TOKEN should be a defined environment variable

OWN_ORG='IBM'
REPO='data-import'

# get PR number from input
PR_NUMBER=$1

# prepare query with the appropriate parameters
QUERY=`cat <<EOF
{"query": 
    "query {
        repository(owner: \"${OWN_ORG}\", name: \"${REPO}\") {
            pullRequest(number: ${PR_NUMBER}) {
                title
                state
                mergeStateStatus
            }
        }
    }"
}
EOF`

# remove new lines so that the api understands the query
QUERY=$(echo $QUERY|tr -d '\n')

curl_opts=(
 -s
 -H "Authorization: bearer $TOKEN"
 -H "Accept: application/vnd.github.merge-info-preview+json"
 -X POST 
 -d "$QUERY"
)

# make the api call
JSON=$(curl "${curl_opts[@]}" https://api.github.com/graphql)


STATE=$(echo $JSON | jq -r '.data.repository.pullRequest.state')
M_STATE=$(echo $JSON | jq -r '.data.repository.pullRequest.mergeStateStatus')

echo $STATE $M_STATE

Luego puede ejecutar el script como:

[anask@supremedev]$ bash get-merge-state-status.sh 10
OPEN CLEAN

Tenga en cuenta que si está utilizando GitHub Enterprise, cambie la dirección de api.github.com a api.github.<SRV_NAME>.com.

avatar de usuario de anask
Anask

git rev-list se puede usar para devolver la diferencia entre dos ramas siempre que la rama PR tenga un punto común con la rama de destino (por ejemplo, maestro):

git rev-list --left-right --count  \                                                                 
    origin/dev_develop...$(git branch --show-current) | \                                        
    awk '{print "Behind "$1" - Ahead "$2""}'

# output example: Behind 13 - Ahead 20

Entonces puede agregar la siguiente verificación con el código de salida apropiado:

target="origin/master"
source=$(git branch --show-current)

# compare the target branch to the pull request branch
behind=`git rev-list --left-right --count  $target...$source | awk '{print $1}'`

if [[ $behind = 0 ]];
    then
        echo 'Up to date!'
        exit 0
    else
        echo 'Please merge!'
        exit 1
fi

Si está utilizando Travis u otros trabajos de CI que no extraen todas las confirmaciones, realice una git fetch antes de comparar las ramas:

# fetch the pull request branch's commits
git config remote.origin.fetch \
    +refs/heads/"${source}":refs/remotes/origin/"${source}"
git fetch origin

avatar de usuario de jd_
jd_

Este es un problema muy común para las personas que desean implementar un flujo de trabajo donde se serializan las fusiones.

Esto es algo que se puede resolver usando fusionar fácilmente. Ofrece exactamente lo que necesita a través de su flujo de trabajo estricto. Mergify se encarga de la actualización de su solicitud de extracción desactualizada y ordena la fusión de las solicitudes de extracción válidas para usted. ¡Creamos Mergify para resolver exactamente este problema en primer lugar!

(Descargo de responsabilidad: soy uno de los autores de Mergify)

¿Ha sido útil esta solución?