Las revisiones de código siempre han sido cruciales para mantener un estándar y enfatizar las mejores prácticas de código en un proyecto. Esta no es una publicación sobre cómo los desarrolladores deberían revisar el código, sino más bien sobre delegar una parte del mismo a la IA.
Como menciona Michael Lynch en su publicación: "Cómo hacer revisiones de código como un humano", deberíamos dejar que las computadoras se encarguen de las partes aburridas de la revisión del código. Si bien Michael hace hincapié en una herramienta de formato, a mí me gustaría ir un paso más allá y dejar que la inteligencia artificial se encargue de ello. Quiero decir, ¿por qué no aprovechar el auge de la IA en la industria?
Ahora bien, no estoy diciendo que la IA deba usarse en lugar de herramientas de formato y linters. En cambio, debe usarse además de eso, para detectar cosas triviales que un humano podría pasar por alto.
Es por eso que decidí crear una acción de github cuyo código revisa una diferencia de solicitud de extracción y genera sugerencias utilizando IA. Déjame explicarte cómo hacerlo.
? Nota
- Esta acción de GitHub ya está disponible en el mercado de GitHub.
- Es una acción de JavaScript: obtenga más información sobre cómo crear acciones de JavaScript en Github.
Para interactuar con la API de github, he usado octokit, que es una especie de SDK o biblioteca cliente para interactuar con la API de github de una manera idiomática.
Para que pueda obtener la diferencia de la solicitud de extracción, debe pasar el encabezado Aceptar con el valor application/vnd.github.diff junto con los parámetros requeridos.
async function getPullRequestDetails(octokit, { mode }) { let AcceptFormat = "application/vnd.github.raw json"; if (mode === "diff") AcceptFormat = "application/vnd.github.diff"; if (mode === "json") AcceptFormat = "application/vnd.github.raw json"; return await octokit.rest.pulls.get({ owner: github.context.repo.owner, repo: github.context.repo.repo, pull_number: github.context.payload.pull_request.number, headers: { accept: AcceptFormat, }, }); }
Si no estás familiarizado con las acciones de github en absoluto, aquí tienes una serie 101 de acciones de github de Victoria Lo y es un buen comienzo.
Una vez que obtengo la diferencia, la analizo y elimino los cambios no deseados, y luego la devuelvo en el esquema que se muestra a continuación:
/** using zod */ schema = z.object({ path: z.string(), position: z.number(), line: z.number(), change: z.object({ type: z.string(), add: z.boolean(), ln: z.number(), content: z.string(), relativePosition: z.number(), }), previously: z.string().optional(), suggestions: z.string().optional(), })
Ignorar archivos es bastante sencillo. La lista de entrada del usuario requiere una cadena de patrones globales separados por punto y coma. Luego se analiza, se concatena con la lista predeterminada de archivos ignorados y se elimina la duplicación.
**/*.md; **/*.env; **/*.lock;
const filesToIgnoreList = [ ...new Set( filesToIgnore .split(";") .map(file => file.trim()) .filter(file => file !== "") .concat(FILES_IGNORED_BY_DEFAULT) ), ];
La lista de archivos ignorados se usa luego para eliminar los cambios de diferencias que se refieren a esos archivos ignorados. Esto le brinda una carga útil sin procesar que contiene solo los cambios que desea.
Una vez que obtengo la carga útil sin procesar después de analizar la diferencia, la paso a la API de la plataforma. Aquí hay una implementación de la API OpenAI.
async function useOpenAI({ rawComments, openAI, rules, modelName, pullRequestContext }) { const result = await openAI.beta.chat.completions.parse({ model: getModelName(modelName, "openai"), messages: [ { role: "system", content: COMMON_SYSTEM_PROMPT, }, { role: "user", content: getUserPrompt(rules, rawComments, pullRequestContext), }, ], response_format: zodResponseFormat(diffPayloadSchema, "json_diff_response"), }); const { message } = result.choices[0]; if (message.refusal) { throw new Error(`the model refused to generate suggestions - ${message.refusal}`); } return message.parsed; }
Es posible que notes el uso del formato de respuesta en la implementación de la API. Esta es una característica proporcionada por muchas plataformas LLM, que le permite indicarle al modelo que genere la respuesta en un esquema/formato específico. Es especialmente útil en este caso, ya que no quiero que el modelo alucine y genere sugerencias para archivos o posiciones incorrectas en la solicitud de extracción, ni agregue nuevas propiedades a la carga útil de respuesta.
El mensaje del sistema está ahí para darle al modelo más contexto sobre cómo debe realizar la revisión del código y cuáles son algunas cosas a tener en cuenta. Puede ver el mensaje del sistema aquí github.com/murtuzaalisurti/better.
El mensaje de usuario contiene la diferencia real, las reglas y el contexto de la solicitud de extracción. Es lo que inicia la revisión del código.
Esta acción de github es compatible con los modelos OpenAI y Anthropic. Así es como implementa la API Anthropic:
async function useAnthropic({ rawComments, anthropic, rules, modelName, pullRequestContext }) { const { definitions } = zodToJsonSchema(diffPayloadSchema, "diffPayloadSchema"); const result = await anthropic.messages.create({ max_tokens: 8192, model: getModelName(modelName, "anthropic"), system: COMMON_SYSTEM_PROMPT, tools: [ { name: "structuredOutput", description: "Structured Output", input_schema: definitions["diffPayloadSchema"], }, ], tool_choice: { type: "tool", name: "structuredOutput", }, messages: [ { role: "user", content: getUserPrompt(rules, rawComments, pullRequestContext), }, ], }); let parsed = null; for (const block of result.content) { if (block.type === "tool_use") { parsed = block.input; break; } } return parsed; }
Finalmente, después de recuperar las sugerencias, las desinfecto y las paso a la API de github para agregar comentarios como parte de la revisión.
Elegí la siguiente forma de agregar comentarios porque al crear una nueva reseña, puedes agregar todos los comentarios de una sola vez en lugar de agregar un solo comentario a la vez. Agregar comentarios uno por uno también puede activar la limitación de la tasa porque agregar comentarios activa notificaciones y no desea enviar spam a los usuarios con notificaciones.
function filterPositionsNotPresentInRawPayload(rawComments, comments) { return comments.filter(comment => rawComments.some(rawComment => rawComment.path === comment.path && rawComment.line === comment.line) ); } async function addReviewComments(suggestions, octokit, rawComments, modelName) { const { info } = log({ withTimestamp: true }); // eslint-disable-line no-use-before-define const comments = filterPositionsNotPresentInRawPayload(rawComments, extractComments().comments(suggestions)); try { await octokit.rest.pulls.createReview({ owner: github.context.repo.owner, repo: github.context.repo.repo, pull_number: github.context.payload.pull_request.number, body: `Code Review by ${modelName}`, event: "COMMENT", comments, }); } catch (error) { info(`Failed to add review comments: ${JSON.stringify(comments, null, 2)}`); throw error; } }
Quería mantener la acción de github abierta y abierta a integraciones y es por eso que puedes usar cualquier modelo de tu elección (consulta la lista de modelos compatibles), o puedes ajustar y construir su propio modelo personalizado además de los modelos base compatibles y úselo con esta acción de github.
Si encuentra algún problema con el token o limitación de velocidad, es posible que desee actualizar los límites de su modelo consultando la documentación de la plataforma respectiva.
Entonces, ¿qué estás esperando? Si tiene un repositorio en github, pruebe la acción ahora: está en el mercado de acciones de github.
Una acción de github de revisión de código impulsada por IA, lista para usar en tu flujo de trabajo.
Cree un archivo de flujo de trabajo dentro de la carpeta .github/workflows (créelo si no existe) de su repositorio con el siguiente contenido:
name: Code Review
on
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
branches:
- main # change this to your target branch
workflow_dispatch: # Allows you to run the workflow manually from the Actions tab
permissions: # necessary permissions
pull-requests: write
contents: read
jobs:
your-job-name:
runs-on: ubuntu-latest
name: your-job-name
steps:
- name: step-name
id: step-id
uses: murtuzaalisurti/better@v2 # this is
…Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3